From noreply at buildbot.pypy.org Fri Jun 1 14:23:40 2012 From: noreply at buildbot.pypy.org (hager) Date: Fri, 1 Jun 2012 14:23:40 +0200 (CEST) Subject: [pypy-commit] extradoc extradoc: quite likely that I'm coming Message-ID: <20120601122340.AE9D91C027E@cobra.cs.uni-duesseldorf.de> Author: Sven Hager Branch: extradoc Changeset: r4208:5db78e31e996 Date: 2012-06-01 14:23 +0200 http://bitbucket.org/pypy/extradoc/changeset/5db78e31e996/ Log: quite likely that I'm coming diff --git a/sprintinfo/leipzig2012/people.txt b/sprintinfo/leipzig2012/people.txt --- a/sprintinfo/leipzig2012/people.txt +++ b/sprintinfo/leipzig2012/people.txt @@ -10,5 +10,6 @@ ==================== ============== ===================== Armin Rigo ? ? Christian Tismer ? ? +Sven Hager ? ? ==================== ============== ===================== From noreply at buildbot.pypy.org Fri Jun 1 15:25:33 2012 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 1 Jun 2012 15:25:33 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: fix test for jit Message-ID: <20120601132533.E9C6D1C0274@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55253:8c584438b1f9 Date: 2012-05-31 23:36 +0300 http://bitbucket.org/pypy/pypy/changeset/8c584438b1f9/ Log: fix test for jit diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py --- a/pypy/rlib/test/test_libffi.py +++ b/pypy/rlib/test/test_libffi.py @@ -6,6 +6,7 @@ from pypy.rlib.test.test_clibffi import BaseFfiTest, make_struct_ffitype_e from pypy.rpython.lltypesystem import rffi, lltype from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED +from pypy.rpython.llinterp import LLException from pypy.rlib.libffi import (CDLL, ArgChain, types, IS_32_BIT, array_getitem, array_setitem) from pypy.rlib.libffi import (struct_getfield_int, struct_setfield_int, @@ -551,6 +552,9 @@ except ValueError, e: assert e.message == 'Procedure called with not enough ' + \ 'arguments (8 bytes missing) or wrong calling convention' + except LLException: + #jitted code raises this + pass else: assert 0, 'wrong calling convention should have raised' From noreply at buildbot.pypy.org Fri Jun 1 15:25:35 2012 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 1 Jun 2012 15:25:35 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: release dll after test Message-ID: <20120601132535.093B91C0274@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55254:8d737aa82c17 Date: 2012-06-01 15:09 +0300 http://bitbucket.org/pypy/pypy/changeset/8d737aa82c17/ Log: release dll after test add WinDLL to libffi diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py --- a/pypy/rlib/libffi.py +++ b/pypy/rlib/libffi.py @@ -5,11 +5,13 @@ from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat, r_longlong from pypy.rlib import jit from pypy.rlib import clibffi -from pypy.rlib.clibffi import FUNCFLAG_CDECL, AbstractFuncPtr, \ - push_arg_as_ffiptr, c_ffi_call, FFI_TYPE_STRUCT +from pypy.rlib.clibffi import FUNCFLAG_CDECL, FUNCFLAG_STDCALL, \ + AbstractFuncPtr, push_arg_as_ffiptr, c_ffi_call, FFI_TYPE_STRUCT from pypy.rlib.rdynload import dlopen, dlclose, dlsym, dlsym_byordinal from pypy.rlib.rdynload import DLLHANDLE +import os + class types(object): """ This namespace contains the primitive types you can use to declare the @@ -416,6 +418,11 @@ def getaddressindll(self, name): return dlsym(self.lib, name) +if os.name == 'nt': + class WinDLL(CDLL): + def getpointer(self, name, argtypes, restype, flags=FUNCFLAG_STDCALL): + return Func(name, argtypes, restype, dlsym(self.lib, name), + flags=flags, keepalive=self) # ====================================================================== @jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)') diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py --- a/pypy/rlib/test/test_libffi.py +++ b/pypy/rlib/test/test_libffi.py @@ -176,6 +176,15 @@ # lltype.free(p, flavor='raw') + def test_windll(self): + if os.name != 'nt': + skip('Run only on windows') + from pypy.rlib.libffi import WinDLL + dll = WinDLL('Kernel32.dll') + sleep = dll.getpointer('Sleep',[types.uint], types.void) + chain = ArgChain() + chain.arg(10) + sleep.call(chain, lltype.Void, is_struct=False) class TestLibffiCall(BaseFfiTest): """ @@ -220,9 +229,16 @@ eci = ExternalCompilationInfo(export_symbols=exports) cls.libfoo_name = str(platform.compile([c_file], eci, 'x', standalone=False)) + cls.dll = cls.CDLL(cls.libfoo_name) + + def teardown_class(cls): + if cls.dll: + cls.dll.__del__() + # Why doesn't this call cls.dll.__del__() ? + #del cls.dll def get_libfoo(self): - return self.CDLL(self.libfoo_name) + return self.dll def call(self, funcspec, args, RESULT, is_struct=False, jitif=[]): """ @@ -262,6 +278,7 @@ func = (libfoo, 'diff_xy', [types.sint, types.signed], types.sint) res = self.call(func, [50, 8], lltype.Signed) assert res == 42 + def test_simple(self): """ int sum_xy(int x, double y) From noreply at buildbot.pypy.org Fri Jun 1 15:25:36 2012 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 1 Jun 2012 15:25:36 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: fix imports Message-ID: <20120601132536.2CCDB1C0274@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55255:5468f42ee359 Date: 2012-06-01 15:28 +0300 http://bitbucket.org/pypy/pypy/changeset/5468f42ee359/ Log: fix imports diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py --- a/pypy/module/_ffi/test/test_funcptr.py +++ b/pypy/module/_ffi/test/test_funcptr.py @@ -1,11 +1,11 @@ from pypy.conftest import gettestobjspace -from pypy.translator.platform import platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.module._rawffi.interp_rawffi import TYPEMAP -from pypy.module._rawffi.tracker import Tracker -from pypy.translator.platform import platform +from pypy.rpython.lltypesystem import rffi +from pypy.rlib.clibffi import get_libc_name +from pypy.rlib.libffi import types +from pypy.rlib.libffi import CDLL +from pypy.rlib.test.test_clibffi import get_libm_name -import os, sys, py +import sys, py class BaseAppTestFFI(object): @@ -37,9 +37,6 @@ return str(platform.compile([c_file], eci, 'x', standalone=False)) def setup_class(cls): - from pypy.rpython.lltypesystem import rffi - from pypy.rlib.libffi import get_libc_name, CDLL, types - from pypy.rlib.test.test_libffi import get_libm_name space = gettestobjspace(usemodules=('_ffi', '_rawffi')) cls.space = space cls.w_iswin32 = space.wrap(sys.platform == 'win32') From noreply at buildbot.pypy.org Fri Jun 1 15:25:37 2012 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 1 Jun 2012 15:25:37 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: test, add WinDLL in _ffi Message-ID: <20120601132537.459461C0274@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55256:3dbd7782528b Date: 2012-06-01 16:25 +0300 http://bitbucket.org/pypy/pypy/changeset/3dbd7782528b/ Log: test, add WinDLL in _ffi diff --git a/pypy/module/_ffi/__init__.py b/pypy/module/_ffi/__init__.py --- a/pypy/module/_ffi/__init__.py +++ b/pypy/module/_ffi/__init__.py @@ -1,4 +1,5 @@ from pypy.interpreter.mixedmodule import MixedModule +import os class Module(MixedModule): @@ -10,7 +11,8 @@ '_StructDescr': 'interp_struct.W__StructDescr', 'Field': 'interp_struct.W_Field', } - + if os.name == 'nt': + interpleveldefs['WinDLL'] = 'interp_funcptr.W_WinDLL' appleveldefs = { 'Structure': 'app_struct.Structure', } diff --git a/pypy/module/_ffi/interp_funcptr.py b/pypy/module/_ffi/interp_funcptr.py --- a/pypy/module/_ffi/interp_funcptr.py +++ b/pypy/module/_ffi/interp_funcptr.py @@ -9,6 +9,7 @@ # from pypy.rlib import jit from pypy.rlib import libffi +from pypy.rlib.clibffi import get_libc_name, StackCheckError from pypy.rlib.rdynload import DLOpenError from pypy.rlib.rarithmetic import intmask, r_uint from pypy.rlib.objectmodel import we_are_translated @@ -59,7 +60,10 @@ self = jit.promote(self) argchain = self.build_argchain(space, args_w) func_caller = CallFunctionConverter(space, self.func, argchain) - return func_caller.do_and_wrap(self.w_restype) + try: + return func_caller.do_and_wrap(self.w_restype) + except StackCheckError, e: + raise OperationError(space.w_ValueError, space.wrap(e.message)) #return self._do_call(space, argchain) def free_temp_buffers(self, space): @@ -254,6 +258,7 @@ class W_CDLL(Wrappable): def __init__(self, space, name, mode): + self.flags = libffi.FUNCFLAG_CDECL self.space = space if name is None: self.name = "" @@ -271,7 +276,8 @@ w_argtypes, w_restype) try: - func = self.cdll.getpointer(name, argtypes, restype) + func = self.cdll.getpointer(name, argtypes, restype, + flags = self.flags) except KeyError: raise operationerrfmt(space.w_AttributeError, "No symbol %s found in library %s", name, self.name) @@ -300,10 +306,26 @@ getaddressindll = interp2app(W_CDLL.getaddressindll), ) +class W_WinDLL(W_CDLL): + def __init__(self, space, name, mode): + W_CDLL.__init__(self, space, name, mode) + self.flags = libffi.FUNCFLAG_STDCALL + + at unwrap_spec(name='str_or_None', mode=int) +def descr_new_windll(space, w_type, name, mode=-1): + return space.wrap(W_WinDLL(space, name, mode)) + + +W_WinDLL.typedef = TypeDef( + '_ffi.WinDLL', + __new__ = interp2app(descr_new_windll), + getfunc = interp2app(W_WinDLL.getfunc), + getaddressindll = interp2app(W_WinDLL.getaddressindll), + ) + # ======================================================================== def get_libc(space): - from pypy.rlib.clibffi import get_libc_name try: return space.wrap(W_CDLL(space, get_libc_name(), -1)) except OSError, e: diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py --- a/pypy/module/_ffi/test/test_funcptr.py +++ b/pypy/module/_ffi/test/test_funcptr.py @@ -93,7 +93,7 @@ def test_getaddressindll(self): import sys - from _ffi import CDLL, types + from _ffi import CDLL libm = CDLL(self.libm_name) pow_addr = libm.getaddressindll('pow') fff = sys.maxint*2-1 @@ -102,7 +102,6 @@ assert pow_addr == self.pow_addr & fff def test_func_fromaddr(self): - import sys from _ffi import CDLL, types, FuncPtr libm = CDLL(self.libm_name) pow_addr = libm.getaddressindll('pow') @@ -566,3 +565,37 @@ skip("unix specific") libnone = CDLL(None) raises(AttributeError, "libnone.getfunc('I_do_not_exist', [], types.void)") + + def test_calling_convention1(self): + if not self.iswin32: + skip("windows specific") + from _ffi import WinDLL, types + libm = WinDLL(self.libm_name) + pow = libm.getfunc('pow', [types.double, types.double], types.double) + try: + pow(2, 3) + except ValueError, e: + assert e.message.startswith('Procedure called with') + else: + assert 0, 'test must assert, wrong calling convention' + + def test_calling_convention2(self): + if not self.iswin32: + skip("windows specific") + from _ffi import WinDLL, types + kernel = WinDLL('Kernel32.dll') + sleep = kernel.getfunc('Sleep', [types.uint], types.void) + sleep(10) + + def test_calling_convention3(self): + if not self.iswin32: + skip("windows specific") + from _ffi import CDLL, types + wrong_kernel = CDLL('Kernel32.dll') + wrong_sleep = wrong_kernel.getfunc('Sleep', [types.uint], types.void) + try: + wrong_sleep(10) + except ValueError, e: + assert e.message.startswith('Procedure called with') + else: + assert 0, 'test must assert, wrong calling convention' From noreply at buildbot.pypy.org Fri Jun 1 15:31:01 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 15:31:01 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Use FLOAT_INT_CONVERSION word in stack for emit_cast_float_to_int and Message-ID: <20120601133101.8A7C01C0274@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55257:a48e4bba5300 Date: 2012-06-01 09:30 -0400 http://bitbucket.org/pypy/pypy/changeset/a48e4bba5300/ Log: Use FLOAT_INT_CONVERSION word in stack for emit_cast_float_to_int and emit_cast_int_to_float. Fix typo in names. diff --git a/pypy/jit/backend/ppc/opassembler.py b/pypy/jit/backend/ppc/opassembler.py --- a/pypy/jit/backend/ppc/opassembler.py +++ b/pypy/jit/backend/ppc/opassembler.py @@ -211,14 +211,16 @@ emit_float_eq = gen_emit_cmp_op(c.EQ, fp=True) emit_float_ne = gen_emit_cmp_op(c.NE, fp=True) - def emit_op_cast_float_to_int(self, op, arglocs, regalloc): + def emit_cast_float_to_int(self, op, arglocs, regalloc): l0, temp_loc, res = arglocs self.mc.fctidz(temp_loc.value, l0.value) - self.mc.mftgpr(res.value, temp_loc.value) + self.mc.stfd(temp_loc.value, r.SPP.value, FORCE_INDEX_OFS + WORD) + self.mc.ld(res.value, r.SPP.value, FORCE_INDEX_OFS + WORD) - def emit_op_cast_int_to_float(self, op, arglocs, regalloc): + def emit_cast_int_to_float(self, op, arglocs, regalloc): l0, temp_loc, res = arglocs - self.mc.mffgpr(temp_loc.value, l0.value) + self.mc.std(l0.value, r.SPP.value, FORCE_INDEX_OFS + WORD) + self.mc.lfd(temp_loc.value, r.SPP.value, FORCE_INDEX_OFS + WORD) self.mc.fcfid(res.value, temp_loc.value) class GuardOpAssembler(object): From noreply at buildbot.pypy.org Fri Jun 1 15:49:02 2012 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 1 Jun 2012 15:49:02 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: fix test Message-ID: <20120601134902.911521C01F2@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55258:6af15b871f5e Date: 2012-06-01 16:48 +0300 http://bitbucket.org/pypy/pypy/changeset/6af15b871f5e/ Log: fix test diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -1,4 +1,3 @@ -import py import sys from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC @@ -78,12 +77,19 @@ from pypy.rlib.test.test_libffi import get_libc_name def main(libc_name, n): import time + import os from threading import Thread - from _ffi import CDLL, types # - libc = CDLL(libc_name) - sleep = libc.getfunc('sleep', [types.uint], types.uint) - delays = [0]*n + [1] + if os.name == 'nt': + from _ffi import WinDLL, types + libc = WinDLL(libc_name) + sleep = libc.getfunc('Sleep', [types.uint], types.uint) + delays = [0]*n + [1000] + else: + from _ffi import CDLL, types + libc = CDLL(libc_name) + sleep = libc.getfunc('sleep', [types.uint], types.uint) + delays = [0]*n + [1] # def loop_of_sleeps(i, delays): for delay in delays: @@ -97,7 +103,6 @@ thread.join() end = time.time() return end - start - # log = self.run(main, [get_libc_name(), 200], threshold=150, import_site=True) assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead From noreply at buildbot.pypy.org Fri Jun 1 17:54:38 2012 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 1 Jun 2012 17:54:38 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: fix imports Message-ID: <20120601155438.87A3B1C02D9@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55259:38ac093c428f Date: 2012-06-01 18:54 +0300 http://bitbucket.org/pypy/pypy/changeset/38ac093c428f/ Log: fix imports diff --git a/pypy/jit/backend/x86/test/test_ztranslation.py b/pypy/jit/backend/x86/test/test_ztranslation.py --- a/pypy/jit/backend/x86/test/test_ztranslation.py +++ b/pypy/jit/backend/x86/test/test_ztranslation.py @@ -69,7 +69,7 @@ # from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.libffi import types, CDLL, ArgChain - from pypy.rlib.test.test_libffi import get_libm_name + from pypy.rlib.test.test_clibffi import get_libm_name libm_name = get_libm_name(sys.platform) jitdriver2 = JitDriver(greens=[], reds = ['i', 'func', 'res', 'x']) def libffi_stuff(i, j): diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -41,7 +41,7 @@ def test__ffi_call_frame_does_not_escape(self): - from pypy.rlib.test.test_libffi import get_libm_name + from pypy.rlib.test.test_clibffi import get_libm_name def main(libm_name): try: from _ffi import CDLL, types @@ -111,7 +111,7 @@ def test_ctypes_call(self): - from pypy.rlib.test.test_libffi import get_libm_name + from pypy.rlib.test.test_clibffi import get_libm_name def main(libm_name): import ctypes libm = ctypes.CDLL(libm_name) From noreply at buildbot.pypy.org Fri Jun 1 20:37:46 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 20:37:46 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Define MANAGED_FP_REGS. Message-ID: <20120601183746.946911C01F2@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55261:ab01c15374da Date: 2012-06-01 14:37 -0400 http://bitbucket.org/pypy/pypy/changeset/ab01c15374da/ Log: Define MANAGED_FP_REGS. diff --git a/pypy/jit/backend/ppc/register.py b/pypy/jit/backend/ppc/register.py --- a/pypy/jit/backend/ppc/register.py +++ b/pypy/jit/backend/ppc/register.py @@ -32,6 +32,8 @@ r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30] +MANAGED_FP_REGS = VOLATILES_FLOAT + NONVOLATILES_FLOAT + PARAM_REGS = [r3, r4, r5, r6, r7, r8, r9, r10] PARAM_FPREGS = [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13] From noreply at buildbot.pypy.org Fri Jun 1 20:37:45 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 20:37:45 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Set width for StackLocation. Message-ID: <20120601183745.6FF731C0141@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55260:f7f3719072f0 Date: 2012-06-01 14:33 -0400 http://bitbucket.org/pypy/pypy/changeset/f7f3719072f0/ Log: Set width for StackLocation. diff --git a/pypy/jit/backend/ppc/locations.py b/pypy/jit/backend/ppc/locations.py --- a/pypy/jit/backend/ppc/locations.py +++ b/pypy/jit/backend/ppc/locations.py @@ -111,6 +111,10 @@ _immutable_ = True def __init__(self, position, num_words=1, type=INT): + if type == FLOAT: + self.width = FWORD + else: + self.width = WORD self.position = position self.type = type self.value = get_spp_offset(position) From noreply at buildbot.pypy.org Fri Jun 1 20:39:03 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 20:39:03 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Import MANAGED_FP_REGS. Message-ID: <20120601183903.947931C0141@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55262:703d6f060356 Date: 2012-06-01 14:38 -0400 http://bitbucket.org/pypy/pypy/changeset/703d6f060356/ Log: Import MANAGED_FP_REGS. FORCE_INDEX_OFS is MANAGED_REGS + MANAGED_FP_REGS. diff --git a/pypy/jit/backend/ppc/arch.py b/pypy/jit/backend/ppc/arch.py --- a/pypy/jit/backend/ppc/arch.py +++ b/pypy/jit/backend/ppc/arch.py @@ -2,7 +2,8 @@ from pypy.jit.backend.ppc.register import (NONVOLATILES, NONVOLATILES_FLOAT, - MANAGED_REGS) + MANAGED_REGS, + MANAGED_FP_REGS) import sys if sys.maxint == (2**31 - 1): @@ -29,7 +30,7 @@ # and one instruction to patch the stack pointer SIZE_LOAD_IMM_PATCH_SP = 6 -FORCE_INDEX_OFS = len(MANAGED_REGS) * WORD +FORCE_INDEX_OFS = (len(MANAGED_REGS) + len(MANAGED_FP_REGS)) * WORD # offset to LR in BACKCHAIN if IS_PPC_32: From noreply at buildbot.pypy.org Fri Jun 1 20:41:03 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 20:41:03 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Change force to call failure_recovery_func instead of Message-ID: <20120601184103.4F53B1C0141@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55263:8b6c0d0abb33 Date: 2012-06-01 14:40 -0400 http://bitbucket.org/pypy/pypy/changeset/8b6c0d0abb33/ Log: Change force to call failure_recovery_func instead of decode_registers_and_descr directly. diff --git a/pypy/jit/backend/ppc/runner.py b/pypy/jit/backend/ppc/runner.py --- a/pypy/jit/backend/ppc/runner.py +++ b/pypy/jit/backend/ppc/runner.py @@ -100,10 +100,9 @@ bytecode = self.asm._find_failure_recovery_bytecode(faildescr) addr_all_null_registers = rffi.cast(rffi.LONG, self.all_null_registers) # start of "no gc operation!" block - fail_index_2 = self.asm.decode_registers_and_descr( + fail_index_2 = self.asm.failure_recovery_func( bytecode, - spilling_pointer, - self.all_null_registers) + spilling_pointer) self.asm.leave_jitted_hook() # end of "no gc operation!" block assert fail_index == fail_index_2 From noreply at buildbot.pypy.org Fri Jun 1 20:49:00 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 20:49:00 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Pass RegisterLocation to mov_loc_loc. Message-ID: <20120601184900.E053B1C0141@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55264:a7d3c4eb71e2 Date: 2012-06-01 14:48 -0400 http://bitbucket.org/pypy/pypy/changeset/a7d3c4eb71e2/ Log: Pass RegisterLocation to mov_loc_loc. Change uses of ENCODING_AREA to FORCE_INDEX_OFS. Add FP args support to emit_call. diff --git a/pypy/jit/backend/ppc/opassembler.py b/pypy/jit/backend/ppc/opassembler.py --- a/pypy/jit/backend/ppc/opassembler.py +++ b/pypy/jit/backend/ppc/opassembler.py @@ -358,7 +358,7 @@ if box.type == FLOAT: adr = self.fail_boxes_float.get_addr_for_num(i) self.mc.stfd(r.f0.value, r.SPP.value, 0) - self.mov_loc_loc(loc, r.f0.value) + self.mov_loc_loc(loc, r.f0) self.mc.load_imm(r.SCRATCH, adr) self.mc.stfdx(r.f0.value, 0, r.SCRATCH.value) self.mc.lfd(r.f0.value, r.SPP.value, 0) @@ -499,28 +499,25 @@ # collect variables that need to go in registers # and the registers they will be stored in num = 0 + fpnum = 0 count = 0 non_float_locs = [] non_float_regs = [] float_locs = [] + float_regs = [] for i in range(reg_args): arg = arglocs[i] - if arg.type == FLOAT and count % 2 != 0: - num += 1 - count = 0 reg = r.PARAM_REGS[num] + fpreg = r.PARAM_FPREGS[fpnum] if arg.type == FLOAT: - float_locs.append((arg, reg)) + float_locs.append(arg) + float_regs.append(fpreg) + fpnum += 1 else: non_float_locs.append(arg) non_float_regs.append(reg) - - if arg.type == FLOAT: num += 1 - else: - num += 1 - count += 1 if adr in non_float_regs: non_float_locs.append(adr) @@ -528,6 +525,7 @@ adr = r.r11 # remap values stored in core registers + remap_frame_layout(self, float_locs, float_regs, r.f0) remap_frame_layout(self, non_float_locs, non_float_regs, r.SCRATCH) # the actual call @@ -1060,8 +1058,7 @@ # use r20 as temporary register, save it in FORCE INDEX slot temp_reg = r.r20 - ENCODING_AREA = len(r.MANAGED_REGS) * WORD - self.mc.store(temp_reg.value, r.SPP.value, ENCODING_AREA) + self.mc.store(temp_reg.value, r.SPP.value, FORCE_INDEX_OFS) self.mc.srli_op(temp_reg.value, loc_index.value, s) self.mc.not_(temp_reg.value, temp_reg.value) @@ -1081,7 +1078,7 @@ # done # restore temporary register r20 - self.mc.load(temp_reg.value, r.SPP.value, ENCODING_AREA) + self.mc.load(temp_reg.value, r.SPP.value, FORCE_INDEX_OFS) # patch the JMP above offset = self.mc.currpos() @@ -1108,9 +1105,8 @@ def emit_force_token(self, op, arglocs, regalloc): res_loc = arglocs[0] - ENCODING_AREA = len(r.MANAGED_REGS) * WORD self.mc.mr(res_loc.value, r.SPP.value) - self.mc.addi(res_loc.value, res_loc.value, ENCODING_AREA) + self.mc.addi(res_loc.value, res_loc.value, FORCE_INDEX_OFS) # self._emit_guard(guard_op, regalloc._prepare_guard(guard_op), c.LT) # from: ../x86/assembler.py:1668 @@ -1218,9 +1214,8 @@ pmc.b(currpos - fast_path_to_end_jump_pos) pmc.overwrite() - ENCODING_AREA = len(r.MANAGED_REGS) * WORD with scratch_reg(self.mc): - self.mc.load(r.SCRATCH.value, r.SPP.value, ENCODING_AREA) + self.mc.load(r.SCRATCH.value, r.SPP.value, FORCE_INDEX_OFS) self.mc.cmp_op(0, r.SCRATCH.value, 0, imm=True) self._emit_guard(guard_op, regalloc._prepare_guard(guard_op), From noreply at buildbot.pypy.org Fri Jun 1 20:57:48 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 20:57:48 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Change uses of ENCODING_AREA to FORCE_INDEX_OFS. Message-ID: <20120601185748.D801A1C0141@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55265:e4ee8736f105 Date: 2012-06-01 14:57 -0400 http://bitbucket.org/pypy/pypy/changeset/e4ee8736f105/ Log: Change uses of ENCODING_AREA to FORCE_INDEX_OFS. Add FP support to failure_recovery_func and decode_registers_and_descr. More experiments with imm_float support for regalloc_mov. diff --git a/pypy/jit/backend/ppc/ppc_assembler.py b/pypy/jit/backend/ppc/ppc_assembler.py --- a/pypy/jit/backend/ppc/ppc_assembler.py +++ b/pypy/jit/backend/ppc/ppc_assembler.py @@ -70,8 +70,7 @@ class AssemblerPPC(OpAssembler): - FORCE_INDEX_AREA = len(r.MANAGED_REGS) * WORD - ENCODING_AREA = len(r.MANAGED_REGS) * WORD + ENCODING_AREA = FORCE_INDEX_OFS OFFSET_SPP_TO_GPR_SAVE_AREA = (FORCE_INDEX + FLOAT_INT_CONVERSION + ENCODING_AREA) OFFSET_SPP_TO_OLD_BACKCHAIN = (OFFSET_SPP_TO_GPR_SAVE_AREA @@ -176,11 +175,14 @@ """ mem_loc is a pointer to the beginning of the encoding. - spilling_pointer is the address of the FORCE_INDEX. + spilling_pointer is the address of the spilling area. """ regs = rffi.cast(rffi.LONGP, spilling_pointer) + fpregs = rffi.ptradd(regs, len(r.MANAGED_REGS)) + fpregs = rffi.cast(rffi.LONGP, fpregs) return self.decode_registers_and_descr(mem_loc, - spilling_pointer, regs) + spilling_pointer, + regs, fpregs) self.failure_recovery_func = failure_recovery_func @@ -188,7 +190,7 @@ lltype.Signed], lltype.Signed)) @rgc.no_collect - def decode_registers_and_descr(self, mem_loc, spp, registers): + def decode_registers_and_descr(self, mem_loc, spp, registers, fp_registers): """Decode locations encoded in memory at mem_loc and write the values to the failboxes. Values for spilled vars and registers are stored on stack at frame_loc """ @@ -531,7 +533,7 @@ addr = rffi.cast(lltype.Signed, decode_func_addr) # load parameters into parameter registers - mc.load(r.RES.value, r.SPP.value, self.FORCE_INDEX_AREA) # address of state encoding + mc.load(r.RES.value, r.SPP.value, FORCE_INDEX_OFS) # address of state encoding mc.mr(r.r4.value, r.SPP.value) # load spilling pointer # # call decoding function @@ -571,6 +573,9 @@ for i in range(len(r.MANAGED_REGS)): reg = r.MANAGED_REGS[i] mc.store(reg.value, r.SPP.value, i * WORD) + for i in range(len(r.MANAGED_FP_REGS)): + fpreg = r.MANAGED_FP_REGS[i] + mc.stfd(fpreg.value, r.SPP.value, i * WORD + len(r.MANAGED_REGS)) def gen_bootstrap_code(self, loophead, spilling_area): self._insert_stack_check() @@ -1099,7 +1104,7 @@ encoding_adr = self.gen_descr_encoding(descr, args, arglocs[1:]) with scratch_reg(self.mc): self.mc.load_imm(r.SCRATCH, encoding_adr) - self.mc.store(r.SCRATCH.value, r.SPP.value, self.ENCODING_AREA) + self.mc.store(r.SCRATCH.value, r.SPP.value, FORCE_INDEX_OFS) self.mc.b_abs(path) return encoding_adr @@ -1182,7 +1187,7 @@ self.mc.load_imm(r.SCRATCH, offset) self.mc.sub(r.SCRATCH.value, r.SPP.value, r.SCRATCH.value) else: - self.mc.sub(r.SCRATCH.value, r.SPP.value, r.SCRARTCH.value) + self.mc.sub(r.SCRATCH.value, r.SPP.value, r.SCRATCH.value) self.mc.lfdx(loc.value, 0, r.SCRATCH.value) return assert 0, "not supported location" @@ -1200,10 +1205,13 @@ return assert 0, "not supported location" elif prev_loc.is_imm_float(): + value = prev_loc.getint() if loc.is_fp_reg(): with scratch_reg(self.mc): self.mc.load_imm(r.SCRATCH, value) - self.mc.lfdx(loc, 0, r.SCRATCH) + self.mc.std(r.SCRATCH.value, r.SPP.value, FORCE_INDEX_OFS + WORD) + self.mc.lfd(loc.value, r.SPP.value, FORCE_INDEX_OFS + WORD) + #self.mc.trap() return elif loc.is_stack(): with scratch_reg(self.mc): @@ -1374,7 +1382,7 @@ def _write_fail_index(self, fail_index): with scratch_reg(self.mc): self.mc.load_imm(r.SCRATCH, fail_index) - self.mc.store(r.SCRATCH.value, r.SPP.value, self.FORCE_INDEX_AREA) + self.mc.store(r.SCRATCH.value, r.SPP.value, FORCE_INDEX_OFS) def load(self, loc, value): assert (loc.is_reg() and value.is_imm() From noreply at buildbot.pypy.org Fri Jun 1 22:43:47 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 22:43:47 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Import remap_frame_layout_mixed and use it in prepare_jump. Message-ID: <20120601204347.2EEF31C0141@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55266:73d86ba2593a Date: 2012-06-01 16:43 -0400 http://bitbucket.org/pypy/pypy/changeset/73d86ba2593a/ Log: Import remap_frame_layout_mixed and use it in prepare_jump. Add FPRM support to update_bindings. diff --git a/pypy/jit/backend/ppc/regalloc.py b/pypy/jit/backend/ppc/regalloc.py --- a/pypy/jit/backend/ppc/regalloc.py +++ b/pypy/jit/backend/ppc/regalloc.py @@ -2,7 +2,8 @@ TempBox, compute_vars_longevity) from pypy.jit.backend.ppc.arch import (WORD, MY_COPY_OF_REGS, IS_PPC_32) from pypy.jit.codewriter import longlong -from pypy.jit.backend.ppc.jump import remap_frame_layout +from pypy.jit.backend.ppc.jump import (remap_frame_layout, + remap_frame_layout_mixed) from pypy.jit.backend.ppc.locations import imm from pypy.jit.backend.ppc.helper.regalloc import (_check_imm_arg, prepare_cmp_op, @@ -259,7 +260,7 @@ if loc.is_reg(): self.rm.reg_bindings[arg] = loc elif loc.is_fp_reg(): - assert 0, "not supported" + self.fprm.reg_bindings[arg] = loc else: assert loc.is_stack() self.frame_manager.set_binding(arg, loc) @@ -270,6 +271,10 @@ for reg in self.rm.all_regs: if reg not in used: self.rm.free_regs.append(reg) + self.fprm.free_regs = [] + for reg in self.fprm.all_regs: + if reg not in used: + self.fprm.free_regs.append(reg) # note: we need to make a copy of inputargs because possibly_free_vars # is also used on op args, which is a non-resizable list self.possibly_free_vars(list(inputargs)) @@ -678,9 +683,9 @@ src_locations2.append(src_loc) dst_locations2.append(dst_loc) - remap_frame_layout(self.assembler, - src_locations1, dst_locations1, tmploc, - src_locations2, dst_locations2, fptmploc) + remap_frame_layout_mixed(self.assembler, + src_locations1, dst_locations1, tmploc, + src_locations2, dst_locations2, fptmploc) return [] def prepare_setfield_gc(self, op): From noreply at buildbot.pypy.org Fri Jun 1 23:35:53 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 23:35:53 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Use offset directly as load float / store float displacement. Message-ID: <20120601213553.B7F391C01F2@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55267:642d5eb12115 Date: 2012-06-01 17:35 -0400 http://bitbucket.org/pypy/pypy/changeset/642d5eb12115/ Log: Use offset directly as load float / store float displacement. diff --git a/pypy/jit/backend/ppc/ppc_assembler.py b/pypy/jit/backend/ppc/ppc_assembler.py --- a/pypy/jit/backend/ppc/ppc_assembler.py +++ b/pypy/jit/backend/ppc/ppc_assembler.py @@ -1179,16 +1179,11 @@ self.mc.load(r.SCRATCH.value, r.SPP.value, offset) self.mc.store(r.SCRATCH.value, r.SPP.value, target_offset) return + # move from memory to fp register elif loc.is_fp_reg(): assert prev_loc.type == FLOAT, 'source not float location' - with scratch_reg(self.mc): - offset = prev_loc.value - if not _check_imm_arg(offset): - self.mc.load_imm(r.SCRATCH, offset) - self.mc.sub(r.SCRATCH.value, r.SPP.value, r.SCRATCH.value) - else: - self.mc.sub(r.SCRATCH.value, r.SPP.value, r.SCRATCH.value) - self.mc.lfdx(loc.value, 0, r.SCRATCH.value) + reg = loc.as_key() + self.mc.lfd(reg, r.SPP.value, offset) return assert 0, "not supported location" elif prev_loc.is_reg(): @@ -1206,6 +1201,7 @@ assert 0, "not supported location" elif prev_loc.is_imm_float(): value = prev_loc.getint() + # move immediate value to fp register if loc.is_fp_reg(): with scratch_reg(self.mc): self.mc.load_imm(r.SCRATCH, value) @@ -1213,6 +1209,7 @@ self.mc.lfd(loc.value, r.SPP.value, FORCE_INDEX_OFS + WORD) #self.mc.trap() return + # move immediate value to memory elif loc.is_stack(): with scratch_reg(self.mc): offset = loc.value @@ -1221,19 +1218,17 @@ return assert 0, "not supported location" elif prev_loc.is_fp_reg(): + reg = prev_loc.as_key() + # move to another fp register if loc.is_fp_reg(): - self.mc.fmr(loc.value, prev_loc.value) + other_reg = loc.as_key() + self.mc.fmr(other_reg, reg) return + # move from fp register to memory elif loc.is_stack(): assert loc.type == FLOAT, "target not float location" - with scratch_reg(self.mc): - offset = loc.value - if not _check_imm_arg(offset): - self.mc.load_imm(r.SCRATCH, offset) - self.mc.sub(r.SCRATCH.value, r.SPP.value, r.SCRATCH.value) - else: - self.mc.subi(r.SCRATCH.value, r.SPP.value, offset) - self.mc.stfdx(prev_loc.value, 0, r.SCRATCH.value) + offset = loc.value + self.mc.stfd(reg, r.SPP.value, offset) return assert 0, "not supported location" assert 0, "not supported location" From noreply at buildbot.pypy.org Fri Jun 1 23:37:34 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 23:37:34 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Temporary kludge for FP arguments in set_initial_bindings. Message-ID: <20120601213734.1482C1C01F2@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55268:363a0e741a26 Date: 2012-06-01 17:37 -0400 http://bitbucket.org/pypy/pypy/changeset/363a0e741a26/ Log: Temporary kludge for FP arguments in set_initial_bindings. diff --git a/pypy/jit/backend/ppc/regalloc.py b/pypy/jit/backend/ppc/regalloc.py --- a/pypy/jit/backend/ppc/regalloc.py +++ b/pypy/jit/backend/ppc/regalloc.py @@ -221,35 +221,34 @@ def _set_initial_bindings(self, inputargs): arg_index = 0 - count = 0 + fparg_index = 0 n_register_args = len(r.PARAM_REGS) + n_fpregister_args = len(r.PARAM_FPREGS) cur_frame_pos = -self.assembler.OFFSET_STACK_ARGS // WORD + 1 for box in inputargs: assert isinstance(box, Box) - if arg_index < n_register_args: - if box.type == FLOAT: - loc = r.PARAM_FPREGS[arg_index] + if box.type == FLOAT: + if fparg_index < n_fpregister_args: + loc = r.PARAM_FPREGS[fparg_index] self.try_allocate_reg(box, selected_reg=loc) - arg_index += 1 + fparg_index += 1 else: - loc = r.PARAM_REGS[arg_index] - self.try_allocate_reg(box, selected_reg=loc) - arg_index += 1 - else: - # treat stack args as stack locations with a negative offset - if box.type == FLOAT: if IS_PPC_32: cur_frame_pos -= 2 else: cur_frame_pos -= 1 - if count % 2 != 0: # Stack argument alignment - cur_frame_pos -= 1 - count = 0 + loc = self.frame_manager.frame_pos(cur_frame_pos, box.type) + self.frame_manager.set_binding(box, loc) + else: + if arg_index < n_register_args: + loc = r.PARAM_REGS[arg_index] + self.try_allocate_reg(box, selected_reg=loc) + arg_index += 1 else: + # treat stack args as stack locations with a negative offset cur_frame_pos -= 1 - count += 1 - loc = self.frame_manager.frame_pos(cur_frame_pos, box.type) - self.frame_manager.set_binding(box, loc) + loc = self.frame_manager.frame_pos(cur_frame_pos, box.type) + self.frame_manager.set_binding(box, loc) def _update_bindings(self, locs, inputargs): used = {} From noreply at buildbot.pypy.org Fri Jun 1 23:49:26 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 23:49:26 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Store FP call arguments on the stack with FP operations. Message-ID: <20120601214926.C9D351C01F2@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55269:38e312eb8e46 Date: 2012-06-01 17:49 -0400 http://bitbucket.org/pypy/pypy/changeset/38e312eb8e46/ Log: Store FP call arguments on the stack with FP operations. diff --git a/pypy/jit/backend/ppc/opassembler.py b/pypy/jit/backend/ppc/opassembler.py --- a/pypy/jit/backend/ppc/opassembler.py +++ b/pypy/jit/backend/ppc/opassembler.py @@ -493,8 +493,12 @@ for i, arg in enumerate(stack_args): offset = param_offset + i * WORD if arg is not None: - self.regalloc_mov(arg, r.SCRATCH) - self.mc.store(r.SCRATCH.value, r.SP.value, offset) + if arg.type == FLOAT: + self.regalloc_mov(arg, r.f0) + self.mc.stfd(r.f0.value, r.SP.value, offset) + else: + self.regalloc_mov(arg, r.SCRATCH) + self.mc.store(r.SCRATCH.value, r.SP.value, offset) # collect variables that need to go in registers # and the registers they will be stored in From noreply at buildbot.pypy.org Fri Jun 1 23:52:53 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Fri, 1 Jun 2012 23:52:53 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Fix typo in emit_guard_value FP case. Message-ID: <20120601215253.CB1801C0274@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55270:d3115c64f0b2 Date: 2012-06-01 17:52 -0400 http://bitbucket.org/pypy/pypy/changeset/d3115c64f0b2/ Log: Fix typo in emit_guard_value FP case. diff --git a/pypy/jit/backend/ppc/opassembler.py b/pypy/jit/backend/ppc/opassembler.py --- a/pypy/jit/backend/ppc/opassembler.py +++ b/pypy/jit/backend/ppc/opassembler.py @@ -285,7 +285,7 @@ self.mc.cmp_op(0, l0.value, l1.value) elif l0.is_fp_reg(): assert l1.is_fp_reg() - self.mc.cmp_op(0, l0,value, l1.value) + self.mc.cmp_op(0, l0.value, l1.value) self._emit_guard(op, failargs, c.NE) emit_guard_nonnull = emit_guard_true From noreply at buildbot.pypy.org Sat Jun 2 09:15:38 2012 From: noreply at buildbot.pypy.org (amauryfa) Date: Sat, 2 Jun 2012 09:15:38 +0200 (CEST) Subject: [pypy-commit] pypy default: Test and fix for RopeString.find Message-ID: <20120602071538.E36F21C0132@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: Changeset: r55271:04e2b329ede5 Date: 2012-06-02 09:14 +0200 http://bitbucket.org/pypy/pypy/changeset/04e2b329ede5/ Log: Test and fix for RopeString.find diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py --- a/pypy/objspace/std/test/test_stringobject.py +++ b/pypy/objspace/std/test/test_stringobject.py @@ -413,6 +413,9 @@ assert 'abcdefghiabc'.find('def', 4) == -1 assert 'abcdef'.find('', 13) == -1 assert 'abcdefg'.find('def', 5, None) == -1 + assert 'abcdef'.find('d', 6, 0) == -1 + assert 'abcdef'.find('d', 3, 3) == -1 + raises(TypeError, 'abcdef'.find, 'd', 1.0) def test_index(self): from sys import maxint diff --git a/pypy/rlib/rope.py b/pypy/rlib/rope.py --- a/pypy/rlib/rope.py +++ b/pypy/rlib/rope.py @@ -769,11 +769,11 @@ len2 = subnode.length() if stop > len1 or stop == -1: stop = len1 + if stop - start < 0: + return -1 if len2 == 1: return find_int(node, subnode.getint(0), start, stop) if len2 == 0: - if (stop - start) < 0: - return -1 return start if len2 > stop - start: return -1 From noreply at buildbot.pypy.org Sat Jun 2 17:01:48 2012 From: noreply at buildbot.pypy.org (edelsohn) Date: Sat, 2 Jun 2012 17:01:48 +0200 (CEST) Subject: [pypy-commit] pypy ppc-backend-2: Fix regalloc_mov for loading float immediate. Message-ID: <20120602150148.33A491C0132@cobra.cs.uni-duesseldorf.de> Author: edelsohn Branch: ppc-backend-2 Changeset: r55272:4e78ce2b0189 Date: 2012-06-02 11:01 -0400 http://bitbucket.org/pypy/pypy/changeset/4e78ce2b0189/ Log: Fix regalloc_mov for loading float immediate. diff --git a/pypy/jit/backend/ppc/ppc_assembler.py b/pypy/jit/backend/ppc/ppc_assembler.py --- a/pypy/jit/backend/ppc/ppc_assembler.py +++ b/pypy/jit/backend/ppc/ppc_assembler.py @@ -1205,9 +1205,7 @@ if loc.is_fp_reg(): with scratch_reg(self.mc): self.mc.load_imm(r.SCRATCH, value) - self.mc.std(r.SCRATCH.value, r.SPP.value, FORCE_INDEX_OFS + WORD) - self.mc.lfd(loc.value, r.SPP.value, FORCE_INDEX_OFS + WORD) - #self.mc.trap() + self.mc.lfdx(loc.value, 0, r.SCRATCH.value) return # move immediate value to memory elif loc.is_stack(): From noreply at buildbot.pypy.org Sat Jun 2 20:49:22 2012 From: noreply at buildbot.pypy.org (mattip) Date: Sat, 2 Jun 2012 20:49:22 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: fix imports Message-ID: <20120602184922.EE89F1C0132@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55273:c01a7c9b5fe9 Date: 2012-06-02 21:17 +0300 http://bitbucket.org/pypy/pypy/changeset/c01a7c9b5fe9/ Log: fix imports diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -4,7 +4,7 @@ class Test__ffi(BaseTestPyPyC): def test__ffi_call(self): - from pypy.rlib.test.test_libffi import get_libm_name + from pypy.rlib.test.test_clibffi import get_libm_name def main(libm_name): try: from _ffi import CDLL, types From noreply at buildbot.pypy.org Sat Jun 2 20:49:24 2012 From: noreply at buildbot.pypy.org (mattip) Date: Sat, 2 Jun 2012 20:49:24 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: fix import, assert correct exception Message-ID: <20120602184924.0E25D1C0132@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55274:163084b063d5 Date: 2012-06-02 21:48 +0300 http://bitbucket.org/pypy/pypy/changeset/163084b063d5/ Log: fix import, assert correct exception diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -74,7 +74,7 @@ assert opnames.count('new_with_vtable') == 1 def test__ffi_call_releases_gil(self): - from pypy.rlib.test.test_libffi import get_libc_name + from pypy.rlib.clibffi import get_libc_name def main(libc_name, n): import time import os diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py --- a/pypy/rlib/test/test_libffi.py +++ b/pypy/rlib/test/test_libffi.py @@ -569,9 +569,9 @@ except ValueError, e: assert e.message == 'Procedure called with not enough ' + \ 'arguments (8 bytes missing) or wrong calling convention' - except LLException: + except LLException, e: #jitted code raises this - pass + assert str(e) == "" else: assert 0, 'wrong calling convention should have raised' From noreply at buildbot.pypy.org Sun Jun 3 11:52:48 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 11:52:48 +0200 (CEST) Subject: [pypy-commit] pypy default: Most of the cygwin patch (Uwe F. Mayer on pypy-dev). Message-ID: <20120603095248.BE6351C00D8@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55275:2907bd0a82ce Date: 2012-06-03 11:52 +0200 http://bitbucket.org/pypy/pypy/changeset/2907bd0a82ce/ Log: Most of the cygwin patch (Uwe F. Mayer on pypy-dev). diff --git a/lib_pypy/ctypes_support.py b/lib_pypy/ctypes_support.py --- a/lib_pypy/ctypes_support.py +++ b/lib_pypy/ctypes_support.py @@ -12,6 +12,8 @@ if sys.platform == 'win32': import _ffi standard_c_lib = ctypes.CDLL('msvcrt', handle=_ffi.get_libc()) +elif sys.platform == 'cygwin': + standard_c_lib = ctypes.CDLL(ctypes.util.find_library('cygwin')) else: standard_c_lib = ctypes.CDLL(ctypes.util.find_library('c')) diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py --- a/pypy/module/_minimal_curses/fficurses.py +++ b/pypy/module/_minimal_curses/fficurses.py @@ -8,11 +8,20 @@ from pypy.rpython.extfunc import register_external from pypy.module._minimal_curses import interp_curses from pypy.translator.tool.cbuild import ExternalCompilationInfo +from sys import platform -eci = ExternalCompilationInfo( - includes = ['curses.h', 'term.h'], - libraries = ['curses'], -) +_CYGWIN = platform == 'cygwin' + +if _CYGWIN: + eci = ExternalCompilationInfo( + includes = ['ncurses/curses.h', 'ncurses/term.h'], + libraries = ['curses'], + ) +else: + eci = ExternalCompilationInfo( + includes = ['curses.h', 'term.h'], + libraries = ['curses'], + ) rffi_platform.verify_eci(eci) diff --git a/pypy/module/rctime/interp_time.py b/pypy/module/rctime/interp_time.py --- a/pypy/module/rctime/interp_time.py +++ b/pypy/module/rctime/interp_time.py @@ -12,6 +12,15 @@ _POSIX = os.name == "posix" _WIN = os.name == "nt" +_CYGWIN = sys.platform == "cygwin" + +_time_zones = [] +if _CYGWIN: + _time_zones = ["GMT-12", "GMT-11", "GMT-10", "GMT-9", "GMT-8", "GMT-7", + "GMT-6", "GMT-5", "GMT-4", "GMT-3", "GMT-2", "GMT-1", + "GMT", "GMT+1", "GMT+2", "GMT+3", "GMT+4", "GMT+5", + "GMT+6", "GMT+7", "GMT+8", "GMT+9", "GMT+10", "GMT+11", + "GMT+12", "GMT+13", "GMT+14"] if _WIN: # Interruptible sleeps on Windows: @@ -107,11 +116,17 @@ CConfig.timeval = platform.Struct("struct timeval", [("tv_sec", rffi.INT), ("tv_usec", rffi.INT)]) - CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), - ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), - ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), - ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT), ("tm_gmtoff", rffi.LONG), - ("tm_zone", rffi.CCHARP)]) + if _CYGWIN: + CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), + ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), + ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), + ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT)]) + else: + CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), + ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), + ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), + ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT), ("tm_gmtoff", rffi.LONG), + ("tm_zone", rffi.CCHARP)]) elif _WIN: calling_conv = 'win' CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), @@ -202,35 +217,81 @@ tzname = rffi.charp2str(tzname_ptr[0]), rffi.charp2str(tzname_ptr[1]) if _POSIX: - YEAR = (365 * 24 + 6) * 3600 + if _CYGWIN: + YEAR = (365 * 24 + 6) * 3600 - t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR) - # we cannot have reference to stack variable, put it on the heap - t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') - t_ref[0] = rffi.cast(rffi.TIME_T, t) - p = c_localtime(t_ref) - janzone = -p.c_tm_gmtoff - tm_zone = rffi.charp2str(p.c_tm_zone) - janname = [" ", tm_zone][bool(tm_zone)] - tt = t + YEAR / 2 - t_ref[0] = rffi.cast(rffi.TIME_T, tt) - p = c_localtime(t_ref) - lltype.free(t_ref, flavor='raw') - tm_zone = rffi.charp2str(p.c_tm_zone) - julyzone = -p.c_tm_gmtoff - julyname = [" ", tm_zone][bool(tm_zone)] + # about January 11th + t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR + 10 * 24 * 3600) + # we cannot have reference to stack variable, put it on the heap + t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') + t_ref[0] = rffi.cast(rffi.TIME_T, t) + p = c_localtime(t_ref) + q = c_gmtime(t_ref) + janzone = (p.c_tm_hour + 24 * p.c_tm_mday) - (q.c_tm_hour + 24 * q.c_tm_mday) + if janzone < -12: + janname = " " + elif janzone > 14: + janname = " " + else: + janname = _time_zones[janzone - 12] + janzone = janzone * 3600 + # about July 11th + tt = t + YEAR / 2 + t_ref[0] = rffi.cast(rffi.TIME_T, tt) + p = c_localtime(t_ref) + q = c_gmtime(t_ref) + julyzone = (p.c_tm_hour + 24 * p.c_tm_mday) - (q.c_tm_hour + 24 * q.c_tm_mday) + if julyzone < -12: + julyname = " " + elif julyzone > 14: + julyname = " " + else: + julyname = _time_zones[julyzone - 12] + julyzone = julyzone * 3600 + lltype.free(t_ref, flavor='raw') - if janzone < julyzone: - # DST is reversed in the southern hemisphere - timezone = julyzone - altzone = janzone - daylight = int(janzone != julyzone) - tzname = [julyname, janname] + if janzone < julyzone: + # DST is reversed in the southern hemisphere + timezone = julyzone + altzone = janzone + daylight = int(janzone != julyzone) + tzname = [julyname, janname] + else: + timezone = janzone + altzone = julyzone + daylight = int(janzone != julyzone) + tzname = [janname, julyname] + else: - timezone = janzone - altzone = julyzone - daylight = int(janzone != julyzone) - tzname = [janname, julyname] + YEAR = (365 * 24 + 6) * 3600 + + t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR) + # we cannot have reference to stack variable, put it on the heap + t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') + t_ref[0] = rffi.cast(rffi.TIME_T, t) + p = c_localtime(t_ref) + janzone = -p.c_tm_gmtoff + tm_zone = rffi.charp2str(p.c_tm_zone) + janname = [" ", tm_zone][bool(tm_zone)] + tt = t + YEAR / 2 + t_ref[0] = rffi.cast(rffi.TIME_T, tt) + p = c_localtime(t_ref) + lltype.free(t_ref, flavor='raw') + tm_zone = rffi.charp2str(p.c_tm_zone) + julyzone = -p.c_tm_gmtoff + julyname = [" ", tm_zone][bool(tm_zone)] + + if janzone < julyzone: + # DST is reversed in the southern hemisphere + timezone = julyzone + altzone = janzone + daylight = int(janzone != julyzone) + tzname = [julyname, janname] + else: + timezone = janzone + altzone = julyzone + daylight = int(janzone != julyzone) + tzname = [janname, julyname] _set_module_object(space, "timezone", space.wrap(timezone)) _set_module_object(space, 'daylight', space.wrap(daylight)) @@ -361,9 +422,12 @@ rffi.setintfield(glob_buf, 'c_tm_yday', tm_yday) rffi.setintfield(glob_buf, 'c_tm_isdst', space.int_w(tup_w[8])) if _POSIX: - # actually never happens, but makes annotator happy - glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) - rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) + if _CYGWIN: + pass + else: + # actually never happens, but makes annotator happy + glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) + rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) w_accept2dyear = _get_module_object(space, "accept2dyear") accept2dyear = space.int_w(w_accept2dyear) diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py --- a/pypy/rpython/module/ll_os.py +++ b/pypy/rpython/module/ll_os.py @@ -148,6 +148,7 @@ else: includes += ['sys/utime.h'] +_CYGWIN = sys.platform == 'cygwin' class CConfig: """ @@ -1329,9 +1330,14 @@ return result else: # Posix - os_waitpid = self.llexternal('waitpid', - [rffi.PID_T, rffi.INTP, rffi.INT], - rffi.PID_T) + if _CYGWIN: + os_waitpid = self.llexternal('cygwin_waitpid', + [rffi.PID_T, rffi.INTP, rffi.INT], + rffi.PID_T) + else: + os_waitpid = self.llexternal('waitpid', + [rffi.PID_T, rffi.INTP, rffi.INT], + rffi.PID_T) def os_waitpid_llimpl(pid, options): status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -145,6 +145,8 @@ archive = str(builddir.join(name + '.tar.bz2')) if sys.platform == 'darwin' or sys.platform.startswith('freebsd'): e = os.system('tar --numeric-owner -cvjf ' + archive + " " + name) + elif sys.platform == 'cygwin': + e = os.system('tar --owner=Administrator --group=Administrators --numeric-owner -cvjf ' + archive + " " + name) else: e = os.system('tar --owner=root --group=root --numeric-owner -cvjf ' + archive + " " + name) if e: diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py --- a/pypy/translator/c/genc.py +++ b/pypy/translator/c/genc.py @@ -15,6 +15,8 @@ from pypy.rlib import exports from pypy.tool.nullpath import NullPyPathLocal +_CYGWIN = sys.platform == 'cygwin' + def import_module_from_directory(dir, modname): file, pathname, description = imp.find_module(modname, [str(dir)]) try: @@ -954,6 +956,8 @@ srcdir / 'profiling.c', srcdir / 'debug_print.c', ] + if _CYGWIN: + files.append(srcdir / 'cygwin_wait.c') return eci.merge(ExternalCompilationInfo(separate_module_files=files)) diff --git a/pypy/translator/c/src/cygwin_wait.c b/pypy/translator/c/src/cygwin_wait.c new file mode 100644 --- /dev/null +++ b/pypy/translator/c/src/cygwin_wait.c @@ -0,0 +1,47 @@ +/* + Work around compile error: + [translation:ERROR] implement_4.c: In function 'pypy_g_ccall_waitpid__Signed_arrayPtr_Signed': + [translation:ERROR] implement_4.c:150095:2: error: incompatible type for argument 2 of 'waitpid' + [translation:ERROR] /usr/include/sys/wait.h:43:7: note: expected '__wait_status_ptr_t' but argument is of type 'long int *' +*/ + +#ifdef __CYGWIN__ + +#include "wait.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* +typedef int *__wait_status_ptr_t; + */ + + /* +pid_t wait (__wait_status_ptr_t __status); +pid_t waitpid (pid_t __pid, __wait_status_ptr_t __status, int __options); +pid_t wait3 (__wait_status_ptr_t __status, int __options, struct rusage *__rusage); +pid_t wait4 (pid_t __pid, __wait_status_ptr_t __status, int __options, struct rusage *__rusage); + */ + + pid_t cygwin_wait (int * __status){ + return wait ((__wait_status_ptr_t) __status); + } + + pid_t cygwin_waitpid (pid_t __pid, int * __status, int __options){ + return waitpid (__pid, (__wait_status_ptr_t) __status, __options); + } + + pid_t cygwin_wait3 (int * __status, int __options, struct rusage *__rusage){ + return wait3 ((__wait_status_ptr_t) __status, __options, __rusage); + } + + pid_t cygwin_wait4 (pid_t __pid, int * __status, int __options, struct rusage *__rusage){ + return wait4 (__pid, (__wait_status_ptr_t) __status, __options, __rusage); + } + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pypy/translator/c/src/cygwin_wait.h b/pypy/translator/c/src/cygwin_wait.h new file mode 100644 --- /dev/null +++ b/pypy/translator/c/src/cygwin_wait.h @@ -0,0 +1,43 @@ +/* + Work around compile error: + [translation:ERROR] implement_4.c: In function 'pypy_g_ccall_waitpid__Signed_arrayPtr_Signed': + [translation:ERROR] implement_4.c:150095:2: error: incompatible type for argument 2 of 'waitpid' + [translation:ERROR] /usr/include/sys/wait.h:43:7: note: expected '__wait_status_ptr_t' but argument is of type 'long int *' +*/ + +#ifdef __CYGWIN__ + +#ifndef _PYPY_WAIT_H +#define _PYPY_WAIT_H + +#ifndef _SYS_WAIT_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /* +typedef int *__wait_status_ptr_t; + */ + + /* +pid_t wait (__wait_status_ptr_t __status); +pid_t waitpid (pid_t __pid, __wait_status_ptr_t __status, int __options); +pid_t wait3 (__wait_status_ptr_t __status, int __options, struct rusage *__rusage); +pid_t wait4 (pid_t __pid, __wait_status_ptr_t __status, int __options, struct rusage *__rusage); + */ + + pid_t cygwin_wait (int * __status); + pid_t cygwin_waitpid (pid_t __pid, int * __status, int __options); + pid_t cygwin_wait3 (int * __status, int __options, struct rusage *__rusage); + pid_t cygwin_wait4 (pid_t __pid, int * __status, int __options, struct rusage *__rusage); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/pypy/translator/c/src/g_include.h b/pypy/translator/c/src/g_include.h --- a/pypy/translator/c/src/g_include.h +++ b/pypy/translator/c/src/g_include.h @@ -61,3 +61,8 @@ # pragma warning(disable: 4033 4102 4101 4716) # endif #endif + +/* work around waitpid expecting different pointer type */ +#ifdef __CYGWIN__ +#include "src/cygwin_wait.h" +#endif diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py --- a/pypy/translator/platform/__init__.py +++ b/pypy/translator/platform/__init__.py @@ -278,6 +278,13 @@ host_factory = Windows else: host_factory = Windows_x64 +elif sys.platform == 'cygwin': + from pypy.translator.platform.cygwin import Cygwin, Cygwin64 + import platform + if platform.architecture()[0] == '32bit': + host_factory = Cygwin + else: + host_factory = Cygwin64 else: # pray from pypy.translator.platform.distutils_platform import DistutilsPlatform diff --git a/pypy/translator/platform/cygwin.py b/pypy/translator/platform/cygwin.py new file mode 100644 --- /dev/null +++ b/pypy/translator/platform/cygwin.py @@ -0,0 +1,56 @@ +"""Support for Cygwin.""" + +import os +import sys +from pypy.translator.platform.posix import BasePosix + +class BaseCygwin(BasePosix): + name = "cygwin" + +# link_flags = tuple( +# ['-pthread',] +# + os.environ.get('LDFLAGS', '').split()) + link_flags = tuple( + [] + + os.environ.get('LDFLAGS', '').split()) + extra_libs = ('-lrt',) +# cflags = tuple( +# ['-O3', '-pthread', '-fomit-frame-pointer', +# '-Wall', '-Wno-unused'] +# + os.environ.get('CFLAGS', '').split()) + cflags = tuple( + ['-O3', '-fomit-frame-pointer', + '-Wall', '-Wno-unused'] + + os.environ.get('CFLAGS', '').split()) + standalone_only = () + shared_only = ('-fPIC',) + so_ext = 'dll' + exe_ext = 'exe' + so_prefixes = ('lib', '') + + def _args_for_shared(self, args): + return ['-shared'] + args + + def _include_dirs_for_libffi(self): + return self._pkg_config("libffi", "--cflags-only-I", + ['/usr/include/libffi']) + + def _library_dirs_for_libffi(self): + return self._pkg_config("libffi", "--libs-only-L", + ['/usr/lib/libffi']) + + def library_dirs_for_libffi_a(self): + # places where we need to look for libffi.a + # XXX obscuuure! only look for libffi.a if run with translate.py + if 'translate' in sys.modules: + return self.library_dirs_for_libffi() + ['/usr/lib'] + else: + return [] + + +class Cygwin(BaseCygwin): + shared_only = () # it seems that on 32-bit linux, compiling with -fPIC + # gives assembler that asmgcc is not happy about. + +class Cygwin64(BaseCygwin): + pass diff --git a/pypy/translator/platform/posix.py b/pypy/translator/platform/posix.py --- a/pypy/translator/platform/posix.py +++ b/pypy/translator/platform/posix.py @@ -1,6 +1,6 @@ """Base support for POSIX-like platforms.""" -import py, os +import py, os, sys from pypy.tool import autopath from pypy.translator.platform import Platform, log, _run_subprocess @@ -55,7 +55,8 @@ if relto: response_file = relto.bestrelpath(response_file) - if self.cc == 'mingw32' or (self.cc== 'gcc' and os.name=='nt'): + if (self.cc == 'mingw32' or (self.cc== 'gcc' and os.name=='nt') + or sys.platform == 'cygwin'): return ["-Wl,--export-all-symbols,--version-script=%s" % \ (response_file,)] return ["-Wl,--export-dynamic,--version-script=%s" % (response_file,)] From noreply at buildbot.pypy.org Sun Jun 3 12:18:58 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 12:18:58 +0200 (CEST) Subject: [pypy-commit] pypy default: In-progress: streamline the write barrier called by the x86 Message-ID: <20120603101858.05F7D1C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55276:247ff481a07e Date: 2012-06-03 01:37 +0200 http://bitbucket.org/pypy/pypy/changeset/247ff481a07e/ Log: In-progress: streamline the write barrier called by the x86 jit backend. The goal is to try out if a simpler write barrier wouldn't be better after all. The additional motivation is that there is a really, really rare potentially buggy corner case with xmm registers not saved around the write barrier. diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py --- a/pypy/jit/backend/llsupport/gc.py +++ b/pypy/jit/backend/llsupport/gc.py @@ -577,7 +577,6 @@ def __init__(self, gc_ll_descr): self.llop1 = gc_ll_descr.llop1 self.WB_FUNCPTR = gc_ll_descr.WB_FUNCPTR - self.WB_ARRAY_FUNCPTR = gc_ll_descr.WB_ARRAY_FUNCPTR self.fielddescr_tid = gc_ll_descr.fielddescr_tid # GCClass = gc_ll_descr.GCClass @@ -592,6 +591,11 @@ self.jit_wb_card_page_shift = GCClass.JIT_WB_CARD_PAGE_SHIFT self.jit_wb_cards_set_byteofs, self.jit_wb_cards_set_singlebyte = ( self.extract_flag_byte(self.jit_wb_cards_set)) + # + # the x86 backend uses the following "accidental" facts to + # avoid one instruction: + assert self.jit_wb_cards_set_byteofs == self.jit_wb_if_flag_byteofs + assert self.jit_wb_cards_set_singlebyte == -0x80 else: self.jit_wb_cards_set = 0 @@ -615,7 +619,7 @@ # returns a function with arguments [array, index, newvalue] llop1 = self.llop1 funcptr = llop1.get_write_barrier_from_array_failing_case( - self.WB_ARRAY_FUNCPTR) + self.WB_FUNCPTR) funcaddr = llmemory.cast_ptr_to_adr(funcptr) return cpu.cast_adr_to_int(funcaddr) # this may return 0 @@ -699,9 +703,7 @@ def _setup_write_barrier(self): self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( - [llmemory.Address, llmemory.Address], lltype.Void)) - self.WB_ARRAY_FUNCPTR = lltype.Ptr(lltype.FuncType( - [llmemory.Address, lltype.Signed, llmemory.Address], lltype.Void)) + [llmemory.Address], lltype.Void)) self.write_barrier_descr = WriteBarrierDescr(self) def _make_functions(self, really_not_translated): @@ -859,8 +861,7 @@ # the GC, and call it immediately llop1 = self.llop1 funcptr = llop1.get_write_barrier_failing_case(self.WB_FUNCPTR) - funcptr(llmemory.cast_ptr_to_adr(gcref_struct), - llmemory.cast_ptr_to_adr(gcref_newptr)) + funcptr(llmemory.cast_ptr_to_adr(gcref_struct)) def can_use_nursery_malloc(self, size): return size < self.max_size_of_young_obj diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py --- a/pypy/jit/backend/x86/assembler.py +++ b/pypy/jit/backend/x86/assembler.py @@ -83,6 +83,7 @@ self.float_const_abs_addr = 0 self.malloc_slowpath1 = 0 self.malloc_slowpath2 = 0 + self.wb_slowpath = [0, 0, 0, 0] self.memcpy_addr = 0 self.setup_failure_recovery() self._debug = False @@ -109,9 +110,13 @@ self.memcpy_addr = self.cpu.cast_ptr_to_int(support.memcpy_fn) self._build_failure_recovery(False) self._build_failure_recovery(True) + self._build_wb_slowpath(False) + self._build_wb_slowpath(True) if self.cpu.supports_floats: self._build_failure_recovery(False, withfloats=True) self._build_failure_recovery(True, withfloats=True) + self._build_wb_slowpath(False, withfloats=True) + self._build_wb_slowpath(True, withfloats=True) support.ensure_sse2_floats() self._build_float_constants() self._build_propagate_exception_path() @@ -344,6 +349,82 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.stack_check_slowpath = rawstart + def _build_wb_slowpath(self, withcards, withfloats=False): + descr = self.cpu.gc_ll_descr.write_barrier_descr + if descr is None: + return + if not withcards: + func = descr.get_write_barrier_fn(self.cpu) + else: + if descr.jit_wb_cards_set == 0: + return + func = descr.get_write_barrier_from_array_fn(self.cpu) + if func == 0: + return + # + # This builds a helper function called from the slow path of + # write barriers. It must save all registers, and optionally + # all XMM registers. It takes a single argument just pushed + # on the stack even on X86_64. It must restore stack alignment + # accordingly. + mc = codebuf.MachineCodeBlockWrapper() + # + frame_size = (1 + # my argument, considered part of my frame + 1 + # my return address + len(self._regalloc.rm.save_around_call_regs)) + if withfloats: + frame_size += 16 # X86_32: 16 words for 8 registers; + # X86_64: just 16 registers + if IS_X86_32: + frame_size += 1 # argument to pass to the call + # + # align to a multiple of 16 bytes + frame_size = (frame_size + (CALL_ALIGN-1)) & ~(CALL_ALIGN-1) + # + correct_esp_by = (frame_size - 2) * WORD + mc.SUB_ri(esp.value, correct_esp_by) + # + ofs = correct_esp_by + for reg in self._regalloc.rm.save_around_call_regs: + ofs -= WORD + mc.MOV_sr(ofs, reg.value) + if withfloats: + for reg in self._regalloc.xmm.save_around_call_regs: + ofs -= 8 + mc.MOVSD_sx(ofs, reg.value) + # + if IS_X86_32: + mc.MOV_rs(eax.value, (frame_size - 1) * WORD) + mc.MOV_sr(0, eax.value) + elif IS_X86_64: + mc.MOV_rs(edi.value, (frame_size - 1) * WORD) + mc.CALL(imm(func)) + # + if withcards: + # A final TEST8 before the RET, for the caller. Careful to + # not follow this instruction with another one that changes + # the status of the CPU flags! + mc.MOV_rs(eax.value, (frame_size - 1) * WORD) + mc.TEST8(addr_add_const(eax, descr.jit_wb_if_flag_byteofs), + imm(-0x80)) + # + ofs = correct_esp_by + for reg in self._regalloc.rm.save_around_call_regs: + ofs -= WORD + mc.MOV_rs(reg.value, ofs) + if withfloats: + for reg in self._regalloc.xmm.save_around_call_regs: + ofs -= 8 + mc.MOVSD_xs(reg.value, ofs) + # + # ADD esp, correct_esp_by --- but cannot use ADD, because + # of its effects on the CPU flags + mc.LEA_rs(esp.value, correct_esp_by) + mc.RET(WORD) + # + rawstart = mc.materialize(self.cpu.asmmemmgr, []) + self.wb_slowpath[withcards + 2 * withfloats] = rawstart + @staticmethod @rgc.no_collect def _release_gil_asmgcc(css): @@ -2324,102 +2405,76 @@ def genop_discard_cond_call_gc_wb(self, op, arglocs): # Write code equivalent to write_barrier() in the GC: it checks - # a flag in the object at arglocs[0], and if set, it calls the - # function remember_young_pointer() from the GC. The arguments - # to the call are in arglocs[:N]. The rest, arglocs[N:], contains - # registers that need to be saved and restored across the call. - # N is either 2 (regular write barrier) or 3 (array write barrier). + # a flag in the object at arglocs[0], and if set, it calls a + # helper piece of assembler. The latter saves registers as needed + # and call the function jit_remember_young_pointer() from the GC. descr = op.getdescr() if we_are_translated(): cls = self.cpu.gc_ll_descr.has_write_barrier_class() assert cls is not None and isinstance(descr, cls) # opnum = op.getopnum() - if opnum == rop.COND_CALL_GC_WB: - N = 2 - func = descr.get_write_barrier_fn(self.cpu) - card_marking = False - elif opnum == rop.COND_CALL_GC_WB_ARRAY: - N = 3 - func = descr.get_write_barrier_from_array_fn(self.cpu) - assert func != 0 - card_marking = descr.jit_wb_cards_set != 0 - else: - raise AssertionError(opnum) + card_marking = False + mask = descr.jit_wb_if_flag_singlebyte + if opnum == rop.COND_CALL_GC_WB_ARRAY and descr.jit_wb_cards_set != 0: + # assumptions the rest of the function depends on: + assert (descr.jit_wb_cards_set_byteofs == + descr.jit_wb_if_flag_byteofs) + assert descr.jit_wb_cards_set_singlebyte == -0x80 + card_marking = True + mask = descr.jit_wb_if_flag_singlebyte | -0x80 # loc_base = arglocs[0] self.mc.TEST8(addr_add_const(loc_base, descr.jit_wb_if_flag_byteofs), - imm(descr.jit_wb_if_flag_singlebyte)) + imm(mask)) self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later jz_location = self.mc.get_relative_pos() # for cond_call_gc_wb_array, also add another fast path: # if GCFLAG_CARDS_SET, then we can just set one bit and be done if card_marking: - self.mc.TEST8(addr_add_const(loc_base, - descr.jit_wb_cards_set_byteofs), - imm(descr.jit_wb_cards_set_singlebyte)) - self.mc.J_il8(rx86.Conditions['NZ'], 0) # patched later - jnz_location = self.mc.get_relative_pos() + # GCFLAG_CARDS_SET is in this byte at 0x80, so this fact can + # been checked by the status flags of the previous TEST8 + self.mc.J_il8(rx86.Conditions['S'], 0) # patched later + js_location = self.mc.get_relative_pos() else: - jnz_location = 0 + js_location = 0 - # the following is supposed to be the slow path, so whenever possible - # we choose the most compact encoding over the most efficient one. - if IS_X86_32: - limit = -1 # push all arglocs on the stack - elif IS_X86_64: - limit = N - 1 # push only arglocs[N:] on the stack - for i in range(len(arglocs)-1, limit, -1): - loc = arglocs[i] - if isinstance(loc, RegLoc): - self.mc.PUSH_r(loc.value) - else: - assert not IS_X86_64 # there should only be regs in arglocs[N:] - self.mc.PUSH_i32(loc.getint()) - if IS_X86_64: - # We clobber these registers to pass the arguments, but that's - # okay, because consider_cond_call_gc_wb makes sure that any - # caller-save registers with values in them are present in - # arglocs[N:] too, so they are saved on the stack above and - # restored below. - if N == 2: - callargs = [edi, esi] - else: - callargs = [edi, esi, edx] - remap_frame_layout(self, arglocs[:N], callargs, - X86_64_SCRATCH_REG) - # - # misaligned stack in the call, but it's ok because the write barrier - # is not going to call anything more. Also, this assumes that the - # write barrier does not touch the xmm registers. (Slightly delicate - # assumption, given that the write barrier can end up calling the - # platform's malloc() from AddressStack.append(). XXX may need to - # be done properly) - self.mc.CALL(imm(func)) - if IS_X86_32: - self.mc.ADD_ri(esp.value, N*WORD) - for i in range(N, len(arglocs)): - loc = arglocs[i] - assert isinstance(loc, RegLoc) - self.mc.POP_r(loc.value) + # Write only a CALL to the helper prepared in advance, passing it as + # argument the address of the structure we are writing into + # (the first argument to COND_CALL_GC_WB). + self.mc.PUSH(loc_base) # push loc_base, either a reg or an immed + helper_num = card_marking + if self._regalloc.xrm.reg_bindings: + helper_num += 2 + self.mc.CALL(imm(self.wb_slowpath[helper_num])) - # if GCFLAG_CARDS_SET, then we can do the whole thing that would - # be done in the CALL above with just four instructions, so here - # is an inline copy of them if card_marking: - self.mc.JMP_l8(0) # jump to the exit, patched later - jmp_location = self.mc.get_relative_pos() - # patch the JNZ above - offset = self.mc.get_relative_pos() - jnz_location + # The helper ends again with a check of the flag in the object. + # So here, we can simply write again a 'JNS', which will be + # taken if GCFLAG_CARDS_SET is still not set. + self.mc.J_il8(rx86.Conditions['NS'], 0) # patched later + jns_location = self.mc.get_relative_pos() + # + # patch the JS above + offset = self.mc.get_relative_pos() - js_location assert 0 < offset <= 127 - self.mc.overwrite(jnz_location-1, chr(offset)) + self.mc.overwrite(js_location-1, chr(offset)) # + # case GCFLAG_CARDS_SET: emit a few instructions to do + # directly the card flag setting loc_index = arglocs[1] if isinstance(loc_index, RegLoc): - # choose a scratch register - tmp1 = loc_index - self.mc.PUSH_r(tmp1.value) + if IS_X86_64 and isinstance(loc_base, RegLoc): + # copy loc_index into r11 + tmp1 = X86_64_SCRATCH_REG + self.mc.MOV_rr(tmp1.value, loc_index.value) + final_pop = False + else: + # must save the register loc_index before it is mutated + self.mc.PUSH_r(loc_index.value) + tmp1 = loc_index + final_pop = True # SHR tmp, card_page_shift self.mc.SHR_ri(tmp1.value, descr.jit_wb_card_page_shift) # XOR tmp, -8 @@ -2427,7 +2482,9 @@ # BTS [loc_base], tmp self.mc.BTS(addr_add_const(loc_base, 0), tmp1) # done - self.mc.POP_r(tmp1.value) + if final_pop: + self.mc.POP_r(loc_index.value) + # elif isinstance(loc_index, ImmedLoc): byte_index = loc_index.value >> descr.jit_wb_card_page_shift byte_ofs = ~(byte_index >> 3) @@ -2435,11 +2492,12 @@ self.mc.OR8(addr_add_const(loc_base, byte_ofs), imm(byte_val)) else: raise AssertionError("index is neither RegLoc nor ImmedLoc") - # patch the JMP above - offset = self.mc.get_relative_pos() - jmp_location + # + # patch the JNS above + offset = self.mc.get_relative_pos() - jns_location assert 0 < offset <= 127 - self.mc.overwrite(jmp_location-1, chr(offset)) - # + self.mc.overwrite(jns_location-1, chr(offset)) + # patch the JZ above offset = self.mc.get_relative_pos() - jz_location assert 0 < offset <= 127 diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py --- a/pypy/jit/backend/x86/regalloc.py +++ b/pypy/jit/backend/x86/regalloc.py @@ -980,16 +980,6 @@ # or setarrayitem_gc. It avoids loading it twice from the memory. arglocs = [self.rm.make_sure_var_in_reg(op.getarg(i), args) for i in range(N)] - # add eax, ecx and edx as extra "arguments" to ensure they are - # saved and restored. Fish in self.rm to know which of these - # registers really need to be saved (a bit of a hack). Moreover, - # we don't save and restore any SSE register because the called - # function, a GC write barrier, is known not to touch them. - # See remember_young_pointer() in rpython/memory/gc/generation.py. - for v, reg in self.rm.reg_bindings.items(): - if (reg in self.rm.save_around_call_regs - and self.rm.stays_alive(v)): - arglocs.append(reg) self.PerformDiscard(op, arglocs) self.rm.possibly_free_vars_for_op(op) diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py --- a/pypy/rpython/memory/gc/minimark.py +++ b/pypy/rpython/memory/gc/minimark.py @@ -111,10 +111,13 @@ # The following flag is set on externally raw_malloc'ed arrays of pointers. # They are allocated with some extra space in front of them for a bitfield, # one bit per 'card_page_indices' indices. -GCFLAG_HAS_CARDS = first_gcflag << 5 -GCFLAG_CARDS_SET = first_gcflag << 6 # <- at least one card bit is set +GCFLAG_HAS_CARDS = first_gcflag << 6 +GCFLAG_CARDS_SET = first_gcflag << 7 # <- at least one card bit is set +# note that GCFLAG_CARDS_SET is the most significant bit of a byte: +# this is required for the JIT (x86) -TID_MASK = (first_gcflag << 7) - 1 +#GCFLAG_UNUSED = first_gcflag << 5 # this flag is free +TID_MASK = (first_gcflag << 8) - 1 FORWARDSTUB = lltype.GcStruct('forwarding_stub', @@ -994,12 +997,9 @@ def _init_writebarrier_logic(self): DEBUG = self.DEBUG # The purpose of attaching remember_young_pointer to the instance - # instead of keeping it as a regular method is to help the JIT call it. - # Additionally, it makes the code in write_barrier() marginally smaller + # instead of keeping it as a regular method is to + # make the code in write_barrier() marginally smaller # (which is important because it is inlined *everywhere*). - # For x86, there is also an extra requirement: when the JIT calls - # remember_young_pointer(), it assumes that it will not touch the SSE - # registers, so it does not save and restore them (that's a *hack*!). def remember_young_pointer(addr_struct, newvalue): # 'addr_struct' is the address of the object in which we write. # 'newvalue' is the address that we are going to write in there. @@ -1033,6 +1033,17 @@ remember_young_pointer._dont_inline_ = True self.remember_young_pointer = remember_young_pointer # + def jit_remember_young_pointer(addr_struct): + # minimal version of the above, with just one argument, + # called by the JIT when GCFLAG_TRACK_YOUNG_PTRS is set + self.old_objects_pointing_to_young.append(addr_struct) + objhdr = self.header(addr_struct) + objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS + if objhdr.tid & GCFLAG_NO_HEAP_PTRS: + objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS + self.prebuilt_root_objects.append(addr_struct) + self.jit_remember_young_pointer = jit_remember_young_pointer + # if self.card_page_indices > 0: self._init_writebarrier_with_card_marker() @@ -1087,60 +1098,21 @@ self.remember_young_pointer_from_array2 = ( remember_young_pointer_from_array2) - # xxx trying it out for the JIT: a 3-arguments version of the above - def remember_young_pointer_from_array3(addr_array, index, newvalue): + def jit_remember_young_pointer_from_array(addr_array): + # minimal version of the above, with just one argument, + # called by the JIT when GCFLAG_TRACK_YOUNG_PTRS is set + # but GCFLAG_CARDS_SET is cleared. This tries to set + # GCFLAG_CARDS_SET if possible; otherwise, it falls back + # to jit_remember_young_pointer(). objhdr = self.header(addr_array) - # - # a single check for the common case of neither GCFLAG_HAS_CARDS - # nor GCFLAG_NO_HEAP_PTRS - if objhdr.tid & (GCFLAG_HAS_CARDS | GCFLAG_NO_HEAP_PTRS) == 0: - # common case: fast path, jump to the end of the function - pass - elif objhdr.tid & GCFLAG_HAS_CARDS == 0: - # no cards, but GCFLAG_NO_HEAP_PTRS is set. - objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.prebuilt_root_objects.append(addr_array) - # jump to the end of the function + if objhdr.tid & GCFLAG_HAS_CARDS: + self.old_objects_with_cards_set.append(addr_array) + objhdr.tid |= GCFLAG_CARDS_SET else: - # case with cards. - # - # If the newly written address does not actually point to a - # young object, leave now. - if not self.appears_to_be_young(newvalue): - return - # - # 'addr_array' is a raw_malloc'ed array with card markers - # in front. Compute the index of the bit to set: - bitindex = index >> self.card_page_shift - byteindex = bitindex >> 3 - bitmask = 1 << (bitindex & 7) - # - # If the bit is already set, leave now. - addr_byte = self.get_card(addr_array, byteindex) - byte = ord(addr_byte.char[0]) - if byte & bitmask: - return - addr_byte.char[0] = chr(byte | bitmask) - # - if objhdr.tid & GCFLAG_CARDS_SET == 0: - self.old_objects_with_cards_set.append(addr_array) - objhdr.tid |= GCFLAG_CARDS_SET - return - # - # Logic for the no-cards case, put here to minimize the number - # of checks done at the start of the function - if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this - ll_assert(self.debug_is_old_object(addr_array), - "young array with no card but GCFLAG_TRACK_YOUNG_PTRS") - # - if self.appears_to_be_young(newvalue): - self.old_objects_pointing_to_young.append(addr_array) - objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS + self.jit_remember_young_pointer(addr_array) - remember_young_pointer_from_array3._dont_inline_ = True - assert self.card_page_indices > 0 - self.remember_young_pointer_from_array3 = ( - remember_young_pointer_from_array3) + self.jit_remember_young_pointer_from_array = ( + jit_remember_young_pointer_from_array) def get_card(self, obj, byteindex): size_gc_header = self.gcheaderbuilder.size_gc_header diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py --- a/pypy/rpython/memory/gctransform/framework.py +++ b/pypy/rpython/memory/gctransform/framework.py @@ -455,13 +455,12 @@ annmodel.SomeAddress()], annmodel.s_None, inline=True) - func = getattr(gcdata.gc, 'remember_young_pointer', None) + func = getattr(gcdata.gc, 'jit_remember_young_pointer', None) if func is not None: # func should not be a bound method, but a real function assert isinstance(func, types.FunctionType) self.write_barrier_failing_case_ptr = getfn(func, - [annmodel.SomeAddress(), - annmodel.SomeAddress()], + [annmodel.SomeAddress()], annmodel.s_None) func = getattr(GCClass, 'write_barrier_from_array', None) if func is not None: @@ -472,16 +471,15 @@ annmodel.SomeInteger()], annmodel.s_None, inline=True) - func = getattr(gcdata.gc, 'remember_young_pointer_from_array3', + func = getattr(gcdata.gc, + 'jit_remember_young_pointer_from_array', None) if func is not None: # func should not be a bound method, but a real function assert isinstance(func, types.FunctionType) self.write_barrier_from_array_failing_case_ptr = \ getfn(func, - [annmodel.SomeAddress(), - annmodel.SomeInteger(), - annmodel.SomeAddress()], + [annmodel.SomeAddress()], annmodel.s_None) self.statistics_ptr = getfn(GCClass.statistics.im_func, [s_gc, annmodel.SomeInteger()], From noreply at buildbot.pypy.org Sun Jun 3 12:18:59 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 12:18:59 +0200 (CEST) Subject: [pypy-commit] pypy default: Fixes Message-ID: <20120603101859.458241C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55277:6bab143c4abe Date: 2012-06-03 10:18 +0200 http://bitbucket.org/pypy/pypy/changeset/6bab143c4abe/ Log: Fixes diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py --- a/pypy/jit/backend/x86/assembler.py +++ b/pypy/jit/backend/x86/assembler.py @@ -10,7 +10,7 @@ from pypy.rlib.jit import AsmInfo from pypy.jit.backend.model import CompiledLoopToken from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale, - gpr_reg_mgr_cls, _valid_addressing_size) + gpr_reg_mgr_cls, xmm_reg_mgr_cls, _valid_addressing_size) from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD, IS_X86_32, IS_X86_64) @@ -371,7 +371,7 @@ # frame_size = (1 + # my argument, considered part of my frame 1 + # my return address - len(self._regalloc.rm.save_around_call_regs)) + len(gpr_reg_mgr_cls.save_around_call_regs)) if withfloats: frame_size += 16 # X86_32: 16 words for 8 registers; # X86_64: just 16 registers @@ -385,13 +385,13 @@ mc.SUB_ri(esp.value, correct_esp_by) # ofs = correct_esp_by - for reg in self._regalloc.rm.save_around_call_regs: + if withfloats: + for reg in xmm_reg_mgr_cls.save_around_call_regs: + ofs -= 8 + mc.MOVSD_sx(ofs, reg.value) + for reg in gpr_reg_mgr_cls.save_around_call_regs: ofs -= WORD mc.MOV_sr(ofs, reg.value) - if withfloats: - for reg in self._regalloc.xmm.save_around_call_regs: - ofs -= 8 - mc.MOVSD_sx(ofs, reg.value) # if IS_X86_32: mc.MOV_rs(eax.value, (frame_size - 1) * WORD) @@ -409,18 +409,18 @@ imm(-0x80)) # ofs = correct_esp_by - for reg in self._regalloc.rm.save_around_call_regs: + if withfloats: + for reg in xmm_reg_mgr_cls.save_around_call_regs: + ofs -= 8 + mc.MOVSD_xs(reg.value, ofs) + for reg in gpr_reg_mgr_cls.save_around_call_regs: ofs -= WORD mc.MOV_rs(reg.value, ofs) - if withfloats: - for reg in self._regalloc.xmm.save_around_call_regs: - ofs -= 8 - mc.MOVSD_xs(reg.value, ofs) # # ADD esp, correct_esp_by --- but cannot use ADD, because # of its effects on the CPU flags mc.LEA_rs(esp.value, correct_esp_by) - mc.RET(WORD) + mc.RET16_i(WORD) # rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.wb_slowpath[withcards + 2 * withfloats] = rawstart @@ -2443,10 +2443,10 @@ # Write only a CALL to the helper prepared in advance, passing it as # argument the address of the structure we are writing into # (the first argument to COND_CALL_GC_WB). - self.mc.PUSH(loc_base) # push loc_base, either a reg or an immed helper_num = card_marking if self._regalloc.xrm.reg_bindings: helper_num += 2 + self.mc.PUSH(loc_base) self.mc.CALL(imm(self.wb_slowpath[helper_num])) if card_marking: diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py --- a/pypy/jit/backend/x86/rx86.py +++ b/pypy/jit/backend/x86/rx86.py @@ -531,7 +531,7 @@ PUSH_r = insn(rex_nw, register(1), '\x50') PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1)) - PUSH_i32 = insn('\x68', immediate(1, 'i')) + PUSH_i = insn('\x68', immediate(1, 'i')) POP_r = insn(rex_nw, register(1), '\x58') POP_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1)) From noreply at buildbot.pypy.org Sun Jun 3 12:19:00 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 12:19:00 +0200 (CEST) Subject: [pypy-commit] pypy default: Remove 'rex_fw' from two places where it has no effect. Comment. Message-ID: <20120603101900.6051A1C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55278:40dc84ac4952 Date: 2012-06-03 10:37 +0200 http://bitbucket.org/pypy/pypy/changeset/40dc84ac4952/ Log: Remove 'rex_fw' from two places where it has no effect. Comment. diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py --- a/pypy/jit/backend/x86/rx86.py +++ b/pypy/jit/backend/x86/rx86.py @@ -316,6 +316,13 @@ assert rexbyte == 0 return 0 +# REX prefixes: 'rex_w' generates a REX_W, forcing the instruction +# to operate on 64-bit. 'rex_nw' doesn't, so the instruction operates +# on 32-bit or less; the complete REX prefix is omitted if unnecessary. +# 'rex_fw' is a special case which doesn't generate a REX_W but forces +# the REX prefix in all cases. It is only useful on instructions which +# have an 8-bit register argument, to force access to the "sil" or "dil" +# registers (as opposed to "ah-dh"). rex_w = encode_rex, 0, (0x40 | REX_W), None # a REX.W prefix rex_nw = encode_rex, 0, 0, None # an optional REX prefix rex_fw = encode_rex, 0, 0x40, None # a forced REX prefix @@ -496,9 +503,9 @@ AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0') OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0') - OR8_mi = insn(rex_fw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), + OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), immediate(2, 'b')) - OR8_ji = insn(rex_fw, '\x80', orbyte(1<<3), abs_, immediate(1), + OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1), immediate(2, 'b')) NEG_r = insn(rex_w, '\xF7', register(1), '\xD8') From noreply at buildbot.pypy.org Sun Jun 3 12:19:01 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 12:19:01 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix the test. Message-ID: <20120603101901.91BF31C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55279:c6a1519817b1 Date: 2012-06-03 11:00 +0200 http://bitbucket.org/pypy/pypy/changeset/c6a1519817b1/ Log: Fix the test. diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py --- a/pypy/jit/backend/test/runner_test.py +++ b/pypy/jit/backend/test/runner_test.py @@ -1835,12 +1835,12 @@ assert not excvalue def test_cond_call_gc_wb(self): - def func_void(a, b): - record.append((a, b)) + def func_void(a): + record.append(a) record = [] # S = lltype.GcStruct('S', ('tid', lltype.Signed)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Ptr(S)], lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): @@ -1866,26 +1866,25 @@ [BoxPtr(sgcref), ConstPtr(tgcref)], 'void', descr=WriteBarrierDescr()) if cond: - assert record == [(s, t)] + assert record == [s] else: assert record == [] def test_cond_call_gc_wb_array(self): - def func_void(a, b, c): - record.append((a, b, c)) + def func_void(a): + record.append(a) record = [] # S = lltype.GcStruct('S', ('tid', lltype.Signed)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)], - lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): jit_wb_if_flag = 4096 jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10') jit_wb_if_flag_singlebyte = 0x10 - jit_wb_cards_set = 0 - def get_write_barrier_from_array_fn(self, cpu): + jit_wb_cards_set = 0 # <= without card marking + def get_write_barrier_fn(self, cpu): return funcbox.getint() # for cond in [False, True]: @@ -1902,13 +1901,15 @@ [BoxPtr(sgcref), ConstInt(123), BoxPtr(sgcref)], 'void', descr=WriteBarrierDescr()) if cond: - assert record == [(s, 123, s)] + assert record == [s] else: assert record == [] def test_cond_call_gc_wb_array_card_marking_fast_path(self): - def func_void(a, b, c): - record.append((a, b, c)) + def func_void(a): + record.append(a) + if cond == 1: # the write barrier sets the flag + s.data.tid |= 32768 record = [] # S = lltype.Struct('S', ('tid', lltype.Signed)) @@ -1922,34 +1923,40 @@ ('card6', lltype.Char), ('card7', lltype.Char), ('data', S)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)], - lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): jit_wb_if_flag = 4096 jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10') jit_wb_if_flag_singlebyte = 0x10 - jit_wb_cards_set = 8192 - jit_wb_cards_set_byteofs = struct.pack("i", 8192).index('\x20') - jit_wb_cards_set_singlebyte = 0x20 + jit_wb_cards_set = 32768 + jit_wb_cards_set_byteofs = struct.pack("i", 32768).index('\x80') + jit_wb_cards_set_singlebyte = -0x80 jit_wb_card_page_shift = 7 def get_write_barrier_from_array_fn(self, cpu): return funcbox.getint() # - for BoxIndexCls in [BoxInt, ConstInt]: - for cond in [False, True]: + for BoxIndexCls in [BoxInt, ConstInt]*3: + for cond in [-1, 0, 1, 2]: + # cond=-1:GCFLAG_TRACK_YOUNG_PTRS, GCFLAG_CARDS_SET are not set + # cond=0: GCFLAG_CARDS_SET is never set + # cond=1: GCFLAG_CARDS_SET is not set, but the wb sets it + # cond=2: GCFLAG_CARDS_SET is already set print print '_'*79 print 'BoxIndexCls =', BoxIndexCls - print 'JIT_WB_CARDS_SET =', cond + print 'testing cond =', cond print value = random.randrange(-sys.maxint, sys.maxint) - value |= 4096 - if cond: - value |= 8192 + if cond >= 0: + value |= 4096 else: - value &= ~8192 + value &= ~4096 + if cond == 2: + value |= 32768 + else: + value &= ~32768 s = lltype.malloc(S_WITH_CARDS, immortal=True, zero=True) s.data.tid = value sgcref = rffi.cast(llmemory.GCREF, s.data) @@ -1958,11 +1965,13 @@ self.execute_operation(rop.COND_CALL_GC_WB_ARRAY, [BoxPtr(sgcref), box_index, BoxPtr(sgcref)], 'void', descr=WriteBarrierDescr()) - if cond: + if cond in [0, 1]: + assert record == [s.data] + else: assert record == [] + if cond in [1, 2]: assert s.card6 == '\x02' else: - assert record == [(s.data, (9<<7) + 17, s.data)] assert s.card6 == '\x00' assert s.card0 == '\x00' assert s.card1 == '\x00' @@ -1971,6 +1980,9 @@ assert s.card4 == '\x00' assert s.card5 == '\x00' assert s.card7 == '\x00' + if cond == 1: + value |= 32768 + assert s.data.tid == value def test_force_operations_returning_void(self): values = [] diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py --- a/pypy/jit/backend/x86/assembler.py +++ b/pypy/jit/backend/x86/assembler.py @@ -2446,6 +2446,13 @@ helper_num = card_marking if self._regalloc.xrm.reg_bindings: helper_num += 2 + if self.wb_slowpath[helper_num] == 0: # tests only + assert not we_are_translated() + self.cpu.gc_ll_descr.write_barrier_descr = descr + self._build_wb_slowpath(card_marking, + bool(self._regalloc.xrm.reg_bindings)) + assert self.wb_slowpath[helper_num] != 0 + # self.mc.PUSH(loc_base) self.mc.CALL(imm(self.wb_slowpath[helper_num])) From noreply at buildbot.pypy.org Sun Jun 3 12:19:02 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 12:19:02 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix tests. Message-ID: <20120603101902.A54E71C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55280:0bf477245547 Date: 2012-06-03 11:07 +0200 http://bitbucket.org/pypy/pypy/changeset/0bf477245547/ Log: Fix tests. diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py --- a/pypy/jit/backend/x86/rx86.py +++ b/pypy/jit/backend/x86/rx86.py @@ -538,7 +538,13 @@ PUSH_r = insn(rex_nw, register(1), '\x50') PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1)) - PUSH_i = insn('\x68', immediate(1, 'i')) + PUSH_i8 = insn('\x6A', immediate(1, 'b')) + PUSH_i32 = insn('\x68', immediate(1, 'i')) + def PUSH_i(mc, immed): + if single_byte(immed): + mc.PUSH_i8(immed) + else: + mc.PUSH_i32(immed) POP_r = insn(rex_nw, register(1), '\x58') POP_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1)) diff --git a/pypy/jit/backend/x86/test/test_rx86.py b/pypy/jit/backend/x86/test/test_rx86.py --- a/pypy/jit/backend/x86/test/test_rx86.py +++ b/pypy/jit/backend/x86/test/test_rx86.py @@ -183,7 +183,8 @@ def test_push32(): cb = CodeBuilder32 - assert_encodes_as(cb, 'PUSH_i32', (9,), '\x68\x09\x00\x00\x00') + assert_encodes_as(cb, 'PUSH_i', (0x10009,), '\x68\x09\x00\x01\x00') + assert_encodes_as(cb, 'PUSH_i', (9,), '\x6A\x09') def test_sub_ji8(): cb = CodeBuilder32 From noreply at buildbot.pypy.org Sun Jun 3 12:19:03 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 12:19:03 +0200 (CEST) Subject: [pypy-commit] pypy default: hg merge Message-ID: <20120603101903.CF2481C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55281:b513e71c997d Date: 2012-06-03 12:18 +0200 http://bitbucket.org/pypy/pypy/changeset/b513e71c997d/ Log: hg merge diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py --- a/pypy/jit/backend/llsupport/gc.py +++ b/pypy/jit/backend/llsupport/gc.py @@ -577,7 +577,6 @@ def __init__(self, gc_ll_descr): self.llop1 = gc_ll_descr.llop1 self.WB_FUNCPTR = gc_ll_descr.WB_FUNCPTR - self.WB_ARRAY_FUNCPTR = gc_ll_descr.WB_ARRAY_FUNCPTR self.fielddescr_tid = gc_ll_descr.fielddescr_tid # GCClass = gc_ll_descr.GCClass @@ -592,6 +591,11 @@ self.jit_wb_card_page_shift = GCClass.JIT_WB_CARD_PAGE_SHIFT self.jit_wb_cards_set_byteofs, self.jit_wb_cards_set_singlebyte = ( self.extract_flag_byte(self.jit_wb_cards_set)) + # + # the x86 backend uses the following "accidental" facts to + # avoid one instruction: + assert self.jit_wb_cards_set_byteofs == self.jit_wb_if_flag_byteofs + assert self.jit_wb_cards_set_singlebyte == -0x80 else: self.jit_wb_cards_set = 0 @@ -615,7 +619,7 @@ # returns a function with arguments [array, index, newvalue] llop1 = self.llop1 funcptr = llop1.get_write_barrier_from_array_failing_case( - self.WB_ARRAY_FUNCPTR) + self.WB_FUNCPTR) funcaddr = llmemory.cast_ptr_to_adr(funcptr) return cpu.cast_adr_to_int(funcaddr) # this may return 0 @@ -699,9 +703,7 @@ def _setup_write_barrier(self): self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( - [llmemory.Address, llmemory.Address], lltype.Void)) - self.WB_ARRAY_FUNCPTR = lltype.Ptr(lltype.FuncType( - [llmemory.Address, lltype.Signed, llmemory.Address], lltype.Void)) + [llmemory.Address], lltype.Void)) self.write_barrier_descr = WriteBarrierDescr(self) def _make_functions(self, really_not_translated): @@ -859,8 +861,7 @@ # the GC, and call it immediately llop1 = self.llop1 funcptr = llop1.get_write_barrier_failing_case(self.WB_FUNCPTR) - funcptr(llmemory.cast_ptr_to_adr(gcref_struct), - llmemory.cast_ptr_to_adr(gcref_newptr)) + funcptr(llmemory.cast_ptr_to_adr(gcref_struct)) def can_use_nursery_malloc(self, size): return size < self.max_size_of_young_obj diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py --- a/pypy/jit/backend/test/runner_test.py +++ b/pypy/jit/backend/test/runner_test.py @@ -1835,12 +1835,12 @@ assert not excvalue def test_cond_call_gc_wb(self): - def func_void(a, b): - record.append((a, b)) + def func_void(a): + record.append(a) record = [] # S = lltype.GcStruct('S', ('tid', lltype.Signed)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Ptr(S)], lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): @@ -1866,26 +1866,25 @@ [BoxPtr(sgcref), ConstPtr(tgcref)], 'void', descr=WriteBarrierDescr()) if cond: - assert record == [(s, t)] + assert record == [s] else: assert record == [] def test_cond_call_gc_wb_array(self): - def func_void(a, b, c): - record.append((a, b, c)) + def func_void(a): + record.append(a) record = [] # S = lltype.GcStruct('S', ('tid', lltype.Signed)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)], - lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): jit_wb_if_flag = 4096 jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10') jit_wb_if_flag_singlebyte = 0x10 - jit_wb_cards_set = 0 - def get_write_barrier_from_array_fn(self, cpu): + jit_wb_cards_set = 0 # <= without card marking + def get_write_barrier_fn(self, cpu): return funcbox.getint() # for cond in [False, True]: @@ -1902,13 +1901,15 @@ [BoxPtr(sgcref), ConstInt(123), BoxPtr(sgcref)], 'void', descr=WriteBarrierDescr()) if cond: - assert record == [(s, 123, s)] + assert record == [s] else: assert record == [] def test_cond_call_gc_wb_array_card_marking_fast_path(self): - def func_void(a, b, c): - record.append((a, b, c)) + def func_void(a): + record.append(a) + if cond == 1: # the write barrier sets the flag + s.data.tid |= 32768 record = [] # S = lltype.Struct('S', ('tid', lltype.Signed)) @@ -1922,34 +1923,40 @@ ('card6', lltype.Char), ('card7', lltype.Char), ('data', S)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)], - lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): jit_wb_if_flag = 4096 jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10') jit_wb_if_flag_singlebyte = 0x10 - jit_wb_cards_set = 8192 - jit_wb_cards_set_byteofs = struct.pack("i", 8192).index('\x20') - jit_wb_cards_set_singlebyte = 0x20 + jit_wb_cards_set = 32768 + jit_wb_cards_set_byteofs = struct.pack("i", 32768).index('\x80') + jit_wb_cards_set_singlebyte = -0x80 jit_wb_card_page_shift = 7 def get_write_barrier_from_array_fn(self, cpu): return funcbox.getint() # - for BoxIndexCls in [BoxInt, ConstInt]: - for cond in [False, True]: + for BoxIndexCls in [BoxInt, ConstInt]*3: + for cond in [-1, 0, 1, 2]: + # cond=-1:GCFLAG_TRACK_YOUNG_PTRS, GCFLAG_CARDS_SET are not set + # cond=0: GCFLAG_CARDS_SET is never set + # cond=1: GCFLAG_CARDS_SET is not set, but the wb sets it + # cond=2: GCFLAG_CARDS_SET is already set print print '_'*79 print 'BoxIndexCls =', BoxIndexCls - print 'JIT_WB_CARDS_SET =', cond + print 'testing cond =', cond print value = random.randrange(-sys.maxint, sys.maxint) - value |= 4096 - if cond: - value |= 8192 + if cond >= 0: + value |= 4096 else: - value &= ~8192 + value &= ~4096 + if cond == 2: + value |= 32768 + else: + value &= ~32768 s = lltype.malloc(S_WITH_CARDS, immortal=True, zero=True) s.data.tid = value sgcref = rffi.cast(llmemory.GCREF, s.data) @@ -1958,11 +1965,13 @@ self.execute_operation(rop.COND_CALL_GC_WB_ARRAY, [BoxPtr(sgcref), box_index, BoxPtr(sgcref)], 'void', descr=WriteBarrierDescr()) - if cond: + if cond in [0, 1]: + assert record == [s.data] + else: assert record == [] + if cond in [1, 2]: assert s.card6 == '\x02' else: - assert record == [(s.data, (9<<7) + 17, s.data)] assert s.card6 == '\x00' assert s.card0 == '\x00' assert s.card1 == '\x00' @@ -1971,6 +1980,9 @@ assert s.card4 == '\x00' assert s.card5 == '\x00' assert s.card7 == '\x00' + if cond == 1: + value |= 32768 + assert s.data.tid == value def test_force_operations_returning_void(self): values = [] diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py --- a/pypy/jit/backend/x86/assembler.py +++ b/pypy/jit/backend/x86/assembler.py @@ -10,7 +10,7 @@ from pypy.rlib.jit import AsmInfo from pypy.jit.backend.model import CompiledLoopToken from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale, - gpr_reg_mgr_cls, _valid_addressing_size) + gpr_reg_mgr_cls, xmm_reg_mgr_cls, _valid_addressing_size) from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD, IS_X86_32, IS_X86_64) @@ -83,6 +83,7 @@ self.float_const_abs_addr = 0 self.malloc_slowpath1 = 0 self.malloc_slowpath2 = 0 + self.wb_slowpath = [0, 0, 0, 0] self.memcpy_addr = 0 self.setup_failure_recovery() self._debug = False @@ -109,9 +110,13 @@ self.memcpy_addr = self.cpu.cast_ptr_to_int(support.memcpy_fn) self._build_failure_recovery(False) self._build_failure_recovery(True) + self._build_wb_slowpath(False) + self._build_wb_slowpath(True) if self.cpu.supports_floats: self._build_failure_recovery(False, withfloats=True) self._build_failure_recovery(True, withfloats=True) + self._build_wb_slowpath(False, withfloats=True) + self._build_wb_slowpath(True, withfloats=True) support.ensure_sse2_floats() self._build_float_constants() self._build_propagate_exception_path() @@ -344,6 +349,82 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.stack_check_slowpath = rawstart + def _build_wb_slowpath(self, withcards, withfloats=False): + descr = self.cpu.gc_ll_descr.write_barrier_descr + if descr is None: + return + if not withcards: + func = descr.get_write_barrier_fn(self.cpu) + else: + if descr.jit_wb_cards_set == 0: + return + func = descr.get_write_barrier_from_array_fn(self.cpu) + if func == 0: + return + # + # This builds a helper function called from the slow path of + # write barriers. It must save all registers, and optionally + # all XMM registers. It takes a single argument just pushed + # on the stack even on X86_64. It must restore stack alignment + # accordingly. + mc = codebuf.MachineCodeBlockWrapper() + # + frame_size = (1 + # my argument, considered part of my frame + 1 + # my return address + len(gpr_reg_mgr_cls.save_around_call_regs)) + if withfloats: + frame_size += 16 # X86_32: 16 words for 8 registers; + # X86_64: just 16 registers + if IS_X86_32: + frame_size += 1 # argument to pass to the call + # + # align to a multiple of 16 bytes + frame_size = (frame_size + (CALL_ALIGN-1)) & ~(CALL_ALIGN-1) + # + correct_esp_by = (frame_size - 2) * WORD + mc.SUB_ri(esp.value, correct_esp_by) + # + ofs = correct_esp_by + if withfloats: + for reg in xmm_reg_mgr_cls.save_around_call_regs: + ofs -= 8 + mc.MOVSD_sx(ofs, reg.value) + for reg in gpr_reg_mgr_cls.save_around_call_regs: + ofs -= WORD + mc.MOV_sr(ofs, reg.value) + # + if IS_X86_32: + mc.MOV_rs(eax.value, (frame_size - 1) * WORD) + mc.MOV_sr(0, eax.value) + elif IS_X86_64: + mc.MOV_rs(edi.value, (frame_size - 1) * WORD) + mc.CALL(imm(func)) + # + if withcards: + # A final TEST8 before the RET, for the caller. Careful to + # not follow this instruction with another one that changes + # the status of the CPU flags! + mc.MOV_rs(eax.value, (frame_size - 1) * WORD) + mc.TEST8(addr_add_const(eax, descr.jit_wb_if_flag_byteofs), + imm(-0x80)) + # + ofs = correct_esp_by + if withfloats: + for reg in xmm_reg_mgr_cls.save_around_call_regs: + ofs -= 8 + mc.MOVSD_xs(reg.value, ofs) + for reg in gpr_reg_mgr_cls.save_around_call_regs: + ofs -= WORD + mc.MOV_rs(reg.value, ofs) + # + # ADD esp, correct_esp_by --- but cannot use ADD, because + # of its effects on the CPU flags + mc.LEA_rs(esp.value, correct_esp_by) + mc.RET16_i(WORD) + # + rawstart = mc.materialize(self.cpu.asmmemmgr, []) + self.wb_slowpath[withcards + 2 * withfloats] = rawstart + @staticmethod @rgc.no_collect def _release_gil_asmgcc(css): @@ -2324,102 +2405,83 @@ def genop_discard_cond_call_gc_wb(self, op, arglocs): # Write code equivalent to write_barrier() in the GC: it checks - # a flag in the object at arglocs[0], and if set, it calls the - # function remember_young_pointer() from the GC. The arguments - # to the call are in arglocs[:N]. The rest, arglocs[N:], contains - # registers that need to be saved and restored across the call. - # N is either 2 (regular write barrier) or 3 (array write barrier). + # a flag in the object at arglocs[0], and if set, it calls a + # helper piece of assembler. The latter saves registers as needed + # and call the function jit_remember_young_pointer() from the GC. descr = op.getdescr() if we_are_translated(): cls = self.cpu.gc_ll_descr.has_write_barrier_class() assert cls is not None and isinstance(descr, cls) # opnum = op.getopnum() - if opnum == rop.COND_CALL_GC_WB: - N = 2 - func = descr.get_write_barrier_fn(self.cpu) - card_marking = False - elif opnum == rop.COND_CALL_GC_WB_ARRAY: - N = 3 - func = descr.get_write_barrier_from_array_fn(self.cpu) - assert func != 0 - card_marking = descr.jit_wb_cards_set != 0 - else: - raise AssertionError(opnum) + card_marking = False + mask = descr.jit_wb_if_flag_singlebyte + if opnum == rop.COND_CALL_GC_WB_ARRAY and descr.jit_wb_cards_set != 0: + # assumptions the rest of the function depends on: + assert (descr.jit_wb_cards_set_byteofs == + descr.jit_wb_if_flag_byteofs) + assert descr.jit_wb_cards_set_singlebyte == -0x80 + card_marking = True + mask = descr.jit_wb_if_flag_singlebyte | -0x80 # loc_base = arglocs[0] self.mc.TEST8(addr_add_const(loc_base, descr.jit_wb_if_flag_byteofs), - imm(descr.jit_wb_if_flag_singlebyte)) + imm(mask)) self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later jz_location = self.mc.get_relative_pos() # for cond_call_gc_wb_array, also add another fast path: # if GCFLAG_CARDS_SET, then we can just set one bit and be done if card_marking: - self.mc.TEST8(addr_add_const(loc_base, - descr.jit_wb_cards_set_byteofs), - imm(descr.jit_wb_cards_set_singlebyte)) - self.mc.J_il8(rx86.Conditions['NZ'], 0) # patched later - jnz_location = self.mc.get_relative_pos() + # GCFLAG_CARDS_SET is in this byte at 0x80, so this fact can + # been checked by the status flags of the previous TEST8 + self.mc.J_il8(rx86.Conditions['S'], 0) # patched later + js_location = self.mc.get_relative_pos() else: - jnz_location = 0 + js_location = 0 - # the following is supposed to be the slow path, so whenever possible - # we choose the most compact encoding over the most efficient one. - if IS_X86_32: - limit = -1 # push all arglocs on the stack - elif IS_X86_64: - limit = N - 1 # push only arglocs[N:] on the stack - for i in range(len(arglocs)-1, limit, -1): - loc = arglocs[i] - if isinstance(loc, RegLoc): - self.mc.PUSH_r(loc.value) - else: - assert not IS_X86_64 # there should only be regs in arglocs[N:] - self.mc.PUSH_i32(loc.getint()) - if IS_X86_64: - # We clobber these registers to pass the arguments, but that's - # okay, because consider_cond_call_gc_wb makes sure that any - # caller-save registers with values in them are present in - # arglocs[N:] too, so they are saved on the stack above and - # restored below. - if N == 2: - callargs = [edi, esi] - else: - callargs = [edi, esi, edx] - remap_frame_layout(self, arglocs[:N], callargs, - X86_64_SCRATCH_REG) + # Write only a CALL to the helper prepared in advance, passing it as + # argument the address of the structure we are writing into + # (the first argument to COND_CALL_GC_WB). + helper_num = card_marking + if self._regalloc.xrm.reg_bindings: + helper_num += 2 + if self.wb_slowpath[helper_num] == 0: # tests only + assert not we_are_translated() + self.cpu.gc_ll_descr.write_barrier_descr = descr + self._build_wb_slowpath(card_marking, + bool(self._regalloc.xrm.reg_bindings)) + assert self.wb_slowpath[helper_num] != 0 # - # misaligned stack in the call, but it's ok because the write barrier - # is not going to call anything more. Also, this assumes that the - # write barrier does not touch the xmm registers. (Slightly delicate - # assumption, given that the write barrier can end up calling the - # platform's malloc() from AddressStack.append(). XXX may need to - # be done properly) - self.mc.CALL(imm(func)) - if IS_X86_32: - self.mc.ADD_ri(esp.value, N*WORD) - for i in range(N, len(arglocs)): - loc = arglocs[i] - assert isinstance(loc, RegLoc) - self.mc.POP_r(loc.value) + self.mc.PUSH(loc_base) + self.mc.CALL(imm(self.wb_slowpath[helper_num])) - # if GCFLAG_CARDS_SET, then we can do the whole thing that would - # be done in the CALL above with just four instructions, so here - # is an inline copy of them if card_marking: - self.mc.JMP_l8(0) # jump to the exit, patched later - jmp_location = self.mc.get_relative_pos() - # patch the JNZ above - offset = self.mc.get_relative_pos() - jnz_location + # The helper ends again with a check of the flag in the object. + # So here, we can simply write again a 'JNS', which will be + # taken if GCFLAG_CARDS_SET is still not set. + self.mc.J_il8(rx86.Conditions['NS'], 0) # patched later + jns_location = self.mc.get_relative_pos() + # + # patch the JS above + offset = self.mc.get_relative_pos() - js_location assert 0 < offset <= 127 - self.mc.overwrite(jnz_location-1, chr(offset)) + self.mc.overwrite(js_location-1, chr(offset)) # + # case GCFLAG_CARDS_SET: emit a few instructions to do + # directly the card flag setting loc_index = arglocs[1] if isinstance(loc_index, RegLoc): - # choose a scratch register - tmp1 = loc_index - self.mc.PUSH_r(tmp1.value) + if IS_X86_64 and isinstance(loc_base, RegLoc): + # copy loc_index into r11 + tmp1 = X86_64_SCRATCH_REG + self.mc.MOV_rr(tmp1.value, loc_index.value) + final_pop = False + else: + # must save the register loc_index before it is mutated + self.mc.PUSH_r(loc_index.value) + tmp1 = loc_index + final_pop = True # SHR tmp, card_page_shift self.mc.SHR_ri(tmp1.value, descr.jit_wb_card_page_shift) # XOR tmp, -8 @@ -2427,7 +2489,9 @@ # BTS [loc_base], tmp self.mc.BTS(addr_add_const(loc_base, 0), tmp1) # done - self.mc.POP_r(tmp1.value) + if final_pop: + self.mc.POP_r(loc_index.value) + # elif isinstance(loc_index, ImmedLoc): byte_index = loc_index.value >> descr.jit_wb_card_page_shift byte_ofs = ~(byte_index >> 3) @@ -2435,11 +2499,12 @@ self.mc.OR8(addr_add_const(loc_base, byte_ofs), imm(byte_val)) else: raise AssertionError("index is neither RegLoc nor ImmedLoc") - # patch the JMP above - offset = self.mc.get_relative_pos() - jmp_location + # + # patch the JNS above + offset = self.mc.get_relative_pos() - jns_location assert 0 < offset <= 127 - self.mc.overwrite(jmp_location-1, chr(offset)) - # + self.mc.overwrite(jns_location-1, chr(offset)) + # patch the JZ above offset = self.mc.get_relative_pos() - jz_location assert 0 < offset <= 127 diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py --- a/pypy/jit/backend/x86/regalloc.py +++ b/pypy/jit/backend/x86/regalloc.py @@ -980,16 +980,6 @@ # or setarrayitem_gc. It avoids loading it twice from the memory. arglocs = [self.rm.make_sure_var_in_reg(op.getarg(i), args) for i in range(N)] - # add eax, ecx and edx as extra "arguments" to ensure they are - # saved and restored. Fish in self.rm to know which of these - # registers really need to be saved (a bit of a hack). Moreover, - # we don't save and restore any SSE register because the called - # function, a GC write barrier, is known not to touch them. - # See remember_young_pointer() in rpython/memory/gc/generation.py. - for v, reg in self.rm.reg_bindings.items(): - if (reg in self.rm.save_around_call_regs - and self.rm.stays_alive(v)): - arglocs.append(reg) self.PerformDiscard(op, arglocs) self.rm.possibly_free_vars_for_op(op) diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py --- a/pypy/jit/backend/x86/rx86.py +++ b/pypy/jit/backend/x86/rx86.py @@ -316,6 +316,13 @@ assert rexbyte == 0 return 0 +# REX prefixes: 'rex_w' generates a REX_W, forcing the instruction +# to operate on 64-bit. 'rex_nw' doesn't, so the instruction operates +# on 32-bit or less; the complete REX prefix is omitted if unnecessary. +# 'rex_fw' is a special case which doesn't generate a REX_W but forces +# the REX prefix in all cases. It is only useful on instructions which +# have an 8-bit register argument, to force access to the "sil" or "dil" +# registers (as opposed to "ah-dh"). rex_w = encode_rex, 0, (0x40 | REX_W), None # a REX.W prefix rex_nw = encode_rex, 0, 0, None # an optional REX prefix rex_fw = encode_rex, 0, 0x40, None # a forced REX prefix @@ -496,9 +503,9 @@ AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0') OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0') - OR8_mi = insn(rex_fw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), + OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), immediate(2, 'b')) - OR8_ji = insn(rex_fw, '\x80', orbyte(1<<3), abs_, immediate(1), + OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1), immediate(2, 'b')) NEG_r = insn(rex_w, '\xF7', register(1), '\xD8') @@ -531,7 +538,13 @@ PUSH_r = insn(rex_nw, register(1), '\x50') PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1)) + PUSH_i8 = insn('\x6A', immediate(1, 'b')) PUSH_i32 = insn('\x68', immediate(1, 'i')) + def PUSH_i(mc, immed): + if single_byte(immed): + mc.PUSH_i8(immed) + else: + mc.PUSH_i32(immed) POP_r = insn(rex_nw, register(1), '\x58') POP_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1)) diff --git a/pypy/jit/backend/x86/test/test_rx86.py b/pypy/jit/backend/x86/test/test_rx86.py --- a/pypy/jit/backend/x86/test/test_rx86.py +++ b/pypy/jit/backend/x86/test/test_rx86.py @@ -183,7 +183,8 @@ def test_push32(): cb = CodeBuilder32 - assert_encodes_as(cb, 'PUSH_i32', (9,), '\x68\x09\x00\x00\x00') + assert_encodes_as(cb, 'PUSH_i', (0x10009,), '\x68\x09\x00\x01\x00') + assert_encodes_as(cb, 'PUSH_i', (9,), '\x6A\x09') def test_sub_ji8(): cb = CodeBuilder32 diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py --- a/pypy/rpython/memory/gc/minimark.py +++ b/pypy/rpython/memory/gc/minimark.py @@ -111,10 +111,13 @@ # The following flag is set on externally raw_malloc'ed arrays of pointers. # They are allocated with some extra space in front of them for a bitfield, # one bit per 'card_page_indices' indices. -GCFLAG_HAS_CARDS = first_gcflag << 5 -GCFLAG_CARDS_SET = first_gcflag << 6 # <- at least one card bit is set +GCFLAG_HAS_CARDS = first_gcflag << 6 +GCFLAG_CARDS_SET = first_gcflag << 7 # <- at least one card bit is set +# note that GCFLAG_CARDS_SET is the most significant bit of a byte: +# this is required for the JIT (x86) -TID_MASK = (first_gcflag << 7) - 1 +#GCFLAG_UNUSED = first_gcflag << 5 # this flag is free +TID_MASK = (first_gcflag << 8) - 1 FORWARDSTUB = lltype.GcStruct('forwarding_stub', @@ -994,12 +997,9 @@ def _init_writebarrier_logic(self): DEBUG = self.DEBUG # The purpose of attaching remember_young_pointer to the instance - # instead of keeping it as a regular method is to help the JIT call it. - # Additionally, it makes the code in write_barrier() marginally smaller + # instead of keeping it as a regular method is to + # make the code in write_barrier() marginally smaller # (which is important because it is inlined *everywhere*). - # For x86, there is also an extra requirement: when the JIT calls - # remember_young_pointer(), it assumes that it will not touch the SSE - # registers, so it does not save and restore them (that's a *hack*!). def remember_young_pointer(addr_struct, newvalue): # 'addr_struct' is the address of the object in which we write. # 'newvalue' is the address that we are going to write in there. @@ -1033,6 +1033,17 @@ remember_young_pointer._dont_inline_ = True self.remember_young_pointer = remember_young_pointer # + def jit_remember_young_pointer(addr_struct): + # minimal version of the above, with just one argument, + # called by the JIT when GCFLAG_TRACK_YOUNG_PTRS is set + self.old_objects_pointing_to_young.append(addr_struct) + objhdr = self.header(addr_struct) + objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS + if objhdr.tid & GCFLAG_NO_HEAP_PTRS: + objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS + self.prebuilt_root_objects.append(addr_struct) + self.jit_remember_young_pointer = jit_remember_young_pointer + # if self.card_page_indices > 0: self._init_writebarrier_with_card_marker() @@ -1087,60 +1098,21 @@ self.remember_young_pointer_from_array2 = ( remember_young_pointer_from_array2) - # xxx trying it out for the JIT: a 3-arguments version of the above - def remember_young_pointer_from_array3(addr_array, index, newvalue): + def jit_remember_young_pointer_from_array(addr_array): + # minimal version of the above, with just one argument, + # called by the JIT when GCFLAG_TRACK_YOUNG_PTRS is set + # but GCFLAG_CARDS_SET is cleared. This tries to set + # GCFLAG_CARDS_SET if possible; otherwise, it falls back + # to jit_remember_young_pointer(). objhdr = self.header(addr_array) - # - # a single check for the common case of neither GCFLAG_HAS_CARDS - # nor GCFLAG_NO_HEAP_PTRS - if objhdr.tid & (GCFLAG_HAS_CARDS | GCFLAG_NO_HEAP_PTRS) == 0: - # common case: fast path, jump to the end of the function - pass - elif objhdr.tid & GCFLAG_HAS_CARDS == 0: - # no cards, but GCFLAG_NO_HEAP_PTRS is set. - objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.prebuilt_root_objects.append(addr_array) - # jump to the end of the function + if objhdr.tid & GCFLAG_HAS_CARDS: + self.old_objects_with_cards_set.append(addr_array) + objhdr.tid |= GCFLAG_CARDS_SET else: - # case with cards. - # - # If the newly written address does not actually point to a - # young object, leave now. - if not self.appears_to_be_young(newvalue): - return - # - # 'addr_array' is a raw_malloc'ed array with card markers - # in front. Compute the index of the bit to set: - bitindex = index >> self.card_page_shift - byteindex = bitindex >> 3 - bitmask = 1 << (bitindex & 7) - # - # If the bit is already set, leave now. - addr_byte = self.get_card(addr_array, byteindex) - byte = ord(addr_byte.char[0]) - if byte & bitmask: - return - addr_byte.char[0] = chr(byte | bitmask) - # - if objhdr.tid & GCFLAG_CARDS_SET == 0: - self.old_objects_with_cards_set.append(addr_array) - objhdr.tid |= GCFLAG_CARDS_SET - return - # - # Logic for the no-cards case, put here to minimize the number - # of checks done at the start of the function - if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this - ll_assert(self.debug_is_old_object(addr_array), - "young array with no card but GCFLAG_TRACK_YOUNG_PTRS") - # - if self.appears_to_be_young(newvalue): - self.old_objects_pointing_to_young.append(addr_array) - objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS + self.jit_remember_young_pointer(addr_array) - remember_young_pointer_from_array3._dont_inline_ = True - assert self.card_page_indices > 0 - self.remember_young_pointer_from_array3 = ( - remember_young_pointer_from_array3) + self.jit_remember_young_pointer_from_array = ( + jit_remember_young_pointer_from_array) def get_card(self, obj, byteindex): size_gc_header = self.gcheaderbuilder.size_gc_header diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py --- a/pypy/rpython/memory/gctransform/framework.py +++ b/pypy/rpython/memory/gctransform/framework.py @@ -455,13 +455,12 @@ annmodel.SomeAddress()], annmodel.s_None, inline=True) - func = getattr(gcdata.gc, 'remember_young_pointer', None) + func = getattr(gcdata.gc, 'jit_remember_young_pointer', None) if func is not None: # func should not be a bound method, but a real function assert isinstance(func, types.FunctionType) self.write_barrier_failing_case_ptr = getfn(func, - [annmodel.SomeAddress(), - annmodel.SomeAddress()], + [annmodel.SomeAddress()], annmodel.s_None) func = getattr(GCClass, 'write_barrier_from_array', None) if func is not None: @@ -472,16 +471,15 @@ annmodel.SomeInteger()], annmodel.s_None, inline=True) - func = getattr(gcdata.gc, 'remember_young_pointer_from_array3', + func = getattr(gcdata.gc, + 'jit_remember_young_pointer_from_array', None) if func is not None: # func should not be a bound method, but a real function assert isinstance(func, types.FunctionType) self.write_barrier_from_array_failing_case_ptr = \ getfn(func, - [annmodel.SomeAddress(), - annmodel.SomeInteger(), - annmodel.SomeAddress()], + [annmodel.SomeAddress()], annmodel.s_None) self.statistics_ptr = getfn(GCClass.statistics.im_func, [s_gc, annmodel.SomeInteger()], From noreply at buildbot.pypy.org Sun Jun 3 15:25:47 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 15:25:47 +0200 (CEST) Subject: [pypy-commit] pypy default: Document. Message-ID: <20120603132547.0DFA81C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55282:d568e4badf9c Date: 2012-06-03 15:25 +0200 http://bitbucket.org/pypy/pypy/changeset/d568e4badf9c/ Log: Document. diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst --- a/pypy/doc/whatsnew-1.9.rst +++ b/pypy/doc/whatsnew-1.9.rst @@ -16,6 +16,8 @@ .. branch: jit-frame-counter Put more debug info into resops. .. branch: kill-geninterp +Kill "geninterp", an old attempt to statically turn some fixed +app-level code to interp-level. .. branch: kqueue Finished select.kqueue. .. branch: kwargsdict-strategy From noreply at buildbot.pypy.org Sun Jun 3 15:31:13 2012 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 3 Jun 2012 15:31:13 +0200 (CEST) Subject: [pypy-commit] pypy default: document some branches Message-ID: <20120603133113.ACBBA1C0181@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r55283:b72d6f50dc2c Date: 2012-06-03 15:30 +0200 http://bitbucket.org/pypy/pypy/changeset/b72d6f50dc2c/ Log: document some branches diff --git a/pypy/bin/rpython b/pypy/bin/rpython old mode 100644 new mode 100755 diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst --- a/pypy/doc/whatsnew-1.9.rst +++ b/pypy/doc/whatsnew-1.9.rst @@ -31,13 +31,19 @@ cpyext: Better support for PyEval_SaveThread and other PyTreadState_* functions. .. branch: numppy-flatitter +flatitier for numpy .. branch: numpy-back-to-applevel +reuse more of original numpy .. branch: numpy-concatenate +concatenation support for numpy .. branch: numpy-indexing-by-arrays-bool +indexing by bool arrays .. branch: numpy-record-dtypes +record dtypes on numpy has been started .. branch: numpy-single-jitdriver .. branch: numpy-ufuncs2 .. branch: numpy-ufuncs3 +various refactorings regarding numpy .. branch: numpypy-issue1137 .. branch: numpypy-out The "out" argument was added to most of the numypypy functions. @@ -46,7 +52,11 @@ .. branch: pytest .. branch: safe-getargs-freelist .. branch: set-strategies +Sets now have strategies just like dictionaries. This means a set +containing only ints will be more compact (and faster) .. branch: speedup-list-comprehension +The simplest case of list comprehension is preallocating the correct size +of the list. This speeds up select benchmarks quite significantly. .. branch: stdlib-unification The directory "lib-python/modified-2.7" has been removed, and its content merged into "lib-python/2.7". @@ -68,6 +78,7 @@ Add os.kill to windows even if translating python does not have os.kill .. branch: win64-stage1 .. branch: zlib-mem-pressure +Memory "leaks" associated with zlib are fixed. .. branch: ffistruct The ``ffistruct`` branch adds a very low level way to express C structures From noreply at buildbot.pypy.org Sun Jun 3 16:10:43 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 16:10:43 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix the test on Linux. Message-ID: <20120603141043.4AEBF1C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55284:f94ef1d4068a Date: 2012-06-03 16:10 +0200 http://bitbucket.org/pypy/pypy/changeset/f94ef1d4068a/ Log: Fix the test on Linux. diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py --- a/pypy/module/_socket/test/test_sock_app.py +++ b/pypy/module/_socket/test/test_sock_app.py @@ -618,9 +618,12 @@ except timeout: pass t.recv(count) - # test sendall() timeout, be sure to send data larger than the - # socket buffer - raises(timeout, cli.sendall, 'foobar' * 7000) + # test sendall() timeout + try: + while 1: + cli.sendall('foobar' * 70) + except timeout: + pass # done cli.close() t.close() From noreply at buildbot.pypy.org Sun Jun 3 16:10:44 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 16:10:44 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20120603141044.734CD1C0181@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55285:7ab659fafde0 Date: 2012-06-03 16:10 +0200 http://bitbucket.org/pypy/pypy/changeset/7ab659fafde0/ Log: merge heads diff --git a/pypy/bin/rpython b/pypy/bin/rpython old mode 100644 new mode 100755 diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst --- a/pypy/doc/whatsnew-1.9.rst +++ b/pypy/doc/whatsnew-1.9.rst @@ -31,13 +31,19 @@ cpyext: Better support for PyEval_SaveThread and other PyTreadState_* functions. .. branch: numppy-flatitter +flatitier for numpy .. branch: numpy-back-to-applevel +reuse more of original numpy .. branch: numpy-concatenate +concatenation support for numpy .. branch: numpy-indexing-by-arrays-bool +indexing by bool arrays .. branch: numpy-record-dtypes +record dtypes on numpy has been started .. branch: numpy-single-jitdriver .. branch: numpy-ufuncs2 .. branch: numpy-ufuncs3 +various refactorings regarding numpy .. branch: numpypy-issue1137 .. branch: numpypy-out The "out" argument was added to most of the numypypy functions. @@ -46,7 +52,11 @@ .. branch: pytest .. branch: safe-getargs-freelist .. branch: set-strategies +Sets now have strategies just like dictionaries. This means a set +containing only ints will be more compact (and faster) .. branch: speedup-list-comprehension +The simplest case of list comprehension is preallocating the correct size +of the list. This speeds up select benchmarks quite significantly. .. branch: stdlib-unification The directory "lib-python/modified-2.7" has been removed, and its content merged into "lib-python/2.7". @@ -68,6 +78,7 @@ Add os.kill to windows even if translating python does not have os.kill .. branch: win64-stage1 .. branch: zlib-mem-pressure +Memory "leaks" associated with zlib are fixed. .. branch: ffistruct The ``ffistruct`` branch adds a very low level way to express C structures From noreply at buildbot.pypy.org Sun Jun 3 16:11:21 2012 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 3 Jun 2012 16:11:21 +0200 (CEST) Subject: [pypy-commit] pypy default: support item() on 1-d 1-elem arrays. I could not care less about the performance of this Message-ID: <20120603141121.82A8E1C0181@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r55286:244ef5a881e9 Date: 2012-06-03 16:10 +0200 http://bitbucket.org/pypy/pypy/changeset/244ef5a881e9/ Log: support item() on 1-d 1-elem arrays. I could not care less about the performance of this diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -692,9 +692,14 @@ def descr_item(self, space, w_arg=None): if space.is_w(w_arg, space.w_None): - if not isinstance(self, Scalar): - raise OperationError(space.w_ValueError, space.wrap("index out of bounds")) - return self.value.item(space) + if isinstance(self, Scalar): + return self.value.item(space) + if support.product(self.shape) == 1: + return self.descr_getitem(space, + space.newtuple([space.wrap(0) for i + in range(len(self.shape))])) + raise OperationError(space.w_ValueError, + space.wrap("index out of bounds")) if space.isinstance_w(w_arg, space.w_int): if isinstance(self, Scalar): raise OperationError(space.w_ValueError, space.wrap("index out of bounds")) diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1999,6 +1999,7 @@ assert a[::2].item(1) == 3 assert (a + a).item(1) == 4 raises(ValueError, "array(5).item(1)") + assert array([1]).item() == 1 class AppTestSupport(BaseNumpyAppTest): def setup_class(cls): From noreply at buildbot.pypy.org Sun Jun 3 16:11:22 2012 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 3 Jun 2012 16:11:22 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20120603141122.A02A31C0181@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r55287:2b960ad2d155 Date: 2012-06-03 16:11 +0200 http://bitbucket.org/pypy/pypy/changeset/2b960ad2d155/ Log: merge diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py --- a/pypy/module/_socket/test/test_sock_app.py +++ b/pypy/module/_socket/test/test_sock_app.py @@ -618,9 +618,12 @@ except timeout: pass t.recv(count) - # test sendall() timeout, be sure to send data larger than the - # socket buffer - raises(timeout, cli.sendall, 'foobar' * 7000) + # test sendall() timeout + try: + while 1: + cli.sendall('foobar' * 70) + except timeout: + pass # done cli.close() t.close() From noreply at buildbot.pypy.org Sun Jun 3 16:14:23 2012 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 3 Jun 2012 16:14:23 +0200 (CEST) Subject: [pypy-commit] pypy default: add a passing test Message-ID: <20120603141423.2CAF71C0181@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r55288:a740a48d05cc Date: 2012-06-03 16:13 +0200 http://bitbucket.org/pypy/pypy/changeset/a740a48d05cc/ Log: add a passing test diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1248,6 +1248,7 @@ a = arange(3*2*6).reshape((3,2,6)) b = arange(3*2*6)[::-1].reshape((2,6,3)) assert dot(a, b)[2,0,1,2] == 1140 + assert (dot([[1,2],[3,4]],[5,6]) == [17, 39]).all() def test_dot_constant(self): from _numpypy import array, dot From noreply at buildbot.pypy.org Sun Jun 3 16:38:04 2012 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 3 Jun 2012 16:38:04 +0200 (CEST) Subject: [pypy-commit] pypy default: unroll this loop Message-ID: <20120603143804.E19521C0181@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r55289:5cc6fbe1c322 Date: 2012-06-03 09:37 -0500 http://bitbucket.org/pypy/pypy/changeset/5cc6fbe1c322/ Log: unroll this loop diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -690,6 +690,7 @@ return self.getitem(offset).convert_to(longdtype).item( space) + @jit.unroll_safe def descr_item(self, space, w_arg=None): if space.is_w(w_arg, space.w_None): if isinstance(self, Scalar): From noreply at buildbot.pypy.org Sun Jun 3 16:55:58 2012 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 3 Jun 2012 16:55:58 +0200 (CEST) Subject: [pypy-commit] pypy default: Implmenet proper hash functions for the numpy types. Message-ID: <20120603145558.D5C3F1C0223@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r55290:0a3cae6d204d Date: 2012-06-03 09:55 -0500 http://bitbucket.org/pypy/pypy/changeset/0a3cae6d204d/ Log: Implmenet proper hash functions for the numpy types. diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -12,15 +12,18 @@ MIXIN_32 = (int_typedef,) if LONG_BIT == 32 else () MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else () + def new_dtype_getter(name): def _get_dtype(space): from pypy.module.micronumpy.interp_dtype import get_dtype_cache return getattr(get_dtype_cache(space), "w_%sdtype" % name) + def new(space, w_subtype, w_value): dtype = _get_dtype(space) return dtype.itemtype.coerce_subtype(space, w_subtype, w_value) return func_with_new_name(new, name + "_box_new"), staticmethod(_get_dtype) + class PrimitiveBox(object): _mixin_ = True @@ -30,6 +33,7 @@ def convert_to(self, dtype): return dtype.box(self.value) + class W_GenericBox(Wrappable): _attrs_ = () @@ -71,7 +75,7 @@ def _binop_right_impl(ufunc_name): def impl(self, space, w_other, w_out=None): from pypy.module.micronumpy import interp_ufuncs - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self, w_out]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name) @@ -132,6 +136,9 @@ w_remainder = self.descr_rmod(space, w_other) return space.newtuple([w_quotient, w_remainder]) + def descr_hash(self, space): + return space.hash(self.item(space)) + def item(self, space): return self.get_dtype(space).itemtype.to_builtin_type(space, self) @@ -315,6 +322,8 @@ __abs__ = interp2app(W_GenericBox.descr_abs), __invert__ = interp2app(W_GenericBox.descr_invert), + __hash__ = interp2app(W_GenericBox.descr_hash), + tolist = interp2app(W_GenericBox.item), ) @@ -440,4 +449,4 @@ __module__ = "numpypy", __new__ = interp2app(W_UnicodeBox.descr__new__unicode_box.im_func), ) - + diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -211,33 +211,23 @@ a = array(range(10), dtype=int64) b = array([0] * 10, dtype=int64) - for idx in b: a[idx] += 1 + for idx in b: + a[idx] += 1 - def test_hash_int8(self): - from _numpypy import int8 + def test_hash(self): + import _numpypy as numpy + for tp, value in [ + (numpy.int8, 4), + (numpy.int16, 5), + (numpy.uint32, 7), + (numpy.int64, 3), + (numpy.float32, 2.0), + (numpy.float64, 4.32), + ]: + assert hash(tp(value)) == hash(value) - hash(int8(0)) - d = {int8(5):99} - def test_hash_int16(self): - from _numpypy import int16 - - hash(int16(0)) - d = {int16(99):42} - - def test_hash_int32(self): - from _numpypy import int32 - - hash(int32(0)) - d = {int32(5):99} - - def test_hash_int64(self): - from _numpypy import int64 - - hash(int64(0)) - d = {int64(99):42} - -class AppTestTypes(BaseNumpyAppTest): +class AppTestTypes(BaseNumpyAppTest): def test_abstract_types(self): import _numpypy as numpy raises(TypeError, numpy.generic, 0) @@ -461,7 +451,7 @@ def test_various_types(self): import _numpypy as numpy import sys - + assert numpy.int16 is numpy.short assert numpy.int8 is numpy.byte assert numpy.bool_ is numpy.bool8 @@ -472,7 +462,7 @@ def test_mro(self): import _numpypy as numpy - + assert numpy.int16.__mro__ == (numpy.int16, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object) @@ -528,7 +518,7 @@ class AppTestStrUnicodeDtypes(BaseNumpyAppTest): def test_str_unicode(self): from _numpypy import str_, unicode_, character, flexible, generic - + assert str_.mro() == [str_, str, basestring, character, flexible, generic, object] assert unicode_.mro() == [unicode_, unicode, basestring, character, flexible, generic, object] @@ -588,7 +578,7 @@ from _numpypy import dtype d = dtype({'names': ['a', 'b', 'c'], }) - + class AppTestNotDirect(BaseNumpyAppTest): def setup_class(cls): BaseNumpyAppTest.setup_class.im_func(cls) diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -13,11 +13,13 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib import jit + VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True}) degToRad = math.pi / 180.0 log2 = math.log(2) -log2e = 1./log2 +log2e = 1. / log2 + def simple_unary_op(func): specialize.argtype(1)(func) @@ -66,7 +68,7 @@ class BaseType(object): _attrs_ = () - + def _unimplemented_ufunc(self, *args): raise NotImplementedError @@ -133,7 +135,7 @@ width, storage, i, offset, value) else: libffi.array_setitem_T(self.T, width, storage, i, offset, value) - + def store(self, arr, width, i, offset, box): self._write(arr.storage, width, i, offset, self.unbox(box)) @@ -242,7 +244,7 @@ class NonNativePrimitive(Primitive): _mixin_ = True - + def _read(self, storage, width, i, offset): if we_are_translated(): res = libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T), @@ -528,7 +530,7 @@ T = rffi.LONGLONG BoxType = interp_boxes.W_Int64Box - format_code = "q" + format_code = "q" _coerce = func_with_new_name(_int64_coerce, '_coerce') @@ -900,7 +902,7 @@ T = rffi.FLOAT BoxType = interp_boxes.W_Float32Box - format_code = "f" + format_code = "f" class Float64(BaseType, Float): _attrs_ = () @@ -918,7 +920,7 @@ class BaseStringType(object): _mixin_ = True - + def __init__(self, size=0): self.size = size @@ -949,14 +951,14 @@ def get_element_size(self): return self.size - + def read(self, arr, width, i, offset, dtype=None): if dtype is None: dtype = arr.dtype return interp_boxes.W_VoidBox(arr, i + offset, dtype) @jit.unroll_safe - def coerce(self, space, dtype, w_item): + def coerce(self, space, dtype, w_item): from pypy.module.micronumpy.interp_numarray import W_NDimArray if isinstance(w_item, interp_boxes.W_VoidBox): From noreply at buildbot.pypy.org Sun Jun 3 16:59:05 2012 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 3 Jun 2012 16:59:05 +0200 (CEST) Subject: [pypy-commit] pypy default: Remove the unused pypy.rlib.rsdl. Message-ID: <20120603145905.1AFC71C0223@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55291:9f2315814be4 Date: 2012-06-03 16:58 +0200 http://bitbucket.org/pypy/pypy/changeset/9f2315814be4/ Log: Remove the unused pypy.rlib.rsdl. diff --git a/pypy/rlib/rsdl/RIMG.py b/pypy/rlib/rsdl/RIMG.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RIMG.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_image.h'], - frameworks = ['SDL_image'], - include_dirs = ['/Library/Frameworks/SDL_image.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_image.h'], - libraries=['SDL_image'], - ) - -eci = eci.merge(RSDL.eci) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -Load = external('IMG_Load', [rffi.CCHARP], RSDL.SurfacePtr) diff --git a/pypy/rlib/rsdl/RMix.py b/pypy/rlib/rsdl/RMix.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix.py +++ /dev/null @@ -1,68 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_mixer.h'], - frameworks = ['SDL_mixer'], - include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_mixer.h'], - libraries=['SDL_mixer'], - ) - -eci = eci.merge(RSDL.eci) -eci = eci.merge(eci) -eci = eci.merge(eci) - -ChunkPtr = lltype.Ptr(lltype.ForwardReference()) - -class CConfig: - _compilation_info_ = eci - - Chunk = platform.Struct('Mix_Chunk', [('allocated', rffi.INT), - ('abuf', RSDL.Uint8P), - ('alen', RSDL.Uint32), - ('volume', RSDL.Uint8)]) - -globals().update(platform.configure(CConfig)) - -ChunkPtr.TO.become(Chunk) - - -Buffer = rffi.CArray(RSDL.Uint8) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -OpenAudio = external('Mix_OpenAudio', - [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], - rffi.INT) - -CloseAudio = external('Mix_CloseAudio', [], lltype.Void) - -LoadWAV_RW = external('Mix_LoadWAV_RW', - [RSDL.RWopsPtr, rffi.INT], - ChunkPtr) - -def LoadWAV(filename_ccharp): - with rffi.scoped_str2charp('rb') as mode: - return LoadWAV_RW(RSDL.RWFromFile(filename_ccharp, mode), 1) - - -PlayChannelTimed = external('Mix_PlayChannelTimed', - [rffi.INT, ChunkPtr, rffi.INT, rffi.INT], - rffi.INT) - -def PlayChannel(channel,chunk,loops): - return PlayChannelTimed(channel, chunk, loops, -1) - -"""Returns zero if the channel is not playing. -Otherwise if you passed in -1, the number of channels playing is returned""" -ChannelPlaying = external('Mix_Playing', [rffi.INT], rffi.INT) diff --git a/pypy/rlib/rsdl/RMix_helper.py b/pypy/rlib/rsdl/RMix_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix_helper.py +++ /dev/null @@ -1,24 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RMix, RSDL -from pypy.rpython.tool import rffi_platform as platform - - -def malloc_buffer_chunk(has_own_allocated_buffer, length_bytes, volume): - buffer_pointer = lltype.malloc(RMix.Buffer, length_bytes, flavor='raw') - return malloc_chunk(has_own_allocated_buffer, length_bytes, volume) - -def malloc_chunk(has_own_allocated_buffer, buffer_pointer, length_bytes, volume): - """ - Creates a new Mix_Chunk. - has_own_allocated_buffer: if 1 struct has its own allocated buffer, - if 0 abuf should not be freed - buffer_pointer: pointer to audio data - length_bytes: length of audio data in bytes - volume: Per-sample volume, 0-128 (normally - MIX_MAX_VOLUME after loading)""" - p = lltype.malloc(RMix.Chunk, flavor='raw') - rffi.setintfield(p, 'c_allocated', has_own_allocated_buffer) - rffi.setintfield(p, 'c_abuf', buffer_pointer) - rffi.setintfield(p, 'c_alen', length_bytes) - rffi.setintfield(p, 'c_volume', volume) - return p \ No newline at end of file diff --git a/pypy/rlib/rsdl/RSDL.py b/pypy/rlib/rsdl/RSDL.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL.py +++ /dev/null @@ -1,249 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.rlib.rsdl.constants import _constants -from pypy.rlib.rsdl.eci import get_rsdl_compilation_info -from pypy.rlib.objectmodel import we_are_translated -import py -import sys - -# ------------------------------------------------------------------------------ - -eci = get_rsdl_compilation_info() - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -# ------------------------------------------------------------------------------ - -RectPtr = lltype.Ptr(lltype.ForwardReference()) -SurfacePtr = lltype.Ptr(lltype.ForwardReference()) -PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) -EventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyPtr = lltype.Ptr(lltype.ForwardReference()) -RWopsPtr = lltype.Ptr(lltype.ForwardReference()) - -# ------------------------------------------------------------------------------ - -class CConfig: - _compilation_info_ = eci - - Uint8 = platform.SimpleType('Uint8', rffi.INT) - Uint16 = platform.SimpleType('Uint16', rffi.INT) - Sint16 = platform.SimpleType('Sint16', rffi.INT) - Uint32 = platform.SimpleType('Uint32', rffi.INT) - - Rect = platform.Struct('SDL_Rect', - [('x', rffi.INT), - ('y', rffi.INT), - ('w', rffi.INT), - ('h', rffi.INT)]) - - Surface = platform.Struct('SDL_Surface', - [('w', rffi.INT), - ('h', rffi.INT), - ('format', PixelFormatPtr), - ('pitch', rffi.INT), - ('pixels', rffi.UCHARP)]) - - PixelFormat = platform.Struct('SDL_PixelFormat', - [('BitsPerPixel', rffi.INT), - ('BytesPerPixel', rffi.INT), - ('Rmask', rffi.INT), - ('Gmask', rffi.INT), - ('Bmask', rffi.INT), - ('Amask', rffi.INT)]) - - Event = platform.Struct('SDL_Event', - [('type', rffi.INT)]) - - keysym = platform.Struct('SDL_keysym', - [('scancode', rffi.INT), - ('sym', rffi.INT), - ('mod', rffi.INT), - ('unicode', rffi.INT)]) - - KeyboardEvent = platform.Struct('SDL_KeyboardEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('keysym', keysym)]) - - MouseButtonEvent = platform.Struct('SDL_MouseButtonEvent', - [('type', rffi.INT), - ('button', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT)]) - - MouseMotionEvent = platform.Struct('SDL_MouseMotionEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT), - ('xrel', rffi.INT), - ('yrel', rffi.INT)]) - - QuitEvent = platform.Struct('SDL_QuitEvent', - [('type', rffi.INT)]) - - RWops = platform.Struct('SDL_RWops', []) - -# ------------------------------------------------------------------------------ - -for _prefix, _list in _constants.items(): - for _name in _list: - setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) - -# ------------------------------------------------------------------------------ - -globals().update(platform.configure(CConfig)) - -# ------------------------------------------------------------------------------ - -RectPtr.TO.become(Rect) -SurfacePtr.TO.become(Surface) -PixelFormatPtr.TO.become(PixelFormat) -EventPtr.TO.become(Event) -KeyboardEventPtr.TO.become(KeyboardEvent) -MouseButtonEventPtr.TO.become(MouseButtonEvent) -MouseMotionEventPtr.TO.become(MouseMotionEvent) -RWopsPtr.TO.become(RWops) - -# ------------------------------------------------------------------------------ - -Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) -Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) -# need to add signed hint here -Sint16P = lltype.Ptr(lltype.Array(Sint16, hints={'nolength': True})) -Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) - - -# ------------------------------------------------------------------------------ - -_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Mac_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Quit = external('SDL_Quit', [], - lltype.Void) - -SetVideoMode = external('SDL_SetVideoMode', - [rffi.INT, rffi.INT, rffi.INT, Uint32], - SurfacePtr) - -WM_SetCaption = external('SDL_WM_SetCaption', - [rffi.CCHARP, rffi.CCHARP], - lltype.Void) - -EnableUNICODE = external('SDL_EnableUNICODE', - [rffi.INT], - rffi.INT) - -WaitEvent = external('SDL_WaitEvent', - [EventPtr], - rffi.INT) - -PollEvent = external('SDL_PollEvent', - [EventPtr], - rffi.INT) - -Flip = external('SDL_Flip', - [SurfacePtr], - rffi.INT) - -CreateRGBSurface = external('SDL_CreateRGBSurface', - [Uint32, rffi.INT, rffi.INT, rffi.INT, - Uint32, Uint32, Uint32, Uint32], - SurfacePtr) - -LockSurface = external('SDL_LockSurface', - [SurfacePtr], - rffi.INT) - -UnlockSurface = external('SDL_UnlockSurface', - [SurfacePtr], - lltype.Void) - -FreeSurface = external('SDL_FreeSurface', - [SurfacePtr], - lltype.Void) - -MapRGB = external('SDL_MapRGB', - [PixelFormatPtr, Uint8, Uint8, Uint8], - Uint32) - -GetRGB = external('SDL_GetRGB', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], - lltype.Void) - -GetRGBA = external('SDL_GetRGBA', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, - Uint8P, Uint8P], - lltype.Void) - -FillRect = external('SDL_FillRect', - [SurfacePtr, RectPtr, Uint32], - rffi.INT) - -BlitSurface = external('SDL_UpperBlit', - [SurfacePtr, RectPtr, SurfacePtr, RectPtr], - rffi.INT) - -SetAlpha = external('SDL_SetAlpha', - [SurfacePtr, Uint32, Uint8], - rffi.INT) - -SetColorKey = external('SDL_SetColorKey', - [SurfacePtr, Uint32, Uint32], - rffi.INT) - -ShowCursor = external('SDL_ShowCursor', - [rffi.INT], - rffi.INT) - -GetTicks = external('SDL_GetTicks', - [], - Uint32) - -Delay = external('SDL_Delay', - [Uint32], - lltype.Void) - -UpdateRect = external('SDL_UpdateRect', - [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], - lltype.Void) - -GetKeyName = external('SDL_GetKeyName', - [rffi.INT], - rffi.CCHARP) - -GetError = external('SDL_GetError', - [], - rffi.CCHARP) - -RWFromFile = external('SDL_RWFromFile', - [rffi.CCHARP, rffi.CCHARP], - RWopsPtr) - -# ------------------------------------------------------------------------------ - - -if sys.platform == 'darwin': - def Init(flags): - if not we_are_translated(): - from AppKit import NSApplication - NSApplication.sharedApplication() - #CustomApplicationMain(0, " ") - return _Init(flags) - #Mac_Init() -else: - Init = _Init - - - diff --git a/pypy/rlib/rsdl/RSDL_helper.py b/pypy/rlib/rsdl/RSDL_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL_helper.py +++ /dev/null @@ -1,108 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RSDL - -def get_rgb(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - RSDL.GetRGB(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result = r, g, b - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_rgba(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 4, flavor='raw') - try: - RSDL.GetRGBA(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2), - rffi.ptradd(rgb, 3)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - a = rffi.cast(lltype.Signed, rgb[3]) - result = r, g, b, a - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_pixel(image, x, y): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 3: - p0 = rffi.cast(lltype.Signed, p[0]) - p1 = rffi.cast(lltype.Signed, p[1]) - p2 = rffi.cast(lltype.Signed, p[2]) - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - result = p0 << 16 | p1 << 8 | p2 - else: - result = p0 | p1 << 8 | p2 << 16 - return rffi.cast(RSDL.Uint32, result) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - return p[0] - else: - raise ValueError("bad BytesPerPixel") - -def set_pixel(image, x, y, pixel): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - p[0] = rffi.cast(rffi.UCHAR,pixel) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - p[0] = rffi.cast(RSDL.Uint16,pixel) - elif bpp == 3: - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - p[0] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - else: - p[0] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - p[0] = rffi.cast(RSDL.Uint32, pixel) - else: - raise ValueError("bad BytesPerPixel") - -def mallocrect(x, y, w, h): - p = lltype.malloc(RSDL.Rect, flavor='raw') - rffi.setintfield(p, 'c_x', x) - rffi.setintfield(p, 'c_y', y) - rffi.setintfield(p, 'c_w', w) - rffi.setintfield(p, 'c_h', h) - return p - -def blit_complete_surface(src, dst, x, y): - dstrect = mallocrect(x, y, rffi.getintfield(src, 'c_w'), rffi.getintfield(src, 'c_w')) - RSDL.BlitSurface(src, lltype.nullptr(RSDL.Rect), dst, dstrect) - lltype.free(dstrect, flavor='raw') - diff --git a/pypy/rlib/rsdl/__init__.py b/pypy/rlib/rsdl/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/constants.py b/pypy/rlib/rsdl/constants.py deleted file mode 100644 --- a/pypy/rlib/rsdl/constants.py +++ /dev/null @@ -1,261 +0,0 @@ - -_constants = { - 'SDL_': [ # constants with the 'SDL_' prefix in C - "YV12_OVERLAY", - "IYUV_OVERLAY", - "YUY2_OVERLAY", - "UYVY_OVERLAY", - "YVYU_OVERLAY", - - "SWSURFACE", - "HWSURFACE", - "RESIZABLE", - "ASYNCBLIT", - "OPENGL", - "OPENGLBLIT", - "ANYFORMAT", - "HWPALETTE", - "DOUBLEBUF", - "FULLSCREEN", - "HWACCEL", - "SRCCOLORKEY", - "RLEACCELOK", - "RLEACCEL", - "SRCALPHA", - "PREALLOC", - "NOFRAME", - - "GL_RED_SIZE", - "GL_GREEN_SIZE", - "GL_BLUE_SIZE", - "GL_ALPHA_SIZE", - "GL_BUFFER_SIZE", - "GL_DOUBLEBUFFER", - "GL_DEPTH_SIZE", - "GL_STENCIL_SIZE", - "GL_ACCUM_RED_SIZE", - "GL_ACCUM_GREEN_SIZE", - "GL_ACCUM_BLUE_SIZE", - "GL_ACCUM_ALPHA_SIZE", - "GL_STEREO", #if SDL_VERSION_ATLEAST(1, 2, 5) - "GL_MULTISAMPLEBUFFERS", #if SDL_VERSION_ATLEAST(1, 2, 6) - "GL_MULTISAMPLESAMPLES", #if SDL_VERSION_ATLEAST(1, 2, 6) - - "NOEVENT", - "ACTIVEEVENT", - "KEYDOWN", - "KEYUP", - "MOUSEMOTION", - "MOUSEBUTTONDOWN", - "MOUSEBUTTONUP", - "BUTTON_LEFT", - "BUTTON_MIDDLE", - "BUTTON_RIGHT", - "BUTTON_WHEELUP", - "BUTTON_WHEELDOWN", - "JOYAXISMOTION", - "JOYBALLMOTION", - "JOYHATMOTION", - "JOYBUTTONDOWN", - "JOYBUTTONUP", - "VIDEORESIZE", - "VIDEOEXPOSE", - "QUIT", - "SYSWMEVENT", - "USEREVENT", - "NUMEVENTS", - - "HAT_CENTERED", - "HAT_UP", - "HAT_RIGHTUP", - "HAT_RIGHT", - "HAT_RIGHTDOWN", - "HAT_DOWN", - "HAT_LEFTDOWN", - "HAT_LEFT", - "HAT_LEFTUP", - - "DISABLE", - "ENABLE", - - # the following ones are not exposed in Pygame - "INIT_VIDEO", - "BYTEORDER", - "BIG_ENDIAN", - "LIL_ENDIAN", - ], - - '': [ # constants with no prefix in C - "TIMER_RESOLUTION", - "AUDIO_U8", - "AUDIO_S8", - "AUDIO_U16LSB", - "AUDIO_S16LSB", - "AUDIO_U16MSB", - "AUDIO_S16MSB", - "AUDIO_U16", - "AUDIO_S16", - "AUDIO_U16SYS", - "AUDIO_S16SYS", - - "KMOD_NONE", - "KMOD_LSHIFT", - "KMOD_RSHIFT", - "KMOD_LCTRL", - "KMOD_RCTRL", - "KMOD_LALT", - "KMOD_RALT", - "KMOD_LMETA", - "KMOD_RMETA", - "KMOD_NUM", - "KMOD_CAPS", - "KMOD_MODE", - - "KMOD_CTRL", - "KMOD_SHIFT", - "KMOD_ALT", - "KMOD_META", - ], - - 'SDL': [ # constants with the 'SDL' prefix in C - "K_UNKNOWN", - "K_FIRST", - "K_BACKSPACE", - "K_TAB", - "K_CLEAR", - "K_RETURN", - "K_PAUSE", - "K_ESCAPE", - "K_SPACE", - "K_EXCLAIM", - "K_QUOTEDBL", - "K_HASH", - "K_DOLLAR", - "K_AMPERSAND", - "K_QUOTE", - "K_LEFTPAREN", - "K_RIGHTPAREN", - "K_ASTERISK", - "K_PLUS", - "K_COMMA", - "K_MINUS", - "K_PERIOD", - "K_SLASH", - "K_0", - "K_1", - "K_2", - "K_3", - "K_4", - "K_5", - "K_6", - "K_7", - "K_8", - "K_9", - "K_COLON", - "K_SEMICOLON", - "K_LESS", - "K_EQUALS", - "K_GREATER", - "K_QUESTION", - "K_AT", - "K_LEFTBRACKET", - "K_BACKSLASH", - "K_RIGHTBRACKET", - "K_CARET", - "K_UNDERSCORE", - "K_BACKQUOTE", - "K_a", - "K_b", - "K_c", - "K_d", - "K_e", - "K_f", - "K_g", - "K_h", - "K_i", - "K_j", - "K_k", - "K_l", - "K_m", - "K_n", - "K_o", - "K_p", - "K_q", - "K_r", - "K_s", - "K_t", - "K_u", - "K_v", - "K_w", - "K_x", - "K_y", - "K_z", - "K_DELETE", - - "K_KP0", - "K_KP1", - "K_KP2", - "K_KP3", - "K_KP4", - "K_KP5", - "K_KP6", - "K_KP7", - "K_KP8", - "K_KP9", - "K_KP_PERIOD", - "K_KP_DIVIDE", - "K_KP_MULTIPLY", - "K_KP_MINUS", - "K_KP_PLUS", - "K_KP_ENTER", - "K_KP_EQUALS", - "K_UP", - "K_DOWN", - "K_RIGHT", - "K_LEFT", - "K_INSERT", - "K_HOME", - "K_END", - "K_PAGEUP", - "K_PAGEDOWN", - "K_F1", - "K_F2", - "K_F3", - "K_F4", - "K_F5", - "K_F6", - "K_F7", - "K_F8", - "K_F9", - "K_F10", - "K_F11", - "K_F12", - "K_F13", - "K_F14", - "K_F15", - - "K_NUMLOCK", - "K_CAPSLOCK", - "K_SCROLLOCK", - "K_RSHIFT", - "K_LSHIFT", - "K_RCTRL", - "K_LCTRL", - "K_RALT", - "K_LALT", - "K_RMETA", - "K_LMETA", - "K_LSUPER", - "K_RSUPER", - "K_MODE", - - "K_HELP", - "K_PRINT", - "K_SYSREQ", - "K_BREAK", - "K_MENU", - "K_POWER", - "K_EURO", - "K_LAST", - ], - } diff --git a/pypy/rlib/rsdl/eci.py b/pypy/rlib/rsdl/eci.py deleted file mode 100644 --- a/pypy/rlib/rsdl/eci.py +++ /dev/null @@ -1,27 +0,0 @@ -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.translator.platform import CompilationError -import py -import sys - -def get_rsdl_compilation_info(): - if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL.h'], - include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], - link_files = [ - str(py.path.local(__file__).dirpath().join('macosx-sdl-main/SDLMain.m')), - ], - frameworks = ['SDL', 'Cocoa'] - ) - else: - eci = ExternalCompilationInfo( - includes=['SDL.h'], - ) - eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) - return eci - -def check_sdl_installation(): - from pypy.rpython.tool import rffi_platform as platform - platform.verify_eci(get_rsdl_compilation_info()) - -SDLNotInstalled = (ImportError, CompilationError) diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import - - at interface SDLMain : NSObject - at end diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m +++ /dev/null @@ -1,384 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import "SDL.h" -#import "SDLMain.h" -#import /* for MAXPATHLEN */ -#import - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ - at interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; - at end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ - at interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; - at end -#endif - - at interface SDLApplication : NSApplication - at end - - at implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} - at end - -/* The main class of the application, the application's delegate */ - at implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { - assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } - -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} - at end - - - at implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - - at end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/pypy/rlib/rsdl/test/__init__.py b/pypy/rlib/rsdl/test/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/test/applause.wav b/pypy/rlib/rsdl/test/applause.wav deleted file mode 100644 Binary file pypy/rlib/rsdl/test/applause.wav has changed diff --git a/pypy/rlib/rsdl/test/autopath.py b/pypy/rlib/rsdl/test/autopath.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/autopath.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -self cloning, automatic path configuration - -copy this into any subdirectory of pypy from which scripts need -to be run, typically all of the test subdirs. -The idea is that any such script simply issues - - import autopath - -and this will make sure that the parent directory containing "pypy" -is in sys.path. - -If you modify the master "autopath.py" version (in pypy/tool/autopath.py) -you can directly run it which will copy itself on all autopath.py files -it finds under the pypy root directory. - -This module always provides these attributes: - - pypydir pypy root directory path - this_dir directory where this autopath.py resides - -""" - -def __dirinfo(part): - """ return (partdir, this_dir) and insert parent of partdir - into sys.path. If the parent directories don't have the part - an EnvironmentError is raised.""" - - import sys, os - try: - head = this_dir = os.path.realpath(os.path.dirname(__file__)) - except NameError: - head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) - - error = None - while head: - partdir = head - head, tail = os.path.split(head) - if tail == part: - checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py') - if not os.path.exists(checkfile): - error = "Cannot find %r" % (os.path.normpath(checkfile),) - break - else: - error = "Cannot find the parent directory %r of the path %r" % ( - partdir, this_dir) - if not error: - # check for bogus end-of-line style (e.g. files checked out on - # Windows and moved to Unix) - f = open(__file__.replace('.pyc', '.py'), 'r') - data = f.read() - f.close() - if data.endswith('\r\n') or data.endswith('\r'): - error = ("Bad end-of-line style in the .py files. Typically " - "caused by a zip file or a checkout done on Windows and " - "moved to Unix or vice-versa.") - if error: - raise EnvironmentError("Invalid source tree - bogus checkout! " + - error) - - pypy_root = os.path.join(head, '') - try: - sys.path.remove(head) - except ValueError: - pass - sys.path.insert(0, head) - - munged = {} - for name, mod in sys.modules.items(): - if '.' in name: - continue - fn = getattr(mod, '__file__', None) - if not isinstance(fn, str): - continue - newname = os.path.splitext(os.path.basename(fn))[0] - if not newname.startswith(part + '.'): - continue - path = os.path.join(os.path.dirname(os.path.realpath(fn)), '') - if path.startswith(pypy_root) and newname != part: - modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep) - if newname != '__init__': - modpaths.append(newname) - modpath = '.'.join(modpaths) - if modpath not in sys.modules: - munged[modpath] = mod - - for name, mod in munged.iteritems(): - if name not in sys.modules: - sys.modules[name] = mod - if '.' in name: - prename = name[:name.rfind('.')] - postname = name[len(prename)+1:] - if prename not in sys.modules: - __import__(prename) - if not hasattr(sys.modules[prename], postname): - setattr(sys.modules[prename], postname, mod) - - return partdir, this_dir - -def __clone(): - """ clone master version of autopath.py into all subdirs """ - from os.path import join, walk - if not this_dir.endswith(join('pypy','tool')): - raise EnvironmentError("can only clone master version " - "'%s'" % join(pypydir, 'tool',_myname)) - - - def sync_walker(arg, dirname, fnames): - if _myname in fnames: - fn = join(dirname, _myname) - f = open(fn, 'rwb+') - try: - if f.read() == arg: - print "checkok", fn - else: - print "syncing", fn - f = open(fn, 'w') - f.write(arg) - finally: - f.close() - s = open(join(pypydir, 'tool', _myname), 'rb').read() - walk(pypydir, sync_walker, s) - -_myname = 'autopath.py' - -# set guaranteed attributes - -pypydir, this_dir = __dirinfo('pypy') - -if __name__ == '__main__': - __clone() diff --git a/pypy/rlib/rsdl/test/conftest.py b/pypy/rlib/rsdl/test/conftest.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -from pypy.rlib.rsdl.eci import check_sdl_installation, SDLNotInstalled -import py - -def pytest_ignore_collect(path): - try: - check_sdl_installation() - except SDLNotInstalled, e: - return True - else: - return False diff --git a/pypy/rlib/rsdl/test/demo.jpg b/pypy/rlib/rsdl/test/demo.jpg deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.jpg has changed diff --git a/pypy/rlib/rsdl/test/demo.png b/pypy/rlib/rsdl/test/demo.png deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.png has changed diff --git a/pypy/rlib/rsdl/test/test_basic.py b/pypy/rlib/rsdl/test/test_basic.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_basic.py +++ /dev/null @@ -1,37 +0,0 @@ -import py -from pypy.rlib.rsdl import RSDL -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import rffi - - -def test_sdl_init(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Quit() - -def test_surface_basic(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - assert surface - assert rffi.getintfield(surface, 'c_w') == 150 - assert rffi.getintfield(surface, 'c_h') == 50 - RSDL.FreeSurface(surface) - RSDL.Quit() - - -def test_get_keyname(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - assert RSDL.GetKeyName(RSDL.K_PLUS)[0] == '+' - assert RSDL.GetKeyName(RSDL.K_RIGHTPAREN)[0] == ')' - assert RSDL.GetKeyName(RSDL.K_z)[0] == 'z' - -def test_delay_getticks(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Delay(10) - i = RSDL.GetTicks() - assert i >= 10 - RSDL.Quit() - \ No newline at end of file diff --git a/pypy/rlib/rsdl/test/test_sdl_image.py b/pypy/rlib/rsdl/test/test_sdl_image.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_image.py +++ /dev/null @@ -1,50 +0,0 @@ -import py, os -import autopath -from pypy.rlib.rsdl import RSDL, RIMG, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - - -def test_load_image(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image, 'c_w') == 17 - assert rffi.getintfield(image, 'c_h') == 23 - RSDL.FreeSurface(image) - -def test_image_pixels(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image.c_format, 'c_BytesPerPixel') in (3, 4) - RSDL.LockSurface(image) - result = {} - try: - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - for y in range(23): - for x in range(y % 13, 17, 13): - color = RSDL_helper.get_pixel(image, x, y) - RSDL.GetRGB(color, - image.c_format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result[x, y] = r, g, b - finally: - lltype.free(rgb, flavor='raw') - finally: - RSDL.UnlockSurface(image) - RSDL.FreeSurface(image) - for x, y in result: - f = (x*17 + y*23) / float(17*17+23*23) - expected_r = int(255.0 * (1.0-f)) - expected_g = 0 - expected_b = int(255.0 * f) - r, g, b = result[x, y] - assert abs(r-expected_r) < 10 - assert abs(g-expected_g) < 10 - assert abs(b-expected_b) < 10 diff --git a/pypy/rlib/rsdl/test/test_sdl_mixer.py b/pypy/rlib/rsdl/test/test_sdl_mixer.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_mixer.py +++ /dev/null @@ -1,33 +0,0 @@ -import py -import os -import time -import autopath -from pypy.rlib.rsdl import RSDL, RMix, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - -def test_open_mixer(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - RMix.CloseAudio() - -def test_load_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.CloseAudio() - -def test_play_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - applause = RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.PlayChannel(-1, applause, -1) - time.sleep(1) - RMix.CloseAudio() - diff --git a/pypy/rlib/rsdl/test/test_surface.py b/pypy/rlib/rsdl/test/test_surface.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_surface.py +++ /dev/null @@ -1,75 +0,0 @@ -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi - -class TestSurface: - - def setup_method(self, meth): - self.dst_surf = RSDL.CreateRGBSurface(0, 300, 300, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - self.src_surf = RSDL.CreateRGBSurface(0, 50, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - fmt = self.src_surf.c_format - self.black = RSDL.MapRGB(fmt, 0, 0, 0) - self.red = RSDL.MapRGB(fmt, 255, 0, 0) - self.blue = RSDL.MapRGB(fmt, 0, 0, 255) - RSDL.FillRect(self.src_surf, lltype.nullptr(RSDL.Rect), self.red) - - def test_simple(self): - pass # only checks that creating the surfaces works - - def test_set_alpha(self): - # prepare - assert RSDL.SetAlpha(self.src_surf, RSDL.SRCALPHA, 128) == 0 - - # draw - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 10, 10) - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 20, 20) - - # check - for position, color in ( - (( 0, 0), ( 0,0,0)), # no rect - ((10,10), (127,0,0)), # one rect - ((20,20), (191,0,0)) # two overlapping rects - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert RSDL_helper.get_rgb(fetched_color, self.dst_surf.c_format) == color - - def test_set_color_key(self): - # prepare - fillrect = RSDL_helper.mallocrect(10, 10, 30, 30) - RSDL.FillRect(self.src_surf, fillrect, self.blue) - lltype.free(fillrect, flavor='raw') - assert RSDL.SetColorKey(self.src_surf, RSDL.SRCCOLORKEY, self.blue) == 0 - - # draw - RSDL_helper.blit_complete_surface(self.src_surf, self.dst_surf, 0, 0) - - # check - for position, color in ( - (( 0, 0), self.red), - ((10,10), self.black), - ((20,20), self.black), - ((40,40), self.red) - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert fetched_color == color - - def teardown_method(self, meth): - RSDL.FreeSurface(self.src_surf) - RSDL.FreeSurface(self.dst_surf) - RSDL.Quit() - diff --git a/pypy/rlib/rsdl/test/test_video.py b/pypy/rlib/rsdl/test/test_video.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_video.py +++ /dev/null @@ -1,241 +0,0 @@ - -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi -from pypy import conftest - -# -# This test file is skipped unless run with "py.test --view". -# If it is run as "py.test --view -s", then it interactively asks -# for confirmation that the window looks as expected. -# - - -class TestVideo: - - def setup_method(self, meth): - if not conftest.option.view: - py.test.skip("'--view' not specified, " - "skipping tests that open a window") - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - self.screen = RSDL.SetVideoMode(640, 480, 32, 0) - assert self.screen - self.is_interactive = sys.stdout.isatty() - - def check(self, msg): - if self.is_interactive: - print - answer = raw_input('Interactive test: %s - ok? [Y] ' % msg) - if answer and not answer.upper().startswith('Y'): - py.test.fail(msg) - else: - print msg - - def test_simple(self): - pass # only checks that opening and closing the window works - - def test_fillrect_full(self): - fmt = self.screen.c_format - for colorname, r, g, b in [('dark red', 128, 0, 0), - ('yellow', 255, 255, 0), - ('blue', 0, 0, 255)]: - color = RSDL.MapRGB(fmt, r, g, b) - RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) - RSDL.Flip(self.screen) - self.check("Screen filled with %s" % colorname) - - def test_caption(self): - RSDL.WM_SetCaption("Hello World!", "Hello World!") - self.check('The window caption is "Hello World!"') - - def test_keypresses(self): - if not self.is_interactive: - py.test.skip("interactive test only") - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window should be printed below." - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - char = rffi.getintfield(p.c_keysym, 'c_unicode') - if char != 0: - print 'Key:', unichr(char).encode('utf-8') - else: - print 'Some special key' - else: - print '(event of type %d)' % c_type - finally: - lltype.free(event, flavor='raw') - - def test_poll(self): - if not self.is_interactive: - py.test.skip("interactive test only") - import time, sys - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window give a dot." - print " Wait 3 seconds to quit." - timeout = time.time() + 3 - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - # busy polling - ok = RSDL.PollEvent(event) - ok = rffi.cast(lltype.Signed, ok) - assert ok >= 0 - if ok > 0: - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - sys.stderr.write('.') - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - timeout = time.time() + 3 - else: - if time.time() > timeout: - break - time.sleep(0.05) - finally: - lltype.free(event, flavor='raw') - - def test_mousemove(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Move the Mouse up and down:" - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor="raw") - directions = [False]*4 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, "c_type") - if c_type == RSDL.MOUSEMOTION: - m = rffi.cast(RSDL.MouseMotionEventPtr, event) - assert rffi.getintfield(m, "c_x") >= 0 - assert rffi.getintfield(m, "c_y") >= 0 - print rffi.getintfield(m, "c_xrel") - directions[0] |= rffi.getintfield(m, "c_xrel")>0 - directions[1] |= rffi.getintfield(m, "c_xrel")<0 - directions[2] |= rffi.getintfield(m, "c_yrel")>0 - directions[3] |= rffi.getintfield(m, "c_yrel")<0 - if False not in directions: - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print " test manually aborted" - py.test.fail(" mousemovement test aborted") - break - finally: - lltype.free(event, flavor='raw') - - - def test_mousebutton_wheel(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Press the given MouseButtons:" - print " Use Escape to pass tests." - - event_tests = [("left button", RSDL.BUTTON_LEFT), - ("middle button", RSDL.BUTTON_MIDDLE), - ("right button", RSDL.BUTTON_RIGHT), - ("scroll up", RSDL.BUTTON_WHEELUP), - ("scroll down", RSDL.BUTTON_WHEELDOWN)] - test_success = [] - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - for button_test in event_tests: - print " press %s:" % button_test[0] - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.MOUSEBUTTONDOWN: - pass - elif c_type == RSDL.MOUSEBUTTONUP: - b = rffi.cast(RSDL.MouseButtonEventPtr, event) - if rffi.getintfield(b, 'c_button') == button_test[1]: - test_success.append(True) - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - test_success.append(False) - print " manually aborted" - break - #break - if False in test_success: - py.test.fail("") - finally: - lltype.free(event, flavor='raw') - - - def test_show_hide_cursor(self): - RSDL.ShowCursor(RSDL.DISABLE) - self.check("Is the cursor hidden? ") - RSDL.ShowCursor(RSDL.ENABLE) - self.check("Is the cursor shown? ") - - def test_bit_pattern(self): - HEIGHT = WIDTH = 10 - fmt = self.screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(self.screen) - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = white - else: - c = black - RSDL_helper.set_pixel(self.screen, i, j, c) - RSDL.UnlockSurface(self.screen) - RSDL.Flip(self.screen) - self.check("Upper left corner 10x10 field with vertical black/white stripes") - - def test_blit_rect(self): - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - fmt = surface.c_format - color = RSDL.MapRGB(fmt, 255, 0, 0) - RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) - - paintrect = RSDL_helper.mallocrect(75, 0, 150, 50) - dstrect = lltype.malloc(RSDL.Rect, flavor='raw') - try: - color = RSDL.MapRGB(fmt, 255, 128, 0) - RSDL.FillRect(surface, paintrect, color) - - rffi.setintfield(dstrect, 'c_x', 10) - rffi.setintfield(dstrect, 'c_y', 10) - rffi.setintfield(dstrect, 'c_w', 150) - rffi.setintfield(dstrect, 'c_h', 50) - RSDL.BlitSurface(surface, lltype.nullptr(RSDL.Rect), self.screen, dstrect) - RSDL.Flip(self.screen) - finally: - lltype.free(dstrect, flavor='raw') - lltype.free(paintrect, flavor='raw') - RSDL.FreeSurface(surface) - self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border") - - def teardown_method(self, meth): - RSDL.Quit() - diff --git a/pypy/translator/goal/targetsimplevideo.py b/pypy/translator/goal/targetsimplevideo.py deleted file mode 100644 --- a/pypy/translator/goal/targetsimplevideo.py +++ /dev/null @@ -1,98 +0,0 @@ -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rpython.lltypesystem import rffi, lltype -import py - -WIDTH = 1000 -HEIGHT = 1000 - -def entry_point(argv=None): - RSDL.Init(RSDL.INIT_VIDEO) >= 0 - screen = RSDL.SetVideoMode(WIDTH, HEIGHT, 32, 0) - event = lltype.malloc(RSDL.Event, flavor='raw') - paintpattern = 0 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - paintpattern += 1 - update_screen(screen, paintpattern) - finally: - lltype.free(event, flavor='raw') - - return 0 - -# ----------------------------------------------------------------------------- - -def chess(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - if (i+j) % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def white(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, colb) - -def black(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, cola) - -def stripes_v(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def stripes_m(screen, cola, colb): - for j in xrange(WIDTH): - for i in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - - -# ----------------------------------------------------------------------------- - -pattern = [chess, white, black, stripes_v, stripes_m] -pl = len(pattern) -def update_screen(screen, paintpattern): - fmt = screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(screen) - pattern[paintpattern % pl](screen, black, white) - RSDL.UnlockSurface(screen) - RSDL.Flip(screen) - RSDL.Delay(10 ) - - -# ----------------------------------------------------------------------------- - -def target(*args): - return entry_point, None - -def test_target(): - entry_point() - -if __name__ == '__main__': - entry_point() - - From noreply at buildbot.pypy.org Tue Jun 5 09:57:28 2012 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Tue, 5 Jun 2012 09:57:28 +0200 (CEST) Subject: [pypy-commit] pypy default: Note for my previous commit. Message-ID: <20120605075728.6D31B1C003C@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r55292:8b94a3a2ae6f Date: 2012-06-03 10:04 -0500 http://bitbucket.org/pypy/pypy/changeset/8b94a3a2ae6f/ Log: Note for my previous commit. diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst --- a/pypy/doc/whatsnew-1.9.rst +++ b/pypy/doc/whatsnew-1.9.rst @@ -5,6 +5,9 @@ .. this is the revision just after the creation of the release-1.8.x branch .. startrev: a4261375b359 +.. branch: default +* Working hash function for numpy types. + .. branch: array_equal .. branch: better-jit-hooks-2 .. branch: faster-heapcache From noreply at buildbot.pypy.org Tue Jun 5 09:57:36 2012 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 5 Jun 2012 09:57:36 +0200 (CEST) Subject: [pypy-commit] pypy default: some more notes Message-ID: <20120605075736.D178C1C0196@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r55294:e1d620f5baaa Date: 2012-06-03 17:03 +0200 http://bitbucket.org/pypy/pypy/changeset/e1d620f5baaa/ Log: some more notes diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst --- a/pypy/doc/whatsnew-1.9.rst +++ b/pypy/doc/whatsnew-1.9.rst @@ -7,6 +7,7 @@ .. branch: array_equal .. branch: better-jit-hooks-2 +Improved jit hooks .. branch: faster-heapcache .. branch: faster-str-decode-escape .. branch: float-bytes @@ -21,6 +22,9 @@ .. branch: kqueue Finished select.kqueue. .. branch: kwargsdict-strategy +Special dictionary strategy for dealing with \*\*kwds. Now having a simple +proxy ``def f(*args, **kwds): return x(*args, **kwds`` should not make +any allocations at all. .. branch: matrixmath-dot numpypy can now handle matrix multiplication. .. branch: merge-2.7.2 @@ -51,6 +55,7 @@ .. branch: numpypy-ufuncs .. branch: pytest .. branch: safe-getargs-freelist +CPyext improvements. For example PyOpenSSL should now work .. branch: set-strategies Sets now have strategies just like dictionaries. This means a set containing only ints will be more compact (and faster) From noreply at buildbot.pypy.org Tue Jun 5 09:57:29 2012 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Tue, 5 Jun 2012 09:57:29 +0200 (CEST) Subject: [pypy-commit] pypy default: Merged default. Message-ID: <20120605075729.B06B51C00B2@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r55293:03aedf3370e0 Date: 2012-06-03 10:04 -0500 http://bitbucket.org/pypy/pypy/changeset/03aedf3370e0/ Log: Merged default. diff --git a/pypy/rlib/rsdl/RIMG.py b/pypy/rlib/rsdl/RIMG.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RIMG.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_image.h'], - frameworks = ['SDL_image'], - include_dirs = ['/Library/Frameworks/SDL_image.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_image.h'], - libraries=['SDL_image'], - ) - -eci = eci.merge(RSDL.eci) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -Load = external('IMG_Load', [rffi.CCHARP], RSDL.SurfacePtr) diff --git a/pypy/rlib/rsdl/RMix.py b/pypy/rlib/rsdl/RMix.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix.py +++ /dev/null @@ -1,68 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_mixer.h'], - frameworks = ['SDL_mixer'], - include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_mixer.h'], - libraries=['SDL_mixer'], - ) - -eci = eci.merge(RSDL.eci) -eci = eci.merge(eci) -eci = eci.merge(eci) - -ChunkPtr = lltype.Ptr(lltype.ForwardReference()) - -class CConfig: - _compilation_info_ = eci - - Chunk = platform.Struct('Mix_Chunk', [('allocated', rffi.INT), - ('abuf', RSDL.Uint8P), - ('alen', RSDL.Uint32), - ('volume', RSDL.Uint8)]) - -globals().update(platform.configure(CConfig)) - -ChunkPtr.TO.become(Chunk) - - -Buffer = rffi.CArray(RSDL.Uint8) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -OpenAudio = external('Mix_OpenAudio', - [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], - rffi.INT) - -CloseAudio = external('Mix_CloseAudio', [], lltype.Void) - -LoadWAV_RW = external('Mix_LoadWAV_RW', - [RSDL.RWopsPtr, rffi.INT], - ChunkPtr) - -def LoadWAV(filename_ccharp): - with rffi.scoped_str2charp('rb') as mode: - return LoadWAV_RW(RSDL.RWFromFile(filename_ccharp, mode), 1) - - -PlayChannelTimed = external('Mix_PlayChannelTimed', - [rffi.INT, ChunkPtr, rffi.INT, rffi.INT], - rffi.INT) - -def PlayChannel(channel,chunk,loops): - return PlayChannelTimed(channel, chunk, loops, -1) - -"""Returns zero if the channel is not playing. -Otherwise if you passed in -1, the number of channels playing is returned""" -ChannelPlaying = external('Mix_Playing', [rffi.INT], rffi.INT) diff --git a/pypy/rlib/rsdl/RMix_helper.py b/pypy/rlib/rsdl/RMix_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix_helper.py +++ /dev/null @@ -1,24 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RMix, RSDL -from pypy.rpython.tool import rffi_platform as platform - - -def malloc_buffer_chunk(has_own_allocated_buffer, length_bytes, volume): - buffer_pointer = lltype.malloc(RMix.Buffer, length_bytes, flavor='raw') - return malloc_chunk(has_own_allocated_buffer, length_bytes, volume) - -def malloc_chunk(has_own_allocated_buffer, buffer_pointer, length_bytes, volume): - """ - Creates a new Mix_Chunk. - has_own_allocated_buffer: if 1 struct has its own allocated buffer, - if 0 abuf should not be freed - buffer_pointer: pointer to audio data - length_bytes: length of audio data in bytes - volume: Per-sample volume, 0-128 (normally - MIX_MAX_VOLUME after loading)""" - p = lltype.malloc(RMix.Chunk, flavor='raw') - rffi.setintfield(p, 'c_allocated', has_own_allocated_buffer) - rffi.setintfield(p, 'c_abuf', buffer_pointer) - rffi.setintfield(p, 'c_alen', length_bytes) - rffi.setintfield(p, 'c_volume', volume) - return p \ No newline at end of file diff --git a/pypy/rlib/rsdl/RSDL.py b/pypy/rlib/rsdl/RSDL.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL.py +++ /dev/null @@ -1,249 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.rlib.rsdl.constants import _constants -from pypy.rlib.rsdl.eci import get_rsdl_compilation_info -from pypy.rlib.objectmodel import we_are_translated -import py -import sys - -# ------------------------------------------------------------------------------ - -eci = get_rsdl_compilation_info() - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -# ------------------------------------------------------------------------------ - -RectPtr = lltype.Ptr(lltype.ForwardReference()) -SurfacePtr = lltype.Ptr(lltype.ForwardReference()) -PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) -EventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyPtr = lltype.Ptr(lltype.ForwardReference()) -RWopsPtr = lltype.Ptr(lltype.ForwardReference()) - -# ------------------------------------------------------------------------------ - -class CConfig: - _compilation_info_ = eci - - Uint8 = platform.SimpleType('Uint8', rffi.INT) - Uint16 = platform.SimpleType('Uint16', rffi.INT) - Sint16 = platform.SimpleType('Sint16', rffi.INT) - Uint32 = platform.SimpleType('Uint32', rffi.INT) - - Rect = platform.Struct('SDL_Rect', - [('x', rffi.INT), - ('y', rffi.INT), - ('w', rffi.INT), - ('h', rffi.INT)]) - - Surface = platform.Struct('SDL_Surface', - [('w', rffi.INT), - ('h', rffi.INT), - ('format', PixelFormatPtr), - ('pitch', rffi.INT), - ('pixels', rffi.UCHARP)]) - - PixelFormat = platform.Struct('SDL_PixelFormat', - [('BitsPerPixel', rffi.INT), - ('BytesPerPixel', rffi.INT), - ('Rmask', rffi.INT), - ('Gmask', rffi.INT), - ('Bmask', rffi.INT), - ('Amask', rffi.INT)]) - - Event = platform.Struct('SDL_Event', - [('type', rffi.INT)]) - - keysym = platform.Struct('SDL_keysym', - [('scancode', rffi.INT), - ('sym', rffi.INT), - ('mod', rffi.INT), - ('unicode', rffi.INT)]) - - KeyboardEvent = platform.Struct('SDL_KeyboardEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('keysym', keysym)]) - - MouseButtonEvent = platform.Struct('SDL_MouseButtonEvent', - [('type', rffi.INT), - ('button', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT)]) - - MouseMotionEvent = platform.Struct('SDL_MouseMotionEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT), - ('xrel', rffi.INT), - ('yrel', rffi.INT)]) - - QuitEvent = platform.Struct('SDL_QuitEvent', - [('type', rffi.INT)]) - - RWops = platform.Struct('SDL_RWops', []) - -# ------------------------------------------------------------------------------ - -for _prefix, _list in _constants.items(): - for _name in _list: - setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) - -# ------------------------------------------------------------------------------ - -globals().update(platform.configure(CConfig)) - -# ------------------------------------------------------------------------------ - -RectPtr.TO.become(Rect) -SurfacePtr.TO.become(Surface) -PixelFormatPtr.TO.become(PixelFormat) -EventPtr.TO.become(Event) -KeyboardEventPtr.TO.become(KeyboardEvent) -MouseButtonEventPtr.TO.become(MouseButtonEvent) -MouseMotionEventPtr.TO.become(MouseMotionEvent) -RWopsPtr.TO.become(RWops) - -# ------------------------------------------------------------------------------ - -Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) -Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) -# need to add signed hint here -Sint16P = lltype.Ptr(lltype.Array(Sint16, hints={'nolength': True})) -Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) - - -# ------------------------------------------------------------------------------ - -_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Mac_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Quit = external('SDL_Quit', [], - lltype.Void) - -SetVideoMode = external('SDL_SetVideoMode', - [rffi.INT, rffi.INT, rffi.INT, Uint32], - SurfacePtr) - -WM_SetCaption = external('SDL_WM_SetCaption', - [rffi.CCHARP, rffi.CCHARP], - lltype.Void) - -EnableUNICODE = external('SDL_EnableUNICODE', - [rffi.INT], - rffi.INT) - -WaitEvent = external('SDL_WaitEvent', - [EventPtr], - rffi.INT) - -PollEvent = external('SDL_PollEvent', - [EventPtr], - rffi.INT) - -Flip = external('SDL_Flip', - [SurfacePtr], - rffi.INT) - -CreateRGBSurface = external('SDL_CreateRGBSurface', - [Uint32, rffi.INT, rffi.INT, rffi.INT, - Uint32, Uint32, Uint32, Uint32], - SurfacePtr) - -LockSurface = external('SDL_LockSurface', - [SurfacePtr], - rffi.INT) - -UnlockSurface = external('SDL_UnlockSurface', - [SurfacePtr], - lltype.Void) - -FreeSurface = external('SDL_FreeSurface', - [SurfacePtr], - lltype.Void) - -MapRGB = external('SDL_MapRGB', - [PixelFormatPtr, Uint8, Uint8, Uint8], - Uint32) - -GetRGB = external('SDL_GetRGB', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], - lltype.Void) - -GetRGBA = external('SDL_GetRGBA', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, - Uint8P, Uint8P], - lltype.Void) - -FillRect = external('SDL_FillRect', - [SurfacePtr, RectPtr, Uint32], - rffi.INT) - -BlitSurface = external('SDL_UpperBlit', - [SurfacePtr, RectPtr, SurfacePtr, RectPtr], - rffi.INT) - -SetAlpha = external('SDL_SetAlpha', - [SurfacePtr, Uint32, Uint8], - rffi.INT) - -SetColorKey = external('SDL_SetColorKey', - [SurfacePtr, Uint32, Uint32], - rffi.INT) - -ShowCursor = external('SDL_ShowCursor', - [rffi.INT], - rffi.INT) - -GetTicks = external('SDL_GetTicks', - [], - Uint32) - -Delay = external('SDL_Delay', - [Uint32], - lltype.Void) - -UpdateRect = external('SDL_UpdateRect', - [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], - lltype.Void) - -GetKeyName = external('SDL_GetKeyName', - [rffi.INT], - rffi.CCHARP) - -GetError = external('SDL_GetError', - [], - rffi.CCHARP) - -RWFromFile = external('SDL_RWFromFile', - [rffi.CCHARP, rffi.CCHARP], - RWopsPtr) - -# ------------------------------------------------------------------------------ - - -if sys.platform == 'darwin': - def Init(flags): - if not we_are_translated(): - from AppKit import NSApplication - NSApplication.sharedApplication() - #CustomApplicationMain(0, " ") - return _Init(flags) - #Mac_Init() -else: - Init = _Init - - - diff --git a/pypy/rlib/rsdl/RSDL_helper.py b/pypy/rlib/rsdl/RSDL_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL_helper.py +++ /dev/null @@ -1,108 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RSDL - -def get_rgb(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - RSDL.GetRGB(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result = r, g, b - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_rgba(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 4, flavor='raw') - try: - RSDL.GetRGBA(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2), - rffi.ptradd(rgb, 3)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - a = rffi.cast(lltype.Signed, rgb[3]) - result = r, g, b, a - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_pixel(image, x, y): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 3: - p0 = rffi.cast(lltype.Signed, p[0]) - p1 = rffi.cast(lltype.Signed, p[1]) - p2 = rffi.cast(lltype.Signed, p[2]) - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - result = p0 << 16 | p1 << 8 | p2 - else: - result = p0 | p1 << 8 | p2 << 16 - return rffi.cast(RSDL.Uint32, result) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - return p[0] - else: - raise ValueError("bad BytesPerPixel") - -def set_pixel(image, x, y, pixel): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - p[0] = rffi.cast(rffi.UCHAR,pixel) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - p[0] = rffi.cast(RSDL.Uint16,pixel) - elif bpp == 3: - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - p[0] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - else: - p[0] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - p[0] = rffi.cast(RSDL.Uint32, pixel) - else: - raise ValueError("bad BytesPerPixel") - -def mallocrect(x, y, w, h): - p = lltype.malloc(RSDL.Rect, flavor='raw') - rffi.setintfield(p, 'c_x', x) - rffi.setintfield(p, 'c_y', y) - rffi.setintfield(p, 'c_w', w) - rffi.setintfield(p, 'c_h', h) - return p - -def blit_complete_surface(src, dst, x, y): - dstrect = mallocrect(x, y, rffi.getintfield(src, 'c_w'), rffi.getintfield(src, 'c_w')) - RSDL.BlitSurface(src, lltype.nullptr(RSDL.Rect), dst, dstrect) - lltype.free(dstrect, flavor='raw') - diff --git a/pypy/rlib/rsdl/__init__.py b/pypy/rlib/rsdl/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/constants.py b/pypy/rlib/rsdl/constants.py deleted file mode 100644 --- a/pypy/rlib/rsdl/constants.py +++ /dev/null @@ -1,261 +0,0 @@ - -_constants = { - 'SDL_': [ # constants with the 'SDL_' prefix in C - "YV12_OVERLAY", - "IYUV_OVERLAY", - "YUY2_OVERLAY", - "UYVY_OVERLAY", - "YVYU_OVERLAY", - - "SWSURFACE", - "HWSURFACE", - "RESIZABLE", - "ASYNCBLIT", - "OPENGL", - "OPENGLBLIT", - "ANYFORMAT", - "HWPALETTE", - "DOUBLEBUF", - "FULLSCREEN", - "HWACCEL", - "SRCCOLORKEY", - "RLEACCELOK", - "RLEACCEL", - "SRCALPHA", - "PREALLOC", - "NOFRAME", - - "GL_RED_SIZE", - "GL_GREEN_SIZE", - "GL_BLUE_SIZE", - "GL_ALPHA_SIZE", - "GL_BUFFER_SIZE", - "GL_DOUBLEBUFFER", - "GL_DEPTH_SIZE", - "GL_STENCIL_SIZE", - "GL_ACCUM_RED_SIZE", - "GL_ACCUM_GREEN_SIZE", - "GL_ACCUM_BLUE_SIZE", - "GL_ACCUM_ALPHA_SIZE", - "GL_STEREO", #if SDL_VERSION_ATLEAST(1, 2, 5) - "GL_MULTISAMPLEBUFFERS", #if SDL_VERSION_ATLEAST(1, 2, 6) - "GL_MULTISAMPLESAMPLES", #if SDL_VERSION_ATLEAST(1, 2, 6) - - "NOEVENT", - "ACTIVEEVENT", - "KEYDOWN", - "KEYUP", - "MOUSEMOTION", - "MOUSEBUTTONDOWN", - "MOUSEBUTTONUP", - "BUTTON_LEFT", - "BUTTON_MIDDLE", - "BUTTON_RIGHT", - "BUTTON_WHEELUP", - "BUTTON_WHEELDOWN", - "JOYAXISMOTION", - "JOYBALLMOTION", - "JOYHATMOTION", - "JOYBUTTONDOWN", - "JOYBUTTONUP", - "VIDEORESIZE", - "VIDEOEXPOSE", - "QUIT", - "SYSWMEVENT", - "USEREVENT", - "NUMEVENTS", - - "HAT_CENTERED", - "HAT_UP", - "HAT_RIGHTUP", - "HAT_RIGHT", - "HAT_RIGHTDOWN", - "HAT_DOWN", - "HAT_LEFTDOWN", - "HAT_LEFT", - "HAT_LEFTUP", - - "DISABLE", - "ENABLE", - - # the following ones are not exposed in Pygame - "INIT_VIDEO", - "BYTEORDER", - "BIG_ENDIAN", - "LIL_ENDIAN", - ], - - '': [ # constants with no prefix in C - "TIMER_RESOLUTION", - "AUDIO_U8", - "AUDIO_S8", - "AUDIO_U16LSB", - "AUDIO_S16LSB", - "AUDIO_U16MSB", - "AUDIO_S16MSB", - "AUDIO_U16", - "AUDIO_S16", - "AUDIO_U16SYS", - "AUDIO_S16SYS", - - "KMOD_NONE", - "KMOD_LSHIFT", - "KMOD_RSHIFT", - "KMOD_LCTRL", - "KMOD_RCTRL", - "KMOD_LALT", - "KMOD_RALT", - "KMOD_LMETA", - "KMOD_RMETA", - "KMOD_NUM", - "KMOD_CAPS", - "KMOD_MODE", - - "KMOD_CTRL", - "KMOD_SHIFT", - "KMOD_ALT", - "KMOD_META", - ], - - 'SDL': [ # constants with the 'SDL' prefix in C - "K_UNKNOWN", - "K_FIRST", - "K_BACKSPACE", - "K_TAB", - "K_CLEAR", - "K_RETURN", - "K_PAUSE", - "K_ESCAPE", - "K_SPACE", - "K_EXCLAIM", - "K_QUOTEDBL", - "K_HASH", - "K_DOLLAR", - "K_AMPERSAND", - "K_QUOTE", - "K_LEFTPAREN", - "K_RIGHTPAREN", - "K_ASTERISK", - "K_PLUS", - "K_COMMA", - "K_MINUS", - "K_PERIOD", - "K_SLASH", - "K_0", - "K_1", - "K_2", - "K_3", - "K_4", - "K_5", - "K_6", - "K_7", - "K_8", - "K_9", - "K_COLON", - "K_SEMICOLON", - "K_LESS", - "K_EQUALS", - "K_GREATER", - "K_QUESTION", - "K_AT", - "K_LEFTBRACKET", - "K_BACKSLASH", - "K_RIGHTBRACKET", - "K_CARET", - "K_UNDERSCORE", - "K_BACKQUOTE", - "K_a", - "K_b", - "K_c", - "K_d", - "K_e", - "K_f", - "K_g", - "K_h", - "K_i", - "K_j", - "K_k", - "K_l", - "K_m", - "K_n", - "K_o", - "K_p", - "K_q", - "K_r", - "K_s", - "K_t", - "K_u", - "K_v", - "K_w", - "K_x", - "K_y", - "K_z", - "K_DELETE", - - "K_KP0", - "K_KP1", - "K_KP2", - "K_KP3", - "K_KP4", - "K_KP5", - "K_KP6", - "K_KP7", - "K_KP8", - "K_KP9", - "K_KP_PERIOD", - "K_KP_DIVIDE", - "K_KP_MULTIPLY", - "K_KP_MINUS", - "K_KP_PLUS", - "K_KP_ENTER", - "K_KP_EQUALS", - "K_UP", - "K_DOWN", - "K_RIGHT", - "K_LEFT", - "K_INSERT", - "K_HOME", - "K_END", - "K_PAGEUP", - "K_PAGEDOWN", - "K_F1", - "K_F2", - "K_F3", - "K_F4", - "K_F5", - "K_F6", - "K_F7", - "K_F8", - "K_F9", - "K_F10", - "K_F11", - "K_F12", - "K_F13", - "K_F14", - "K_F15", - - "K_NUMLOCK", - "K_CAPSLOCK", - "K_SCROLLOCK", - "K_RSHIFT", - "K_LSHIFT", - "K_RCTRL", - "K_LCTRL", - "K_RALT", - "K_LALT", - "K_RMETA", - "K_LMETA", - "K_LSUPER", - "K_RSUPER", - "K_MODE", - - "K_HELP", - "K_PRINT", - "K_SYSREQ", - "K_BREAK", - "K_MENU", - "K_POWER", - "K_EURO", - "K_LAST", - ], - } diff --git a/pypy/rlib/rsdl/eci.py b/pypy/rlib/rsdl/eci.py deleted file mode 100644 --- a/pypy/rlib/rsdl/eci.py +++ /dev/null @@ -1,27 +0,0 @@ -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.translator.platform import CompilationError -import py -import sys - -def get_rsdl_compilation_info(): - if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL.h'], - include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], - link_files = [ - str(py.path.local(__file__).dirpath().join('macosx-sdl-main/SDLMain.m')), - ], - frameworks = ['SDL', 'Cocoa'] - ) - else: - eci = ExternalCompilationInfo( - includes=['SDL.h'], - ) - eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) - return eci - -def check_sdl_installation(): - from pypy.rpython.tool import rffi_platform as platform - platform.verify_eci(get_rsdl_compilation_info()) - -SDLNotInstalled = (ImportError, CompilationError) diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import - - at interface SDLMain : NSObject - at end diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m +++ /dev/null @@ -1,384 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import "SDL.h" -#import "SDLMain.h" -#import /* for MAXPATHLEN */ -#import - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ - at interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; - at end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ - at interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; - at end -#endif - - at interface SDLApplication : NSApplication - at end - - at implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} - at end - -/* The main class of the application, the application's delegate */ - at implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { - assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } - -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} - at end - - - at implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - - at end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/pypy/rlib/rsdl/test/__init__.py b/pypy/rlib/rsdl/test/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/test/applause.wav b/pypy/rlib/rsdl/test/applause.wav deleted file mode 100644 Binary file pypy/rlib/rsdl/test/applause.wav has changed diff --git a/pypy/rlib/rsdl/test/autopath.py b/pypy/rlib/rsdl/test/autopath.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/autopath.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -self cloning, automatic path configuration - -copy this into any subdirectory of pypy from which scripts need -to be run, typically all of the test subdirs. -The idea is that any such script simply issues - - import autopath - -and this will make sure that the parent directory containing "pypy" -is in sys.path. - -If you modify the master "autopath.py" version (in pypy/tool/autopath.py) -you can directly run it which will copy itself on all autopath.py files -it finds under the pypy root directory. - -This module always provides these attributes: - - pypydir pypy root directory path - this_dir directory where this autopath.py resides - -""" - -def __dirinfo(part): - """ return (partdir, this_dir) and insert parent of partdir - into sys.path. If the parent directories don't have the part - an EnvironmentError is raised.""" - - import sys, os - try: - head = this_dir = os.path.realpath(os.path.dirname(__file__)) - except NameError: - head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) - - error = None - while head: - partdir = head - head, tail = os.path.split(head) - if tail == part: - checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py') - if not os.path.exists(checkfile): - error = "Cannot find %r" % (os.path.normpath(checkfile),) - break - else: - error = "Cannot find the parent directory %r of the path %r" % ( - partdir, this_dir) - if not error: - # check for bogus end-of-line style (e.g. files checked out on - # Windows and moved to Unix) - f = open(__file__.replace('.pyc', '.py'), 'r') - data = f.read() - f.close() - if data.endswith('\r\n') or data.endswith('\r'): - error = ("Bad end-of-line style in the .py files. Typically " - "caused by a zip file or a checkout done on Windows and " - "moved to Unix or vice-versa.") - if error: - raise EnvironmentError("Invalid source tree - bogus checkout! " + - error) - - pypy_root = os.path.join(head, '') - try: - sys.path.remove(head) - except ValueError: - pass - sys.path.insert(0, head) - - munged = {} - for name, mod in sys.modules.items(): - if '.' in name: - continue - fn = getattr(mod, '__file__', None) - if not isinstance(fn, str): - continue - newname = os.path.splitext(os.path.basename(fn))[0] - if not newname.startswith(part + '.'): - continue - path = os.path.join(os.path.dirname(os.path.realpath(fn)), '') - if path.startswith(pypy_root) and newname != part: - modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep) - if newname != '__init__': - modpaths.append(newname) - modpath = '.'.join(modpaths) - if modpath not in sys.modules: - munged[modpath] = mod - - for name, mod in munged.iteritems(): - if name not in sys.modules: - sys.modules[name] = mod - if '.' in name: - prename = name[:name.rfind('.')] - postname = name[len(prename)+1:] - if prename not in sys.modules: - __import__(prename) - if not hasattr(sys.modules[prename], postname): - setattr(sys.modules[prename], postname, mod) - - return partdir, this_dir - -def __clone(): - """ clone master version of autopath.py into all subdirs """ - from os.path import join, walk - if not this_dir.endswith(join('pypy','tool')): - raise EnvironmentError("can only clone master version " - "'%s'" % join(pypydir, 'tool',_myname)) - - - def sync_walker(arg, dirname, fnames): - if _myname in fnames: - fn = join(dirname, _myname) - f = open(fn, 'rwb+') - try: - if f.read() == arg: - print "checkok", fn - else: - print "syncing", fn - f = open(fn, 'w') - f.write(arg) - finally: - f.close() - s = open(join(pypydir, 'tool', _myname), 'rb').read() - walk(pypydir, sync_walker, s) - -_myname = 'autopath.py' - -# set guaranteed attributes - -pypydir, this_dir = __dirinfo('pypy') - -if __name__ == '__main__': - __clone() diff --git a/pypy/rlib/rsdl/test/conftest.py b/pypy/rlib/rsdl/test/conftest.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -from pypy.rlib.rsdl.eci import check_sdl_installation, SDLNotInstalled -import py - -def pytest_ignore_collect(path): - try: - check_sdl_installation() - except SDLNotInstalled, e: - return True - else: - return False diff --git a/pypy/rlib/rsdl/test/demo.jpg b/pypy/rlib/rsdl/test/demo.jpg deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.jpg has changed diff --git a/pypy/rlib/rsdl/test/demo.png b/pypy/rlib/rsdl/test/demo.png deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.png has changed diff --git a/pypy/rlib/rsdl/test/test_basic.py b/pypy/rlib/rsdl/test/test_basic.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_basic.py +++ /dev/null @@ -1,37 +0,0 @@ -import py -from pypy.rlib.rsdl import RSDL -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import rffi - - -def test_sdl_init(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Quit() - -def test_surface_basic(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - assert surface - assert rffi.getintfield(surface, 'c_w') == 150 - assert rffi.getintfield(surface, 'c_h') == 50 - RSDL.FreeSurface(surface) - RSDL.Quit() - - -def test_get_keyname(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - assert RSDL.GetKeyName(RSDL.K_PLUS)[0] == '+' - assert RSDL.GetKeyName(RSDL.K_RIGHTPAREN)[0] == ')' - assert RSDL.GetKeyName(RSDL.K_z)[0] == 'z' - -def test_delay_getticks(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Delay(10) - i = RSDL.GetTicks() - assert i >= 10 - RSDL.Quit() - \ No newline at end of file diff --git a/pypy/rlib/rsdl/test/test_sdl_image.py b/pypy/rlib/rsdl/test/test_sdl_image.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_image.py +++ /dev/null @@ -1,50 +0,0 @@ -import py, os -import autopath -from pypy.rlib.rsdl import RSDL, RIMG, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - - -def test_load_image(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image, 'c_w') == 17 - assert rffi.getintfield(image, 'c_h') == 23 - RSDL.FreeSurface(image) - -def test_image_pixels(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image.c_format, 'c_BytesPerPixel') in (3, 4) - RSDL.LockSurface(image) - result = {} - try: - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - for y in range(23): - for x in range(y % 13, 17, 13): - color = RSDL_helper.get_pixel(image, x, y) - RSDL.GetRGB(color, - image.c_format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result[x, y] = r, g, b - finally: - lltype.free(rgb, flavor='raw') - finally: - RSDL.UnlockSurface(image) - RSDL.FreeSurface(image) - for x, y in result: - f = (x*17 + y*23) / float(17*17+23*23) - expected_r = int(255.0 * (1.0-f)) - expected_g = 0 - expected_b = int(255.0 * f) - r, g, b = result[x, y] - assert abs(r-expected_r) < 10 - assert abs(g-expected_g) < 10 - assert abs(b-expected_b) < 10 diff --git a/pypy/rlib/rsdl/test/test_sdl_mixer.py b/pypy/rlib/rsdl/test/test_sdl_mixer.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_mixer.py +++ /dev/null @@ -1,33 +0,0 @@ -import py -import os -import time -import autopath -from pypy.rlib.rsdl import RSDL, RMix, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - -def test_open_mixer(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - RMix.CloseAudio() - -def test_load_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.CloseAudio() - -def test_play_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - applause = RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.PlayChannel(-1, applause, -1) - time.sleep(1) - RMix.CloseAudio() - diff --git a/pypy/rlib/rsdl/test/test_surface.py b/pypy/rlib/rsdl/test/test_surface.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_surface.py +++ /dev/null @@ -1,75 +0,0 @@ -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi - -class TestSurface: - - def setup_method(self, meth): - self.dst_surf = RSDL.CreateRGBSurface(0, 300, 300, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - self.src_surf = RSDL.CreateRGBSurface(0, 50, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - fmt = self.src_surf.c_format - self.black = RSDL.MapRGB(fmt, 0, 0, 0) - self.red = RSDL.MapRGB(fmt, 255, 0, 0) - self.blue = RSDL.MapRGB(fmt, 0, 0, 255) - RSDL.FillRect(self.src_surf, lltype.nullptr(RSDL.Rect), self.red) - - def test_simple(self): - pass # only checks that creating the surfaces works - - def test_set_alpha(self): - # prepare - assert RSDL.SetAlpha(self.src_surf, RSDL.SRCALPHA, 128) == 0 - - # draw - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 10, 10) - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 20, 20) - - # check - for position, color in ( - (( 0, 0), ( 0,0,0)), # no rect - ((10,10), (127,0,0)), # one rect - ((20,20), (191,0,0)) # two overlapping rects - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert RSDL_helper.get_rgb(fetched_color, self.dst_surf.c_format) == color - - def test_set_color_key(self): - # prepare - fillrect = RSDL_helper.mallocrect(10, 10, 30, 30) - RSDL.FillRect(self.src_surf, fillrect, self.blue) - lltype.free(fillrect, flavor='raw') - assert RSDL.SetColorKey(self.src_surf, RSDL.SRCCOLORKEY, self.blue) == 0 - - # draw - RSDL_helper.blit_complete_surface(self.src_surf, self.dst_surf, 0, 0) - - # check - for position, color in ( - (( 0, 0), self.red), - ((10,10), self.black), - ((20,20), self.black), - ((40,40), self.red) - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert fetched_color == color - - def teardown_method(self, meth): - RSDL.FreeSurface(self.src_surf) - RSDL.FreeSurface(self.dst_surf) - RSDL.Quit() - diff --git a/pypy/rlib/rsdl/test/test_video.py b/pypy/rlib/rsdl/test/test_video.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_video.py +++ /dev/null @@ -1,241 +0,0 @@ - -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi -from pypy import conftest - -# -# This test file is skipped unless run with "py.test --view". -# If it is run as "py.test --view -s", then it interactively asks -# for confirmation that the window looks as expected. -# - - -class TestVideo: - - def setup_method(self, meth): - if not conftest.option.view: - py.test.skip("'--view' not specified, " - "skipping tests that open a window") - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - self.screen = RSDL.SetVideoMode(640, 480, 32, 0) - assert self.screen - self.is_interactive = sys.stdout.isatty() - - def check(self, msg): - if self.is_interactive: - print - answer = raw_input('Interactive test: %s - ok? [Y] ' % msg) - if answer and not answer.upper().startswith('Y'): - py.test.fail(msg) - else: - print msg - - def test_simple(self): - pass # only checks that opening and closing the window works - - def test_fillrect_full(self): - fmt = self.screen.c_format - for colorname, r, g, b in [('dark red', 128, 0, 0), - ('yellow', 255, 255, 0), - ('blue', 0, 0, 255)]: - color = RSDL.MapRGB(fmt, r, g, b) - RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) - RSDL.Flip(self.screen) - self.check("Screen filled with %s" % colorname) - - def test_caption(self): - RSDL.WM_SetCaption("Hello World!", "Hello World!") - self.check('The window caption is "Hello World!"') - - def test_keypresses(self): - if not self.is_interactive: - py.test.skip("interactive test only") - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window should be printed below." - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - char = rffi.getintfield(p.c_keysym, 'c_unicode') - if char != 0: - print 'Key:', unichr(char).encode('utf-8') - else: - print 'Some special key' - else: - print '(event of type %d)' % c_type - finally: - lltype.free(event, flavor='raw') - - def test_poll(self): - if not self.is_interactive: - py.test.skip("interactive test only") - import time, sys - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window give a dot." - print " Wait 3 seconds to quit." - timeout = time.time() + 3 - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - # busy polling - ok = RSDL.PollEvent(event) - ok = rffi.cast(lltype.Signed, ok) - assert ok >= 0 - if ok > 0: - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - sys.stderr.write('.') - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - timeout = time.time() + 3 - else: - if time.time() > timeout: - break - time.sleep(0.05) - finally: - lltype.free(event, flavor='raw') - - def test_mousemove(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Move the Mouse up and down:" - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor="raw") - directions = [False]*4 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, "c_type") - if c_type == RSDL.MOUSEMOTION: - m = rffi.cast(RSDL.MouseMotionEventPtr, event) - assert rffi.getintfield(m, "c_x") >= 0 - assert rffi.getintfield(m, "c_y") >= 0 - print rffi.getintfield(m, "c_xrel") - directions[0] |= rffi.getintfield(m, "c_xrel")>0 - directions[1] |= rffi.getintfield(m, "c_xrel")<0 - directions[2] |= rffi.getintfield(m, "c_yrel")>0 - directions[3] |= rffi.getintfield(m, "c_yrel")<0 - if False not in directions: - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print " test manually aborted" - py.test.fail(" mousemovement test aborted") - break - finally: - lltype.free(event, flavor='raw') - - - def test_mousebutton_wheel(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Press the given MouseButtons:" - print " Use Escape to pass tests." - - event_tests = [("left button", RSDL.BUTTON_LEFT), - ("middle button", RSDL.BUTTON_MIDDLE), - ("right button", RSDL.BUTTON_RIGHT), - ("scroll up", RSDL.BUTTON_WHEELUP), - ("scroll down", RSDL.BUTTON_WHEELDOWN)] - test_success = [] - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - for button_test in event_tests: - print " press %s:" % button_test[0] - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.MOUSEBUTTONDOWN: - pass - elif c_type == RSDL.MOUSEBUTTONUP: - b = rffi.cast(RSDL.MouseButtonEventPtr, event) - if rffi.getintfield(b, 'c_button') == button_test[1]: - test_success.append(True) - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - test_success.append(False) - print " manually aborted" - break - #break - if False in test_success: - py.test.fail("") - finally: - lltype.free(event, flavor='raw') - - - def test_show_hide_cursor(self): - RSDL.ShowCursor(RSDL.DISABLE) - self.check("Is the cursor hidden? ") - RSDL.ShowCursor(RSDL.ENABLE) - self.check("Is the cursor shown? ") - - def test_bit_pattern(self): - HEIGHT = WIDTH = 10 - fmt = self.screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(self.screen) - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = white - else: - c = black - RSDL_helper.set_pixel(self.screen, i, j, c) - RSDL.UnlockSurface(self.screen) - RSDL.Flip(self.screen) - self.check("Upper left corner 10x10 field with vertical black/white stripes") - - def test_blit_rect(self): - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - fmt = surface.c_format - color = RSDL.MapRGB(fmt, 255, 0, 0) - RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) - - paintrect = RSDL_helper.mallocrect(75, 0, 150, 50) - dstrect = lltype.malloc(RSDL.Rect, flavor='raw') - try: - color = RSDL.MapRGB(fmt, 255, 128, 0) - RSDL.FillRect(surface, paintrect, color) - - rffi.setintfield(dstrect, 'c_x', 10) - rffi.setintfield(dstrect, 'c_y', 10) - rffi.setintfield(dstrect, 'c_w', 150) - rffi.setintfield(dstrect, 'c_h', 50) - RSDL.BlitSurface(surface, lltype.nullptr(RSDL.Rect), self.screen, dstrect) - RSDL.Flip(self.screen) - finally: - lltype.free(dstrect, flavor='raw') - lltype.free(paintrect, flavor='raw') - RSDL.FreeSurface(surface) - self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border") - - def teardown_method(self, meth): - RSDL.Quit() - diff --git a/pypy/translator/goal/targetsimplevideo.py b/pypy/translator/goal/targetsimplevideo.py deleted file mode 100644 --- a/pypy/translator/goal/targetsimplevideo.py +++ /dev/null @@ -1,98 +0,0 @@ -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rpython.lltypesystem import rffi, lltype -import py - -WIDTH = 1000 -HEIGHT = 1000 - -def entry_point(argv=None): - RSDL.Init(RSDL.INIT_VIDEO) >= 0 - screen = RSDL.SetVideoMode(WIDTH, HEIGHT, 32, 0) - event = lltype.malloc(RSDL.Event, flavor='raw') - paintpattern = 0 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - paintpattern += 1 - update_screen(screen, paintpattern) - finally: - lltype.free(event, flavor='raw') - - return 0 - -# ----------------------------------------------------------------------------- - -def chess(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - if (i+j) % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def white(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, colb) - -def black(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, cola) - -def stripes_v(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def stripes_m(screen, cola, colb): - for j in xrange(WIDTH): - for i in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - - -# ----------------------------------------------------------------------------- - -pattern = [chess, white, black, stripes_v, stripes_m] -pl = len(pattern) -def update_screen(screen, paintpattern): - fmt = screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(screen) - pattern[paintpattern % pl](screen, black, white) - RSDL.UnlockSurface(screen) - RSDL.Flip(screen) - RSDL.Delay(10 ) - - -# ----------------------------------------------------------------------------- - -def target(*args): - return entry_point, None - -def test_target(): - entry_point() - -if __name__ == '__main__': - entry_point() - - From noreply at buildbot.pypy.org Tue Jun 5 09:57:38 2012 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 5 Jun 2012 09:57:38 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20120605075738.1963B1C003C@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r55295:4493578f29bb Date: 2012-06-03 17:08 +0200 http://bitbucket.org/pypy/pypy/changeset/4493578f29bb/ Log: merge diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -12,15 +12,18 @@ MIXIN_32 = (int_typedef,) if LONG_BIT == 32 else () MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else () + def new_dtype_getter(name): def _get_dtype(space): from pypy.module.micronumpy.interp_dtype import get_dtype_cache return getattr(get_dtype_cache(space), "w_%sdtype" % name) + def new(space, w_subtype, w_value): dtype = _get_dtype(space) return dtype.itemtype.coerce_subtype(space, w_subtype, w_value) return func_with_new_name(new, name + "_box_new"), staticmethod(_get_dtype) + class PrimitiveBox(object): _mixin_ = True @@ -30,6 +33,7 @@ def convert_to(self, dtype): return dtype.box(self.value) + class W_GenericBox(Wrappable): _attrs_ = () @@ -71,7 +75,7 @@ def _binop_right_impl(ufunc_name): def impl(self, space, w_other, w_out=None): from pypy.module.micronumpy import interp_ufuncs - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self, w_out]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name) @@ -132,6 +136,9 @@ w_remainder = self.descr_rmod(space, w_other) return space.newtuple([w_quotient, w_remainder]) + def descr_hash(self, space): + return space.hash(self.item(space)) + def item(self, space): return self.get_dtype(space).itemtype.to_builtin_type(space, self) @@ -315,6 +322,8 @@ __abs__ = interp2app(W_GenericBox.descr_abs), __invert__ = interp2app(W_GenericBox.descr_invert), + __hash__ = interp2app(W_GenericBox.descr_hash), + tolist = interp2app(W_GenericBox.item), ) @@ -440,4 +449,4 @@ __module__ = "numpypy", __new__ = interp2app(W_UnicodeBox.descr__new__unicode_box.im_func), ) - + diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -690,6 +690,7 @@ return self.getitem(offset).convert_to(longdtype).item( space) + @jit.unroll_safe def descr_item(self, space, w_arg=None): if space.is_w(w_arg, space.w_None): if isinstance(self, Scalar): diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -211,33 +211,23 @@ a = array(range(10), dtype=int64) b = array([0] * 10, dtype=int64) - for idx in b: a[idx] += 1 + for idx in b: + a[idx] += 1 - def test_hash_int8(self): - from _numpypy import int8 + def test_hash(self): + import _numpypy as numpy + for tp, value in [ + (numpy.int8, 4), + (numpy.int16, 5), + (numpy.uint32, 7), + (numpy.int64, 3), + (numpy.float32, 2.0), + (numpy.float64, 4.32), + ]: + assert hash(tp(value)) == hash(value) - hash(int8(0)) - d = {int8(5):99} - def test_hash_int16(self): - from _numpypy import int16 - - hash(int16(0)) - d = {int16(99):42} - - def test_hash_int32(self): - from _numpypy import int32 - - hash(int32(0)) - d = {int32(5):99} - - def test_hash_int64(self): - from _numpypy import int64 - - hash(int64(0)) - d = {int64(99):42} - -class AppTestTypes(BaseNumpyAppTest): +class AppTestTypes(BaseNumpyAppTest): def test_abstract_types(self): import _numpypy as numpy raises(TypeError, numpy.generic, 0) @@ -461,7 +451,7 @@ def test_various_types(self): import _numpypy as numpy import sys - + assert numpy.int16 is numpy.short assert numpy.int8 is numpy.byte assert numpy.bool_ is numpy.bool8 @@ -472,7 +462,7 @@ def test_mro(self): import _numpypy as numpy - + assert numpy.int16.__mro__ == (numpy.int16, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object) @@ -528,7 +518,7 @@ class AppTestStrUnicodeDtypes(BaseNumpyAppTest): def test_str_unicode(self): from _numpypy import str_, unicode_, character, flexible, generic - + assert str_.mro() == [str_, str, basestring, character, flexible, generic, object] assert unicode_.mro() == [unicode_, unicode, basestring, character, flexible, generic, object] @@ -588,7 +578,7 @@ from _numpypy import dtype d = dtype({'names': ['a', 'b', 'c'], }) - + class AppTestNotDirect(BaseNumpyAppTest): def setup_class(cls): BaseNumpyAppTest.setup_class.im_func(cls) diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -13,11 +13,13 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib import jit + VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True}) degToRad = math.pi / 180.0 log2 = math.log(2) -log2e = 1./log2 +log2e = 1. / log2 + def simple_unary_op(func): specialize.argtype(1)(func) @@ -66,7 +68,7 @@ class BaseType(object): _attrs_ = () - + def _unimplemented_ufunc(self, *args): raise NotImplementedError @@ -133,7 +135,7 @@ width, storage, i, offset, value) else: libffi.array_setitem_T(self.T, width, storage, i, offset, value) - + def store(self, arr, width, i, offset, box): self._write(arr.storage, width, i, offset, self.unbox(box)) @@ -242,7 +244,7 @@ class NonNativePrimitive(Primitive): _mixin_ = True - + def _read(self, storage, width, i, offset): if we_are_translated(): res = libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T), @@ -528,7 +530,7 @@ T = rffi.LONGLONG BoxType = interp_boxes.W_Int64Box - format_code = "q" + format_code = "q" _coerce = func_with_new_name(_int64_coerce, '_coerce') @@ -900,7 +902,7 @@ T = rffi.FLOAT BoxType = interp_boxes.W_Float32Box - format_code = "f" + format_code = "f" class Float64(BaseType, Float): _attrs_ = () @@ -918,7 +920,7 @@ class BaseStringType(object): _mixin_ = True - + def __init__(self, size=0): self.size = size @@ -949,14 +951,14 @@ def get_element_size(self): return self.size - + def read(self, arr, width, i, offset, dtype=None): if dtype is None: dtype = arr.dtype return interp_boxes.W_VoidBox(arr, i + offset, dtype) @jit.unroll_safe - def coerce(self, space, dtype, w_item): + def coerce(self, space, dtype, w_item): from pypy.module.micronumpy.interp_numarray import W_NDimArray if isinstance(w_item, interp_boxes.W_VoidBox): diff --git a/pypy/rlib/rsdl/RIMG.py b/pypy/rlib/rsdl/RIMG.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RIMG.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_image.h'], - frameworks = ['SDL_image'], - include_dirs = ['/Library/Frameworks/SDL_image.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_image.h'], - libraries=['SDL_image'], - ) - -eci = eci.merge(RSDL.eci) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -Load = external('IMG_Load', [rffi.CCHARP], RSDL.SurfacePtr) diff --git a/pypy/rlib/rsdl/RMix.py b/pypy/rlib/rsdl/RMix.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix.py +++ /dev/null @@ -1,68 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_mixer.h'], - frameworks = ['SDL_mixer'], - include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_mixer.h'], - libraries=['SDL_mixer'], - ) - -eci = eci.merge(RSDL.eci) -eci = eci.merge(eci) -eci = eci.merge(eci) - -ChunkPtr = lltype.Ptr(lltype.ForwardReference()) - -class CConfig: - _compilation_info_ = eci - - Chunk = platform.Struct('Mix_Chunk', [('allocated', rffi.INT), - ('abuf', RSDL.Uint8P), - ('alen', RSDL.Uint32), - ('volume', RSDL.Uint8)]) - -globals().update(platform.configure(CConfig)) - -ChunkPtr.TO.become(Chunk) - - -Buffer = rffi.CArray(RSDL.Uint8) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -OpenAudio = external('Mix_OpenAudio', - [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], - rffi.INT) - -CloseAudio = external('Mix_CloseAudio', [], lltype.Void) - -LoadWAV_RW = external('Mix_LoadWAV_RW', - [RSDL.RWopsPtr, rffi.INT], - ChunkPtr) - -def LoadWAV(filename_ccharp): - with rffi.scoped_str2charp('rb') as mode: - return LoadWAV_RW(RSDL.RWFromFile(filename_ccharp, mode), 1) - - -PlayChannelTimed = external('Mix_PlayChannelTimed', - [rffi.INT, ChunkPtr, rffi.INT, rffi.INT], - rffi.INT) - -def PlayChannel(channel,chunk,loops): - return PlayChannelTimed(channel, chunk, loops, -1) - -"""Returns zero if the channel is not playing. -Otherwise if you passed in -1, the number of channels playing is returned""" -ChannelPlaying = external('Mix_Playing', [rffi.INT], rffi.INT) diff --git a/pypy/rlib/rsdl/RMix_helper.py b/pypy/rlib/rsdl/RMix_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix_helper.py +++ /dev/null @@ -1,24 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RMix, RSDL -from pypy.rpython.tool import rffi_platform as platform - - -def malloc_buffer_chunk(has_own_allocated_buffer, length_bytes, volume): - buffer_pointer = lltype.malloc(RMix.Buffer, length_bytes, flavor='raw') - return malloc_chunk(has_own_allocated_buffer, length_bytes, volume) - -def malloc_chunk(has_own_allocated_buffer, buffer_pointer, length_bytes, volume): - """ - Creates a new Mix_Chunk. - has_own_allocated_buffer: if 1 struct has its own allocated buffer, - if 0 abuf should not be freed - buffer_pointer: pointer to audio data - length_bytes: length of audio data in bytes - volume: Per-sample volume, 0-128 (normally - MIX_MAX_VOLUME after loading)""" - p = lltype.malloc(RMix.Chunk, flavor='raw') - rffi.setintfield(p, 'c_allocated', has_own_allocated_buffer) - rffi.setintfield(p, 'c_abuf', buffer_pointer) - rffi.setintfield(p, 'c_alen', length_bytes) - rffi.setintfield(p, 'c_volume', volume) - return p \ No newline at end of file diff --git a/pypy/rlib/rsdl/RSDL.py b/pypy/rlib/rsdl/RSDL.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL.py +++ /dev/null @@ -1,249 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.rlib.rsdl.constants import _constants -from pypy.rlib.rsdl.eci import get_rsdl_compilation_info -from pypy.rlib.objectmodel import we_are_translated -import py -import sys - -# ------------------------------------------------------------------------------ - -eci = get_rsdl_compilation_info() - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -# ------------------------------------------------------------------------------ - -RectPtr = lltype.Ptr(lltype.ForwardReference()) -SurfacePtr = lltype.Ptr(lltype.ForwardReference()) -PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) -EventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyPtr = lltype.Ptr(lltype.ForwardReference()) -RWopsPtr = lltype.Ptr(lltype.ForwardReference()) - -# ------------------------------------------------------------------------------ - -class CConfig: - _compilation_info_ = eci - - Uint8 = platform.SimpleType('Uint8', rffi.INT) - Uint16 = platform.SimpleType('Uint16', rffi.INT) - Sint16 = platform.SimpleType('Sint16', rffi.INT) - Uint32 = platform.SimpleType('Uint32', rffi.INT) - - Rect = platform.Struct('SDL_Rect', - [('x', rffi.INT), - ('y', rffi.INT), - ('w', rffi.INT), - ('h', rffi.INT)]) - - Surface = platform.Struct('SDL_Surface', - [('w', rffi.INT), - ('h', rffi.INT), - ('format', PixelFormatPtr), - ('pitch', rffi.INT), - ('pixels', rffi.UCHARP)]) - - PixelFormat = platform.Struct('SDL_PixelFormat', - [('BitsPerPixel', rffi.INT), - ('BytesPerPixel', rffi.INT), - ('Rmask', rffi.INT), - ('Gmask', rffi.INT), - ('Bmask', rffi.INT), - ('Amask', rffi.INT)]) - - Event = platform.Struct('SDL_Event', - [('type', rffi.INT)]) - - keysym = platform.Struct('SDL_keysym', - [('scancode', rffi.INT), - ('sym', rffi.INT), - ('mod', rffi.INT), - ('unicode', rffi.INT)]) - - KeyboardEvent = platform.Struct('SDL_KeyboardEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('keysym', keysym)]) - - MouseButtonEvent = platform.Struct('SDL_MouseButtonEvent', - [('type', rffi.INT), - ('button', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT)]) - - MouseMotionEvent = platform.Struct('SDL_MouseMotionEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT), - ('xrel', rffi.INT), - ('yrel', rffi.INT)]) - - QuitEvent = platform.Struct('SDL_QuitEvent', - [('type', rffi.INT)]) - - RWops = platform.Struct('SDL_RWops', []) - -# ------------------------------------------------------------------------------ - -for _prefix, _list in _constants.items(): - for _name in _list: - setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) - -# ------------------------------------------------------------------------------ - -globals().update(platform.configure(CConfig)) - -# ------------------------------------------------------------------------------ - -RectPtr.TO.become(Rect) -SurfacePtr.TO.become(Surface) -PixelFormatPtr.TO.become(PixelFormat) -EventPtr.TO.become(Event) -KeyboardEventPtr.TO.become(KeyboardEvent) -MouseButtonEventPtr.TO.become(MouseButtonEvent) -MouseMotionEventPtr.TO.become(MouseMotionEvent) -RWopsPtr.TO.become(RWops) - -# ------------------------------------------------------------------------------ - -Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) -Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) -# need to add signed hint here -Sint16P = lltype.Ptr(lltype.Array(Sint16, hints={'nolength': True})) -Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) - - -# ------------------------------------------------------------------------------ - -_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Mac_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Quit = external('SDL_Quit', [], - lltype.Void) - -SetVideoMode = external('SDL_SetVideoMode', - [rffi.INT, rffi.INT, rffi.INT, Uint32], - SurfacePtr) - -WM_SetCaption = external('SDL_WM_SetCaption', - [rffi.CCHARP, rffi.CCHARP], - lltype.Void) - -EnableUNICODE = external('SDL_EnableUNICODE', - [rffi.INT], - rffi.INT) - -WaitEvent = external('SDL_WaitEvent', - [EventPtr], - rffi.INT) - -PollEvent = external('SDL_PollEvent', - [EventPtr], - rffi.INT) - -Flip = external('SDL_Flip', - [SurfacePtr], - rffi.INT) - -CreateRGBSurface = external('SDL_CreateRGBSurface', - [Uint32, rffi.INT, rffi.INT, rffi.INT, - Uint32, Uint32, Uint32, Uint32], - SurfacePtr) - -LockSurface = external('SDL_LockSurface', - [SurfacePtr], - rffi.INT) - -UnlockSurface = external('SDL_UnlockSurface', - [SurfacePtr], - lltype.Void) - -FreeSurface = external('SDL_FreeSurface', - [SurfacePtr], - lltype.Void) - -MapRGB = external('SDL_MapRGB', - [PixelFormatPtr, Uint8, Uint8, Uint8], - Uint32) - -GetRGB = external('SDL_GetRGB', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], - lltype.Void) - -GetRGBA = external('SDL_GetRGBA', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, - Uint8P, Uint8P], - lltype.Void) - -FillRect = external('SDL_FillRect', - [SurfacePtr, RectPtr, Uint32], - rffi.INT) - -BlitSurface = external('SDL_UpperBlit', - [SurfacePtr, RectPtr, SurfacePtr, RectPtr], - rffi.INT) - -SetAlpha = external('SDL_SetAlpha', - [SurfacePtr, Uint32, Uint8], - rffi.INT) - -SetColorKey = external('SDL_SetColorKey', - [SurfacePtr, Uint32, Uint32], - rffi.INT) - -ShowCursor = external('SDL_ShowCursor', - [rffi.INT], - rffi.INT) - -GetTicks = external('SDL_GetTicks', - [], - Uint32) - -Delay = external('SDL_Delay', - [Uint32], - lltype.Void) - -UpdateRect = external('SDL_UpdateRect', - [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], - lltype.Void) - -GetKeyName = external('SDL_GetKeyName', - [rffi.INT], - rffi.CCHARP) - -GetError = external('SDL_GetError', - [], - rffi.CCHARP) - -RWFromFile = external('SDL_RWFromFile', - [rffi.CCHARP, rffi.CCHARP], - RWopsPtr) - -# ------------------------------------------------------------------------------ - - -if sys.platform == 'darwin': - def Init(flags): - if not we_are_translated(): - from AppKit import NSApplication - NSApplication.sharedApplication() - #CustomApplicationMain(0, " ") - return _Init(flags) - #Mac_Init() -else: - Init = _Init - - - diff --git a/pypy/rlib/rsdl/RSDL_helper.py b/pypy/rlib/rsdl/RSDL_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL_helper.py +++ /dev/null @@ -1,108 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RSDL - -def get_rgb(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - RSDL.GetRGB(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result = r, g, b - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_rgba(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 4, flavor='raw') - try: - RSDL.GetRGBA(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2), - rffi.ptradd(rgb, 3)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - a = rffi.cast(lltype.Signed, rgb[3]) - result = r, g, b, a - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_pixel(image, x, y): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 3: - p0 = rffi.cast(lltype.Signed, p[0]) - p1 = rffi.cast(lltype.Signed, p[1]) - p2 = rffi.cast(lltype.Signed, p[2]) - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - result = p0 << 16 | p1 << 8 | p2 - else: - result = p0 | p1 << 8 | p2 << 16 - return rffi.cast(RSDL.Uint32, result) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - return p[0] - else: - raise ValueError("bad BytesPerPixel") - -def set_pixel(image, x, y, pixel): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - p[0] = rffi.cast(rffi.UCHAR,pixel) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - p[0] = rffi.cast(RSDL.Uint16,pixel) - elif bpp == 3: - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - p[0] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - else: - p[0] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - p[0] = rffi.cast(RSDL.Uint32, pixel) - else: - raise ValueError("bad BytesPerPixel") - -def mallocrect(x, y, w, h): - p = lltype.malloc(RSDL.Rect, flavor='raw') - rffi.setintfield(p, 'c_x', x) - rffi.setintfield(p, 'c_y', y) - rffi.setintfield(p, 'c_w', w) - rffi.setintfield(p, 'c_h', h) - return p - -def blit_complete_surface(src, dst, x, y): - dstrect = mallocrect(x, y, rffi.getintfield(src, 'c_w'), rffi.getintfield(src, 'c_w')) - RSDL.BlitSurface(src, lltype.nullptr(RSDL.Rect), dst, dstrect) - lltype.free(dstrect, flavor='raw') - diff --git a/pypy/rlib/rsdl/__init__.py b/pypy/rlib/rsdl/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/constants.py b/pypy/rlib/rsdl/constants.py deleted file mode 100644 --- a/pypy/rlib/rsdl/constants.py +++ /dev/null @@ -1,261 +0,0 @@ - -_constants = { - 'SDL_': [ # constants with the 'SDL_' prefix in C - "YV12_OVERLAY", - "IYUV_OVERLAY", - "YUY2_OVERLAY", - "UYVY_OVERLAY", - "YVYU_OVERLAY", - - "SWSURFACE", - "HWSURFACE", - "RESIZABLE", - "ASYNCBLIT", - "OPENGL", - "OPENGLBLIT", - "ANYFORMAT", - "HWPALETTE", - "DOUBLEBUF", - "FULLSCREEN", - "HWACCEL", - "SRCCOLORKEY", - "RLEACCELOK", - "RLEACCEL", - "SRCALPHA", - "PREALLOC", - "NOFRAME", - - "GL_RED_SIZE", - "GL_GREEN_SIZE", - "GL_BLUE_SIZE", - "GL_ALPHA_SIZE", - "GL_BUFFER_SIZE", - "GL_DOUBLEBUFFER", - "GL_DEPTH_SIZE", - "GL_STENCIL_SIZE", - "GL_ACCUM_RED_SIZE", - "GL_ACCUM_GREEN_SIZE", - "GL_ACCUM_BLUE_SIZE", - "GL_ACCUM_ALPHA_SIZE", - "GL_STEREO", #if SDL_VERSION_ATLEAST(1, 2, 5) - "GL_MULTISAMPLEBUFFERS", #if SDL_VERSION_ATLEAST(1, 2, 6) - "GL_MULTISAMPLESAMPLES", #if SDL_VERSION_ATLEAST(1, 2, 6) - - "NOEVENT", - "ACTIVEEVENT", - "KEYDOWN", - "KEYUP", - "MOUSEMOTION", - "MOUSEBUTTONDOWN", - "MOUSEBUTTONUP", - "BUTTON_LEFT", - "BUTTON_MIDDLE", - "BUTTON_RIGHT", - "BUTTON_WHEELUP", - "BUTTON_WHEELDOWN", - "JOYAXISMOTION", - "JOYBALLMOTION", - "JOYHATMOTION", - "JOYBUTTONDOWN", - "JOYBUTTONUP", - "VIDEORESIZE", - "VIDEOEXPOSE", - "QUIT", - "SYSWMEVENT", - "USEREVENT", - "NUMEVENTS", - - "HAT_CENTERED", - "HAT_UP", - "HAT_RIGHTUP", - "HAT_RIGHT", - "HAT_RIGHTDOWN", - "HAT_DOWN", - "HAT_LEFTDOWN", - "HAT_LEFT", - "HAT_LEFTUP", - - "DISABLE", - "ENABLE", - - # the following ones are not exposed in Pygame - "INIT_VIDEO", - "BYTEORDER", - "BIG_ENDIAN", - "LIL_ENDIAN", - ], - - '': [ # constants with no prefix in C - "TIMER_RESOLUTION", - "AUDIO_U8", - "AUDIO_S8", - "AUDIO_U16LSB", - "AUDIO_S16LSB", - "AUDIO_U16MSB", - "AUDIO_S16MSB", - "AUDIO_U16", - "AUDIO_S16", - "AUDIO_U16SYS", - "AUDIO_S16SYS", - - "KMOD_NONE", - "KMOD_LSHIFT", - "KMOD_RSHIFT", - "KMOD_LCTRL", - "KMOD_RCTRL", - "KMOD_LALT", - "KMOD_RALT", - "KMOD_LMETA", - "KMOD_RMETA", - "KMOD_NUM", - "KMOD_CAPS", - "KMOD_MODE", - - "KMOD_CTRL", - "KMOD_SHIFT", - "KMOD_ALT", - "KMOD_META", - ], - - 'SDL': [ # constants with the 'SDL' prefix in C - "K_UNKNOWN", - "K_FIRST", - "K_BACKSPACE", - "K_TAB", - "K_CLEAR", - "K_RETURN", - "K_PAUSE", - "K_ESCAPE", - "K_SPACE", - "K_EXCLAIM", - "K_QUOTEDBL", - "K_HASH", - "K_DOLLAR", - "K_AMPERSAND", - "K_QUOTE", - "K_LEFTPAREN", - "K_RIGHTPAREN", - "K_ASTERISK", - "K_PLUS", - "K_COMMA", - "K_MINUS", - "K_PERIOD", - "K_SLASH", - "K_0", - "K_1", - "K_2", - "K_3", - "K_4", - "K_5", - "K_6", - "K_7", - "K_8", - "K_9", - "K_COLON", - "K_SEMICOLON", - "K_LESS", - "K_EQUALS", - "K_GREATER", - "K_QUESTION", - "K_AT", - "K_LEFTBRACKET", - "K_BACKSLASH", - "K_RIGHTBRACKET", - "K_CARET", - "K_UNDERSCORE", - "K_BACKQUOTE", - "K_a", - "K_b", - "K_c", - "K_d", - "K_e", - "K_f", - "K_g", - "K_h", - "K_i", - "K_j", - "K_k", - "K_l", - "K_m", - "K_n", - "K_o", - "K_p", - "K_q", - "K_r", - "K_s", - "K_t", - "K_u", - "K_v", - "K_w", - "K_x", - "K_y", - "K_z", - "K_DELETE", - - "K_KP0", - "K_KP1", - "K_KP2", - "K_KP3", - "K_KP4", - "K_KP5", - "K_KP6", - "K_KP7", - "K_KP8", - "K_KP9", - "K_KP_PERIOD", - "K_KP_DIVIDE", - "K_KP_MULTIPLY", - "K_KP_MINUS", - "K_KP_PLUS", - "K_KP_ENTER", - "K_KP_EQUALS", - "K_UP", - "K_DOWN", - "K_RIGHT", - "K_LEFT", - "K_INSERT", - "K_HOME", - "K_END", - "K_PAGEUP", - "K_PAGEDOWN", - "K_F1", - "K_F2", - "K_F3", - "K_F4", - "K_F5", - "K_F6", - "K_F7", - "K_F8", - "K_F9", - "K_F10", - "K_F11", - "K_F12", - "K_F13", - "K_F14", - "K_F15", - - "K_NUMLOCK", - "K_CAPSLOCK", - "K_SCROLLOCK", - "K_RSHIFT", - "K_LSHIFT", - "K_RCTRL", - "K_LCTRL", - "K_RALT", - "K_LALT", - "K_RMETA", - "K_LMETA", - "K_LSUPER", - "K_RSUPER", - "K_MODE", - - "K_HELP", - "K_PRINT", - "K_SYSREQ", - "K_BREAK", - "K_MENU", - "K_POWER", - "K_EURO", - "K_LAST", - ], - } diff --git a/pypy/rlib/rsdl/eci.py b/pypy/rlib/rsdl/eci.py deleted file mode 100644 --- a/pypy/rlib/rsdl/eci.py +++ /dev/null @@ -1,27 +0,0 @@ -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.translator.platform import CompilationError -import py -import sys - -def get_rsdl_compilation_info(): - if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL.h'], - include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], - link_files = [ - str(py.path.local(__file__).dirpath().join('macosx-sdl-main/SDLMain.m')), - ], - frameworks = ['SDL', 'Cocoa'] - ) - else: - eci = ExternalCompilationInfo( - includes=['SDL.h'], - ) - eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) - return eci - -def check_sdl_installation(): - from pypy.rpython.tool import rffi_platform as platform - platform.verify_eci(get_rsdl_compilation_info()) - -SDLNotInstalled = (ImportError, CompilationError) diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import - - at interface SDLMain : NSObject - at end diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m +++ /dev/null @@ -1,384 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import "SDL.h" -#import "SDLMain.h" -#import /* for MAXPATHLEN */ -#import - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ - at interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; - at end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ - at interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; - at end -#endif - - at interface SDLApplication : NSApplication - at end - - at implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} - at end - -/* The main class of the application, the application's delegate */ - at implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { - assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } - -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} - at end - - - at implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - - at end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/pypy/rlib/rsdl/test/__init__.py b/pypy/rlib/rsdl/test/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/test/applause.wav b/pypy/rlib/rsdl/test/applause.wav deleted file mode 100644 Binary file pypy/rlib/rsdl/test/applause.wav has changed diff --git a/pypy/rlib/rsdl/test/autopath.py b/pypy/rlib/rsdl/test/autopath.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/autopath.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -self cloning, automatic path configuration - -copy this into any subdirectory of pypy from which scripts need -to be run, typically all of the test subdirs. -The idea is that any such script simply issues - - import autopath - -and this will make sure that the parent directory containing "pypy" -is in sys.path. - -If you modify the master "autopath.py" version (in pypy/tool/autopath.py) -you can directly run it which will copy itself on all autopath.py files -it finds under the pypy root directory. - -This module always provides these attributes: - - pypydir pypy root directory path - this_dir directory where this autopath.py resides - -""" - -def __dirinfo(part): - """ return (partdir, this_dir) and insert parent of partdir - into sys.path. If the parent directories don't have the part - an EnvironmentError is raised.""" - - import sys, os - try: - head = this_dir = os.path.realpath(os.path.dirname(__file__)) - except NameError: - head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) - - error = None - while head: - partdir = head - head, tail = os.path.split(head) - if tail == part: - checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py') - if not os.path.exists(checkfile): - error = "Cannot find %r" % (os.path.normpath(checkfile),) - break - else: - error = "Cannot find the parent directory %r of the path %r" % ( - partdir, this_dir) - if not error: - # check for bogus end-of-line style (e.g. files checked out on - # Windows and moved to Unix) - f = open(__file__.replace('.pyc', '.py'), 'r') - data = f.read() - f.close() - if data.endswith('\r\n') or data.endswith('\r'): - error = ("Bad end-of-line style in the .py files. Typically " - "caused by a zip file or a checkout done on Windows and " - "moved to Unix or vice-versa.") - if error: - raise EnvironmentError("Invalid source tree - bogus checkout! " + - error) - - pypy_root = os.path.join(head, '') - try: - sys.path.remove(head) - except ValueError: - pass - sys.path.insert(0, head) - - munged = {} - for name, mod in sys.modules.items(): - if '.' in name: - continue - fn = getattr(mod, '__file__', None) - if not isinstance(fn, str): - continue - newname = os.path.splitext(os.path.basename(fn))[0] - if not newname.startswith(part + '.'): - continue - path = os.path.join(os.path.dirname(os.path.realpath(fn)), '') - if path.startswith(pypy_root) and newname != part: - modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep) - if newname != '__init__': - modpaths.append(newname) - modpath = '.'.join(modpaths) - if modpath not in sys.modules: - munged[modpath] = mod - - for name, mod in munged.iteritems(): - if name not in sys.modules: - sys.modules[name] = mod - if '.' in name: - prename = name[:name.rfind('.')] - postname = name[len(prename)+1:] - if prename not in sys.modules: - __import__(prename) - if not hasattr(sys.modules[prename], postname): - setattr(sys.modules[prename], postname, mod) - - return partdir, this_dir - -def __clone(): - """ clone master version of autopath.py into all subdirs """ - from os.path import join, walk - if not this_dir.endswith(join('pypy','tool')): - raise EnvironmentError("can only clone master version " - "'%s'" % join(pypydir, 'tool',_myname)) - - - def sync_walker(arg, dirname, fnames): - if _myname in fnames: - fn = join(dirname, _myname) - f = open(fn, 'rwb+') - try: - if f.read() == arg: - print "checkok", fn - else: - print "syncing", fn - f = open(fn, 'w') - f.write(arg) - finally: - f.close() - s = open(join(pypydir, 'tool', _myname), 'rb').read() - walk(pypydir, sync_walker, s) - -_myname = 'autopath.py' - -# set guaranteed attributes - -pypydir, this_dir = __dirinfo('pypy') - -if __name__ == '__main__': - __clone() diff --git a/pypy/rlib/rsdl/test/conftest.py b/pypy/rlib/rsdl/test/conftest.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -from pypy.rlib.rsdl.eci import check_sdl_installation, SDLNotInstalled -import py - -def pytest_ignore_collect(path): - try: - check_sdl_installation() - except SDLNotInstalled, e: - return True - else: - return False diff --git a/pypy/rlib/rsdl/test/demo.jpg b/pypy/rlib/rsdl/test/demo.jpg deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.jpg has changed diff --git a/pypy/rlib/rsdl/test/demo.png b/pypy/rlib/rsdl/test/demo.png deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.png has changed diff --git a/pypy/rlib/rsdl/test/test_basic.py b/pypy/rlib/rsdl/test/test_basic.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_basic.py +++ /dev/null @@ -1,37 +0,0 @@ -import py -from pypy.rlib.rsdl import RSDL -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import rffi - - -def test_sdl_init(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Quit() - -def test_surface_basic(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - assert surface - assert rffi.getintfield(surface, 'c_w') == 150 - assert rffi.getintfield(surface, 'c_h') == 50 - RSDL.FreeSurface(surface) - RSDL.Quit() - - -def test_get_keyname(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - assert RSDL.GetKeyName(RSDL.K_PLUS)[0] == '+' - assert RSDL.GetKeyName(RSDL.K_RIGHTPAREN)[0] == ')' - assert RSDL.GetKeyName(RSDL.K_z)[0] == 'z' - -def test_delay_getticks(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Delay(10) - i = RSDL.GetTicks() - assert i >= 10 - RSDL.Quit() - \ No newline at end of file diff --git a/pypy/rlib/rsdl/test/test_sdl_image.py b/pypy/rlib/rsdl/test/test_sdl_image.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_image.py +++ /dev/null @@ -1,50 +0,0 @@ -import py, os -import autopath -from pypy.rlib.rsdl import RSDL, RIMG, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - - -def test_load_image(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image, 'c_w') == 17 - assert rffi.getintfield(image, 'c_h') == 23 - RSDL.FreeSurface(image) - -def test_image_pixels(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image.c_format, 'c_BytesPerPixel') in (3, 4) - RSDL.LockSurface(image) - result = {} - try: - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - for y in range(23): - for x in range(y % 13, 17, 13): - color = RSDL_helper.get_pixel(image, x, y) - RSDL.GetRGB(color, - image.c_format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result[x, y] = r, g, b - finally: - lltype.free(rgb, flavor='raw') - finally: - RSDL.UnlockSurface(image) - RSDL.FreeSurface(image) - for x, y in result: - f = (x*17 + y*23) / float(17*17+23*23) - expected_r = int(255.0 * (1.0-f)) - expected_g = 0 - expected_b = int(255.0 * f) - r, g, b = result[x, y] - assert abs(r-expected_r) < 10 - assert abs(g-expected_g) < 10 - assert abs(b-expected_b) < 10 diff --git a/pypy/rlib/rsdl/test/test_sdl_mixer.py b/pypy/rlib/rsdl/test/test_sdl_mixer.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_mixer.py +++ /dev/null @@ -1,33 +0,0 @@ -import py -import os -import time -import autopath -from pypy.rlib.rsdl import RSDL, RMix, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - -def test_open_mixer(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - RMix.CloseAudio() - -def test_load_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.CloseAudio() - -def test_play_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - applause = RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.PlayChannel(-1, applause, -1) - time.sleep(1) - RMix.CloseAudio() - diff --git a/pypy/rlib/rsdl/test/test_surface.py b/pypy/rlib/rsdl/test/test_surface.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_surface.py +++ /dev/null @@ -1,75 +0,0 @@ -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi - -class TestSurface: - - def setup_method(self, meth): - self.dst_surf = RSDL.CreateRGBSurface(0, 300, 300, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - self.src_surf = RSDL.CreateRGBSurface(0, 50, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - fmt = self.src_surf.c_format - self.black = RSDL.MapRGB(fmt, 0, 0, 0) - self.red = RSDL.MapRGB(fmt, 255, 0, 0) - self.blue = RSDL.MapRGB(fmt, 0, 0, 255) - RSDL.FillRect(self.src_surf, lltype.nullptr(RSDL.Rect), self.red) - - def test_simple(self): - pass # only checks that creating the surfaces works - - def test_set_alpha(self): - # prepare - assert RSDL.SetAlpha(self.src_surf, RSDL.SRCALPHA, 128) == 0 - - # draw - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 10, 10) - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 20, 20) - - # check - for position, color in ( - (( 0, 0), ( 0,0,0)), # no rect - ((10,10), (127,0,0)), # one rect - ((20,20), (191,0,0)) # two overlapping rects - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert RSDL_helper.get_rgb(fetched_color, self.dst_surf.c_format) == color - - def test_set_color_key(self): - # prepare - fillrect = RSDL_helper.mallocrect(10, 10, 30, 30) - RSDL.FillRect(self.src_surf, fillrect, self.blue) - lltype.free(fillrect, flavor='raw') - assert RSDL.SetColorKey(self.src_surf, RSDL.SRCCOLORKEY, self.blue) == 0 - - # draw - RSDL_helper.blit_complete_surface(self.src_surf, self.dst_surf, 0, 0) - - # check - for position, color in ( - (( 0, 0), self.red), - ((10,10), self.black), - ((20,20), self.black), - ((40,40), self.red) - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert fetched_color == color - - def teardown_method(self, meth): - RSDL.FreeSurface(self.src_surf) - RSDL.FreeSurface(self.dst_surf) - RSDL.Quit() - diff --git a/pypy/rlib/rsdl/test/test_video.py b/pypy/rlib/rsdl/test/test_video.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_video.py +++ /dev/null @@ -1,241 +0,0 @@ - -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi -from pypy import conftest - -# -# This test file is skipped unless run with "py.test --view". -# If it is run as "py.test --view -s", then it interactively asks -# for confirmation that the window looks as expected. -# - - -class TestVideo: - - def setup_method(self, meth): - if not conftest.option.view: - py.test.skip("'--view' not specified, " - "skipping tests that open a window") - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - self.screen = RSDL.SetVideoMode(640, 480, 32, 0) - assert self.screen - self.is_interactive = sys.stdout.isatty() - - def check(self, msg): - if self.is_interactive: - print - answer = raw_input('Interactive test: %s - ok? [Y] ' % msg) - if answer and not answer.upper().startswith('Y'): - py.test.fail(msg) - else: - print msg - - def test_simple(self): - pass # only checks that opening and closing the window works - - def test_fillrect_full(self): - fmt = self.screen.c_format - for colorname, r, g, b in [('dark red', 128, 0, 0), - ('yellow', 255, 255, 0), - ('blue', 0, 0, 255)]: - color = RSDL.MapRGB(fmt, r, g, b) - RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) - RSDL.Flip(self.screen) - self.check("Screen filled with %s" % colorname) - - def test_caption(self): - RSDL.WM_SetCaption("Hello World!", "Hello World!") - self.check('The window caption is "Hello World!"') - - def test_keypresses(self): - if not self.is_interactive: - py.test.skip("interactive test only") - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window should be printed below." - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - char = rffi.getintfield(p.c_keysym, 'c_unicode') - if char != 0: - print 'Key:', unichr(char).encode('utf-8') - else: - print 'Some special key' - else: - print '(event of type %d)' % c_type - finally: - lltype.free(event, flavor='raw') - - def test_poll(self): - if not self.is_interactive: - py.test.skip("interactive test only") - import time, sys - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window give a dot." - print " Wait 3 seconds to quit." - timeout = time.time() + 3 - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - # busy polling - ok = RSDL.PollEvent(event) - ok = rffi.cast(lltype.Signed, ok) - assert ok >= 0 - if ok > 0: - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - sys.stderr.write('.') - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - timeout = time.time() + 3 - else: - if time.time() > timeout: - break - time.sleep(0.05) - finally: - lltype.free(event, flavor='raw') - - def test_mousemove(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Move the Mouse up and down:" - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor="raw") - directions = [False]*4 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, "c_type") - if c_type == RSDL.MOUSEMOTION: - m = rffi.cast(RSDL.MouseMotionEventPtr, event) - assert rffi.getintfield(m, "c_x") >= 0 - assert rffi.getintfield(m, "c_y") >= 0 - print rffi.getintfield(m, "c_xrel") - directions[0] |= rffi.getintfield(m, "c_xrel")>0 - directions[1] |= rffi.getintfield(m, "c_xrel")<0 - directions[2] |= rffi.getintfield(m, "c_yrel")>0 - directions[3] |= rffi.getintfield(m, "c_yrel")<0 - if False not in directions: - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print " test manually aborted" - py.test.fail(" mousemovement test aborted") - break - finally: - lltype.free(event, flavor='raw') - - - def test_mousebutton_wheel(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Press the given MouseButtons:" - print " Use Escape to pass tests." - - event_tests = [("left button", RSDL.BUTTON_LEFT), - ("middle button", RSDL.BUTTON_MIDDLE), - ("right button", RSDL.BUTTON_RIGHT), - ("scroll up", RSDL.BUTTON_WHEELUP), - ("scroll down", RSDL.BUTTON_WHEELDOWN)] - test_success = [] - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - for button_test in event_tests: - print " press %s:" % button_test[0] - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.MOUSEBUTTONDOWN: - pass - elif c_type == RSDL.MOUSEBUTTONUP: - b = rffi.cast(RSDL.MouseButtonEventPtr, event) - if rffi.getintfield(b, 'c_button') == button_test[1]: - test_success.append(True) - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - test_success.append(False) - print " manually aborted" - break - #break - if False in test_success: - py.test.fail("") - finally: - lltype.free(event, flavor='raw') - - - def test_show_hide_cursor(self): - RSDL.ShowCursor(RSDL.DISABLE) - self.check("Is the cursor hidden? ") - RSDL.ShowCursor(RSDL.ENABLE) - self.check("Is the cursor shown? ") - - def test_bit_pattern(self): - HEIGHT = WIDTH = 10 - fmt = self.screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(self.screen) - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = white - else: - c = black - RSDL_helper.set_pixel(self.screen, i, j, c) - RSDL.UnlockSurface(self.screen) - RSDL.Flip(self.screen) - self.check("Upper left corner 10x10 field with vertical black/white stripes") - - def test_blit_rect(self): - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - fmt = surface.c_format - color = RSDL.MapRGB(fmt, 255, 0, 0) - RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) - - paintrect = RSDL_helper.mallocrect(75, 0, 150, 50) - dstrect = lltype.malloc(RSDL.Rect, flavor='raw') - try: - color = RSDL.MapRGB(fmt, 255, 128, 0) - RSDL.FillRect(surface, paintrect, color) - - rffi.setintfield(dstrect, 'c_x', 10) - rffi.setintfield(dstrect, 'c_y', 10) - rffi.setintfield(dstrect, 'c_w', 150) - rffi.setintfield(dstrect, 'c_h', 50) - RSDL.BlitSurface(surface, lltype.nullptr(RSDL.Rect), self.screen, dstrect) - RSDL.Flip(self.screen) - finally: - lltype.free(dstrect, flavor='raw') - lltype.free(paintrect, flavor='raw') - RSDL.FreeSurface(surface) - self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border") - - def teardown_method(self, meth): - RSDL.Quit() - diff --git a/pypy/translator/goal/targetsimplevideo.py b/pypy/translator/goal/targetsimplevideo.py deleted file mode 100644 --- a/pypy/translator/goal/targetsimplevideo.py +++ /dev/null @@ -1,98 +0,0 @@ -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rpython.lltypesystem import rffi, lltype -import py - -WIDTH = 1000 -HEIGHT = 1000 - -def entry_point(argv=None): - RSDL.Init(RSDL.INIT_VIDEO) >= 0 - screen = RSDL.SetVideoMode(WIDTH, HEIGHT, 32, 0) - event = lltype.malloc(RSDL.Event, flavor='raw') - paintpattern = 0 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - paintpattern += 1 - update_screen(screen, paintpattern) - finally: - lltype.free(event, flavor='raw') - - return 0 - -# ----------------------------------------------------------------------------- - -def chess(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - if (i+j) % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def white(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, colb) - -def black(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, cola) - -def stripes_v(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def stripes_m(screen, cola, colb): - for j in xrange(WIDTH): - for i in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - - -# ----------------------------------------------------------------------------- - -pattern = [chess, white, black, stripes_v, stripes_m] -pl = len(pattern) -def update_screen(screen, paintpattern): - fmt = screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(screen) - pattern[paintpattern % pl](screen, black, white) - RSDL.UnlockSurface(screen) - RSDL.Flip(screen) - RSDL.Delay(10 ) - - -# ----------------------------------------------------------------------------- - -def target(*args): - return entry_point, None - -def test_target(): - entry_point() - -if __name__ == '__main__': - entry_point() - - From noreply at buildbot.pypy.org Tue Jun 5 09:57:39 2012 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 5 Jun 2012 09:57:39 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20120605075739.3C33A1C003C@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r55296:650162137831 Date: 2012-06-03 17:08 +0200 http://bitbucket.org/pypy/pypy/changeset/650162137831/ Log: merge diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst --- a/pypy/doc/whatsnew-1.9.rst +++ b/pypy/doc/whatsnew-1.9.rst @@ -5,6 +5,9 @@ .. this is the revision just after the creation of the release-1.8.x branch .. startrev: a4261375b359 +.. branch: default +* Working hash function for numpy types. + .. branch: array_equal .. branch: better-jit-hooks-2 Improved jit hooks From noreply at buildbot.pypy.org Tue Jun 5 09:57:47 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:57:47 +0200 (CEST) Subject: [pypy-commit] lang-gameboy default: Copy rsdl here. It was removed from the pypy tree. Message-ID: <20120605075747.016B51C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r4:d08013e51a42 Date: 2012-06-03 17:13 +0200 http://bitbucket.org/pypy/lang-gameboy/changeset/d08013e51a42/ Log: Copy rsdl here. It was removed from the pypy tree. diff --git a/pygirl/gameboy_implementation.py b/pygirl/gameboy_implementation.py --- a/pygirl/gameboy_implementation.py +++ b/pygirl/gameboy_implementation.py @@ -15,7 +15,7 @@ show_metadata = False # Extends the window with windows visualizing meta-data if constants.USE_RSDL: - from pypy.rlib.rsdl import RSDL, RSDL_helper #, RMix + from rsdl import RSDL, RSDL_helper #, RMix from pypy.rpython.lltypesystem import lltype, rffi get_ticks = RSDL.GetTicks def delay(secs): diff --git a/pygirl/test/test_gameboy_implementaton.py b/pygirl/test/test_gameboy_implementaton.py --- a/pygirl/test/test_gameboy_implementaton.py +++ b/pygirl/test/test_gameboy_implementaton.py @@ -1,5 +1,4 @@ import py, sys -from pypy import conftest from pygirl import constants @@ -13,6 +12,7 @@ # This test file is skipped unless run with "py.test --view". # If it is run as "py.test --view -s", then it interactively asks # for confirmation that the window looks as expected. +# XXX always run for now # if sys.platform == 'darwin': @@ -25,9 +25,9 @@ class TestGameBoyImplementation(object): def setup_method(self, meth): - if not conftest.option.view: - py.test.skip("'--view' not specified, " - "skipping tests that open a window") + #if not conftest.option.view: + # py.test.skip("'--view' not specified, " + # "skipping tests that open a window") self.gameboy = GameBoyImplementation() self.is_interactive = sys.stdout.isatty() diff --git a/rsdl/RIMG.py b/rsdl/RIMG.py new file mode 100644 --- /dev/null +++ b/rsdl/RIMG.py @@ -0,0 +1,25 @@ +import sys +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.tool import rffi_platform as platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from rsdl import RSDL + + +if sys.platform == 'darwin': + eci = ExternalCompilationInfo( + includes = ['SDL_image.h'], + frameworks = ['SDL_image'], + include_dirs = ['/Library/Frameworks/SDL_image.framework/Headers'] + ) +else: + eci = ExternalCompilationInfo( + includes=['SDL_image.h'], + libraries=['SDL_image'], + ) + +eci = eci.merge(RSDL.eci) + +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci) + +Load = external('IMG_Load', [rffi.CCHARP], RSDL.SurfacePtr) diff --git a/rsdl/RMix.py b/rsdl/RMix.py new file mode 100644 --- /dev/null +++ b/rsdl/RMix.py @@ -0,0 +1,68 @@ +import sys +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.tool import rffi_platform as platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from rsdl import RSDL + + +if sys.platform == 'darwin': + eci = ExternalCompilationInfo( + includes = ['SDL_mixer.h'], + frameworks = ['SDL_mixer'], + include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Headers'] + ) +else: + eci = ExternalCompilationInfo( + includes=['SDL_mixer.h'], + libraries=['SDL_mixer'], + ) + +eci = eci.merge(RSDL.eci) +eci = eci.merge(eci) +eci = eci.merge(eci) + +ChunkPtr = lltype.Ptr(lltype.ForwardReference()) + +class CConfig: + _compilation_info_ = eci + + Chunk = platform.Struct('Mix_Chunk', [('allocated', rffi.INT), + ('abuf', RSDL.Uint8P), + ('alen', RSDL.Uint32), + ('volume', RSDL.Uint8)]) + +globals().update(platform.configure(CConfig)) + +ChunkPtr.TO.become(Chunk) + + +Buffer = rffi.CArray(RSDL.Uint8) + +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci) + +OpenAudio = external('Mix_OpenAudio', + [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], + rffi.INT) + +CloseAudio = external('Mix_CloseAudio', [], lltype.Void) + +LoadWAV_RW = external('Mix_LoadWAV_RW', + [RSDL.RWopsPtr, rffi.INT], + ChunkPtr) + +def LoadWAV(filename_ccharp): + with rffi.scoped_str2charp('rb') as mode: + return LoadWAV_RW(RSDL.RWFromFile(filename_ccharp, mode), 1) + + +PlayChannelTimed = external('Mix_PlayChannelTimed', + [rffi.INT, ChunkPtr, rffi.INT, rffi.INT], + rffi.INT) + +def PlayChannel(channel,chunk,loops): + return PlayChannelTimed(channel, chunk, loops, -1) + +"""Returns zero if the channel is not playing. +Otherwise if you passed in -1, the number of channels playing is returned""" +ChannelPlaying = external('Mix_Playing', [rffi.INT], rffi.INT) diff --git a/rsdl/RMix_helper.py b/rsdl/RMix_helper.py new file mode 100644 --- /dev/null +++ b/rsdl/RMix_helper.py @@ -0,0 +1,24 @@ +from pypy.rpython.lltypesystem import lltype, rffi +from rsdl import RMix, RSDL +from pypy.rpython.tool import rffi_platform as platform + + +def malloc_buffer_chunk(has_own_allocated_buffer, length_bytes, volume): + buffer_pointer = lltype.malloc(RMix.Buffer, length_bytes, flavor='raw') + return malloc_chunk(has_own_allocated_buffer, length_bytes, volume) + +def malloc_chunk(has_own_allocated_buffer, buffer_pointer, length_bytes, volume): + """ + Creates a new Mix_Chunk. + has_own_allocated_buffer: if 1 struct has its own allocated buffer, + if 0 abuf should not be freed + buffer_pointer: pointer to audio data + length_bytes: length of audio data in bytes + volume: Per-sample volume, 0-128 (normally + MIX_MAX_VOLUME after loading)""" + p = lltype.malloc(RMix.Chunk, flavor='raw') + rffi.setintfield(p, 'c_allocated', has_own_allocated_buffer) + rffi.setintfield(p, 'c_abuf', buffer_pointer) + rffi.setintfield(p, 'c_alen', length_bytes) + rffi.setintfield(p, 'c_volume', volume) + return p diff --git a/rsdl/RSDL.py b/rsdl/RSDL.py new file mode 100644 --- /dev/null +++ b/rsdl/RSDL.py @@ -0,0 +1,249 @@ +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.tool import rffi_platform as platform +from rsdl.constants import _constants +from rsdl.eci import get_rsdl_compilation_info +from pypy.rlib.objectmodel import we_are_translated +import py +import sys + +# ------------------------------------------------------------------------------ + +eci = get_rsdl_compilation_info() + +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci) + +# ------------------------------------------------------------------------------ + +RectPtr = lltype.Ptr(lltype.ForwardReference()) +SurfacePtr = lltype.Ptr(lltype.ForwardReference()) +PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) +EventPtr = lltype.Ptr(lltype.ForwardReference()) +KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) +MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) +MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) +KeyPtr = lltype.Ptr(lltype.ForwardReference()) +RWopsPtr = lltype.Ptr(lltype.ForwardReference()) + +# ------------------------------------------------------------------------------ + +class CConfig: + _compilation_info_ = eci + + Uint8 = platform.SimpleType('Uint8', rffi.INT) + Uint16 = platform.SimpleType('Uint16', rffi.INT) + Sint16 = platform.SimpleType('Sint16', rffi.INT) + Uint32 = platform.SimpleType('Uint32', rffi.INT) + + Rect = platform.Struct('SDL_Rect', + [('x', rffi.INT), + ('y', rffi.INT), + ('w', rffi.INT), + ('h', rffi.INT)]) + + Surface = platform.Struct('SDL_Surface', + [('w', rffi.INT), + ('h', rffi.INT), + ('format', PixelFormatPtr), + ('pitch', rffi.INT), + ('pixels', rffi.UCHARP)]) + + PixelFormat = platform.Struct('SDL_PixelFormat', + [('BitsPerPixel', rffi.INT), + ('BytesPerPixel', rffi.INT), + ('Rmask', rffi.INT), + ('Gmask', rffi.INT), + ('Bmask', rffi.INT), + ('Amask', rffi.INT)]) + + Event = platform.Struct('SDL_Event', + [('type', rffi.INT)]) + + keysym = platform.Struct('SDL_keysym', + [('scancode', rffi.INT), + ('sym', rffi.INT), + ('mod', rffi.INT), + ('unicode', rffi.INT)]) + + KeyboardEvent = platform.Struct('SDL_KeyboardEvent', + [('type', rffi.INT), + ('state', rffi.INT), + ('keysym', keysym)]) + + MouseButtonEvent = platform.Struct('SDL_MouseButtonEvent', + [('type', rffi.INT), + ('button', rffi.INT), + ('state', rffi.INT), + ('x', rffi.INT), + ('y', rffi.INT)]) + + MouseMotionEvent = platform.Struct('SDL_MouseMotionEvent', + [('type', rffi.INT), + ('state', rffi.INT), + ('x', rffi.INT), + ('y', rffi.INT), + ('xrel', rffi.INT), + ('yrel', rffi.INT)]) + + QuitEvent = platform.Struct('SDL_QuitEvent', + [('type', rffi.INT)]) + + RWops = platform.Struct('SDL_RWops', []) + +# ------------------------------------------------------------------------------ + +for _prefix, _list in _constants.items(): + for _name in _list: + setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) + +# ------------------------------------------------------------------------------ + +globals().update(platform.configure(CConfig)) + +# ------------------------------------------------------------------------------ + +RectPtr.TO.become(Rect) +SurfacePtr.TO.become(Surface) +PixelFormatPtr.TO.become(PixelFormat) +EventPtr.TO.become(Event) +KeyboardEventPtr.TO.become(KeyboardEvent) +MouseButtonEventPtr.TO.become(MouseButtonEvent) +MouseMotionEventPtr.TO.become(MouseMotionEvent) +RWopsPtr.TO.become(RWops) + +# ------------------------------------------------------------------------------ + +Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) +Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) +# need to add signed hint here +Sint16P = lltype.Ptr(lltype.Array(Sint16, hints={'nolength': True})) +Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) + + +# ------------------------------------------------------------------------------ + +_Init = external('SDL_Init', + [Uint32], + rffi.INT) + +Mac_Init = external('SDL_Init', + [Uint32], + rffi.INT) + +Quit = external('SDL_Quit', [], + lltype.Void) + +SetVideoMode = external('SDL_SetVideoMode', + [rffi.INT, rffi.INT, rffi.INT, Uint32], + SurfacePtr) + +WM_SetCaption = external('SDL_WM_SetCaption', + [rffi.CCHARP, rffi.CCHARP], + lltype.Void) + +EnableUNICODE = external('SDL_EnableUNICODE', + [rffi.INT], + rffi.INT) + +WaitEvent = external('SDL_WaitEvent', + [EventPtr], + rffi.INT) + +PollEvent = external('SDL_PollEvent', + [EventPtr], + rffi.INT) + +Flip = external('SDL_Flip', + [SurfacePtr], + rffi.INT) + +CreateRGBSurface = external('SDL_CreateRGBSurface', + [Uint32, rffi.INT, rffi.INT, rffi.INT, + Uint32, Uint32, Uint32, Uint32], + SurfacePtr) + +LockSurface = external('SDL_LockSurface', + [SurfacePtr], + rffi.INT) + +UnlockSurface = external('SDL_UnlockSurface', + [SurfacePtr], + lltype.Void) + +FreeSurface = external('SDL_FreeSurface', + [SurfacePtr], + lltype.Void) + +MapRGB = external('SDL_MapRGB', + [PixelFormatPtr, Uint8, Uint8, Uint8], + Uint32) + +GetRGB = external('SDL_GetRGB', + [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], + lltype.Void) + +GetRGBA = external('SDL_GetRGBA', + [Uint32, PixelFormatPtr, Uint8P, Uint8P, + Uint8P, Uint8P], + lltype.Void) + +FillRect = external('SDL_FillRect', + [SurfacePtr, RectPtr, Uint32], + rffi.INT) + +BlitSurface = external('SDL_UpperBlit', + [SurfacePtr, RectPtr, SurfacePtr, RectPtr], + rffi.INT) + +SetAlpha = external('SDL_SetAlpha', + [SurfacePtr, Uint32, Uint8], + rffi.INT) + +SetColorKey = external('SDL_SetColorKey', + [SurfacePtr, Uint32, Uint32], + rffi.INT) + +ShowCursor = external('SDL_ShowCursor', + [rffi.INT], + rffi.INT) + +GetTicks = external('SDL_GetTicks', + [], + Uint32) + +Delay = external('SDL_Delay', + [Uint32], + lltype.Void) + +UpdateRect = external('SDL_UpdateRect', + [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], + lltype.Void) + +GetKeyName = external('SDL_GetKeyName', + [rffi.INT], + rffi.CCHARP) + +GetError = external('SDL_GetError', + [], + rffi.CCHARP) + +RWFromFile = external('SDL_RWFromFile', + [rffi.CCHARP, rffi.CCHARP], + RWopsPtr) + +# ------------------------------------------------------------------------------ + + +if sys.platform == 'darwin': + def Init(flags): + if not we_are_translated(): + from AppKit import NSApplication + NSApplication.sharedApplication() + #CustomApplicationMain(0, " ") + return _Init(flags) + #Mac_Init() +else: + Init = _Init + + + diff --git a/rsdl/RSDL_helper.py b/rsdl/RSDL_helper.py new file mode 100644 --- /dev/null +++ b/rsdl/RSDL_helper.py @@ -0,0 +1,108 @@ +from pypy.rpython.lltypesystem import lltype, rffi +from rsdl import RSDL + +def get_rgb(color, format): + rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') + try: + RSDL.GetRGB(color, + format, + rffi.ptradd(rgb, 0), + rffi.ptradd(rgb, 1), + rffi.ptradd(rgb, 2)) + r = rffi.cast(lltype.Signed, rgb[0]) + g = rffi.cast(lltype.Signed, rgb[1]) + b = rffi.cast(lltype.Signed, rgb[2]) + result = r, g, b + finally: + lltype.free(rgb, flavor='raw') + + return result + +def get_rgba(color, format): + rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 4, flavor='raw') + try: + RSDL.GetRGBA(color, + format, + rffi.ptradd(rgb, 0), + rffi.ptradd(rgb, 1), + rffi.ptradd(rgb, 2), + rffi.ptradd(rgb, 3)) + r = rffi.cast(lltype.Signed, rgb[0]) + g = rffi.cast(lltype.Signed, rgb[1]) + b = rffi.cast(lltype.Signed, rgb[2]) + a = rffi.cast(lltype.Signed, rgb[3]) + result = r, g, b, a + finally: + lltype.free(rgb, flavor='raw') + + return result + +def get_pixel(image, x, y): + """Return the pixel value at (x, y) + NOTE: The surface must be locked before calling this! + """ + bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') + pitch = rffi.getintfield(image, 'c_pitch') + # Here p is the address to the pixel we want to retrieve + p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) + if bpp == 1: + return rffi.cast(RSDL.Uint32, p[0]) + elif bpp == 2: + p = rffi.cast(RSDL.Uint16P, p) + return rffi.cast(RSDL.Uint32, p[0]) + elif bpp == 3: + p0 = rffi.cast(lltype.Signed, p[0]) + p1 = rffi.cast(lltype.Signed, p[1]) + p2 = rffi.cast(lltype.Signed, p[2]) + if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: + result = p0 << 16 | p1 << 8 | p2 + else: + result = p0 | p1 << 8 | p2 << 16 + return rffi.cast(RSDL.Uint32, result) + elif bpp == 4: + p = rffi.cast(RSDL.Uint32P, p) + return p[0] + else: + raise ValueError("bad BytesPerPixel") + +def set_pixel(image, x, y, pixel): + """Return the pixel value at (x, y) + NOTE: The surface must be locked before calling this! + """ + bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') + pitch = rffi.getintfield(image, 'c_pitch') + # Here p is the address to the pixel we want to retrieve + p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) + if bpp == 1: + p[0] = rffi.cast(rffi.UCHAR,pixel) + elif bpp == 2: + p = rffi.cast(RSDL.Uint16P, p) + p[0] = rffi.cast(RSDL.Uint16,pixel) + elif bpp == 3: + if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: + p[0] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) + p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) + p[2] = rffi.cast(rffi.UCHAR,pixel & 0xFF) + else: + p[0] = rffi.cast(rffi.UCHAR,pixel & 0xFF) + p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) + p[2] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) + elif bpp == 4: + p = rffi.cast(RSDL.Uint32P, p) + p[0] = rffi.cast(RSDL.Uint32, pixel) + else: + raise ValueError("bad BytesPerPixel") + +def mallocrect(x, y, w, h): + p = lltype.malloc(RSDL.Rect, flavor='raw') + rffi.setintfield(p, 'c_x', x) + rffi.setintfield(p, 'c_y', y) + rffi.setintfield(p, 'c_w', w) + rffi.setintfield(p, 'c_h', h) + return p + +def blit_complete_surface(src, dst, x, y): + dstrect = mallocrect(x, y, rffi.getintfield(src, 'c_w'), rffi.getintfield(src, 'c_w')) + RSDL.BlitSurface(src, lltype.nullptr(RSDL.Rect), dst, dstrect) + lltype.free(dstrect, flavor='raw') + diff --git a/rsdl/__init__.py b/rsdl/__init__.py new file mode 100644 diff --git a/rsdl/constants.py b/rsdl/constants.py new file mode 100644 --- /dev/null +++ b/rsdl/constants.py @@ -0,0 +1,261 @@ + +_constants = { + 'SDL_': [ # constants with the 'SDL_' prefix in C + "YV12_OVERLAY", + "IYUV_OVERLAY", + "YUY2_OVERLAY", + "UYVY_OVERLAY", + "YVYU_OVERLAY", + + "SWSURFACE", + "HWSURFACE", + "RESIZABLE", + "ASYNCBLIT", + "OPENGL", + "OPENGLBLIT", + "ANYFORMAT", + "HWPALETTE", + "DOUBLEBUF", + "FULLSCREEN", + "HWACCEL", + "SRCCOLORKEY", + "RLEACCELOK", + "RLEACCEL", + "SRCALPHA", + "PREALLOC", + "NOFRAME", + + "GL_RED_SIZE", + "GL_GREEN_SIZE", + "GL_BLUE_SIZE", + "GL_ALPHA_SIZE", + "GL_BUFFER_SIZE", + "GL_DOUBLEBUFFER", + "GL_DEPTH_SIZE", + "GL_STENCIL_SIZE", + "GL_ACCUM_RED_SIZE", + "GL_ACCUM_GREEN_SIZE", + "GL_ACCUM_BLUE_SIZE", + "GL_ACCUM_ALPHA_SIZE", + "GL_STEREO", #if SDL_VERSION_ATLEAST(1, 2, 5) + "GL_MULTISAMPLEBUFFERS", #if SDL_VERSION_ATLEAST(1, 2, 6) + "GL_MULTISAMPLESAMPLES", #if SDL_VERSION_ATLEAST(1, 2, 6) + + "NOEVENT", + "ACTIVEEVENT", + "KEYDOWN", + "KEYUP", + "MOUSEMOTION", + "MOUSEBUTTONDOWN", + "MOUSEBUTTONUP", + "BUTTON_LEFT", + "BUTTON_MIDDLE", + "BUTTON_RIGHT", + "BUTTON_WHEELUP", + "BUTTON_WHEELDOWN", + "JOYAXISMOTION", + "JOYBALLMOTION", + "JOYHATMOTION", + "JOYBUTTONDOWN", + "JOYBUTTONUP", + "VIDEORESIZE", + "VIDEOEXPOSE", + "QUIT", + "SYSWMEVENT", + "USEREVENT", + "NUMEVENTS", + + "HAT_CENTERED", + "HAT_UP", + "HAT_RIGHTUP", + "HAT_RIGHT", + "HAT_RIGHTDOWN", + "HAT_DOWN", + "HAT_LEFTDOWN", + "HAT_LEFT", + "HAT_LEFTUP", + + "DISABLE", + "ENABLE", + + # the following ones are not exposed in Pygame + "INIT_VIDEO", + "BYTEORDER", + "BIG_ENDIAN", + "LIL_ENDIAN", + ], + + '': [ # constants with no prefix in C + "TIMER_RESOLUTION", + "AUDIO_U8", + "AUDIO_S8", + "AUDIO_U16LSB", + "AUDIO_S16LSB", + "AUDIO_U16MSB", + "AUDIO_S16MSB", + "AUDIO_U16", + "AUDIO_S16", + "AUDIO_U16SYS", + "AUDIO_S16SYS", + + "KMOD_NONE", + "KMOD_LSHIFT", + "KMOD_RSHIFT", + "KMOD_LCTRL", + "KMOD_RCTRL", + "KMOD_LALT", + "KMOD_RALT", + "KMOD_LMETA", + "KMOD_RMETA", + "KMOD_NUM", + "KMOD_CAPS", + "KMOD_MODE", + + "KMOD_CTRL", + "KMOD_SHIFT", + "KMOD_ALT", + "KMOD_META", + ], + + 'SDL': [ # constants with the 'SDL' prefix in C + "K_UNKNOWN", + "K_FIRST", + "K_BACKSPACE", + "K_TAB", + "K_CLEAR", + "K_RETURN", + "K_PAUSE", + "K_ESCAPE", + "K_SPACE", + "K_EXCLAIM", + "K_QUOTEDBL", + "K_HASH", + "K_DOLLAR", + "K_AMPERSAND", + "K_QUOTE", + "K_LEFTPAREN", + "K_RIGHTPAREN", + "K_ASTERISK", + "K_PLUS", + "K_COMMA", + "K_MINUS", + "K_PERIOD", + "K_SLASH", + "K_0", + "K_1", + "K_2", + "K_3", + "K_4", + "K_5", + "K_6", + "K_7", + "K_8", + "K_9", + "K_COLON", + "K_SEMICOLON", + "K_LESS", + "K_EQUALS", + "K_GREATER", + "K_QUESTION", + "K_AT", + "K_LEFTBRACKET", + "K_BACKSLASH", + "K_RIGHTBRACKET", + "K_CARET", + "K_UNDERSCORE", + "K_BACKQUOTE", + "K_a", + "K_b", + "K_c", + "K_d", + "K_e", + "K_f", + "K_g", + "K_h", + "K_i", + "K_j", + "K_k", + "K_l", + "K_m", + "K_n", + "K_o", + "K_p", + "K_q", + "K_r", + "K_s", + "K_t", + "K_u", + "K_v", + "K_w", + "K_x", + "K_y", + "K_z", + "K_DELETE", + + "K_KP0", + "K_KP1", + "K_KP2", + "K_KP3", + "K_KP4", + "K_KP5", + "K_KP6", + "K_KP7", + "K_KP8", + "K_KP9", + "K_KP_PERIOD", + "K_KP_DIVIDE", + "K_KP_MULTIPLY", + "K_KP_MINUS", + "K_KP_PLUS", + "K_KP_ENTER", + "K_KP_EQUALS", + "K_UP", + "K_DOWN", + "K_RIGHT", + "K_LEFT", + "K_INSERT", + "K_HOME", + "K_END", + "K_PAGEUP", + "K_PAGEDOWN", + "K_F1", + "K_F2", + "K_F3", + "K_F4", + "K_F5", + "K_F6", + "K_F7", + "K_F8", + "K_F9", + "K_F10", + "K_F11", + "K_F12", + "K_F13", + "K_F14", + "K_F15", + + "K_NUMLOCK", + "K_CAPSLOCK", + "K_SCROLLOCK", + "K_RSHIFT", + "K_LSHIFT", + "K_RCTRL", + "K_LCTRL", + "K_RALT", + "K_LALT", + "K_RMETA", + "K_LMETA", + "K_LSUPER", + "K_RSUPER", + "K_MODE", + + "K_HELP", + "K_PRINT", + "K_SYSREQ", + "K_BREAK", + "K_MENU", + "K_POWER", + "K_EURO", + "K_LAST", + ], + } diff --git a/rsdl/eci.py b/rsdl/eci.py new file mode 100644 --- /dev/null +++ b/rsdl/eci.py @@ -0,0 +1,27 @@ +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.platform import CompilationError +import py +import sys + +def get_rsdl_compilation_info(): + if sys.platform == 'darwin': + eci = ExternalCompilationInfo( + includes = ['SDL.h'], + include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], + link_files = [ + str(py.path.local(__file__).dirpath().join('macosx-sdl-main/SDLMain.m')), + ], + frameworks = ['SDL', 'Cocoa'] + ) + else: + eci = ExternalCompilationInfo( + includes=['SDL.h'], + ) + eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) + return eci + +def check_sdl_installation(): + from pypy.rpython.tool import rffi_platform as platform + platform.verify_eci(get_rsdl_compilation_info()) + +SDLNotInstalled = (ImportError, CompilationError) diff --git a/rsdl/macosx-sdl-main/SDLMain.h b/rsdl/macosx-sdl-main/SDLMain.h new file mode 100644 --- /dev/null +++ b/rsdl/macosx-sdl-main/SDLMain.h @@ -0,0 +1,11 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#import + + at interface SDLMain : NSObject + at end diff --git a/rsdl/macosx-sdl-main/SDLMain.m b/rsdl/macosx-sdl-main/SDLMain.m new file mode 100644 --- /dev/null +++ b/rsdl/macosx-sdl-main/SDLMain.m @@ -0,0 +1,384 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#import "SDL.h" +#import "SDLMain.h" +#import /* for MAXPATHLEN */ +#import + +/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, + but the method still is there and works. To avoid warnings, we declare + it ourselves here. */ + at interface NSApplication(SDL_Missing_Methods) +- (void)setAppleMenu:(NSMenu *)menu; + at end + +/* Use this flag to determine whether we use SDLMain.nib or not */ +#define SDL_USE_NIB_FILE 0 + +/* Use this flag to determine whether we use CPS (docking) or not */ +#define SDL_USE_CPS 1 +#ifdef SDL_USE_CPS +/* Portions of CPS.h */ +typedef struct CPSProcessSerNum +{ + UInt32 lo; + UInt32 hi; +} CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +#endif /* SDL_USE_CPS */ + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +static BOOL gCalledAppMainline = FALSE; + +static NSString *getApplicationName(void) +{ + NSDictionary *dict; + NSString *appName = 0; + + /* Determine the application name */ + dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); + if (dict) + appName = [dict objectForKey: @"CFBundleName"]; + + if (![appName length]) + appName = [[NSProcessInfo processInfo] processName]; + + return appName; +} + +#if SDL_USE_NIB_FILE +/* A helper category for NSString */ + at interface NSString (ReplaceSubString) +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; + at end +#endif + + at interface SDLApplication : NSApplication + at end + + at implementation SDLApplication +/* Invoked from the Quit menu item */ +- (void)terminate:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); +} + at end + +/* The main class of the application, the application's delegate */ + at implementation SDLMain + +/* Set the working directory to the .app's parent directory */ +- (void) setupWorkingDirectory:(BOOL)shouldChdir +{ + if (shouldChdir) + { + char parentdir[MAXPATHLEN]; + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); + if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { + assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ + } + CFRelease(url); + CFRelease(url2); + } + +} + +#if SDL_USE_NIB_FILE + +/* Fix menu to contain the real app name instead of "SDL App" */ +- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName +{ + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; + + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; + + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } + [ aMenu sizeToFit ]; +} + +#else + +static void setApplicationMenu(void) +{ + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *title; + NSString *appName; + + appName = getApplicationName(); + appleMenu = [[NSMenu alloc] initWithTitle:@""]; + + /* Add menu items */ + title = [@"About " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; +} + +/* Create a window menu */ +static void setupWindowMenu(void) +{ + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; + + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; +} + +/* Replacement for NSApplicationMain */ +static void CustomApplicationMain (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + + /* Ensure the application object is initialised */ + [SDLApplication sharedApplication]; + +#ifdef SDL_USE_CPS + { + CPSProcessSerNum PSN; + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [SDLApplication sharedApplication]; + } +#endif /* SDL_USE_CPS */ + + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); + + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; +} + +#endif + + +/* + * Catch document open requests...this lets us notice files when the app + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. + * + * Files are added to gArgv, so to the app, they'll look like command line + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. + * + * This message may be received multiple times to open several docs on launch. + * + * This message is ignored once the app's mainline has been called. + */ +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + const char *temparg; + size_t arglen; + char *arg; + char **newargv; + + if (!gFinderLaunch) /* MacOS is passing command line args. */ + return FALSE; + + if (gCalledAppMainline) /* app has started, ignore this document. */ + return FALSE; + + temparg = [filename UTF8String]; + arglen = SDL_strlen(temparg) + 1; + arg = (char *) SDL_malloc(arglen); + if (arg == NULL) + return FALSE; + + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv; + + SDL_strlcpy(arg, temparg, arglen); + gArgv[gArgc++] = arg; + gArgv[gArgc] = NULL; + return TRUE; +} + + +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + +#if SDL_USE_NIB_FILE + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; +#endif + + /* Hand off to main application code */ + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} + at end + + + at implementation NSString (ReplaceSubString) + +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; +} + + at end + + + +#ifdef main +# undef main +#endif + + +/* Main entry point to executable - should *not* be SDL_main! */ +int main (int argc, char **argv) +{ + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } + +#if SDL_USE_NIB_FILE + [SDLApplication poseAsClass:[NSApplication class]]; + NSApplicationMain (argc, argv); +#else + CustomApplicationMain (argc, argv); +#endif + return 0; +} + diff --git a/rsdl/test/__init__.py b/rsdl/test/__init__.py new file mode 100644 diff --git a/rsdl/test/applause.wav b/rsdl/test/applause.wav new file mode 100644 index 0000000000000000000000000000000000000000..6d8358339785e5c31dfad2a89b3531abe8b9dae5 GIT binary patch [cut] diff --git a/rsdl/test/conftest.py b/rsdl/test/conftest.py new file mode 100644 --- /dev/null +++ b/rsdl/test/conftest.py @@ -0,0 +1,10 @@ +from pypy.rlib.rsdl.eci import check_sdl_installation, SDLNotInstalled +import py + +def pytest_ignore_collect(path): + try: + check_sdl_installation() + except SDLNotInstalled, e: + return True + else: + return False diff --git a/rsdl/test/demo.jpg b/rsdl/test/demo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0a7e1c2f43f25d28ace66c06736f3422c5d8e8c0 GIT binary patch [cut] diff --git a/rsdl/test/demo.png b/rsdl/test/demo.png new file mode 100644 index 0000000000000000000000000000000000000000..fa06ef56cce7e4d62edc180fb562b6350e4bb3bc GIT binary patch [cut] diff --git a/rsdl/test/test_basic.py b/rsdl/test/test_basic.py new file mode 100644 --- /dev/null +++ b/rsdl/test/test_basic.py @@ -0,0 +1,37 @@ +import py +from pypy.rlib.rsdl import RSDL +from pypy.rlib.rarithmetic import r_uint +from pypy.rpython.lltypesystem import rffi + + +def test_sdl_init(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + RSDL.Quit() + +def test_surface_basic(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + surface = RSDL.CreateRGBSurface(0, 150, 50, 32, + r_uint(0x000000FF), + r_uint(0x0000FF00), + r_uint(0x00FF0000), + r_uint(0xFF000000)) + assert surface + assert rffi.getintfield(surface, 'c_w') == 150 + assert rffi.getintfield(surface, 'c_h') == 50 + RSDL.FreeSurface(surface) + RSDL.Quit() + + +def test_get_keyname(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + assert RSDL.GetKeyName(RSDL.K_PLUS)[0] == '+' + assert RSDL.GetKeyName(RSDL.K_RIGHTPAREN)[0] == ')' + assert RSDL.GetKeyName(RSDL.K_z)[0] == 'z' + +def test_delay_getticks(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + RSDL.Delay(10) + i = RSDL.GetTicks() + assert i >= 10 + RSDL.Quit() + \ No newline at end of file diff --git a/rsdl/test/test_sdl_image.py b/rsdl/test/test_sdl_image.py new file mode 100644 --- /dev/null +++ b/rsdl/test/test_sdl_image.py @@ -0,0 +1,50 @@ +import py, os +from rsdl import RSDL, RIMG, RSDL_helper, test +from pypy.rpython.lltypesystem import lltype, rffi +this_dir = test.__path__[0] + + +def test_load_image(): + for filename in ["demo.jpg", "demo.png"]: + image = RIMG.Load(os.path.join(this_dir, filename)) + assert image + assert rffi.getintfield(image, 'c_w') == 17 + assert rffi.getintfield(image, 'c_h') == 23 + RSDL.FreeSurface(image) + +def test_image_pixels(): + for filename in ["demo.jpg", "demo.png"]: + image = RIMG.Load(os.path.join(this_dir, filename)) + assert image + assert rffi.getintfield(image.c_format, 'c_BytesPerPixel') in (3, 4) + RSDL.LockSurface(image) + result = {} + try: + rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') + try: + for y in range(23): + for x in range(y % 13, 17, 13): + color = RSDL_helper.get_pixel(image, x, y) + RSDL.GetRGB(color, + image.c_format, + rffi.ptradd(rgb, 0), + rffi.ptradd(rgb, 1), + rffi.ptradd(rgb, 2)) + r = rffi.cast(lltype.Signed, rgb[0]) + g = rffi.cast(lltype.Signed, rgb[1]) + b = rffi.cast(lltype.Signed, rgb[2]) + result[x, y] = r, g, b + finally: + lltype.free(rgb, flavor='raw') + finally: + RSDL.UnlockSurface(image) + RSDL.FreeSurface(image) + for x, y in result: + f = (x*17 + y*23) / float(17*17+23*23) + expected_r = int(255.0 * (1.0-f)) + expected_g = 0 + expected_b = int(255.0 * f) + r, g, b = result[x, y] + assert abs(r-expected_r) < 10 + assert abs(g-expected_g) < 10 + assert abs(b-expected_b) < 10 diff --git a/rsdl/test/test_sdl_mixer.py b/rsdl/test/test_sdl_mixer.py new file mode 100644 --- /dev/null +++ b/rsdl/test/test_sdl_mixer.py @@ -0,0 +1,32 @@ +import py +import os +import time +from pypy.rlib.rsdl import RSDL, RMix, RSDL_helper +from pypy.rpython.lltypesystem import lltype, rffi + +def test_open_mixer(): + if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: + error = rffi.charp2str(RSDL.GetError()) + raise Exception(error) + RMix.CloseAudio() + +def test_load_wav(): + if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: + error = rffi.charp2str(RSDL.GetError()) + raise Exception(error) + filename = rffi.str2charp('applause.wav') + RMix.LoadWAV(filename) + rffi.free_charp(filename) + RMix.CloseAudio() + +def test_play_wav(): + if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: + error = rffi.charp2str(RSDL.GetError()) + raise Exception(error) + filename = rffi.str2charp('applause.wav') + applause = RMix.LoadWAV(filename) + rffi.free_charp(filename) + RMix.PlayChannel(-1, applause, -1) + time.sleep(1) + RMix.CloseAudio() + diff --git a/rsdl/test/test_surface.py b/rsdl/test/test_surface.py new file mode 100644 --- /dev/null +++ b/rsdl/test/test_surface.py @@ -0,0 +1,75 @@ +import py, sys +from pypy.rlib.rsdl import RSDL, RSDL_helper +from pypy.rlib.rarithmetic import r_uint +from pypy.rpython.lltypesystem import lltype, rffi + +class TestSurface: + + def setup_method(self, meth): + self.dst_surf = RSDL.CreateRGBSurface(0, 300, 300, 32, + r_uint(0x000000FF), + r_uint(0x0000FF00), + r_uint(0x00FF0000), + r_uint(0x00000000)) + self.src_surf = RSDL.CreateRGBSurface(0, 50, 50, 32, + r_uint(0x000000FF), + r_uint(0x0000FF00), + r_uint(0x00FF0000), + r_uint(0x00000000)) + fmt = self.src_surf.c_format + self.black = RSDL.MapRGB(fmt, 0, 0, 0) + self.red = RSDL.MapRGB(fmt, 255, 0, 0) + self.blue = RSDL.MapRGB(fmt, 0, 0, 255) + RSDL.FillRect(self.src_surf, lltype.nullptr(RSDL.Rect), self.red) + + def test_simple(self): + pass # only checks that creating the surfaces works + + def test_set_alpha(self): + # prepare + assert RSDL.SetAlpha(self.src_surf, RSDL.SRCALPHA, 128) == 0 + + # draw + RSDL_helper.blit_complete_surface( + self.src_surf, + self.dst_surf, + 10, 10) + RSDL_helper.blit_complete_surface( + self.src_surf, + self.dst_surf, + 20, 20) + + # check + for position, color in ( + (( 0, 0), ( 0,0,0)), # no rect + ((10,10), (127,0,0)), # one rect + ((20,20), (191,0,0)) # two overlapping rects + ): + fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) + assert RSDL_helper.get_rgb(fetched_color, self.dst_surf.c_format) == color + + def test_set_color_key(self): + # prepare + fillrect = RSDL_helper.mallocrect(10, 10, 30, 30) + RSDL.FillRect(self.src_surf, fillrect, self.blue) + lltype.free(fillrect, flavor='raw') + assert RSDL.SetColorKey(self.src_surf, RSDL.SRCCOLORKEY, self.blue) == 0 + + # draw + RSDL_helper.blit_complete_surface(self.src_surf, self.dst_surf, 0, 0) + + # check + for position, color in ( + (( 0, 0), self.red), + ((10,10), self.black), + ((20,20), self.black), + ((40,40), self.red) + ): + fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) + assert fetched_color == color + + def teardown_method(self, meth): + RSDL.FreeSurface(self.src_surf) + RSDL.FreeSurface(self.dst_surf) + RSDL.Quit() + diff --git a/rsdl/test/test_video.py b/rsdl/test/test_video.py new file mode 100644 --- /dev/null +++ b/rsdl/test/test_video.py @@ -0,0 +1,241 @@ + +import py, sys +from pypy.rlib.rsdl import RSDL, RSDL_helper +from pypy.rlib.rarithmetic import r_uint +from pypy.rpython.lltypesystem import lltype, rffi + +# +# This test file is skipped unless run with "py.test --view". +# If it is run as "py.test --view -s", then it interactively asks +# for confirmation that the window looks as expected. +# XXX always run for now. +# + + +class TestVideo: + + def setup_method(self, meth): + #if not conftest.option.view: + # py.test.skip("'--view' not specified, " + # "skipping tests that open a window") + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + self.screen = RSDL.SetVideoMode(640, 480, 32, 0) + assert self.screen + self.is_interactive = sys.stdout.isatty() + + def check(self, msg): + if self.is_interactive: + print + answer = raw_input('Interactive test: %s - ok? [Y] ' % msg) + if answer and not answer.upper().startswith('Y'): + py.test.fail(msg) + else: + print msg + + def test_simple(self): + pass # only checks that opening and closing the window works + + def test_fillrect_full(self): + fmt = self.screen.c_format + for colorname, r, g, b in [('dark red', 128, 0, 0), + ('yellow', 255, 255, 0), + ('blue', 0, 0, 255)]: + color = RSDL.MapRGB(fmt, r, g, b) + RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) + RSDL.Flip(self.screen) + self.check("Screen filled with %s" % colorname) + + def test_caption(self): + RSDL.WM_SetCaption("Hello World!", "Hello World!") + self.check('The window caption is "Hello World!"') + + def test_keypresses(self): + if not self.is_interactive: + py.test.skip("interactive test only") + RSDL.EnableUNICODE(1) + print + print "Keys pressed in the Pygame window should be printed below." + print " Use Escape to quit." + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + while True: + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.KEYDOWN: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + print 'Escape key' + break + char = rffi.getintfield(p.c_keysym, 'c_unicode') + if char != 0: + print 'Key:', unichr(char).encode('utf-8') + else: + print 'Some special key' + else: + print '(event of type %d)' % c_type + finally: + lltype.free(event, flavor='raw') + + def test_poll(self): + if not self.is_interactive: + py.test.skip("interactive test only") + import time, sys + RSDL.EnableUNICODE(1) + print + print "Keys pressed in the Pygame window give a dot." + print " Wait 3 seconds to quit." + timeout = time.time() + 3 + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + while True: + # busy polling + ok = RSDL.PollEvent(event) + ok = rffi.cast(lltype.Signed, ok) + assert ok >= 0 + if ok > 0: + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.KEYDOWN: + sys.stderr.write('.') + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + print 'Escape key' + break + timeout = time.time() + 3 + else: + if time.time() > timeout: + break + time.sleep(0.05) + finally: + lltype.free(event, flavor='raw') + + def test_mousemove(self): + if not self.is_interactive: + py.test.skip("interactive test only") + print + print "Move the Mouse up and down:" + print " Use Escape to quit." + event = lltype.malloc(RSDL.Event, flavor="raw") + directions = [False]*4 + try: + while True: + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + c_type = rffi.getintfield(event, "c_type") + if c_type == RSDL.MOUSEMOTION: + m = rffi.cast(RSDL.MouseMotionEventPtr, event) + assert rffi.getintfield(m, "c_x") >= 0 + assert rffi.getintfield(m, "c_y") >= 0 + print rffi.getintfield(m, "c_xrel") + directions[0] |= rffi.getintfield(m, "c_xrel")>0 + directions[1] |= rffi.getintfield(m, "c_xrel")<0 + directions[2] |= rffi.getintfield(m, "c_yrel")>0 + directions[3] |= rffi.getintfield(m, "c_yrel")<0 + if False not in directions: + break + elif c_type == RSDL.KEYUP: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + print " test manually aborted" + py.test.fail(" mousemovement test aborted") + break + finally: + lltype.free(event, flavor='raw') + + + def test_mousebutton_wheel(self): + if not self.is_interactive: + py.test.skip("interactive test only") + print + print "Press the given MouseButtons:" + print " Use Escape to pass tests." + + event_tests = [("left button", RSDL.BUTTON_LEFT), + ("middle button", RSDL.BUTTON_MIDDLE), + ("right button", RSDL.BUTTON_RIGHT), + ("scroll up", RSDL.BUTTON_WHEELUP), + ("scroll down", RSDL.BUTTON_WHEELDOWN)] + test_success = [] + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + for button_test in event_tests: + print " press %s:" % button_test[0] + while True: + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.MOUSEBUTTONDOWN: + pass + elif c_type == RSDL.MOUSEBUTTONUP: + b = rffi.cast(RSDL.MouseButtonEventPtr, event) + if rffi.getintfield(b, 'c_button') == button_test[1]: + test_success.append(True) + break + elif c_type == RSDL.KEYUP: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + test_success.append(False) + print " manually aborted" + break + #break + if False in test_success: + py.test.fail("") + finally: + lltype.free(event, flavor='raw') + + + def test_show_hide_cursor(self): + RSDL.ShowCursor(RSDL.DISABLE) + self.check("Is the cursor hidden? ") + RSDL.ShowCursor(RSDL.ENABLE) + self.check("Is the cursor shown? ") + + def test_bit_pattern(self): + HEIGHT = WIDTH = 10 + fmt = self.screen.c_format + white = RSDL.MapRGB(fmt, 255, 255, 255) + black = RSDL.MapRGB(fmt, 0, 0, 0) + RSDL.LockSurface(self.screen) + for i in xrange(WIDTH): + for j in xrange(HEIGHT): + k = j*WIDTH + i + if k % 2: + c = white + else: + c = black + RSDL_helper.set_pixel(self.screen, i, j, c) + RSDL.UnlockSurface(self.screen) + RSDL.Flip(self.screen) + self.check("Upper left corner 10x10 field with vertical black/white stripes") + + def test_blit_rect(self): + surface = RSDL.CreateRGBSurface(0, 150, 50, 32, + r_uint(0x000000FF), + r_uint(0x0000FF00), + r_uint(0x00FF0000), + r_uint(0xFF000000)) + fmt = surface.c_format + color = RSDL.MapRGB(fmt, 255, 0, 0) + RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) + + paintrect = RSDL_helper.mallocrect(75, 0, 150, 50) + dstrect = lltype.malloc(RSDL.Rect, flavor='raw') + try: + color = RSDL.MapRGB(fmt, 255, 128, 0) + RSDL.FillRect(surface, paintrect, color) + + rffi.setintfield(dstrect, 'c_x', 10) + rffi.setintfield(dstrect, 'c_y', 10) + rffi.setintfield(dstrect, 'c_w', 150) + rffi.setintfield(dstrect, 'c_h', 50) + RSDL.BlitSurface(surface, lltype.nullptr(RSDL.Rect), self.screen, dstrect) + RSDL.Flip(self.screen) + finally: + lltype.free(dstrect, flavor='raw') + lltype.free(paintrect, flavor='raw') + RSDL.FreeSurface(surface) + self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border") + + def teardown_method(self, meth): + RSDL.Quit() + From noreply at buildbot.pypy.org Tue Jun 5 09:57:53 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:57:53 +0200 (CEST) Subject: [pypy-commit] pypy default: Kill this method. This adds yet another special case which Message-ID: <20120605075753.BE7441C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55297:d4ed2c8ac9b1 Date: 2012-06-03 19:52 +0200 http://bitbucket.org/pypy/pypy/changeset/d4ed2c8ac9b1/ Log: Kill this method. This adds yet another special case which can potentially break code. diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py --- a/lib_pypy/_ctypes/basics.py +++ b/lib_pypy/_ctypes/basics.py @@ -47,10 +47,6 @@ else: return self.from_param(as_parameter) - def get_ffi_param(self, value): - cdata = self.from_param(value) - return cdata, cdata._to_ffi_param() - def get_ffi_argtype(self): if self._ffiargtype: return self._ffiargtype diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -444,10 +444,6 @@ @classmethod def _conv_param(cls, argtype, arg): - if isinstance(argtype, _CDataMeta): - cobj, ffiparam = argtype.get_ffi_param(arg) - return cobj, ffiparam, argtype - if argtype is not None: arg = argtype.from_param(arg) if hasattr(arg, '_as_parameter_'): From noreply at buildbot.pypy.org Tue Jun 5 09:58:00 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:58:00 +0200 (CEST) Subject: [pypy-commit] pypy default: Write a test for d4ed2c8ac9b1 (thanks lahwran for reporting it) Message-ID: <20120605075800.77A331C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55298:f772351ebc1b Date: 2012-06-03 20:23 +0200 http://bitbucket.org/pypy/pypy/changeset/f772351ebc1b/ Log: Write a test for d4ed2c8ac9b1 (thanks lahwran for reporting it) diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py @@ -484,6 +484,20 @@ assert tf_b(-126) == -42 assert tf_b._ptr is ptr + def test_custom_from_param(self): + class A(c_byte): + @classmethod + def from_param(cls, obj): + seen.append(obj) + return -126 + tf_b = dll.tf_b + tf_b.restype = c_byte + tf_b.argtypes = (c_byte,) + tf_b.argtypes = [A] + seen = [] + assert tf_b("yadda") == -42 + assert seen == ["yadda"] + def test_warnings(self): import warnings warnings.simplefilter("always") From noreply at buildbot.pypy.org Tue Jun 5 09:58:07 2012 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 5 Jun 2012 09:58:07 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: pass flags into _ffi's Func.from_addr Message-ID: <20120605075807.312001C003C@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55299:cc265a91e7de Date: 2012-06-03 23:33 +0300 http://bitbucket.org/pypy/pypy/changeset/cc265a91e7de/ Log: pass flags into _ffi's Func.from_addr diff --git a/lib-python/2.7/ctypes/__init__.py b/lib-python/2.7/ctypes/__init__.py --- a/lib-python/2.7/ctypes/__init__.py +++ b/lib-python/2.7/ctypes/__init__.py @@ -351,7 +351,10 @@ self._FuncPtr = _FuncPtr if handle is None: - self._handle = _ffi.CDLL(name, mode) + if flags & _FUNCFLAG_CDECL: + self._handle = _ffi.CDLL(name, mode) + else: + self._handle = _ffi.WinDLL(name, mode) else: self._handle = handle diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -391,7 +391,7 @@ address = self._get_address() ffiargs = [argtype.get_ffi_argtype() for argtype in argtypes] ffires = restype.get_ffi_argtype() - return _ffi.FuncPtr.fromaddr(address, '', ffiargs, ffires) + return _ffi.FuncPtr.fromaddr(address, '', ffiargs, ffires, self._flags_) def _getfuncptr(self, argtypes, restype, thisarg=None): if self._ptr is not None and (argtypes is self._argtypes_ or argtypes == self._argtypes_): @@ -412,7 +412,7 @@ ptr = thisarg[0][self._com_index - 0x1000] ffiargs = [argtype.get_ffi_argtype() for argtype in argtypes] ffires = restype.get_ffi_argtype() - return _ffi.FuncPtr.fromaddr(ptr, '', ffiargs, ffires) + return _ffi.FuncPtr.fromaddr(ptr, '', ffiargs, ffires, self._flags_) cdll = self.dll._handle try: diff --git a/pypy/module/_ffi/interp_funcptr.py b/pypy/module/_ffi/interp_funcptr.py --- a/pypy/module/_ffi/interp_funcptr.py +++ b/pypy/module/_ffi/interp_funcptr.py @@ -234,13 +234,14 @@ restype = unwrap_ffitype(space, w_restype, allow_void=True) return argtypes_w, argtypes, w_restype, restype - at unwrap_spec(addr=r_uint, name=str) -def descr_fromaddr(space, w_cls, addr, name, w_argtypes, w_restype): + at unwrap_spec(addr=r_uint, name=str, flags=int) +def descr_fromaddr(space, w_cls, addr, name, w_argtypes, + w_restype, flags=libffi.FUNCFLAG_CDECL): argtypes_w, argtypes, w_restype, restype = unpack_argtypes(space, w_argtypes, w_restype) addr = rffi.cast(rffi.VOIDP, addr) - func = libffi.Func(name, argtypes, restype, addr) + func = libffi.Func(name, argtypes, restype, addr, flags) return W_FuncPtr(func, argtypes_w, w_restype) diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py --- a/pypy/module/_ffi/test/test_funcptr.py +++ b/pypy/module/_ffi/test/test_funcptr.py @@ -599,3 +599,32 @@ assert e.message.startswith('Procedure called with') else: assert 0, 'test must assert, wrong calling convention' + + def test_func_fromaddr2(self): + if not self.iswin32: + skip("windows specific") + from _ffi import CDLL, types, FuncPtr + from _rawffi import FUNCFLAG_STDCALL + libm = CDLL(self.libm_name) + pow_addr = libm.getaddressindll('pow') + wrong_pow = FuncPtr.fromaddr(pow_addr, 'pow', + [types.double, types.double], types.double, FUNCFLAG_STDCALL) + try: + wrong_pow(2, 3) == 8 + except ValueError, e: + assert e.message.startswith('Procedure called with') + else: + assert 0, 'test must assert, wrong calling convention' + + def test_func_fromaddr3(self): + if not self.iswin32: + skip("windows specific") + from _ffi import WinDLL, types, FuncPtr + from _rawffi import FUNCFLAG_STDCALL + kernel = WinDLL('Kernel32.dll') + sleep_addr = kernel.getaddressindll('Sleep') + sleep = FuncPtr.fromaddr(sleep_addr, 'sleep', [types.uint], + types.void, FUNCFLAG_STDCALL) + sleep(10) + + From noreply at buildbot.pypy.org Tue Jun 5 09:58:14 2012 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 5 Jun 2012 09:58:14 +0200 (CEST) Subject: [pypy-commit] pypy win_ffi: merge default into branch Message-ID: <20120605075814.5B9521C003C@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: win_ffi Changeset: r55300:b2be8b853d7e Date: 2012-06-04 07:43 +0300 http://bitbucket.org/pypy/pypy/changeset/b2be8b853d7e/ Log: merge default into branch diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py --- a/lib_pypy/_ctypes/basics.py +++ b/lib_pypy/_ctypes/basics.py @@ -47,10 +47,6 @@ else: return self.from_param(as_parameter) - def get_ffi_param(self, value): - cdata = self.from_param(value) - return cdata, cdata._to_ffi_param() - def get_ffi_argtype(self): if self._ffiargtype: return self._ffiargtype diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -444,10 +444,6 @@ @classmethod def _conv_param(cls, argtype, arg): - if isinstance(argtype, _CDataMeta): - cobj, ffiparam = argtype.get_ffi_param(arg) - return cobj, ffiparam, argtype - if argtype is not None: arg = argtype.from_param(arg) if hasattr(arg, '_as_parameter_'): diff --git a/lib_pypy/ctypes_support.py b/lib_pypy/ctypes_support.py --- a/lib_pypy/ctypes_support.py +++ b/lib_pypy/ctypes_support.py @@ -12,6 +12,8 @@ if sys.platform == 'win32': import _ffi standard_c_lib = ctypes.CDLL('msvcrt', handle=_ffi.get_libc()) +elif sys.platform == 'cygwin': + standard_c_lib = ctypes.CDLL(ctypes.util.find_library('cygwin')) else: standard_c_lib = ctypes.CDLL(ctypes.util.find_library('c')) diff --git a/pypy/bin/rpython b/pypy/bin/rpython old mode 100644 new mode 100755 diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst --- a/pypy/doc/whatsnew-1.9.rst +++ b/pypy/doc/whatsnew-1.9.rst @@ -5,8 +5,12 @@ .. this is the revision just after the creation of the release-1.8.x branch .. startrev: a4261375b359 +.. branch: default +* Working hash function for numpy types. + .. branch: array_equal .. branch: better-jit-hooks-2 +Improved jit hooks .. branch: faster-heapcache .. branch: faster-str-decode-escape .. branch: float-bytes @@ -16,9 +20,14 @@ .. branch: jit-frame-counter Put more debug info into resops. .. branch: kill-geninterp +Kill "geninterp", an old attempt to statically turn some fixed +app-level code to interp-level. .. branch: kqueue Finished select.kqueue. .. branch: kwargsdict-strategy +Special dictionary strategy for dealing with \*\*kwds. Now having a simple +proxy ``def f(*args, **kwds): return x(*args, **kwds`` should not make +any allocations at all. .. branch: matrixmath-dot numpypy can now handle matrix multiplication. .. branch: merge-2.7.2 @@ -29,13 +38,19 @@ cpyext: Better support for PyEval_SaveThread and other PyTreadState_* functions. .. branch: numppy-flatitter +flatitier for numpy .. branch: numpy-back-to-applevel +reuse more of original numpy .. branch: numpy-concatenate +concatenation support for numpy .. branch: numpy-indexing-by-arrays-bool +indexing by bool arrays .. branch: numpy-record-dtypes +record dtypes on numpy has been started .. branch: numpy-single-jitdriver .. branch: numpy-ufuncs2 .. branch: numpy-ufuncs3 +various refactorings regarding numpy .. branch: numpypy-issue1137 .. branch: numpypy-out The "out" argument was added to most of the numypypy functions. @@ -43,8 +58,13 @@ .. branch: numpypy-ufuncs .. branch: pytest .. branch: safe-getargs-freelist +CPyext improvements. For example PyOpenSSL should now work .. branch: set-strategies +Sets now have strategies just like dictionaries. This means a set +containing only ints will be more compact (and faster) .. branch: speedup-list-comprehension +The simplest case of list comprehension is preallocating the correct size +of the list. This speeds up select benchmarks quite significantly. .. branch: stdlib-unification The directory "lib-python/modified-2.7" has been removed, and its content merged into "lib-python/2.7". @@ -66,6 +86,7 @@ Add os.kill to windows even if translating python does not have os.kill .. branch: win64-stage1 .. branch: zlib-mem-pressure +Memory "leaks" associated with zlib are fixed. .. branch: ffistruct The ``ffistruct`` branch adds a very low level way to express C structures diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py --- a/pypy/jit/backend/llsupport/gc.py +++ b/pypy/jit/backend/llsupport/gc.py @@ -577,7 +577,6 @@ def __init__(self, gc_ll_descr): self.llop1 = gc_ll_descr.llop1 self.WB_FUNCPTR = gc_ll_descr.WB_FUNCPTR - self.WB_ARRAY_FUNCPTR = gc_ll_descr.WB_ARRAY_FUNCPTR self.fielddescr_tid = gc_ll_descr.fielddescr_tid # GCClass = gc_ll_descr.GCClass @@ -592,6 +591,11 @@ self.jit_wb_card_page_shift = GCClass.JIT_WB_CARD_PAGE_SHIFT self.jit_wb_cards_set_byteofs, self.jit_wb_cards_set_singlebyte = ( self.extract_flag_byte(self.jit_wb_cards_set)) + # + # the x86 backend uses the following "accidental" facts to + # avoid one instruction: + assert self.jit_wb_cards_set_byteofs == self.jit_wb_if_flag_byteofs + assert self.jit_wb_cards_set_singlebyte == -0x80 else: self.jit_wb_cards_set = 0 @@ -615,7 +619,7 @@ # returns a function with arguments [array, index, newvalue] llop1 = self.llop1 funcptr = llop1.get_write_barrier_from_array_failing_case( - self.WB_ARRAY_FUNCPTR) + self.WB_FUNCPTR) funcaddr = llmemory.cast_ptr_to_adr(funcptr) return cpu.cast_adr_to_int(funcaddr) # this may return 0 @@ -699,9 +703,7 @@ def _setup_write_barrier(self): self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( - [llmemory.Address, llmemory.Address], lltype.Void)) - self.WB_ARRAY_FUNCPTR = lltype.Ptr(lltype.FuncType( - [llmemory.Address, lltype.Signed, llmemory.Address], lltype.Void)) + [llmemory.Address], lltype.Void)) self.write_barrier_descr = WriteBarrierDescr(self) def _make_functions(self, really_not_translated): @@ -859,8 +861,7 @@ # the GC, and call it immediately llop1 = self.llop1 funcptr = llop1.get_write_barrier_failing_case(self.WB_FUNCPTR) - funcptr(llmemory.cast_ptr_to_adr(gcref_struct), - llmemory.cast_ptr_to_adr(gcref_newptr)) + funcptr(llmemory.cast_ptr_to_adr(gcref_struct)) def can_use_nursery_malloc(self, size): return size < self.max_size_of_young_obj diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py --- a/pypy/jit/backend/test/runner_test.py +++ b/pypy/jit/backend/test/runner_test.py @@ -1835,12 +1835,12 @@ assert not excvalue def test_cond_call_gc_wb(self): - def func_void(a, b): - record.append((a, b)) + def func_void(a): + record.append(a) record = [] # S = lltype.GcStruct('S', ('tid', lltype.Signed)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Ptr(S)], lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): @@ -1866,26 +1866,25 @@ [BoxPtr(sgcref), ConstPtr(tgcref)], 'void', descr=WriteBarrierDescr()) if cond: - assert record == [(s, t)] + assert record == [s] else: assert record == [] def test_cond_call_gc_wb_array(self): - def func_void(a, b, c): - record.append((a, b, c)) + def func_void(a): + record.append(a) record = [] # S = lltype.GcStruct('S', ('tid', lltype.Signed)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)], - lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): jit_wb_if_flag = 4096 jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10') jit_wb_if_flag_singlebyte = 0x10 - jit_wb_cards_set = 0 - def get_write_barrier_from_array_fn(self, cpu): + jit_wb_cards_set = 0 # <= without card marking + def get_write_barrier_fn(self, cpu): return funcbox.getint() # for cond in [False, True]: @@ -1902,13 +1901,15 @@ [BoxPtr(sgcref), ConstInt(123), BoxPtr(sgcref)], 'void', descr=WriteBarrierDescr()) if cond: - assert record == [(s, 123, s)] + assert record == [s] else: assert record == [] def test_cond_call_gc_wb_array_card_marking_fast_path(self): - def func_void(a, b, c): - record.append((a, b, c)) + def func_void(a): + record.append(a) + if cond == 1: # the write barrier sets the flag + s.data.tid |= 32768 record = [] # S = lltype.Struct('S', ('tid', lltype.Signed)) @@ -1922,34 +1923,40 @@ ('card6', lltype.Char), ('card7', lltype.Char), ('data', S)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)], - lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): jit_wb_if_flag = 4096 jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10') jit_wb_if_flag_singlebyte = 0x10 - jit_wb_cards_set = 8192 - jit_wb_cards_set_byteofs = struct.pack("i", 8192).index('\x20') - jit_wb_cards_set_singlebyte = 0x20 + jit_wb_cards_set = 32768 + jit_wb_cards_set_byteofs = struct.pack("i", 32768).index('\x80') + jit_wb_cards_set_singlebyte = -0x80 jit_wb_card_page_shift = 7 def get_write_barrier_from_array_fn(self, cpu): return funcbox.getint() # - for BoxIndexCls in [BoxInt, ConstInt]: - for cond in [False, True]: + for BoxIndexCls in [BoxInt, ConstInt]*3: + for cond in [-1, 0, 1, 2]: + # cond=-1:GCFLAG_TRACK_YOUNG_PTRS, GCFLAG_CARDS_SET are not set + # cond=0: GCFLAG_CARDS_SET is never set + # cond=1: GCFLAG_CARDS_SET is not set, but the wb sets it + # cond=2: GCFLAG_CARDS_SET is already set print print '_'*79 print 'BoxIndexCls =', BoxIndexCls - print 'JIT_WB_CARDS_SET =', cond + print 'testing cond =', cond print value = random.randrange(-sys.maxint, sys.maxint) - value |= 4096 - if cond: - value |= 8192 + if cond >= 0: + value |= 4096 else: - value &= ~8192 + value &= ~4096 + if cond == 2: + value |= 32768 + else: + value &= ~32768 s = lltype.malloc(S_WITH_CARDS, immortal=True, zero=True) s.data.tid = value sgcref = rffi.cast(llmemory.GCREF, s.data) @@ -1958,11 +1965,13 @@ self.execute_operation(rop.COND_CALL_GC_WB_ARRAY, [BoxPtr(sgcref), box_index, BoxPtr(sgcref)], 'void', descr=WriteBarrierDescr()) - if cond: + if cond in [0, 1]: + assert record == [s.data] + else: assert record == [] + if cond in [1, 2]: assert s.card6 == '\x02' else: - assert record == [(s.data, (9<<7) + 17, s.data)] assert s.card6 == '\x00' assert s.card0 == '\x00' assert s.card1 == '\x00' @@ -1971,6 +1980,9 @@ assert s.card4 == '\x00' assert s.card5 == '\x00' assert s.card7 == '\x00' + if cond == 1: + value |= 32768 + assert s.data.tid == value def test_force_operations_returning_void(self): values = [] diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py --- a/pypy/jit/backend/x86/assembler.py +++ b/pypy/jit/backend/x86/assembler.py @@ -10,7 +10,7 @@ from pypy.rlib.jit import AsmInfo from pypy.jit.backend.model import CompiledLoopToken from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale, - gpr_reg_mgr_cls, _valid_addressing_size) + gpr_reg_mgr_cls, xmm_reg_mgr_cls, _valid_addressing_size) from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD, IS_X86_32, IS_X86_64) @@ -83,6 +83,7 @@ self.float_const_abs_addr = 0 self.malloc_slowpath1 = 0 self.malloc_slowpath2 = 0 + self.wb_slowpath = [0, 0, 0, 0] self.memcpy_addr = 0 self.setup_failure_recovery() self._debug = False @@ -109,9 +110,13 @@ self.memcpy_addr = self.cpu.cast_ptr_to_int(support.memcpy_fn) self._build_failure_recovery(False) self._build_failure_recovery(True) + self._build_wb_slowpath(False) + self._build_wb_slowpath(True) if self.cpu.supports_floats: self._build_failure_recovery(False, withfloats=True) self._build_failure_recovery(True, withfloats=True) + self._build_wb_slowpath(False, withfloats=True) + self._build_wb_slowpath(True, withfloats=True) support.ensure_sse2_floats() self._build_float_constants() self._build_propagate_exception_path() @@ -344,6 +349,82 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.stack_check_slowpath = rawstart + def _build_wb_slowpath(self, withcards, withfloats=False): + descr = self.cpu.gc_ll_descr.write_barrier_descr + if descr is None: + return + if not withcards: + func = descr.get_write_barrier_fn(self.cpu) + else: + if descr.jit_wb_cards_set == 0: + return + func = descr.get_write_barrier_from_array_fn(self.cpu) + if func == 0: + return + # + # This builds a helper function called from the slow path of + # write barriers. It must save all registers, and optionally + # all XMM registers. It takes a single argument just pushed + # on the stack even on X86_64. It must restore stack alignment + # accordingly. + mc = codebuf.MachineCodeBlockWrapper() + # + frame_size = (1 + # my argument, considered part of my frame + 1 + # my return address + len(gpr_reg_mgr_cls.save_around_call_regs)) + if withfloats: + frame_size += 16 # X86_32: 16 words for 8 registers; + # X86_64: just 16 registers + if IS_X86_32: + frame_size += 1 # argument to pass to the call + # + # align to a multiple of 16 bytes + frame_size = (frame_size + (CALL_ALIGN-1)) & ~(CALL_ALIGN-1) + # + correct_esp_by = (frame_size - 2) * WORD + mc.SUB_ri(esp.value, correct_esp_by) + # + ofs = correct_esp_by + if withfloats: + for reg in xmm_reg_mgr_cls.save_around_call_regs: + ofs -= 8 + mc.MOVSD_sx(ofs, reg.value) + for reg in gpr_reg_mgr_cls.save_around_call_regs: + ofs -= WORD + mc.MOV_sr(ofs, reg.value) + # + if IS_X86_32: + mc.MOV_rs(eax.value, (frame_size - 1) * WORD) + mc.MOV_sr(0, eax.value) + elif IS_X86_64: + mc.MOV_rs(edi.value, (frame_size - 1) * WORD) + mc.CALL(imm(func)) + # + if withcards: + # A final TEST8 before the RET, for the caller. Careful to + # not follow this instruction with another one that changes + # the status of the CPU flags! + mc.MOV_rs(eax.value, (frame_size - 1) * WORD) + mc.TEST8(addr_add_const(eax, descr.jit_wb_if_flag_byteofs), + imm(-0x80)) + # + ofs = correct_esp_by + if withfloats: + for reg in xmm_reg_mgr_cls.save_around_call_regs: + ofs -= 8 + mc.MOVSD_xs(reg.value, ofs) + for reg in gpr_reg_mgr_cls.save_around_call_regs: + ofs -= WORD + mc.MOV_rs(reg.value, ofs) + # + # ADD esp, correct_esp_by --- but cannot use ADD, because + # of its effects on the CPU flags + mc.LEA_rs(esp.value, correct_esp_by) + mc.RET16_i(WORD) + # + rawstart = mc.materialize(self.cpu.asmmemmgr, []) + self.wb_slowpath[withcards + 2 * withfloats] = rawstart + @staticmethod @rgc.no_collect def _release_gil_asmgcc(css): @@ -2324,102 +2405,83 @@ def genop_discard_cond_call_gc_wb(self, op, arglocs): # Write code equivalent to write_barrier() in the GC: it checks - # a flag in the object at arglocs[0], and if set, it calls the - # function remember_young_pointer() from the GC. The arguments - # to the call are in arglocs[:N]. The rest, arglocs[N:], contains - # registers that need to be saved and restored across the call. - # N is either 2 (regular write barrier) or 3 (array write barrier). + # a flag in the object at arglocs[0], and if set, it calls a + # helper piece of assembler. The latter saves registers as needed + # and call the function jit_remember_young_pointer() from the GC. descr = op.getdescr() if we_are_translated(): cls = self.cpu.gc_ll_descr.has_write_barrier_class() assert cls is not None and isinstance(descr, cls) # opnum = op.getopnum() - if opnum == rop.COND_CALL_GC_WB: - N = 2 - func = descr.get_write_barrier_fn(self.cpu) - card_marking = False - elif opnum == rop.COND_CALL_GC_WB_ARRAY: - N = 3 - func = descr.get_write_barrier_from_array_fn(self.cpu) - assert func != 0 - card_marking = descr.jit_wb_cards_set != 0 - else: - raise AssertionError(opnum) + card_marking = False + mask = descr.jit_wb_if_flag_singlebyte + if opnum == rop.COND_CALL_GC_WB_ARRAY and descr.jit_wb_cards_set != 0: + # assumptions the rest of the function depends on: + assert (descr.jit_wb_cards_set_byteofs == + descr.jit_wb_if_flag_byteofs) + assert descr.jit_wb_cards_set_singlebyte == -0x80 + card_marking = True + mask = descr.jit_wb_if_flag_singlebyte | -0x80 # loc_base = arglocs[0] self.mc.TEST8(addr_add_const(loc_base, descr.jit_wb_if_flag_byteofs), - imm(descr.jit_wb_if_flag_singlebyte)) + imm(mask)) self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later jz_location = self.mc.get_relative_pos() # for cond_call_gc_wb_array, also add another fast path: # if GCFLAG_CARDS_SET, then we can just set one bit and be done if card_marking: - self.mc.TEST8(addr_add_const(loc_base, - descr.jit_wb_cards_set_byteofs), - imm(descr.jit_wb_cards_set_singlebyte)) - self.mc.J_il8(rx86.Conditions['NZ'], 0) # patched later - jnz_location = self.mc.get_relative_pos() + # GCFLAG_CARDS_SET is in this byte at 0x80, so this fact can + # been checked by the status flags of the previous TEST8 + self.mc.J_il8(rx86.Conditions['S'], 0) # patched later + js_location = self.mc.get_relative_pos() else: - jnz_location = 0 + js_location = 0 - # the following is supposed to be the slow path, so whenever possible - # we choose the most compact encoding over the most efficient one. - if IS_X86_32: - limit = -1 # push all arglocs on the stack - elif IS_X86_64: - limit = N - 1 # push only arglocs[N:] on the stack - for i in range(len(arglocs)-1, limit, -1): - loc = arglocs[i] - if isinstance(loc, RegLoc): - self.mc.PUSH_r(loc.value) - else: - assert not IS_X86_64 # there should only be regs in arglocs[N:] - self.mc.PUSH_i32(loc.getint()) - if IS_X86_64: - # We clobber these registers to pass the arguments, but that's - # okay, because consider_cond_call_gc_wb makes sure that any - # caller-save registers with values in them are present in - # arglocs[N:] too, so they are saved on the stack above and - # restored below. - if N == 2: - callargs = [edi, esi] - else: - callargs = [edi, esi, edx] - remap_frame_layout(self, arglocs[:N], callargs, - X86_64_SCRATCH_REG) + # Write only a CALL to the helper prepared in advance, passing it as + # argument the address of the structure we are writing into + # (the first argument to COND_CALL_GC_WB). + helper_num = card_marking + if self._regalloc.xrm.reg_bindings: + helper_num += 2 + if self.wb_slowpath[helper_num] == 0: # tests only + assert not we_are_translated() + self.cpu.gc_ll_descr.write_barrier_descr = descr + self._build_wb_slowpath(card_marking, + bool(self._regalloc.xrm.reg_bindings)) + assert self.wb_slowpath[helper_num] != 0 # - # misaligned stack in the call, but it's ok because the write barrier - # is not going to call anything more. Also, this assumes that the - # write barrier does not touch the xmm registers. (Slightly delicate - # assumption, given that the write barrier can end up calling the - # platform's malloc() from AddressStack.append(). XXX may need to - # be done properly) - self.mc.CALL(imm(func)) - if IS_X86_32: - self.mc.ADD_ri(esp.value, N*WORD) - for i in range(N, len(arglocs)): - loc = arglocs[i] - assert isinstance(loc, RegLoc) - self.mc.POP_r(loc.value) + self.mc.PUSH(loc_base) + self.mc.CALL(imm(self.wb_slowpath[helper_num])) - # if GCFLAG_CARDS_SET, then we can do the whole thing that would - # be done in the CALL above with just four instructions, so here - # is an inline copy of them if card_marking: - self.mc.JMP_l8(0) # jump to the exit, patched later - jmp_location = self.mc.get_relative_pos() - # patch the JNZ above - offset = self.mc.get_relative_pos() - jnz_location + # The helper ends again with a check of the flag in the object. + # So here, we can simply write again a 'JNS', which will be + # taken if GCFLAG_CARDS_SET is still not set. + self.mc.J_il8(rx86.Conditions['NS'], 0) # patched later + jns_location = self.mc.get_relative_pos() + # + # patch the JS above + offset = self.mc.get_relative_pos() - js_location assert 0 < offset <= 127 - self.mc.overwrite(jnz_location-1, chr(offset)) + self.mc.overwrite(js_location-1, chr(offset)) # + # case GCFLAG_CARDS_SET: emit a few instructions to do + # directly the card flag setting loc_index = arglocs[1] if isinstance(loc_index, RegLoc): - # choose a scratch register - tmp1 = loc_index - self.mc.PUSH_r(tmp1.value) + if IS_X86_64 and isinstance(loc_base, RegLoc): + # copy loc_index into r11 + tmp1 = X86_64_SCRATCH_REG + self.mc.MOV_rr(tmp1.value, loc_index.value) + final_pop = False + else: + # must save the register loc_index before it is mutated + self.mc.PUSH_r(loc_index.value) + tmp1 = loc_index + final_pop = True # SHR tmp, card_page_shift self.mc.SHR_ri(tmp1.value, descr.jit_wb_card_page_shift) # XOR tmp, -8 @@ -2427,7 +2489,9 @@ # BTS [loc_base], tmp self.mc.BTS(addr_add_const(loc_base, 0), tmp1) # done - self.mc.POP_r(tmp1.value) + if final_pop: + self.mc.POP_r(loc_index.value) + # elif isinstance(loc_index, ImmedLoc): byte_index = loc_index.value >> descr.jit_wb_card_page_shift byte_ofs = ~(byte_index >> 3) @@ -2435,11 +2499,12 @@ self.mc.OR8(addr_add_const(loc_base, byte_ofs), imm(byte_val)) else: raise AssertionError("index is neither RegLoc nor ImmedLoc") - # patch the JMP above - offset = self.mc.get_relative_pos() - jmp_location + # + # patch the JNS above + offset = self.mc.get_relative_pos() - jns_location assert 0 < offset <= 127 - self.mc.overwrite(jmp_location-1, chr(offset)) - # + self.mc.overwrite(jns_location-1, chr(offset)) + # patch the JZ above offset = self.mc.get_relative_pos() - jz_location assert 0 < offset <= 127 diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py --- a/pypy/jit/backend/x86/regalloc.py +++ b/pypy/jit/backend/x86/regalloc.py @@ -980,16 +980,6 @@ # or setarrayitem_gc. It avoids loading it twice from the memory. arglocs = [self.rm.make_sure_var_in_reg(op.getarg(i), args) for i in range(N)] - # add eax, ecx and edx as extra "arguments" to ensure they are - # saved and restored. Fish in self.rm to know which of these - # registers really need to be saved (a bit of a hack). Moreover, - # we don't save and restore any SSE register because the called - # function, a GC write barrier, is known not to touch them. - # See remember_young_pointer() in rpython/memory/gc/generation.py. - for v, reg in self.rm.reg_bindings.items(): - if (reg in self.rm.save_around_call_regs - and self.rm.stays_alive(v)): - arglocs.append(reg) self.PerformDiscard(op, arglocs) self.rm.possibly_free_vars_for_op(op) diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py --- a/pypy/jit/backend/x86/rx86.py +++ b/pypy/jit/backend/x86/rx86.py @@ -316,6 +316,13 @@ assert rexbyte == 0 return 0 +# REX prefixes: 'rex_w' generates a REX_W, forcing the instruction +# to operate on 64-bit. 'rex_nw' doesn't, so the instruction operates +# on 32-bit or less; the complete REX prefix is omitted if unnecessary. +# 'rex_fw' is a special case which doesn't generate a REX_W but forces +# the REX prefix in all cases. It is only useful on instructions which +# have an 8-bit register argument, to force access to the "sil" or "dil" +# registers (as opposed to "ah-dh"). rex_w = encode_rex, 0, (0x40 | REX_W), None # a REX.W prefix rex_nw = encode_rex, 0, 0, None # an optional REX prefix rex_fw = encode_rex, 0, 0x40, None # a forced REX prefix @@ -496,9 +503,9 @@ AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0') OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0') - OR8_mi = insn(rex_fw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), + OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), immediate(2, 'b')) - OR8_ji = insn(rex_fw, '\x80', orbyte(1<<3), abs_, immediate(1), + OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1), immediate(2, 'b')) NEG_r = insn(rex_w, '\xF7', register(1), '\xD8') @@ -531,7 +538,13 @@ PUSH_r = insn(rex_nw, register(1), '\x50') PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1)) + PUSH_i8 = insn('\x6A', immediate(1, 'b')) PUSH_i32 = insn('\x68', immediate(1, 'i')) + def PUSH_i(mc, immed): + if single_byte(immed): + mc.PUSH_i8(immed) + else: + mc.PUSH_i32(immed) POP_r = insn(rex_nw, register(1), '\x58') POP_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1)) diff --git a/pypy/jit/backend/x86/test/test_rx86.py b/pypy/jit/backend/x86/test/test_rx86.py --- a/pypy/jit/backend/x86/test/test_rx86.py +++ b/pypy/jit/backend/x86/test/test_rx86.py @@ -183,7 +183,8 @@ def test_push32(): cb = CodeBuilder32 - assert_encodes_as(cb, 'PUSH_i32', (9,), '\x68\x09\x00\x00\x00') + assert_encodes_as(cb, 'PUSH_i', (0x10009,), '\x68\x09\x00\x01\x00') + assert_encodes_as(cb, 'PUSH_i', (9,), '\x6A\x09') def test_sub_ji8(): cb = CodeBuilder32 diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py --- a/pypy/module/_minimal_curses/fficurses.py +++ b/pypy/module/_minimal_curses/fficurses.py @@ -8,11 +8,20 @@ from pypy.rpython.extfunc import register_external from pypy.module._minimal_curses import interp_curses from pypy.translator.tool.cbuild import ExternalCompilationInfo +from sys import platform -eci = ExternalCompilationInfo( - includes = ['curses.h', 'term.h'], - libraries = ['curses'], -) +_CYGWIN = platform == 'cygwin' + +if _CYGWIN: + eci = ExternalCompilationInfo( + includes = ['ncurses/curses.h', 'ncurses/term.h'], + libraries = ['curses'], + ) +else: + eci = ExternalCompilationInfo( + includes = ['curses.h', 'term.h'], + libraries = ['curses'], + ) rffi_platform.verify_eci(eci) diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py --- a/pypy/module/_socket/test/test_sock_app.py +++ b/pypy/module/_socket/test/test_sock_app.py @@ -618,9 +618,12 @@ except timeout: pass t.recv(count) - # test sendall() timeout, be sure to send data larger than the - # socket buffer - raises(timeout, cli.sendall, 'foobar' * 7000) + # test sendall() timeout + try: + while 1: + cli.sendall('foobar' * 70) + except timeout: + pass # done cli.close() t.close() diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -12,15 +12,18 @@ MIXIN_32 = (int_typedef,) if LONG_BIT == 32 else () MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else () + def new_dtype_getter(name): def _get_dtype(space): from pypy.module.micronumpy.interp_dtype import get_dtype_cache return getattr(get_dtype_cache(space), "w_%sdtype" % name) + def new(space, w_subtype, w_value): dtype = _get_dtype(space) return dtype.itemtype.coerce_subtype(space, w_subtype, w_value) return func_with_new_name(new, name + "_box_new"), staticmethod(_get_dtype) + class PrimitiveBox(object): _mixin_ = True @@ -30,6 +33,7 @@ def convert_to(self, dtype): return dtype.box(self.value) + class W_GenericBox(Wrappable): _attrs_ = () @@ -71,7 +75,7 @@ def _binop_right_impl(ufunc_name): def impl(self, space, w_other, w_out=None): from pypy.module.micronumpy import interp_ufuncs - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self, w_out]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name) @@ -132,6 +136,9 @@ w_remainder = self.descr_rmod(space, w_other) return space.newtuple([w_quotient, w_remainder]) + def descr_hash(self, space): + return space.hash(self.item(space)) + def item(self, space): return self.get_dtype(space).itemtype.to_builtin_type(space, self) @@ -315,6 +322,8 @@ __abs__ = interp2app(W_GenericBox.descr_abs), __invert__ = interp2app(W_GenericBox.descr_invert), + __hash__ = interp2app(W_GenericBox.descr_hash), + tolist = interp2app(W_GenericBox.item), ) @@ -440,4 +449,4 @@ __module__ = "numpypy", __new__ = interp2app(W_UnicodeBox.descr__new__unicode_box.im_func), ) - + diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -690,11 +690,17 @@ return self.getitem(offset).convert_to(longdtype).item( space) + @jit.unroll_safe def descr_item(self, space, w_arg=None): if space.is_w(w_arg, space.w_None): - if not isinstance(self, Scalar): - raise OperationError(space.w_ValueError, space.wrap("index out of bounds")) - return self.value.item(space) + if isinstance(self, Scalar): + return self.value.item(space) + if support.product(self.shape) == 1: + return self.descr_getitem(space, + space.newtuple([space.wrap(0) for i + in range(len(self.shape))])) + raise OperationError(space.w_ValueError, + space.wrap("index out of bounds")) if space.isinstance_w(w_arg, space.w_int): if isinstance(self, Scalar): raise OperationError(space.w_ValueError, space.wrap("index out of bounds")) diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -211,33 +211,23 @@ a = array(range(10), dtype=int64) b = array([0] * 10, dtype=int64) - for idx in b: a[idx] += 1 + for idx in b: + a[idx] += 1 - def test_hash_int8(self): - from _numpypy import int8 + def test_hash(self): + import _numpypy as numpy + for tp, value in [ + (numpy.int8, 4), + (numpy.int16, 5), + (numpy.uint32, 7), + (numpy.int64, 3), + (numpy.float32, 2.0), + (numpy.float64, 4.32), + ]: + assert hash(tp(value)) == hash(value) - hash(int8(0)) - d = {int8(5):99} - def test_hash_int16(self): - from _numpypy import int16 - - hash(int16(0)) - d = {int16(99):42} - - def test_hash_int32(self): - from _numpypy import int32 - - hash(int32(0)) - d = {int32(5):99} - - def test_hash_int64(self): - from _numpypy import int64 - - hash(int64(0)) - d = {int64(99):42} - -class AppTestTypes(BaseNumpyAppTest): +class AppTestTypes(BaseNumpyAppTest): def test_abstract_types(self): import _numpypy as numpy raises(TypeError, numpy.generic, 0) @@ -461,7 +451,7 @@ def test_various_types(self): import _numpypy as numpy import sys - + assert numpy.int16 is numpy.short assert numpy.int8 is numpy.byte assert numpy.bool_ is numpy.bool8 @@ -472,7 +462,7 @@ def test_mro(self): import _numpypy as numpy - + assert numpy.int16.__mro__ == (numpy.int16, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object) @@ -528,7 +518,7 @@ class AppTestStrUnicodeDtypes(BaseNumpyAppTest): def test_str_unicode(self): from _numpypy import str_, unicode_, character, flexible, generic - + assert str_.mro() == [str_, str, basestring, character, flexible, generic, object] assert unicode_.mro() == [unicode_, unicode, basestring, character, flexible, generic, object] @@ -588,7 +578,7 @@ from _numpypy import dtype d = dtype({'names': ['a', 'b', 'c'], }) - + class AppTestNotDirect(BaseNumpyAppTest): def setup_class(cls): BaseNumpyAppTest.setup_class.im_func(cls) diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1248,6 +1248,7 @@ a = arange(3*2*6).reshape((3,2,6)) b = arange(3*2*6)[::-1].reshape((2,6,3)) assert dot(a, b)[2,0,1,2] == 1140 + assert (dot([[1,2],[3,4]],[5,6]) == [17, 39]).all() def test_dot_constant(self): from _numpypy import array, dot @@ -1999,6 +2000,7 @@ assert a[::2].item(1) == 3 assert (a + a).item(1) == 4 raises(ValueError, "array(5).item(1)") + assert array([1]).item() == 1 class AppTestSupport(BaseNumpyAppTest): def setup_class(cls): diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -13,11 +13,13 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib import jit + VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True}) degToRad = math.pi / 180.0 log2 = math.log(2) -log2e = 1./log2 +log2e = 1. / log2 + def simple_unary_op(func): specialize.argtype(1)(func) @@ -66,7 +68,7 @@ class BaseType(object): _attrs_ = () - + def _unimplemented_ufunc(self, *args): raise NotImplementedError @@ -133,7 +135,7 @@ width, storage, i, offset, value) else: libffi.array_setitem_T(self.T, width, storage, i, offset, value) - + def store(self, arr, width, i, offset, box): self._write(arr.storage, width, i, offset, self.unbox(box)) @@ -242,7 +244,7 @@ class NonNativePrimitive(Primitive): _mixin_ = True - + def _read(self, storage, width, i, offset): if we_are_translated(): res = libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T), @@ -528,7 +530,7 @@ T = rffi.LONGLONG BoxType = interp_boxes.W_Int64Box - format_code = "q" + format_code = "q" _coerce = func_with_new_name(_int64_coerce, '_coerce') @@ -900,7 +902,7 @@ T = rffi.FLOAT BoxType = interp_boxes.W_Float32Box - format_code = "f" + format_code = "f" class Float64(BaseType, Float): _attrs_ = () @@ -918,7 +920,7 @@ class BaseStringType(object): _mixin_ = True - + def __init__(self, size=0): self.size = size @@ -949,14 +951,14 @@ def get_element_size(self): return self.size - + def read(self, arr, width, i, offset, dtype=None): if dtype is None: dtype = arr.dtype return interp_boxes.W_VoidBox(arr, i + offset, dtype) @jit.unroll_safe - def coerce(self, space, dtype, w_item): + def coerce(self, space, dtype, w_item): from pypy.module.micronumpy.interp_numarray import W_NDimArray if isinstance(w_item, interp_boxes.W_VoidBox): diff --git a/pypy/module/rctime/interp_time.py b/pypy/module/rctime/interp_time.py --- a/pypy/module/rctime/interp_time.py +++ b/pypy/module/rctime/interp_time.py @@ -12,6 +12,15 @@ _POSIX = os.name == "posix" _WIN = os.name == "nt" +_CYGWIN = sys.platform == "cygwin" + +_time_zones = [] +if _CYGWIN: + _time_zones = ["GMT-12", "GMT-11", "GMT-10", "GMT-9", "GMT-8", "GMT-7", + "GMT-6", "GMT-5", "GMT-4", "GMT-3", "GMT-2", "GMT-1", + "GMT", "GMT+1", "GMT+2", "GMT+3", "GMT+4", "GMT+5", + "GMT+6", "GMT+7", "GMT+8", "GMT+9", "GMT+10", "GMT+11", + "GMT+12", "GMT+13", "GMT+14"] if _WIN: # Interruptible sleeps on Windows: @@ -107,11 +116,17 @@ CConfig.timeval = platform.Struct("struct timeval", [("tv_sec", rffi.INT), ("tv_usec", rffi.INT)]) - CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), - ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), - ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), - ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT), ("tm_gmtoff", rffi.LONG), - ("tm_zone", rffi.CCHARP)]) + if _CYGWIN: + CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), + ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), + ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), + ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT)]) + else: + CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), + ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), + ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), + ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT), ("tm_gmtoff", rffi.LONG), + ("tm_zone", rffi.CCHARP)]) elif _WIN: calling_conv = 'win' CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), @@ -202,35 +217,81 @@ tzname = rffi.charp2str(tzname_ptr[0]), rffi.charp2str(tzname_ptr[1]) if _POSIX: - YEAR = (365 * 24 + 6) * 3600 + if _CYGWIN: + YEAR = (365 * 24 + 6) * 3600 - t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR) - # we cannot have reference to stack variable, put it on the heap - t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') - t_ref[0] = rffi.cast(rffi.TIME_T, t) - p = c_localtime(t_ref) - janzone = -p.c_tm_gmtoff - tm_zone = rffi.charp2str(p.c_tm_zone) - janname = [" ", tm_zone][bool(tm_zone)] - tt = t + YEAR / 2 - t_ref[0] = rffi.cast(rffi.TIME_T, tt) - p = c_localtime(t_ref) - lltype.free(t_ref, flavor='raw') - tm_zone = rffi.charp2str(p.c_tm_zone) - julyzone = -p.c_tm_gmtoff - julyname = [" ", tm_zone][bool(tm_zone)] + # about January 11th + t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR + 10 * 24 * 3600) + # we cannot have reference to stack variable, put it on the heap + t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') + t_ref[0] = rffi.cast(rffi.TIME_T, t) + p = c_localtime(t_ref) + q = c_gmtime(t_ref) + janzone = (p.c_tm_hour + 24 * p.c_tm_mday) - (q.c_tm_hour + 24 * q.c_tm_mday) + if janzone < -12: + janname = " " + elif janzone > 14: + janname = " " + else: + janname = _time_zones[janzone - 12] + janzone = janzone * 3600 + # about July 11th + tt = t + YEAR / 2 + t_ref[0] = rffi.cast(rffi.TIME_T, tt) + p = c_localtime(t_ref) + q = c_gmtime(t_ref) + julyzone = (p.c_tm_hour + 24 * p.c_tm_mday) - (q.c_tm_hour + 24 * q.c_tm_mday) + if julyzone < -12: + julyname = " " + elif julyzone > 14: + julyname = " " + else: + julyname = _time_zones[julyzone - 12] + julyzone = julyzone * 3600 + lltype.free(t_ref, flavor='raw') - if janzone < julyzone: - # DST is reversed in the southern hemisphere - timezone = julyzone - altzone = janzone - daylight = int(janzone != julyzone) - tzname = [julyname, janname] + if janzone < julyzone: + # DST is reversed in the southern hemisphere + timezone = julyzone + altzone = janzone + daylight = int(janzone != julyzone) + tzname = [julyname, janname] + else: + timezone = janzone + altzone = julyzone + daylight = int(janzone != julyzone) + tzname = [janname, julyname] + else: - timezone = janzone - altzone = julyzone - daylight = int(janzone != julyzone) - tzname = [janname, julyname] + YEAR = (365 * 24 + 6) * 3600 + + t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR) + # we cannot have reference to stack variable, put it on the heap + t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') + t_ref[0] = rffi.cast(rffi.TIME_T, t) + p = c_localtime(t_ref) + janzone = -p.c_tm_gmtoff + tm_zone = rffi.charp2str(p.c_tm_zone) + janname = [" ", tm_zone][bool(tm_zone)] + tt = t + YEAR / 2 + t_ref[0] = rffi.cast(rffi.TIME_T, tt) + p = c_localtime(t_ref) + lltype.free(t_ref, flavor='raw') + tm_zone = rffi.charp2str(p.c_tm_zone) + julyzone = -p.c_tm_gmtoff + julyname = [" ", tm_zone][bool(tm_zone)] + + if janzone < julyzone: + # DST is reversed in the southern hemisphere + timezone = julyzone + altzone = janzone + daylight = int(janzone != julyzone) + tzname = [julyname, janname] + else: + timezone = janzone + altzone = julyzone + daylight = int(janzone != julyzone) + tzname = [janname, julyname] _set_module_object(space, "timezone", space.wrap(timezone)) _set_module_object(space, 'daylight', space.wrap(daylight)) @@ -361,9 +422,12 @@ rffi.setintfield(glob_buf, 'c_tm_yday', tm_yday) rffi.setintfield(glob_buf, 'c_tm_isdst', space.int_w(tup_w[8])) if _POSIX: - # actually never happens, but makes annotator happy - glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) - rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) + if _CYGWIN: + pass + else: + # actually never happens, but makes annotator happy + glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) + rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) w_accept2dyear = _get_module_object(space, "accept2dyear") accept2dyear = space.int_w(w_accept2dyear) diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py @@ -484,6 +484,20 @@ assert tf_b(-126) == -42 assert tf_b._ptr is ptr + def test_custom_from_param(self): + class A(c_byte): + @classmethod + def from_param(cls, obj): + seen.append(obj) + return -126 + tf_b = dll.tf_b + tf_b.restype = c_byte + tf_b.argtypes = (c_byte,) + tf_b.argtypes = [A] + seen = [] + assert tf_b("yadda") == -42 + assert seen == ["yadda"] + def test_warnings(self): import warnings warnings.simplefilter("always") diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py --- a/pypy/objspace/std/test/test_stringobject.py +++ b/pypy/objspace/std/test/test_stringobject.py @@ -413,6 +413,9 @@ assert 'abcdefghiabc'.find('def', 4) == -1 assert 'abcdef'.find('', 13) == -1 assert 'abcdefg'.find('def', 5, None) == -1 + assert 'abcdef'.find('d', 6, 0) == -1 + assert 'abcdef'.find('d', 3, 3) == -1 + raises(TypeError, 'abcdef'.find, 'd', 1.0) def test_index(self): from sys import maxint diff --git a/pypy/rlib/rope.py b/pypy/rlib/rope.py --- a/pypy/rlib/rope.py +++ b/pypy/rlib/rope.py @@ -769,11 +769,11 @@ len2 = subnode.length() if stop > len1 or stop == -1: stop = len1 + if stop - start < 0: + return -1 if len2 == 1: return find_int(node, subnode.getint(0), start, stop) if len2 == 0: - if (stop - start) < 0: - return -1 return start if len2 > stop - start: return -1 diff --git a/pypy/rlib/rsdl/RIMG.py b/pypy/rlib/rsdl/RIMG.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RIMG.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_image.h'], - frameworks = ['SDL_image'], - include_dirs = ['/Library/Frameworks/SDL_image.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_image.h'], - libraries=['SDL_image'], - ) - -eci = eci.merge(RSDL.eci) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -Load = external('IMG_Load', [rffi.CCHARP], RSDL.SurfacePtr) diff --git a/pypy/rlib/rsdl/RMix.py b/pypy/rlib/rsdl/RMix.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix.py +++ /dev/null @@ -1,68 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_mixer.h'], - frameworks = ['SDL_mixer'], - include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_mixer.h'], - libraries=['SDL_mixer'], - ) - -eci = eci.merge(RSDL.eci) -eci = eci.merge(eci) -eci = eci.merge(eci) - -ChunkPtr = lltype.Ptr(lltype.ForwardReference()) - -class CConfig: - _compilation_info_ = eci - - Chunk = platform.Struct('Mix_Chunk', [('allocated', rffi.INT), - ('abuf', RSDL.Uint8P), - ('alen', RSDL.Uint32), - ('volume', RSDL.Uint8)]) - -globals().update(platform.configure(CConfig)) - -ChunkPtr.TO.become(Chunk) - - -Buffer = rffi.CArray(RSDL.Uint8) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -OpenAudio = external('Mix_OpenAudio', - [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], - rffi.INT) - -CloseAudio = external('Mix_CloseAudio', [], lltype.Void) - -LoadWAV_RW = external('Mix_LoadWAV_RW', - [RSDL.RWopsPtr, rffi.INT], - ChunkPtr) - -def LoadWAV(filename_ccharp): - with rffi.scoped_str2charp('rb') as mode: - return LoadWAV_RW(RSDL.RWFromFile(filename_ccharp, mode), 1) - - -PlayChannelTimed = external('Mix_PlayChannelTimed', - [rffi.INT, ChunkPtr, rffi.INT, rffi.INT], - rffi.INT) - -def PlayChannel(channel,chunk,loops): - return PlayChannelTimed(channel, chunk, loops, -1) - -"""Returns zero if the channel is not playing. -Otherwise if you passed in -1, the number of channels playing is returned""" -ChannelPlaying = external('Mix_Playing', [rffi.INT], rffi.INT) diff --git a/pypy/rlib/rsdl/RMix_helper.py b/pypy/rlib/rsdl/RMix_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix_helper.py +++ /dev/null @@ -1,24 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RMix, RSDL -from pypy.rpython.tool import rffi_platform as platform - - -def malloc_buffer_chunk(has_own_allocated_buffer, length_bytes, volume): - buffer_pointer = lltype.malloc(RMix.Buffer, length_bytes, flavor='raw') - return malloc_chunk(has_own_allocated_buffer, length_bytes, volume) - -def malloc_chunk(has_own_allocated_buffer, buffer_pointer, length_bytes, volume): - """ - Creates a new Mix_Chunk. - has_own_allocated_buffer: if 1 struct has its own allocated buffer, - if 0 abuf should not be freed - buffer_pointer: pointer to audio data - length_bytes: length of audio data in bytes - volume: Per-sample volume, 0-128 (normally - MIX_MAX_VOLUME after loading)""" - p = lltype.malloc(RMix.Chunk, flavor='raw') - rffi.setintfield(p, 'c_allocated', has_own_allocated_buffer) - rffi.setintfield(p, 'c_abuf', buffer_pointer) - rffi.setintfield(p, 'c_alen', length_bytes) - rffi.setintfield(p, 'c_volume', volume) - return p \ No newline at end of file diff --git a/pypy/rlib/rsdl/RSDL.py b/pypy/rlib/rsdl/RSDL.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL.py +++ /dev/null @@ -1,249 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.rlib.rsdl.constants import _constants -from pypy.rlib.rsdl.eci import get_rsdl_compilation_info -from pypy.rlib.objectmodel import we_are_translated -import py -import sys - -# ------------------------------------------------------------------------------ - -eci = get_rsdl_compilation_info() - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -# ------------------------------------------------------------------------------ - -RectPtr = lltype.Ptr(lltype.ForwardReference()) -SurfacePtr = lltype.Ptr(lltype.ForwardReference()) -PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) -EventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyPtr = lltype.Ptr(lltype.ForwardReference()) -RWopsPtr = lltype.Ptr(lltype.ForwardReference()) - -# ------------------------------------------------------------------------------ - -class CConfig: - _compilation_info_ = eci - - Uint8 = platform.SimpleType('Uint8', rffi.INT) - Uint16 = platform.SimpleType('Uint16', rffi.INT) - Sint16 = platform.SimpleType('Sint16', rffi.INT) - Uint32 = platform.SimpleType('Uint32', rffi.INT) - - Rect = platform.Struct('SDL_Rect', - [('x', rffi.INT), - ('y', rffi.INT), - ('w', rffi.INT), - ('h', rffi.INT)]) - - Surface = platform.Struct('SDL_Surface', - [('w', rffi.INT), - ('h', rffi.INT), - ('format', PixelFormatPtr), - ('pitch', rffi.INT), - ('pixels', rffi.UCHARP)]) - - PixelFormat = platform.Struct('SDL_PixelFormat', - [('BitsPerPixel', rffi.INT), - ('BytesPerPixel', rffi.INT), - ('Rmask', rffi.INT), - ('Gmask', rffi.INT), - ('Bmask', rffi.INT), - ('Amask', rffi.INT)]) - - Event = platform.Struct('SDL_Event', - [('type', rffi.INT)]) - - keysym = platform.Struct('SDL_keysym', - [('scancode', rffi.INT), - ('sym', rffi.INT), - ('mod', rffi.INT), - ('unicode', rffi.INT)]) - - KeyboardEvent = platform.Struct('SDL_KeyboardEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('keysym', keysym)]) - - MouseButtonEvent = platform.Struct('SDL_MouseButtonEvent', - [('type', rffi.INT), - ('button', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT)]) - - MouseMotionEvent = platform.Struct('SDL_MouseMotionEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT), - ('xrel', rffi.INT), - ('yrel', rffi.INT)]) - - QuitEvent = platform.Struct('SDL_QuitEvent', - [('type', rffi.INT)]) - - RWops = platform.Struct('SDL_RWops', []) - -# ------------------------------------------------------------------------------ - -for _prefix, _list in _constants.items(): - for _name in _list: - setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) - -# ------------------------------------------------------------------------------ - -globals().update(platform.configure(CConfig)) - -# ------------------------------------------------------------------------------ - -RectPtr.TO.become(Rect) -SurfacePtr.TO.become(Surface) -PixelFormatPtr.TO.become(PixelFormat) -EventPtr.TO.become(Event) -KeyboardEventPtr.TO.become(KeyboardEvent) -MouseButtonEventPtr.TO.become(MouseButtonEvent) -MouseMotionEventPtr.TO.become(MouseMotionEvent) -RWopsPtr.TO.become(RWops) - -# ------------------------------------------------------------------------------ - -Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) -Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) -# need to add signed hint here -Sint16P = lltype.Ptr(lltype.Array(Sint16, hints={'nolength': True})) -Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) - - -# ------------------------------------------------------------------------------ - -_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Mac_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Quit = external('SDL_Quit', [], - lltype.Void) - -SetVideoMode = external('SDL_SetVideoMode', - [rffi.INT, rffi.INT, rffi.INT, Uint32], - SurfacePtr) - -WM_SetCaption = external('SDL_WM_SetCaption', - [rffi.CCHARP, rffi.CCHARP], - lltype.Void) - -EnableUNICODE = external('SDL_EnableUNICODE', - [rffi.INT], - rffi.INT) - -WaitEvent = external('SDL_WaitEvent', - [EventPtr], - rffi.INT) - -PollEvent = external('SDL_PollEvent', - [EventPtr], - rffi.INT) - -Flip = external('SDL_Flip', - [SurfacePtr], - rffi.INT) - -CreateRGBSurface = external('SDL_CreateRGBSurface', - [Uint32, rffi.INT, rffi.INT, rffi.INT, - Uint32, Uint32, Uint32, Uint32], - SurfacePtr) - -LockSurface = external('SDL_LockSurface', - [SurfacePtr], - rffi.INT) - -UnlockSurface = external('SDL_UnlockSurface', - [SurfacePtr], - lltype.Void) - -FreeSurface = external('SDL_FreeSurface', - [SurfacePtr], - lltype.Void) - -MapRGB = external('SDL_MapRGB', - [PixelFormatPtr, Uint8, Uint8, Uint8], - Uint32) - -GetRGB = external('SDL_GetRGB', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], - lltype.Void) - -GetRGBA = external('SDL_GetRGBA', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, - Uint8P, Uint8P], - lltype.Void) - -FillRect = external('SDL_FillRect', - [SurfacePtr, RectPtr, Uint32], - rffi.INT) - -BlitSurface = external('SDL_UpperBlit', - [SurfacePtr, RectPtr, SurfacePtr, RectPtr], - rffi.INT) - -SetAlpha = external('SDL_SetAlpha', - [SurfacePtr, Uint32, Uint8], - rffi.INT) - -SetColorKey = external('SDL_SetColorKey', - [SurfacePtr, Uint32, Uint32], - rffi.INT) - -ShowCursor = external('SDL_ShowCursor', - [rffi.INT], - rffi.INT) - -GetTicks = external('SDL_GetTicks', - [], - Uint32) - -Delay = external('SDL_Delay', - [Uint32], - lltype.Void) - -UpdateRect = external('SDL_UpdateRect', - [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], - lltype.Void) - -GetKeyName = external('SDL_GetKeyName', - [rffi.INT], - rffi.CCHARP) - -GetError = external('SDL_GetError', - [], - rffi.CCHARP) - -RWFromFile = external('SDL_RWFromFile', - [rffi.CCHARP, rffi.CCHARP], - RWopsPtr) - -# ------------------------------------------------------------------------------ - - -if sys.platform == 'darwin': - def Init(flags): - if not we_are_translated(): - from AppKit import NSApplication - NSApplication.sharedApplication() - #CustomApplicationMain(0, " ") - return _Init(flags) - #Mac_Init() -else: - Init = _Init - - - diff --git a/pypy/rlib/rsdl/RSDL_helper.py b/pypy/rlib/rsdl/RSDL_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL_helper.py +++ /dev/null @@ -1,108 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RSDL - -def get_rgb(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - RSDL.GetRGB(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result = r, g, b - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_rgba(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 4, flavor='raw') - try: - RSDL.GetRGBA(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2), - rffi.ptradd(rgb, 3)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - a = rffi.cast(lltype.Signed, rgb[3]) - result = r, g, b, a - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_pixel(image, x, y): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 3: - p0 = rffi.cast(lltype.Signed, p[0]) - p1 = rffi.cast(lltype.Signed, p[1]) - p2 = rffi.cast(lltype.Signed, p[2]) - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - result = p0 << 16 | p1 << 8 | p2 - else: - result = p0 | p1 << 8 | p2 << 16 - return rffi.cast(RSDL.Uint32, result) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - return p[0] - else: - raise ValueError("bad BytesPerPixel") - -def set_pixel(image, x, y, pixel): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - p[0] = rffi.cast(rffi.UCHAR,pixel) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - p[0] = rffi.cast(RSDL.Uint16,pixel) - elif bpp == 3: - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - p[0] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - else: - p[0] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - p[0] = rffi.cast(RSDL.Uint32, pixel) - else: - raise ValueError("bad BytesPerPixel") - -def mallocrect(x, y, w, h): - p = lltype.malloc(RSDL.Rect, flavor='raw') - rffi.setintfield(p, 'c_x', x) - rffi.setintfield(p, 'c_y', y) - rffi.setintfield(p, 'c_w', w) - rffi.setintfield(p, 'c_h', h) - return p - -def blit_complete_surface(src, dst, x, y): - dstrect = mallocrect(x, y, rffi.getintfield(src, 'c_w'), rffi.getintfield(src, 'c_w')) - RSDL.BlitSurface(src, lltype.nullptr(RSDL.Rect), dst, dstrect) - lltype.free(dstrect, flavor='raw') - diff --git a/pypy/rlib/rsdl/__init__.py b/pypy/rlib/rsdl/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/constants.py b/pypy/rlib/rsdl/constants.py deleted file mode 100644 --- a/pypy/rlib/rsdl/constants.py +++ /dev/null @@ -1,261 +0,0 @@ - -_constants = { - 'SDL_': [ # constants with the 'SDL_' prefix in C - "YV12_OVERLAY", - "IYUV_OVERLAY", - "YUY2_OVERLAY", - "UYVY_OVERLAY", - "YVYU_OVERLAY", - - "SWSURFACE", - "HWSURFACE", - "RESIZABLE", - "ASYNCBLIT", - "OPENGL", - "OPENGLBLIT", - "ANYFORMAT", - "HWPALETTE", - "DOUBLEBUF", - "FULLSCREEN", - "HWACCEL", - "SRCCOLORKEY", - "RLEACCELOK", - "RLEACCEL", - "SRCALPHA", - "PREALLOC", - "NOFRAME", - - "GL_RED_SIZE", - "GL_GREEN_SIZE", - "GL_BLUE_SIZE", - "GL_ALPHA_SIZE", - "GL_BUFFER_SIZE", - "GL_DOUBLEBUFFER", - "GL_DEPTH_SIZE", - "GL_STENCIL_SIZE", - "GL_ACCUM_RED_SIZE", - "GL_ACCUM_GREEN_SIZE", - "GL_ACCUM_BLUE_SIZE", - "GL_ACCUM_ALPHA_SIZE", - "GL_STEREO", #if SDL_VERSION_ATLEAST(1, 2, 5) - "GL_MULTISAMPLEBUFFERS", #if SDL_VERSION_ATLEAST(1, 2, 6) - "GL_MULTISAMPLESAMPLES", #if SDL_VERSION_ATLEAST(1, 2, 6) - - "NOEVENT", - "ACTIVEEVENT", - "KEYDOWN", - "KEYUP", - "MOUSEMOTION", - "MOUSEBUTTONDOWN", - "MOUSEBUTTONUP", - "BUTTON_LEFT", - "BUTTON_MIDDLE", - "BUTTON_RIGHT", - "BUTTON_WHEELUP", - "BUTTON_WHEELDOWN", - "JOYAXISMOTION", - "JOYBALLMOTION", - "JOYHATMOTION", - "JOYBUTTONDOWN", - "JOYBUTTONUP", - "VIDEORESIZE", - "VIDEOEXPOSE", - "QUIT", - "SYSWMEVENT", - "USEREVENT", - "NUMEVENTS", - - "HAT_CENTERED", - "HAT_UP", - "HAT_RIGHTUP", - "HAT_RIGHT", - "HAT_RIGHTDOWN", - "HAT_DOWN", - "HAT_LEFTDOWN", - "HAT_LEFT", - "HAT_LEFTUP", - - "DISABLE", - "ENABLE", - - # the following ones are not exposed in Pygame - "INIT_VIDEO", - "BYTEORDER", - "BIG_ENDIAN", - "LIL_ENDIAN", - ], - - '': [ # constants with no prefix in C - "TIMER_RESOLUTION", - "AUDIO_U8", - "AUDIO_S8", - "AUDIO_U16LSB", - "AUDIO_S16LSB", - "AUDIO_U16MSB", - "AUDIO_S16MSB", - "AUDIO_U16", - "AUDIO_S16", - "AUDIO_U16SYS", - "AUDIO_S16SYS", - - "KMOD_NONE", - "KMOD_LSHIFT", - "KMOD_RSHIFT", - "KMOD_LCTRL", - "KMOD_RCTRL", - "KMOD_LALT", - "KMOD_RALT", - "KMOD_LMETA", - "KMOD_RMETA", - "KMOD_NUM", - "KMOD_CAPS", - "KMOD_MODE", - - "KMOD_CTRL", - "KMOD_SHIFT", - "KMOD_ALT", - "KMOD_META", - ], - - 'SDL': [ # constants with the 'SDL' prefix in C - "K_UNKNOWN", - "K_FIRST", - "K_BACKSPACE", - "K_TAB", - "K_CLEAR", - "K_RETURN", - "K_PAUSE", - "K_ESCAPE", - "K_SPACE", - "K_EXCLAIM", - "K_QUOTEDBL", - "K_HASH", - "K_DOLLAR", - "K_AMPERSAND", - "K_QUOTE", - "K_LEFTPAREN", - "K_RIGHTPAREN", - "K_ASTERISK", - "K_PLUS", - "K_COMMA", - "K_MINUS", - "K_PERIOD", - "K_SLASH", - "K_0", - "K_1", - "K_2", - "K_3", - "K_4", - "K_5", - "K_6", - "K_7", - "K_8", - "K_9", - "K_COLON", - "K_SEMICOLON", - "K_LESS", - "K_EQUALS", - "K_GREATER", - "K_QUESTION", - "K_AT", - "K_LEFTBRACKET", - "K_BACKSLASH", - "K_RIGHTBRACKET", - "K_CARET", - "K_UNDERSCORE", - "K_BACKQUOTE", - "K_a", - "K_b", - "K_c", - "K_d", - "K_e", - "K_f", - "K_g", - "K_h", - "K_i", - "K_j", - "K_k", - "K_l", - "K_m", - "K_n", - "K_o", - "K_p", - "K_q", - "K_r", - "K_s", - "K_t", - "K_u", - "K_v", - "K_w", - "K_x", - "K_y", - "K_z", - "K_DELETE", - - "K_KP0", - "K_KP1", - "K_KP2", - "K_KP3", - "K_KP4", - "K_KP5", - "K_KP6", - "K_KP7", - "K_KP8", - "K_KP9", - "K_KP_PERIOD", - "K_KP_DIVIDE", - "K_KP_MULTIPLY", - "K_KP_MINUS", - "K_KP_PLUS", - "K_KP_ENTER", - "K_KP_EQUALS", - "K_UP", - "K_DOWN", - "K_RIGHT", - "K_LEFT", - "K_INSERT", - "K_HOME", - "K_END", - "K_PAGEUP", - "K_PAGEDOWN", - "K_F1", - "K_F2", - "K_F3", - "K_F4", - "K_F5", - "K_F6", - "K_F7", - "K_F8", - "K_F9", - "K_F10", - "K_F11", - "K_F12", - "K_F13", - "K_F14", - "K_F15", - - "K_NUMLOCK", - "K_CAPSLOCK", - "K_SCROLLOCK", - "K_RSHIFT", - "K_LSHIFT", - "K_RCTRL", - "K_LCTRL", - "K_RALT", - "K_LALT", - "K_RMETA", - "K_LMETA", - "K_LSUPER", - "K_RSUPER", - "K_MODE", - - "K_HELP", - "K_PRINT", - "K_SYSREQ", - "K_BREAK", - "K_MENU", - "K_POWER", - "K_EURO", - "K_LAST", - ], - } diff --git a/pypy/rlib/rsdl/eci.py b/pypy/rlib/rsdl/eci.py deleted file mode 100644 --- a/pypy/rlib/rsdl/eci.py +++ /dev/null @@ -1,27 +0,0 @@ -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.translator.platform import CompilationError -import py -import sys - -def get_rsdl_compilation_info(): - if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL.h'], - include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], - link_files = [ - str(py.path.local(__file__).dirpath().join('macosx-sdl-main/SDLMain.m')), - ], - frameworks = ['SDL', 'Cocoa'] - ) - else: - eci = ExternalCompilationInfo( - includes=['SDL.h'], - ) - eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) - return eci - -def check_sdl_installation(): - from pypy.rpython.tool import rffi_platform as platform - platform.verify_eci(get_rsdl_compilation_info()) - -SDLNotInstalled = (ImportError, CompilationError) diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import - - at interface SDLMain : NSObject - at end diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m +++ /dev/null @@ -1,384 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import "SDL.h" -#import "SDLMain.h" -#import /* for MAXPATHLEN */ -#import - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ - at interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; - at end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ - at interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; - at end -#endif - - at interface SDLApplication : NSApplication - at end - - at implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} - at end - -/* The main class of the application, the application's delegate */ - at implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { - assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } - -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} - at end - - - at implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - - at end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/pypy/rlib/rsdl/test/__init__.py b/pypy/rlib/rsdl/test/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/test/applause.wav b/pypy/rlib/rsdl/test/applause.wav deleted file mode 100644 Binary file pypy/rlib/rsdl/test/applause.wav has changed diff --git a/pypy/rlib/rsdl/test/autopath.py b/pypy/rlib/rsdl/test/autopath.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/autopath.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -self cloning, automatic path configuration - -copy this into any subdirectory of pypy from which scripts need -to be run, typically all of the test subdirs. -The idea is that any such script simply issues - - import autopath - -and this will make sure that the parent directory containing "pypy" -is in sys.path. - -If you modify the master "autopath.py" version (in pypy/tool/autopath.py) -you can directly run it which will copy itself on all autopath.py files -it finds under the pypy root directory. - -This module always provides these attributes: - - pypydir pypy root directory path - this_dir directory where this autopath.py resides - -""" - -def __dirinfo(part): - """ return (partdir, this_dir) and insert parent of partdir - into sys.path. If the parent directories don't have the part - an EnvironmentError is raised.""" - - import sys, os - try: - head = this_dir = os.path.realpath(os.path.dirname(__file__)) - except NameError: - head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) - - error = None - while head: - partdir = head - head, tail = os.path.split(head) - if tail == part: - checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py') - if not os.path.exists(checkfile): - error = "Cannot find %r" % (os.path.normpath(checkfile),) - break - else: - error = "Cannot find the parent directory %r of the path %r" % ( - partdir, this_dir) - if not error: - # check for bogus end-of-line style (e.g. files checked out on - # Windows and moved to Unix) - f = open(__file__.replace('.pyc', '.py'), 'r') - data = f.read() - f.close() - if data.endswith('\r\n') or data.endswith('\r'): - error = ("Bad end-of-line style in the .py files. Typically " - "caused by a zip file or a checkout done on Windows and " - "moved to Unix or vice-versa.") - if error: - raise EnvironmentError("Invalid source tree - bogus checkout! " + - error) - - pypy_root = os.path.join(head, '') - try: - sys.path.remove(head) - except ValueError: - pass - sys.path.insert(0, head) - - munged = {} - for name, mod in sys.modules.items(): - if '.' in name: - continue - fn = getattr(mod, '__file__', None) - if not isinstance(fn, str): - continue - newname = os.path.splitext(os.path.basename(fn))[0] - if not newname.startswith(part + '.'): - continue - path = os.path.join(os.path.dirname(os.path.realpath(fn)), '') - if path.startswith(pypy_root) and newname != part: - modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep) - if newname != '__init__': - modpaths.append(newname) - modpath = '.'.join(modpaths) - if modpath not in sys.modules: - munged[modpath] = mod - - for name, mod in munged.iteritems(): - if name not in sys.modules: - sys.modules[name] = mod - if '.' in name: - prename = name[:name.rfind('.')] - postname = name[len(prename)+1:] - if prename not in sys.modules: - __import__(prename) - if not hasattr(sys.modules[prename], postname): - setattr(sys.modules[prename], postname, mod) - - return partdir, this_dir - -def __clone(): - """ clone master version of autopath.py into all subdirs """ - from os.path import join, walk - if not this_dir.endswith(join('pypy','tool')): - raise EnvironmentError("can only clone master version " - "'%s'" % join(pypydir, 'tool',_myname)) - - - def sync_walker(arg, dirname, fnames): - if _myname in fnames: - fn = join(dirname, _myname) - f = open(fn, 'rwb+') - try: - if f.read() == arg: - print "checkok", fn - else: - print "syncing", fn - f = open(fn, 'w') - f.write(arg) - finally: - f.close() - s = open(join(pypydir, 'tool', _myname), 'rb').read() - walk(pypydir, sync_walker, s) - -_myname = 'autopath.py' - -# set guaranteed attributes - -pypydir, this_dir = __dirinfo('pypy') - -if __name__ == '__main__': - __clone() diff --git a/pypy/rlib/rsdl/test/conftest.py b/pypy/rlib/rsdl/test/conftest.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -from pypy.rlib.rsdl.eci import check_sdl_installation, SDLNotInstalled -import py - -def pytest_ignore_collect(path): - try: - check_sdl_installation() - except SDLNotInstalled, e: - return True - else: - return False diff --git a/pypy/rlib/rsdl/test/demo.jpg b/pypy/rlib/rsdl/test/demo.jpg deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.jpg has changed diff --git a/pypy/rlib/rsdl/test/demo.png b/pypy/rlib/rsdl/test/demo.png deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.png has changed diff --git a/pypy/rlib/rsdl/test/test_basic.py b/pypy/rlib/rsdl/test/test_basic.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_basic.py +++ /dev/null @@ -1,37 +0,0 @@ -import py -from pypy.rlib.rsdl import RSDL -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import rffi - - -def test_sdl_init(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Quit() - -def test_surface_basic(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - assert surface - assert rffi.getintfield(surface, 'c_w') == 150 - assert rffi.getintfield(surface, 'c_h') == 50 - RSDL.FreeSurface(surface) - RSDL.Quit() - - -def test_get_keyname(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - assert RSDL.GetKeyName(RSDL.K_PLUS)[0] == '+' - assert RSDL.GetKeyName(RSDL.K_RIGHTPAREN)[0] == ')' - assert RSDL.GetKeyName(RSDL.K_z)[0] == 'z' - -def test_delay_getticks(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Delay(10) - i = RSDL.GetTicks() - assert i >= 10 - RSDL.Quit() - \ No newline at end of file diff --git a/pypy/rlib/rsdl/test/test_sdl_image.py b/pypy/rlib/rsdl/test/test_sdl_image.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_image.py +++ /dev/null @@ -1,50 +0,0 @@ -import py, os -import autopath -from pypy.rlib.rsdl import RSDL, RIMG, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - - -def test_load_image(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image, 'c_w') == 17 - assert rffi.getintfield(image, 'c_h') == 23 - RSDL.FreeSurface(image) - -def test_image_pixels(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image.c_format, 'c_BytesPerPixel') in (3, 4) - RSDL.LockSurface(image) - result = {} - try: - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - for y in range(23): - for x in range(y % 13, 17, 13): - color = RSDL_helper.get_pixel(image, x, y) - RSDL.GetRGB(color, - image.c_format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result[x, y] = r, g, b - finally: - lltype.free(rgb, flavor='raw') - finally: - RSDL.UnlockSurface(image) - RSDL.FreeSurface(image) - for x, y in result: - f = (x*17 + y*23) / float(17*17+23*23) - expected_r = int(255.0 * (1.0-f)) - expected_g = 0 - expected_b = int(255.0 * f) - r, g, b = result[x, y] - assert abs(r-expected_r) < 10 - assert abs(g-expected_g) < 10 - assert abs(b-expected_b) < 10 diff --git a/pypy/rlib/rsdl/test/test_sdl_mixer.py b/pypy/rlib/rsdl/test/test_sdl_mixer.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_mixer.py +++ /dev/null @@ -1,33 +0,0 @@ -import py -import os -import time -import autopath -from pypy.rlib.rsdl import RSDL, RMix, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - -def test_open_mixer(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - RMix.CloseAudio() - -def test_load_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.CloseAudio() - -def test_play_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - applause = RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.PlayChannel(-1, applause, -1) - time.sleep(1) - RMix.CloseAudio() - diff --git a/pypy/rlib/rsdl/test/test_surface.py b/pypy/rlib/rsdl/test/test_surface.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_surface.py +++ /dev/null @@ -1,75 +0,0 @@ -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi - -class TestSurface: - - def setup_method(self, meth): - self.dst_surf = RSDL.CreateRGBSurface(0, 300, 300, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - self.src_surf = RSDL.CreateRGBSurface(0, 50, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - fmt = self.src_surf.c_format - self.black = RSDL.MapRGB(fmt, 0, 0, 0) - self.red = RSDL.MapRGB(fmt, 255, 0, 0) - self.blue = RSDL.MapRGB(fmt, 0, 0, 255) - RSDL.FillRect(self.src_surf, lltype.nullptr(RSDL.Rect), self.red) - - def test_simple(self): - pass # only checks that creating the surfaces works - - def test_set_alpha(self): - # prepare - assert RSDL.SetAlpha(self.src_surf, RSDL.SRCALPHA, 128) == 0 - - # draw - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 10, 10) - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 20, 20) - - # check - for position, color in ( - (( 0, 0), ( 0,0,0)), # no rect - ((10,10), (127,0,0)), # one rect - ((20,20), (191,0,0)) # two overlapping rects - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert RSDL_helper.get_rgb(fetched_color, self.dst_surf.c_format) == color - - def test_set_color_key(self): - # prepare - fillrect = RSDL_helper.mallocrect(10, 10, 30, 30) - RSDL.FillRect(self.src_surf, fillrect, self.blue) - lltype.free(fillrect, flavor='raw') - assert RSDL.SetColorKey(self.src_surf, RSDL.SRCCOLORKEY, self.blue) == 0 - - # draw - RSDL_helper.blit_complete_surface(self.src_surf, self.dst_surf, 0, 0) - - # check - for position, color in ( - (( 0, 0), self.red), - ((10,10), self.black), - ((20,20), self.black), - ((40,40), self.red) - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert fetched_color == color - - def teardown_method(self, meth): - RSDL.FreeSurface(self.src_surf) - RSDL.FreeSurface(self.dst_surf) - RSDL.Quit() - diff --git a/pypy/rlib/rsdl/test/test_video.py b/pypy/rlib/rsdl/test/test_video.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_video.py +++ /dev/null @@ -1,241 +0,0 @@ - -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi -from pypy import conftest - -# -# This test file is skipped unless run with "py.test --view". -# If it is run as "py.test --view -s", then it interactively asks -# for confirmation that the window looks as expected. -# - - -class TestVideo: - - def setup_method(self, meth): - if not conftest.option.view: - py.test.skip("'--view' not specified, " - "skipping tests that open a window") - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - self.screen = RSDL.SetVideoMode(640, 480, 32, 0) - assert self.screen - self.is_interactive = sys.stdout.isatty() - - def check(self, msg): - if self.is_interactive: - print - answer = raw_input('Interactive test: %s - ok? [Y] ' % msg) - if answer and not answer.upper().startswith('Y'): - py.test.fail(msg) - else: - print msg - - def test_simple(self): - pass # only checks that opening and closing the window works - - def test_fillrect_full(self): - fmt = self.screen.c_format - for colorname, r, g, b in [('dark red', 128, 0, 0), - ('yellow', 255, 255, 0), - ('blue', 0, 0, 255)]: - color = RSDL.MapRGB(fmt, r, g, b) - RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) - RSDL.Flip(self.screen) - self.check("Screen filled with %s" % colorname) - - def test_caption(self): - RSDL.WM_SetCaption("Hello World!", "Hello World!") - self.check('The window caption is "Hello World!"') - - def test_keypresses(self): - if not self.is_interactive: - py.test.skip("interactive test only") - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window should be printed below." - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - char = rffi.getintfield(p.c_keysym, 'c_unicode') - if char != 0: - print 'Key:', unichr(char).encode('utf-8') - else: - print 'Some special key' - else: - print '(event of type %d)' % c_type - finally: - lltype.free(event, flavor='raw') - - def test_poll(self): - if not self.is_interactive: - py.test.skip("interactive test only") - import time, sys - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window give a dot." - print " Wait 3 seconds to quit." - timeout = time.time() + 3 - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - # busy polling - ok = RSDL.PollEvent(event) - ok = rffi.cast(lltype.Signed, ok) - assert ok >= 0 - if ok > 0: - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - sys.stderr.write('.') - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - timeout = time.time() + 3 - else: - if time.time() > timeout: - break - time.sleep(0.05) - finally: - lltype.free(event, flavor='raw') - - def test_mousemove(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Move the Mouse up and down:" - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor="raw") - directions = [False]*4 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, "c_type") - if c_type == RSDL.MOUSEMOTION: - m = rffi.cast(RSDL.MouseMotionEventPtr, event) - assert rffi.getintfield(m, "c_x") >= 0 - assert rffi.getintfield(m, "c_y") >= 0 - print rffi.getintfield(m, "c_xrel") - directions[0] |= rffi.getintfield(m, "c_xrel")>0 - directions[1] |= rffi.getintfield(m, "c_xrel")<0 - directions[2] |= rffi.getintfield(m, "c_yrel")>0 - directions[3] |= rffi.getintfield(m, "c_yrel")<0 - if False not in directions: - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print " test manually aborted" - py.test.fail(" mousemovement test aborted") - break - finally: - lltype.free(event, flavor='raw') - - - def test_mousebutton_wheel(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Press the given MouseButtons:" - print " Use Escape to pass tests." - - event_tests = [("left button", RSDL.BUTTON_LEFT), - ("middle button", RSDL.BUTTON_MIDDLE), - ("right button", RSDL.BUTTON_RIGHT), - ("scroll up", RSDL.BUTTON_WHEELUP), - ("scroll down", RSDL.BUTTON_WHEELDOWN)] - test_success = [] - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - for button_test in event_tests: - print " press %s:" % button_test[0] - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.MOUSEBUTTONDOWN: - pass - elif c_type == RSDL.MOUSEBUTTONUP: - b = rffi.cast(RSDL.MouseButtonEventPtr, event) - if rffi.getintfield(b, 'c_button') == button_test[1]: - test_success.append(True) - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - test_success.append(False) - print " manually aborted" - break - #break - if False in test_success: - py.test.fail("") - finally: - lltype.free(event, flavor='raw') - - - def test_show_hide_cursor(self): - RSDL.ShowCursor(RSDL.DISABLE) - self.check("Is the cursor hidden? ") - RSDL.ShowCursor(RSDL.ENABLE) - self.check("Is the cursor shown? ") - - def test_bit_pattern(self): - HEIGHT = WIDTH = 10 - fmt = self.screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(self.screen) - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = white - else: - c = black - RSDL_helper.set_pixel(self.screen, i, j, c) - RSDL.UnlockSurface(self.screen) - RSDL.Flip(self.screen) - self.check("Upper left corner 10x10 field with vertical black/white stripes") - - def test_blit_rect(self): - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - fmt = surface.c_format - color = RSDL.MapRGB(fmt, 255, 0, 0) - RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) - - paintrect = RSDL_helper.mallocrect(75, 0, 150, 50) - dstrect = lltype.malloc(RSDL.Rect, flavor='raw') - try: - color = RSDL.MapRGB(fmt, 255, 128, 0) - RSDL.FillRect(surface, paintrect, color) - - rffi.setintfield(dstrect, 'c_x', 10) - rffi.setintfield(dstrect, 'c_y', 10) - rffi.setintfield(dstrect, 'c_w', 150) - rffi.setintfield(dstrect, 'c_h', 50) - RSDL.BlitSurface(surface, lltype.nullptr(RSDL.Rect), self.screen, dstrect) - RSDL.Flip(self.screen) - finally: - lltype.free(dstrect, flavor='raw') - lltype.free(paintrect, flavor='raw') - RSDL.FreeSurface(surface) - self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border") - - def teardown_method(self, meth): - RSDL.Quit() - diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py --- a/pypy/rpython/memory/gc/minimark.py +++ b/pypy/rpython/memory/gc/minimark.py @@ -111,10 +111,13 @@ # The following flag is set on externally raw_malloc'ed arrays of pointers. # They are allocated with some extra space in front of them for a bitfield, # one bit per 'card_page_indices' indices. -GCFLAG_HAS_CARDS = first_gcflag << 5 -GCFLAG_CARDS_SET = first_gcflag << 6 # <- at least one card bit is set +GCFLAG_HAS_CARDS = first_gcflag << 6 +GCFLAG_CARDS_SET = first_gcflag << 7 # <- at least one card bit is set +# note that GCFLAG_CARDS_SET is the most significant bit of a byte: +# this is required for the JIT (x86) -TID_MASK = (first_gcflag << 7) - 1 +#GCFLAG_UNUSED = first_gcflag << 5 # this flag is free +TID_MASK = (first_gcflag << 8) - 1 FORWARDSTUB = lltype.GcStruct('forwarding_stub', @@ -994,12 +997,9 @@ def _init_writebarrier_logic(self): DEBUG = self.DEBUG # The purpose of attaching remember_young_pointer to the instance - # instead of keeping it as a regular method is to help the JIT call it. - # Additionally, it makes the code in write_barrier() marginally smaller + # instead of keeping it as a regular method is to + # make the code in write_barrier() marginally smaller # (which is important because it is inlined *everywhere*). - # For x86, there is also an extra requirement: when the JIT calls - # remember_young_pointer(), it assumes that it will not touch the SSE - # registers, so it does not save and restore them (that's a *hack*!). def remember_young_pointer(addr_struct, newvalue): # 'addr_struct' is the address of the object in which we write. # 'newvalue' is the address that we are going to write in there. @@ -1033,6 +1033,17 @@ remember_young_pointer._dont_inline_ = True self.remember_young_pointer = remember_young_pointer # + def jit_remember_young_pointer(addr_struct): + # minimal version of the above, with just one argument, + # called by the JIT when GCFLAG_TRACK_YOUNG_PTRS is set + self.old_objects_pointing_to_young.append(addr_struct) + objhdr = self.header(addr_struct) + objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS + if objhdr.tid & GCFLAG_NO_HEAP_PTRS: + objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS + self.prebuilt_root_objects.append(addr_struct) + self.jit_remember_young_pointer = jit_remember_young_pointer + # if self.card_page_indices > 0: self._init_writebarrier_with_card_marker() @@ -1087,60 +1098,21 @@ self.remember_young_pointer_from_array2 = ( remember_young_pointer_from_array2) - # xxx trying it out for the JIT: a 3-arguments version of the above - def remember_young_pointer_from_array3(addr_array, index, newvalue): + def jit_remember_young_pointer_from_array(addr_array): + # minimal version of the above, with just one argument, + # called by the JIT when GCFLAG_TRACK_YOUNG_PTRS is set + # but GCFLAG_CARDS_SET is cleared. This tries to set + # GCFLAG_CARDS_SET if possible; otherwise, it falls back + # to jit_remember_young_pointer(). objhdr = self.header(addr_array) - # - # a single check for the common case of neither GCFLAG_HAS_CARDS - # nor GCFLAG_NO_HEAP_PTRS - if objhdr.tid & (GCFLAG_HAS_CARDS | GCFLAG_NO_HEAP_PTRS) == 0: - # common case: fast path, jump to the end of the function - pass - elif objhdr.tid & GCFLAG_HAS_CARDS == 0: - # no cards, but GCFLAG_NO_HEAP_PTRS is set. - objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.prebuilt_root_objects.append(addr_array) - # jump to the end of the function + if objhdr.tid & GCFLAG_HAS_CARDS: + self.old_objects_with_cards_set.append(addr_array) + objhdr.tid |= GCFLAG_CARDS_SET else: - # case with cards. - # - # If the newly written address does not actually point to a - # young object, leave now. - if not self.appears_to_be_young(newvalue): - return - # - # 'addr_array' is a raw_malloc'ed array with card markers - # in front. Compute the index of the bit to set: - bitindex = index >> self.card_page_shift - byteindex = bitindex >> 3 - bitmask = 1 << (bitindex & 7) - # - # If the bit is already set, leave now. - addr_byte = self.get_card(addr_array, byteindex) - byte = ord(addr_byte.char[0]) - if byte & bitmask: - return - addr_byte.char[0] = chr(byte | bitmask) - # - if objhdr.tid & GCFLAG_CARDS_SET == 0: - self.old_objects_with_cards_set.append(addr_array) - objhdr.tid |= GCFLAG_CARDS_SET - return - # - # Logic for the no-cards case, put here to minimize the number - # of checks done at the start of the function - if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this - ll_assert(self.debug_is_old_object(addr_array), - "young array with no card but GCFLAG_TRACK_YOUNG_PTRS") - # - if self.appears_to_be_young(newvalue): - self.old_objects_pointing_to_young.append(addr_array) - objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS + self.jit_remember_young_pointer(addr_array) - remember_young_pointer_from_array3._dont_inline_ = True - assert self.card_page_indices > 0 - self.remember_young_pointer_from_array3 = ( - remember_young_pointer_from_array3) + self.jit_remember_young_pointer_from_array = ( + jit_remember_young_pointer_from_array) def get_card(self, obj, byteindex): size_gc_header = self.gcheaderbuilder.size_gc_header diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py --- a/pypy/rpython/memory/gctransform/framework.py +++ b/pypy/rpython/memory/gctransform/framework.py @@ -455,13 +455,12 @@ annmodel.SomeAddress()], annmodel.s_None, inline=True) - func = getattr(gcdata.gc, 'remember_young_pointer', None) + func = getattr(gcdata.gc, 'jit_remember_young_pointer', None) if func is not None: # func should not be a bound method, but a real function assert isinstance(func, types.FunctionType) self.write_barrier_failing_case_ptr = getfn(func, - [annmodel.SomeAddress(), - annmodel.SomeAddress()], + [annmodel.SomeAddress()], annmodel.s_None) func = getattr(GCClass, 'write_barrier_from_array', None) if func is not None: @@ -472,16 +471,15 @@ annmodel.SomeInteger()], annmodel.s_None, inline=True) - func = getattr(gcdata.gc, 'remember_young_pointer_from_array3', + func = getattr(gcdata.gc, + 'jit_remember_young_pointer_from_array', None) if func is not None: # func should not be a bound method, but a real function assert isinstance(func, types.FunctionType) self.write_barrier_from_array_failing_case_ptr = \ getfn(func, - [annmodel.SomeAddress(), - annmodel.SomeInteger(), - annmodel.SomeAddress()], + [annmodel.SomeAddress()], annmodel.s_None) self.statistics_ptr = getfn(GCClass.statistics.im_func, [s_gc, annmodel.SomeInteger()], diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py --- a/pypy/rpython/module/ll_os.py +++ b/pypy/rpython/module/ll_os.py @@ -148,6 +148,7 @@ else: includes += ['sys/utime.h'] +_CYGWIN = sys.platform == 'cygwin' class CConfig: """ @@ -1329,9 +1330,14 @@ return result else: # Posix - os_waitpid = self.llexternal('waitpid', - [rffi.PID_T, rffi.INTP, rffi.INT], - rffi.PID_T) + if _CYGWIN: + os_waitpid = self.llexternal('cygwin_waitpid', + [rffi.PID_T, rffi.INTP, rffi.INT], + rffi.PID_T) + else: + os_waitpid = self.llexternal('waitpid', + [rffi.PID_T, rffi.INTP, rffi.INT], + rffi.PID_T) def os_waitpid_llimpl(pid, options): status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -145,6 +145,8 @@ archive = str(builddir.join(name + '.tar.bz2')) if sys.platform == 'darwin' or sys.platform.startswith('freebsd'): e = os.system('tar --numeric-owner -cvjf ' + archive + " " + name) + elif sys.platform == 'cygwin': + e = os.system('tar --owner=Administrator --group=Administrators --numeric-owner -cvjf ' + archive + " " + name) else: e = os.system('tar --owner=root --group=root --numeric-owner -cvjf ' + archive + " " + name) if e: diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py --- a/pypy/translator/c/genc.py +++ b/pypy/translator/c/genc.py @@ -15,6 +15,8 @@ from pypy.rlib import exports from pypy.tool.nullpath import NullPyPathLocal +_CYGWIN = sys.platform == 'cygwin' + def import_module_from_directory(dir, modname): file, pathname, description = imp.find_module(modname, [str(dir)]) try: @@ -954,6 +956,8 @@ srcdir / 'profiling.c', srcdir / 'debug_print.c', ] + if _CYGWIN: + files.append(srcdir / 'cygwin_wait.c') return eci.merge(ExternalCompilationInfo(separate_module_files=files)) diff --git a/pypy/translator/c/src/cygwin_wait.c b/pypy/translator/c/src/cygwin_wait.c new file mode 100644 --- /dev/null +++ b/pypy/translator/c/src/cygwin_wait.c @@ -0,0 +1,47 @@ +/* + Work around compile error: + [translation:ERROR] implement_4.c: In function 'pypy_g_ccall_waitpid__Signed_arrayPtr_Signed': + [translation:ERROR] implement_4.c:150095:2: error: incompatible type for argument 2 of 'waitpid' + [translation:ERROR] /usr/include/sys/wait.h:43:7: note: expected '__wait_status_ptr_t' but argument is of type 'long int *' +*/ + +#ifdef __CYGWIN__ + +#include "wait.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* +typedef int *__wait_status_ptr_t; + */ + + /* +pid_t wait (__wait_status_ptr_t __status); +pid_t waitpid (pid_t __pid, __wait_status_ptr_t __status, int __options); +pid_t wait3 (__wait_status_ptr_t __status, int __options, struct rusage *__rusage); +pid_t wait4 (pid_t __pid, __wait_status_ptr_t __status, int __options, struct rusage *__rusage); + */ + + pid_t cygwin_wait (int * __status){ + return wait ((__wait_status_ptr_t) __status); + } + + pid_t cygwin_waitpid (pid_t __pid, int * __status, int __options){ + return waitpid (__pid, (__wait_status_ptr_t) __status, __options); + } + + pid_t cygwin_wait3 (int * __status, int __options, struct rusage *__rusage){ + return wait3 ((__wait_status_ptr_t) __status, __options, __rusage); + } + + pid_t cygwin_wait4 (pid_t __pid, int * __status, int __options, struct rusage *__rusage){ + return wait4 (__pid, (__wait_status_ptr_t) __status, __options, __rusage); + } + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pypy/translator/c/src/cygwin_wait.h b/pypy/translator/c/src/cygwin_wait.h new file mode 100644 --- /dev/null +++ b/pypy/translator/c/src/cygwin_wait.h @@ -0,0 +1,43 @@ +/* + Work around compile error: + [translation:ERROR] implement_4.c: In function 'pypy_g_ccall_waitpid__Signed_arrayPtr_Signed': + [translation:ERROR] implement_4.c:150095:2: error: incompatible type for argument 2 of 'waitpid' + [translation:ERROR] /usr/include/sys/wait.h:43:7: note: expected '__wait_status_ptr_t' but argument is of type 'long int *' +*/ + +#ifdef __CYGWIN__ + +#ifndef _PYPY_WAIT_H +#define _PYPY_WAIT_H + +#ifndef _SYS_WAIT_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /* +typedef int *__wait_status_ptr_t; + */ + + /* +pid_t wait (__wait_status_ptr_t __status); +pid_t waitpid (pid_t __pid, __wait_status_ptr_t __status, int __options); +pid_t wait3 (__wait_status_ptr_t __status, int __options, struct rusage *__rusage); +pid_t wait4 (pid_t __pid, __wait_status_ptr_t __status, int __options, struct rusage *__rusage); + */ + + pid_t cygwin_wait (int * __status); + pid_t cygwin_waitpid (pid_t __pid, int * __status, int __options); + pid_t cygwin_wait3 (int * __status, int __options, struct rusage *__rusage); + pid_t cygwin_wait4 (pid_t __pid, int * __status, int __options, struct rusage *__rusage); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/pypy/translator/c/src/g_include.h b/pypy/translator/c/src/g_include.h --- a/pypy/translator/c/src/g_include.h +++ b/pypy/translator/c/src/g_include.h @@ -61,3 +61,8 @@ # pragma warning(disable: 4033 4102 4101 4716) # endif #endif + +/* work around waitpid expecting different pointer type */ +#ifdef __CYGWIN__ +#include "src/cygwin_wait.h" +#endif diff --git a/pypy/translator/goal/targetsimplevideo.py b/pypy/translator/goal/targetsimplevideo.py deleted file mode 100644 --- a/pypy/translator/goal/targetsimplevideo.py +++ /dev/null @@ -1,98 +0,0 @@ -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rpython.lltypesystem import rffi, lltype -import py - -WIDTH = 1000 -HEIGHT = 1000 - -def entry_point(argv=None): - RSDL.Init(RSDL.INIT_VIDEO) >= 0 - screen = RSDL.SetVideoMode(WIDTH, HEIGHT, 32, 0) - event = lltype.malloc(RSDL.Event, flavor='raw') - paintpattern = 0 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - paintpattern += 1 - update_screen(screen, paintpattern) - finally: - lltype.free(event, flavor='raw') - - return 0 - -# ----------------------------------------------------------------------------- - -def chess(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - if (i+j) % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def white(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, colb) - -def black(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, cola) - -def stripes_v(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def stripes_m(screen, cola, colb): - for j in xrange(WIDTH): - for i in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - - -# ----------------------------------------------------------------------------- - -pattern = [chess, white, black, stripes_v, stripes_m] -pl = len(pattern) -def update_screen(screen, paintpattern): - fmt = screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(screen) - pattern[paintpattern % pl](screen, black, white) - RSDL.UnlockSurface(screen) - RSDL.Flip(screen) - RSDL.Delay(10 ) - - -# ----------------------------------------------------------------------------- - -def target(*args): - return entry_point, None - -def test_target(): - entry_point() - -if __name__ == '__main__': - entry_point() - - diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py --- a/pypy/translator/platform/__init__.py +++ b/pypy/translator/platform/__init__.py @@ -278,6 +278,13 @@ host_factory = Windows else: host_factory = Windows_x64 +elif sys.platform == 'cygwin': + from pypy.translator.platform.cygwin import Cygwin, Cygwin64 + import platform + if platform.architecture()[0] == '32bit': + host_factory = Cygwin + else: + host_factory = Cygwin64 else: # pray from pypy.translator.platform.distutils_platform import DistutilsPlatform diff --git a/pypy/translator/platform/cygwin.py b/pypy/translator/platform/cygwin.py new file mode 100644 --- /dev/null +++ b/pypy/translator/platform/cygwin.py @@ -0,0 +1,56 @@ +"""Support for Cygwin.""" + +import os +import sys +from pypy.translator.platform.posix import BasePosix + +class BaseCygwin(BasePosix): + name = "cygwin" + +# link_flags = tuple( +# ['-pthread',] +# + os.environ.get('LDFLAGS', '').split()) + link_flags = tuple( + [] + + os.environ.get('LDFLAGS', '').split()) + extra_libs = ('-lrt',) +# cflags = tuple( +# ['-O3', '-pthread', '-fomit-frame-pointer', +# '-Wall', '-Wno-unused'] +# + os.environ.get('CFLAGS', '').split()) + cflags = tuple( + ['-O3', '-fomit-frame-pointer', + '-Wall', '-Wno-unused'] + + os.environ.get('CFLAGS', '').split()) + standalone_only = () + shared_only = ('-fPIC',) + so_ext = 'dll' + exe_ext = 'exe' + so_prefixes = ('lib', '') + + def _args_for_shared(self, args): + return ['-shared'] + args + + def _include_dirs_for_libffi(self): + return self._pkg_config("libffi", "--cflags-only-I", + ['/usr/include/libffi']) + + def _library_dirs_for_libffi(self): + return self._pkg_config("libffi", "--libs-only-L", + ['/usr/lib/libffi']) + + def library_dirs_for_libffi_a(self): + # places where we need to look for libffi.a + # XXX obscuuure! only look for libffi.a if run with translate.py + if 'translate' in sys.modules: + return self.library_dirs_for_libffi() + ['/usr/lib'] + else: + return [] + + +class Cygwin(BaseCygwin): + shared_only = () # it seems that on 32-bit linux, compiling with -fPIC + # gives assembler that asmgcc is not happy about. + +class Cygwin64(BaseCygwin): + pass diff --git a/pypy/translator/platform/posix.py b/pypy/translator/platform/posix.py --- a/pypy/translator/platform/posix.py +++ b/pypy/translator/platform/posix.py @@ -1,6 +1,6 @@ """Base support for POSIX-like platforms.""" -import py, os +import py, os, sys from pypy.tool import autopath from pypy.translator.platform import Platform, log, _run_subprocess @@ -55,7 +55,8 @@ if relto: response_file = relto.bestrelpath(response_file) - if self.cc == 'mingw32' or (self.cc== 'gcc' and os.name=='nt'): + if (self.cc == 'mingw32' or (self.cc== 'gcc' and os.name=='nt') + or sys.platform == 'cygwin'): return ["-Wl,--export-all-symbols,--version-script=%s" % \ (response_file,)] return ["-Wl,--export-dynamic,--version-script=%s" % (response_file,)] From noreply at buildbot.pypy.org Tue Jun 5 09:58:21 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:58:21 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix test Message-ID: <20120605075821.227191C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55301:e239c051d488 Date: 2012-06-04 11:07 +0200 http://bitbucket.org/pypy/pypy/changeset/e239c051d488/ Log: Fix test diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py --- a/pypy/jit/backend/llsupport/test/test_gc.py +++ b/pypy/jit/backend/llsupport/test/test_gc.py @@ -276,8 +276,8 @@ repr(offset_to_length), p)) return p - def _write_barrier_failing_case(self, adr_struct, adr_newptr): - self.record.append(('barrier', adr_struct, adr_newptr)) + def _write_barrier_failing_case(self, adr_struct): + self.record.append(('barrier', adr_struct)) def get_write_barrier_failing_case(self, FPTRTYPE): return llhelper(FPTRTYPE, self._write_barrier_failing_case) @@ -402,7 +402,7 @@ # s_hdr.tid |= gc_ll_descr.GCClass.JIT_WB_IF_FLAG gc_ll_descr.do_write_barrier(s_gcref, r_gcref) - assert self.llop1.record == [('barrier', s_adr, r_adr)] + assert self.llop1.record == [('barrier', s_adr)] def test_gen_write_barrier(self): gc_ll_descr = self.gc_ll_descr From noreply at buildbot.pypy.org Tue Jun 5 09:58:28 2012 From: noreply at buildbot.pypy.org (antocuni) Date: Tue, 5 Jun 2012 09:58:28 +0200 (CEST) Subject: [pypy-commit] pypy default: don't complain if 'default' is documented Message-ID: <20120605075828.1D8B01C003C@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: Changeset: r55302:efedebf46f63 Date: 2012-06-04 11:51 +0200 http://bitbucket.org/pypy/pypy/changeset/efedebf46f63/ Log: don't complain if 'default' is documented diff --git a/pypy/doc/test/test_whatsnew.py b/pypy/doc/test/test_whatsnew.py --- a/pypy/doc/test/test_whatsnew.py +++ b/pypy/doc/test/test_whatsnew.py @@ -16,6 +16,7 @@ startrev = parseline(line) elif line.startswith('.. branch:'): branches.add(parseline(line)) + branches.discard('default') return startrev, branches def get_merged_branches(path, startrev, endrev): @@ -51,6 +52,10 @@ .. branch: hello qqq www ttt + +.. branch: default + +"default" should be ignored and not put in the set of documented branches """ startrev, branches = parse_doc(s) assert startrev == '12345' From noreply at buildbot.pypy.org Tue Jun 5 09:58:34 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:58:34 +0200 (CEST) Subject: [pypy-commit] pypy default: A failing test from issue872. Message-ID: <20120605075834.CB0FA1C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55303:a3ce5fe94074 Date: 2012-06-04 15:11 +0200 http://bitbucket.org/pypy/pypy/changeset/a3ce5fe94074/ Log: A failing test from issue872. diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -945,6 +945,20 @@ import os assert hasattr(os, 'kill') + def test_pipe_flush(self): + os = self.posix + ffd, gfd = os.pipe() + f = os.fdopen(ffd, 'r') + g = os.fdopen(gfd, 'w') + g.write('he') + g.flush() + x = f.read(1) + assert x == 'h' + f.flush() + x = f.read(1) + assert x == 'e' + + class AppTestEnvironment(object): def setup_class(cls): cls.space = space From noreply at buildbot.pypy.org Tue Jun 5 09:58:35 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:58:35 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix attempt for a3ce5fe94074. Message-ID: <20120605075835.E35BF1C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55304:865681d756a9 Date: 2012-06-04 15:16 +0200 http://bitbucket.org/pypy/pypy/changeset/865681d756a9/ Log: Fix attempt for a3ce5fe94074. diff --git a/pypy/rlib/streamio.py b/pypy/rlib/streamio.py --- a/pypy/rlib/streamio.py +++ b/pypy/rlib/streamio.py @@ -500,7 +500,7 @@ if self.buf: try: self.do_seek(self.tell(), 0) - except MyNotImplementedError: + except (MyNotImplementedError, OSError): pass else: self.buf = "" @@ -713,7 +713,7 @@ if self.buf is not None: try: self.do_seek(self.bufstart-len(self.buf), 1) - except MyNotImplementedError: + except (MyNotImplementedError, OSError): pass else: self.buf = None @@ -968,7 +968,10 @@ def flush_buffers(self): if self.lfbuffer: - self.base.seek(-len(self.lfbuffer), 1) + try: + self.base.seek(-len(self.lfbuffer), 1) + except (MyNotImplementedError, OSError): + return self.lfbuffer = "" self.do_flush() @@ -1102,7 +1105,7 @@ if self.buf: try: self.base.seek(-len(self.buf), 1) - except MyNotImplementedError: + except (MyNotImplementedError, OSError): pass else: self.buf = "" From noreply at buildbot.pypy.org Tue Jun 5 09:58:57 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:58:57 +0200 (CEST) Subject: [pypy-commit] pypy stackroot-speedup: hg merge default Message-ID: <20120605075857.EAAF11C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stackroot-speedup Changeset: r55305:960a8ef83e41 Date: 2012-06-04 15:50 +0200 http://bitbucket.org/pypy/pypy/changeset/960a8ef83e41/ Log: hg merge default diff too long, truncating to 10000 out of 392244 lines diff --git a/_pytest/__init__.py b/_pytest/__init__.py --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.1.0.dev4' +__version__ = '2.2.4.dev2' diff --git a/_pytest/assertion/__init__.py b/_pytest/assertion/__init__.py --- a/_pytest/assertion/__init__.py +++ b/_pytest/assertion/__init__.py @@ -2,35 +2,25 @@ support for presenting detailed information in failing assertions. """ import py -import imp -import marshal -import struct import sys import pytest from _pytest.monkeypatch import monkeypatch -from _pytest.assertion import reinterpret, util - -try: - from _pytest.assertion.rewrite import rewrite_asserts -except ImportError: - rewrite_asserts = None -else: - import ast +from _pytest.assertion import util def pytest_addoption(parser): group = parser.getgroup("debugconfig") - group.addoption('--assertmode', action="store", dest="assertmode", - choices=("on", "old", "off", "default"), default="default", - metavar="on|old|off", + group.addoption('--assert', action="store", dest="assertmode", + choices=("rewrite", "reinterp", "plain",), + default="rewrite", metavar="MODE", help="""control assertion debugging tools. -'off' performs no assertion debugging. -'old' reinterprets the expressions in asserts to glean information. -'on' (the default) rewrites the assert statements in test modules to provide -sub-expression results.""") +'plain' performs no assertion debugging. +'reinterp' reinterprets assert statements after they failed to provide assertion expression information. +'rewrite' (the default) rewrites assert statements in test modules on import +to provide assert expression information. """) group.addoption('--no-assert', action="store_true", default=False, - dest="noassert", help="DEPRECATED equivalent to --assertmode=off") + dest="noassert", help="DEPRECATED equivalent to --assert=plain") group.addoption('--nomagic', action="store_true", default=False, - dest="nomagic", help="DEPRECATED equivalent to --assertmode=off") + dest="nomagic", help="DEPRECATED equivalent to --assert=plain") class AssertionState: """State for the assertion plugin.""" @@ -40,89 +30,90 @@ self.trace = config.trace.root.get("assertion") def pytest_configure(config): - warn_about_missing_assertion() mode = config.getvalue("assertmode") if config.getvalue("noassert") or config.getvalue("nomagic"): - if mode not in ("off", "default"): - raise pytest.UsageError("assertion options conflict") - mode = "off" - elif mode == "default": - mode = "on" - if mode != "off": - def callbinrepr(op, left, right): - hook_result = config.hook.pytest_assertrepr_compare( - config=config, op=op, left=left, right=right) - for new_expl in hook_result: - if new_expl: - return '\n~'.join(new_expl) + mode = "plain" + if mode == "rewrite": + try: + import ast + except ImportError: + mode = "reinterp" + else: + if sys.platform.startswith('java'): + mode = "reinterp" + if mode != "plain": + _load_modules(mode) m = monkeypatch() config._cleanup.append(m.undo) m.setattr(py.builtin.builtins, 'AssertionError', reinterpret.AssertionError) - m.setattr(util, '_reprcompare', callbinrepr) - if mode == "on" and rewrite_asserts is None: - mode = "old" + hook = None + if mode == "rewrite": + hook = rewrite.AssertionRewritingHook() + sys.meta_path.append(hook) + warn_about_missing_assertion(mode) config._assertstate = AssertionState(config, mode) + config._assertstate.hook = hook config._assertstate.trace("configured with mode set to %r" % (mode,)) -def _write_pyc(co, source_path): - if hasattr(imp, "cache_from_source"): - # Handle PEP 3147 pycs. - pyc = py.path.local(imp.cache_from_source(str(source_path))) - pyc.ensure() - else: - pyc = source_path + "c" - mtime = int(source_path.mtime()) - fp = pyc.open("wb") - try: - fp.write(imp.get_magic()) - fp.write(struct.pack(" 0 and - item.identifier != "__future__"): + elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or + item.module != "__future__"): lineno = item.lineno break pos += 1 @@ -118,9 +357,9 @@ for alias in aliases] mod.body[pos:pos] = imports # Collect asserts. - nodes = collections.deque([mod]) + nodes = [mod] while nodes: - node = nodes.popleft() + node = nodes.pop() for name, field in ast.iter_fields(node): if isinstance(field, list): new = [] @@ -143,7 +382,7 @@ """Get a new variable.""" # Use a character invalid in python identifiers to avoid clashing. name = "@py_assert" + str(next(self.variable_counter)) - self.variables.add(name) + self.variables.append(name) return name def assign(self, expr): @@ -198,7 +437,8 @@ # There's already a message. Don't mess with it. return [assert_] self.statements = [] - self.variables = set() + self.cond_chain = () + self.variables = [] self.variable_counter = itertools.count() self.stack = [] self.on_failure = [] @@ -220,11 +460,11 @@ else: raise_ = ast.Raise(exc, None, None) body.append(raise_) - # Delete temporary variables. - names = [ast.Name(name, ast.Del()) for name in self.variables] - if names: - delete = ast.Delete(names) - self.statements.append(delete) + # Clear temporary variables by setting them to None. + if self.variables: + variables = [ast.Name(name, ast.Store()) for name in self.variables] + clear = ast.Assign(variables, ast.Name("None", ast.Load())) + self.statements.append(clear) # Fix line numbers. for stmt in self.statements: set_location(stmt, assert_.lineno, assert_.col_offset) @@ -240,21 +480,38 @@ return name, self.explanation_param(expr) def visit_BoolOp(self, boolop): - operands = [] - explanations = [] + res_var = self.variable() + expl_list = self.assign(ast.List([], ast.Load())) + app = ast.Attribute(expl_list, "append", ast.Load()) + is_or = int(isinstance(boolop.op, ast.Or)) + body = save = self.statements + fail_save = self.on_failure + levels = len(boolop.values) - 1 self.push_format_context() - for operand in boolop.values: - res, explanation = self.visit(operand) - operands.append(res) - explanations.append(explanation) - expls = ast.Tuple([ast.Str(expl) for expl in explanations], ast.Load()) - is_or = ast.Num(isinstance(boolop.op, ast.Or)) - expl_template = self.helper("format_boolop", - ast.Tuple(operands, ast.Load()), expls, - is_or) + # Process each operand, short-circuting if needed. + for i, v in enumerate(boolop.values): + if i: + fail_inner = [] + self.on_failure.append(ast.If(cond, fail_inner, [])) + self.on_failure = fail_inner + self.push_format_context() + res, expl = self.visit(v) + body.append(ast.Assign([ast.Name(res_var, ast.Store())], res)) + expl_format = self.pop_format_context(ast.Str(expl)) + call = ast.Call(app, [expl_format], [], None, None) + self.on_failure.append(ast.Expr(call)) + if i < levels: + cond = res + if is_or: + cond = ast.UnaryOp(ast.Not(), cond) + inner = [] + self.statements.append(ast.If(cond, inner, [])) + self.statements = body = inner + self.statements = save + self.on_failure = fail_save + expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or)) expl = self.pop_format_context(expl_template) - res = self.assign(ast.BoolOp(boolop.op, operands)) - return res, self.explanation_param(expl) + return ast.Name(res_var, ast.Load()), self.explanation_param(expl) def visit_UnaryOp(self, unary): pattern = unary_map[unary.op.__class__] @@ -288,7 +545,7 @@ new_star, expl = self.visit(call.starargs) arg_expls.append("*" + expl) if call.kwargs: - new_kwarg, expl = self.visit(call.kwarg) + new_kwarg, expl = self.visit(call.kwargs) arg_expls.append("**" + expl) expl = "%s(%s)" % (func_expl, ', '.join(arg_expls)) new_call = ast.Call(new_func, new_args, new_kwargs, new_star, new_kwarg) diff --git a/_pytest/assertion/util.py b/_pytest/assertion/util.py --- a/_pytest/assertion/util.py +++ b/_pytest/assertion/util.py @@ -2,6 +2,7 @@ import py +BuiltinAssertionError = py.builtin.builtins.AssertionError # The _reprcompare attribute on the util module is used by the new assertion # interpretation code and assertion rewriter to detect this plugin was diff --git a/_pytest/capture.py b/_pytest/capture.py --- a/_pytest/capture.py +++ b/_pytest/capture.py @@ -11,22 +11,22 @@ group._addoption('-s', action="store_const", const="no", dest="capture", help="shortcut for --capture=no.") + at pytest.mark.tryfirst +def pytest_cmdline_parse(pluginmanager, args): + # we want to perform capturing already for plugin/conftest loading + if '-s' in args or "--capture=no" in args: + method = "no" + elif hasattr(os, 'dup') and '--capture=sys' not in args: + method = "fd" + else: + method = "sys" + capman = CaptureManager(method) + pluginmanager.register(capman, "capturemanager") + def addouterr(rep, outerr): - repr = getattr(rep, 'longrepr', None) - if not hasattr(repr, 'addsection'): - return for secname, content in zip(["out", "err"], outerr): if content: - repr.addsection("Captured std%s" % secname, content.rstrip()) - -def pytest_unconfigure(config): - # registered in config.py during early conftest.py loading - capman = config.pluginmanager.getplugin('capturemanager') - while capman._method2capture: - name, cap = capman._method2capture.popitem() - # XXX logging module may wants to close it itself on process exit - # otherwise we could do finalization here and call "reset()". - cap.suspend() + rep.sections.append(("Captured std%s" % secname, content)) class NoCapture: def startall(self): @@ -39,8 +39,9 @@ return "", "" class CaptureManager: - def __init__(self): + def __init__(self, defaultmethod=None): self._method2capture = {} + self._defaultmethod = defaultmethod def _maketempfile(self): f = py.std.tempfile.TemporaryFile() @@ -65,14 +66,6 @@ else: raise ValueError("unknown capturing method: %r" % method) - def _getmethod_preoptionparse(self, args): - if '-s' in args or "--capture=no" in args: - return "no" - elif hasattr(os, 'dup') and '--capture=sys' not in args: - return "fd" - else: - return "sys" - def _getmethod(self, config, fspath): if config.option.capture: method = config.option.capture @@ -85,16 +78,22 @@ method = "sys" return method + def reset_capturings(self): + for name, cap in self._method2capture.items(): + cap.reset() + def resumecapture_item(self, item): method = self._getmethod(item.config, item.fspath) if not hasattr(item, 'outerr'): item.outerr = ('', '') # we accumulate outerr on the item return self.resumecapture(method) - def resumecapture(self, method): + def resumecapture(self, method=None): if hasattr(self, '_capturing'): raise ValueError("cannot resume, already capturing with %r" % (self._capturing,)) + if method is None: + method = self._defaultmethod cap = self._method2capture.get(method) self._capturing = method if cap is None: @@ -164,17 +163,6 @@ def pytest_runtest_teardown(self, item): self.resumecapture_item(item) - def pytest__teardown_final(self, __multicall__, session): - method = self._getmethod(session.config, None) - self.resumecapture(method) - try: - rep = __multicall__.execute() - finally: - outerr = self.suspendcapture() - if rep: - addouterr(rep, outerr) - return rep - def pytest_keyboard_interrupt(self, excinfo): if hasattr(self, '_capturing'): self.suspendcapture() diff --git a/_pytest/config.py b/_pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -8,13 +8,15 @@ def pytest_cmdline_parse(pluginmanager, args): config = Config(pluginmanager) config.parse(args) - if config.option.debug: - config.trace.root.setwriter(sys.stderr.write) return config def pytest_unconfigure(config): - for func in config._cleanup: - func() + while 1: + try: + fin = config._cleanup.pop() + except IndexError: + break + fin() class Parser: """ Parser for command line arguments. """ @@ -81,6 +83,7 @@ self._inidict[name] = (help, type, default) self._ininames.append(name) + class OptionGroup: def __init__(self, name, description="", parser=None): self.name = name @@ -256,11 +259,14 @@ self.hook = self.pluginmanager.hook self._inicache = {} self._cleanup = [] - + @classmethod def fromdictargs(cls, option_dict, args): """ constructor useable for subprocesses. """ config = cls() + # XXX slightly crude way to initialize capturing + import _pytest.capture + _pytest.capture.pytest_cmdline_parse(config.pluginmanager, args) config._preparse(args, addopts=False) config.option.__dict__.update(option_dict) for x in config.option.plugins: @@ -285,11 +291,10 @@ def _setinitialconftest(self, args): # capture output during conftest init (#issue93) - from _pytest.capture import CaptureManager - capman = CaptureManager() - self.pluginmanager.register(capman, 'capturemanager') - # will be unregistered in capture.py's unconfigure() - capman.resumecapture(capman._getmethod_preoptionparse(args)) + # XXX introduce load_conftest hook to avoid needing to know + # about capturing plugin here + capman = self.pluginmanager.getplugin("capturemanager") + capman.resumecapture() try: try: self._conftest.setinitial(args) @@ -334,6 +339,7 @@ # Note that this can only be called once per testing process. assert not hasattr(self, 'args'), ( "can only parse cmdline args at most once per Config object") + self._origargs = args self._preparse(args) self._parser.hints.extend(self.pluginmanager._hints) args = self._parser.parse_setoption(args, self.option) @@ -341,6 +347,14 @@ args.append(py.std.os.getcwd()) self.args = args + def addinivalue_line(self, name, line): + """ add a line to an ini-file option. The option must have been + declared but might not yet be set in which case the line becomes the + the first line in its value. """ + x = self.getini(name) + assert isinstance(x, list) + x.append(line) # modifies the cached list inline + def getini(self, name): """ return configuration value from an ini file. If the specified name hasn't been registered through a prior ``parse.addini`` @@ -422,7 +436,7 @@ def getcfg(args, inibasenames): - args = [x for x in args if str(x)[0] != "-"] + args = [x for x in args if not str(x).startswith("-")] if not args: args = [py.path.local()] for arg in args: diff --git a/_pytest/core.py b/_pytest/core.py --- a/_pytest/core.py +++ b/_pytest/core.py @@ -16,11 +16,10 @@ "junitxml resultlog doctest").split() class TagTracer: - def __init__(self, prefix="[pytest] "): + def __init__(self): self._tag2proc = {} self.writer = None self.indent = 0 - self.prefix = prefix def get(self, name): return TagTracerSub(self, (name,)) @@ -30,7 +29,7 @@ if args: indent = " " * self.indent content = " ".join(map(str, args)) - self.writer("%s%s%s\n" %(self.prefix, indent, content)) + self.writer("%s%s [%s]\n" %(indent, content, ":".join(tags))) try: self._tag2proc[tags](tags, args) except KeyError: @@ -212,6 +211,14 @@ self.register(mod, modname) self.consider_module(mod) + def pytest_configure(self, config): + config.addinivalue_line("markers", + "tryfirst: mark a hook implementation function such that the " + "plugin machinery will try to call it first/as early as possible.") + config.addinivalue_line("markers", + "trylast: mark a hook implementation function such that the " + "plugin machinery will try to call it last/as late as possible.") + def pytest_plugin_registered(self, plugin): import pytest dic = self.call_plugin(plugin, "pytest_namespace", {}) or {} @@ -432,10 +439,7 @@ def _preloadplugins(): _preinit.append(PluginManager(load=True)) -def main(args=None, plugins=None): - """ returned exit code integer, after an in-process testing run - with the given command line arguments, preloading an optional list - of passed in plugin objects. """ +def _prepareconfig(args=None, plugins=None): if args is None: args = sys.argv[1:] elif isinstance(args, py.path.local): @@ -449,13 +453,19 @@ else: # subsequent calls to main will create a fresh instance _pluginmanager = PluginManager(load=True) hook = _pluginmanager.hook + if plugins: + for plugin in plugins: + _pluginmanager.register(plugin) + return hook.pytest_cmdline_parse( + pluginmanager=_pluginmanager, args=args) + +def main(args=None, plugins=None): + """ returned exit code integer, after an in-process testing run + with the given command line arguments, preloading an optional list + of passed in plugin objects. """ try: - if plugins: - for plugin in plugins: - _pluginmanager.register(plugin) - config = hook.pytest_cmdline_parse( - pluginmanager=_pluginmanager, args=args) - exitstatus = hook.pytest_cmdline_main(config=config) + config = _prepareconfig(args, plugins) + exitstatus = config.hook.pytest_cmdline_main(config=config) except UsageError: e = sys.exc_info()[1] sys.stderr.write("ERROR: %s\n" %(e.args[0],)) diff --git a/_pytest/helpconfig.py b/_pytest/helpconfig.py --- a/_pytest/helpconfig.py +++ b/_pytest/helpconfig.py @@ -1,7 +1,7 @@ """ version info, help messages, tracing configuration. """ import py import pytest -import inspect, sys +import os, inspect, sys from _pytest.core import varnames def pytest_addoption(parser): @@ -18,7 +18,29 @@ help="trace considerations of conftest.py files."), group.addoption('--debug', action="store_true", dest="debug", default=False, - help="generate and show internal debugging information.") + help="store internal tracing debug information in 'pytestdebug.log'.") + + +def pytest_cmdline_parse(__multicall__): + config = __multicall__.execute() + if config.option.debug: + path = os.path.abspath("pytestdebug.log") + f = open(path, 'w') + config._debugfile = f + f.write("versions pytest-%s, py-%s, python-%s\ncwd=%s\nargs=%s\n\n" %( + pytest.__version__, py.__version__, ".".join(map(str, sys.version_info)), + os.getcwd(), config._origargs)) + config.trace.root.setwriter(f.write) + sys.stderr.write("writing pytestdebug information to %s\n" % path) + return config + + at pytest.mark.trylast +def pytest_unconfigure(config): + if hasattr(config, '_debugfile'): + config._debugfile.close() + sys.stderr.write("wrote pytestdebug information to %s\n" % + config._debugfile.name) + config.trace.root.setwriter(None) def pytest_cmdline_main(config): @@ -34,6 +56,7 @@ elif config.option.help: config.pluginmanager.do_configure(config) showhelp(config) + config.pluginmanager.do_unconfigure(config) return 0 def showhelp(config): @@ -91,7 +114,7 @@ verinfo = getpluginversioninfo(config) if verinfo: lines.extend(verinfo) - + if config.option.traceconfig: lines.append("active plugins:") plugins = [] diff --git a/_pytest/hookspec.py b/_pytest/hookspec.py --- a/_pytest/hookspec.py +++ b/_pytest/hookspec.py @@ -121,16 +121,23 @@ def pytest_itemstart(item, node=None): """ (deprecated, use pytest_runtest_logstart). """ -def pytest_runtest_protocol(item): - """ implements the standard runtest_setup/call/teardown protocol including - capturing exceptions and calling reporting hooks on the results accordingly. +def pytest_runtest_protocol(item, nextitem): + """ implements the runtest_setup/call/teardown protocol for + the given test item, including capturing exceptions and calling + reporting hooks. + + :arg item: test item for which the runtest protocol is performed. + + :arg nexitem: the scheduled-to-be-next test item (or None if this + is the end my friend). This argument is passed on to + :py:func:`pytest_runtest_teardown`. :return boolean: True if no further hook implementations should be invoked. """ pytest_runtest_protocol.firstresult = True def pytest_runtest_logstart(nodeid, location): - """ signal the start of a test run. """ + """ signal the start of running a single test item. """ def pytest_runtest_setup(item): """ called before ``pytest_runtest_call(item)``. """ @@ -138,8 +145,14 @@ def pytest_runtest_call(item): """ called to execute the test ``item``. """ -def pytest_runtest_teardown(item): - """ called after ``pytest_runtest_call``. """ +def pytest_runtest_teardown(item, nextitem): + """ called after ``pytest_runtest_call``. + + :arg nexitem: the scheduled-to-be-next test item (None if no further + test item is scheduled). This argument can be used to + perform exact teardowns, i.e. calling just enough finalizers + so that nextitem only needs to call setup-functions. + """ def pytest_runtest_makereport(item, call): """ return a :py:class:`_pytest.runner.TestReport` object @@ -149,15 +162,8 @@ pytest_runtest_makereport.firstresult = True def pytest_runtest_logreport(report): - """ process item test report. """ - -# special handling for final teardown - somewhat internal for now -def pytest__teardown_final(session): - """ called before test session finishes. """ -pytest__teardown_final.firstresult = True - -def pytest__teardown_final_logerror(report, session): - """ called if runtest_teardown_final failed. """ + """ process a test setup/call/teardown report relating to + the respective phase of executing a test. """ # ------------------------------------------------------------------------- # test session related hooks diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -25,21 +25,39 @@ long = int +class Junit(py.xml.Namespace): + pass + + # We need to get the subset of the invalid unicode ranges according to # XML 1.0 which are valid in this python build. Hence we calculate # this dynamically instead of hardcoding it. The spec range of valid # chars is: Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] # | [#x10000-#x10FFFF] -_illegal_unichrs = [(0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x19), - (0xD800, 0xDFFF), (0xFDD0, 0xFFFF)] -_illegal_ranges = [unicode("%s-%s") % (unichr(low), unichr(high)) - for (low, high) in _illegal_unichrs +_legal_chars = (0x09, 0x0A, 0x0d) +_legal_ranges = ( + (0x20, 0xD7FF), + (0xE000, 0xFFFD), + (0x10000, 0x10FFFF), +) +_legal_xml_re = [unicode("%s-%s") % (unichr(low), unichr(high)) + for (low, high) in _legal_ranges if low < sys.maxunicode] -illegal_xml_re = re.compile(unicode('[%s]') % - unicode('').join(_illegal_ranges)) -del _illegal_unichrs -del _illegal_ranges +_legal_xml_re = [unichr(x) for x in _legal_chars] + _legal_xml_re +illegal_xml_re = re.compile(unicode('[^%s]') % + unicode('').join(_legal_xml_re)) +del _legal_chars +del _legal_ranges +del _legal_xml_re +def bin_xml_escape(arg): + def repl(matchobj): + i = ord(matchobj.group()) + if i <= 0xFF: + return unicode('#x%02X') % i + else: + return unicode('#x%04X') % i + return illegal_xml_re.sub(repl, py.xml.escape(arg)) def pytest_addoption(parser): group = parser.getgroup("terminal reporting") @@ -68,117 +86,97 @@ logfile = os.path.expanduser(os.path.expandvars(logfile)) self.logfile = os.path.normpath(logfile) self.prefix = prefix - self.test_logs = [] + self.tests = [] self.passed = self.skipped = 0 self.failed = self.errors = 0 - self._durations = {} def _opentestcase(self, report): names = report.nodeid.split("::") names[0] = names[0].replace("/", '.') - names = tuple(names) - d = {'time': self._durations.pop(report.nodeid, "0")} names = [x.replace(".py", "") for x in names if x != "()"] classnames = names[:-1] if self.prefix: classnames.insert(0, self.prefix) - d['classname'] = ".".join(classnames) - d['name'] = py.xml.escape(names[-1]) - attrs = ['%s="%s"' % item for item in sorted(d.items())] - self.test_logs.append("\n" % " ".join(attrs)) + self.tests.append(Junit.testcase( + classname=".".join(classnames), + name=names[-1], + time=getattr(report, 'duration', 0) + )) - def _closetestcase(self): - self.test_logs.append("") - - def appendlog(self, fmt, *args): - def repl(matchobj): - i = ord(matchobj.group()) - if i <= 0xFF: - return unicode('#x%02X') % i - else: - return unicode('#x%04X') % i - args = tuple([illegal_xml_re.sub(repl, py.xml.escape(arg)) - for arg in args]) - self.test_logs.append(fmt % args) + def append(self, obj): + self.tests[-1].append(obj) def append_pass(self, report): self.passed += 1 - self._opentestcase(report) - self._closetestcase() def append_failure(self, report): - self._opentestcase(report) #msg = str(report.longrepr.reprtraceback.extraline) if "xfail" in report.keywords: - self.appendlog( - '') + self.append( + Junit.skipped(message="xfail-marked test passes unexpectedly")) self.skipped += 1 else: - self.appendlog('%s', - report.longrepr) + sec = dict(report.sections) + fail = Junit.failure(message="test failure") + fail.append(str(report.longrepr)) + self.append(fail) + for name in ('out', 'err'): + content = sec.get("Captured std%s" % name) + if content: + tag = getattr(Junit, 'system-'+name) + self.append(tag(bin_xml_escape(content))) self.failed += 1 - self._closetestcase() def append_collect_failure(self, report): - self._opentestcase(report) #msg = str(report.longrepr.reprtraceback.extraline) - self.appendlog('%s', - report.longrepr) - self._closetestcase() + self.append(Junit.failure(str(report.longrepr), + message="collection failure")) self.errors += 1 def append_collect_skipped(self, report): - self._opentestcase(report) #msg = str(report.longrepr.reprtraceback.extraline) - self.appendlog('%s', - report.longrepr) - self._closetestcase() + self.append(Junit.skipped(str(report.longrepr), + message="collection skipped")) self.skipped += 1 def append_error(self, report): - self._opentestcase(report) - self.appendlog('%s', - report.longrepr) - self._closetestcase() + self.append(Junit.error(str(report.longrepr), + message="test setup failure")) self.errors += 1 def append_skipped(self, report): - self._opentestcase(report) if "xfail" in report.keywords: - self.appendlog( - '%s', - report.keywords['xfail']) + self.append(Junit.skipped(str(report.keywords['xfail']), + message="expected test failure")) else: filename, lineno, skipreason = report.longrepr if skipreason.startswith("Skipped: "): skipreason = skipreason[9:] - self.appendlog('%s', - skipreason, "%s:%s: %s" % report.longrepr, - ) - self._closetestcase() + self.append( + Junit.skipped("%s:%s: %s" % report.longrepr, + type="pytest.skip", + message=skipreason + )) self.skipped += 1 def pytest_runtest_logreport(self, report): if report.passed: - self.append_pass(report) + if report.when == "call": # ignore setup/teardown + self._opentestcase(report) + self.append_pass(report) elif report.failed: + self._opentestcase(report) if report.when != "call": self.append_error(report) else: self.append_failure(report) elif report.skipped: + self._opentestcase(report) self.append_skipped(report) - def pytest_runtest_call(self, item, __multicall__): - start = time.time() - try: - return __multicall__.execute() - finally: - self._durations[item.nodeid] = time.time() - start - def pytest_collectreport(self, report): if not report.passed: + self._opentestcase(report) if report.failed: self.append_collect_failure(report) else: @@ -187,10 +185,11 @@ def pytest_internalerror(self, excrepr): self.errors += 1 data = py.xml.escape(excrepr) - self.test_logs.append( - '\n' - ' ' - '%s' % data) + self.tests.append( + Junit.testcase( + Junit.error(data, message="internal error"), + classname="pytest", + name="internal")) def pytest_sessionstart(self, session): self.suite_start_time = time.time() @@ -204,17 +203,17 @@ suite_stop_time = time.time() suite_time_delta = suite_stop_time - self.suite_start_time numtests = self.passed + self.failed + logfile.write('') - logfile.write('') - logfile.writelines(self.test_logs) - logfile.write('') + logfile.write(Junit.testsuite( + self.tests, + name="", + errors=self.errors, + failures=self.failed, + skips=self.skipped, + tests=numtests, + time="%.3f" % suite_time_delta, + ).unicode(indent=0)) logfile.close() def pytest_terminal_summary(self, terminalreporter): diff --git a/_pytest/main.py b/_pytest/main.py --- a/_pytest/main.py +++ b/_pytest/main.py @@ -2,7 +2,7 @@ import py import pytest, _pytest -import os, sys +import os, sys, imp tracebackcutdir = py.path.local(_pytest.__file__).dirpath() # exitcodes for the command line @@ -11,6 +11,8 @@ EXIT_INTERRUPTED = 2 EXIT_INTERNALERROR = 3 +name_re = py.std.re.compile("^[a-zA-Z_]\w*$") + def pytest_addoption(parser): parser.addini("norecursedirs", "directory patterns to avoid for recursion", type="args", default=('.*', 'CVS', '_darcs', '{arch}')) @@ -27,6 +29,9 @@ action="store", type="int", dest="maxfail", default=0, help="exit after first num failures or errors.") + group._addoption('--strict', action="store_true", + help="run pytest in strict mode, warnings become errors.") + group = parser.getgroup("collect", "collection") group.addoption('--collectonly', action="store_true", dest="collectonly", @@ -48,7 +53,7 @@ def pytest_namespace(): collect = dict(Item=Item, Collector=Collector, File=File, Session=Session) return dict(collect=collect) - + def pytest_configure(config): py.test.config = config # compatibiltiy if config.option.exitfirst: @@ -77,11 +82,11 @@ session.exitstatus = EXIT_INTERNALERROR if excinfo.errisinstance(SystemExit): sys.stderr.write("mainloop: caught Spurious SystemExit!\n") + if initstate >= 2: + config.hook.pytest_sessionfinish(session=session, + exitstatus=session.exitstatus or (session._testsfailed and 1)) if not session.exitstatus and session._testsfailed: session.exitstatus = EXIT_TESTSFAILED - if initstate >= 2: - config.hook.pytest_sessionfinish(session=session, - exitstatus=session.exitstatus) if initstate >= 1: config.pluginmanager.do_unconfigure(config) return session.exitstatus @@ -101,8 +106,12 @@ def pytest_runtestloop(session): if session.config.option.collectonly: return True - for item in session.session.items: - item.config.hook.pytest_runtest_protocol(item=item) + for i, item in enumerate(session.items): + try: + nextitem = session.items[i+1] + except IndexError: + nextitem = None + item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem) if session.shouldstop: raise session.Interrupted(session.shouldstop) return True @@ -132,7 +141,7 @@ return getattr(pytest, name) return property(fget, None, None, "deprecated attribute %r, use pytest.%s" % (name,name)) - + class Node(object): """ base class for all Nodes in the collection tree. Collector subclasses have children, Items are terminal nodes.""" @@ -143,13 +152,13 @@ #: the parent collector node. self.parent = parent - + #: the test config object self.config = config or parent.config #: the collection this node is part of self.session = session or parent.session - + #: filesystem path where this node was collected from self.fspath = getattr(parent, 'fspath', None) self.ihook = self.session.gethookproxy(self.fspath) @@ -224,13 +233,13 @@ def listchain(self): """ return list of all parent collectors up to self, starting from root of collection tree. """ - l = [self] - while 1: - x = l[0] - if x.parent is not None: # and x.parent.parent is not None: - l.insert(0, x.parent) - else: - return l + chain = [] + item = self + while item is not None: + chain.append(item) + item = item.parent + chain.reverse() + return chain def listnames(self): return [x.name for x in self.listchain()] @@ -325,6 +334,8 @@ """ a basic test invocation item. Note that for a single function there might be multiple test invocation items. """ + nextitem = None + def reportinfo(self): return self.fspath, None, "" @@ -399,6 +410,7 @@ self._notfound = [] self._initialpaths = set() self._initialparts = [] + self.items = items = [] for arg in args: parts = self._parsearg(arg) self._initialparts.append(parts) @@ -414,7 +426,6 @@ if not genitems: return rep.result else: - self.items = items = [] if rep.passed: for node in rep.result: self.items.extend(self.genitems(node)) @@ -469,16 +480,29 @@ return True def _tryconvertpyarg(self, x): - try: - mod = __import__(x, None, None, ['__doc__']) - except (ValueError, ImportError): - return x - p = py.path.local(mod.__file__) - if p.purebasename == "__init__": - p = p.dirpath() - else: - p = p.new(basename=p.purebasename+".py") - return str(p) + mod = None + path = [os.path.abspath('.')] + sys.path + for name in x.split('.'): + # ignore anything that's not a proper name here + # else something like --pyargs will mess up '.' + # since imp.find_module will actually sometimes work for it + # but it's supposed to be considered a filesystem path + # not a package + if name_re.match(name) is None: + return x + try: + fd, mod, type_ = imp.find_module(name, path) + except ImportError: + return x + else: + if fd is not None: + fd.close() + + if type_[2] != imp.PKG_DIRECTORY: + path = [os.path.dirname(mod)] + else: + path = [mod] + return mod def _parsearg(self, arg): """ return (fspath, names) tuple after checking the file exists. """ @@ -496,7 +520,7 @@ raise pytest.UsageError(msg + arg) parts[0] = path return parts - + def matchnodes(self, matching, names): self.trace("matchnodes", matching, names) self.trace.root.indent += 1 diff --git a/_pytest/mark.py b/_pytest/mark.py --- a/_pytest/mark.py +++ b/_pytest/mark.py @@ -14,12 +14,37 @@ "Terminate expression with ':' to make the first match match " "all subsequent tests (usually file-order). ") + group._addoption("-m", + action="store", dest="markexpr", default="", metavar="MARKEXPR", + help="only run tests matching given mark expression. " + "example: -m 'mark1 and not mark2'." + ) + + group.addoption("--markers", action="store_true", help= + "show markers (builtin, plugin and per-project ones).") + + parser.addini("markers", "markers for test functions", 'linelist') + +def pytest_cmdline_main(config): + if config.option.markers: + config.pluginmanager.do_configure(config) + tw = py.io.TerminalWriter() + for line in config.getini("markers"): + name, rest = line.split(":", 1) + tw.write("@pytest.mark.%s:" % name, bold=True) + tw.line(rest) + tw.line() + config.pluginmanager.do_unconfigure(config) + return 0 +pytest_cmdline_main.tryfirst = True + def pytest_collection_modifyitems(items, config): keywordexpr = config.option.keyword - if not keywordexpr: + matchexpr = config.option.markexpr + if not keywordexpr and not matchexpr: return selectuntil = False - if keywordexpr[-1] == ":": + if keywordexpr[-1:] == ":": selectuntil = True keywordexpr = keywordexpr[:-1] @@ -29,21 +54,38 @@ if keywordexpr and skipbykeyword(colitem, keywordexpr): deselected.append(colitem) else: - remaining.append(colitem) if selectuntil: keywordexpr = None + if matchexpr: + if not matchmark(colitem, matchexpr): + deselected.append(colitem) + continue + remaining.append(colitem) if deselected: config.hook.pytest_deselected(items=deselected) items[:] = remaining +class BoolDict: + def __init__(self, mydict): + self._mydict = mydict + def __getitem__(self, name): + return name in self._mydict + +def matchmark(colitem, matchexpr): + return eval(matchexpr, {}, BoolDict(colitem.obj.__dict__)) + +def pytest_configure(config): + if config.option.strict: + pytest.mark._config = config + def skipbykeyword(colitem, keywordexpr): """ return True if they given keyword expression means to skip this collector/item. """ if not keywordexpr: return - + itemkeywords = getkeywords(colitem) for key in filter(None, keywordexpr.split()): eor = key[:1] == '-' @@ -77,15 +119,31 @@ @py.test.mark.slowtest def test_function(): pass - + will set a 'slowtest' :class:`MarkInfo` object on the ``test_function`` object. """ def __getattr__(self, name): if name[0] == "_": raise AttributeError(name) + if hasattr(self, '_config'): + self._check(name) return MarkDecorator(name) + def _check(self, name): + try: + if name in self._markers: + return + except AttributeError: + pass + self._markers = l = set() + for line in self._config.getini("markers"): + beginning = line.split(":", 1) + x = beginning[0].split("(", 1)[0] + l.add(x) + if name not in self._markers: + raise AttributeError("%r not a registered marker" % (name,)) + class MarkDecorator: """ A decorator for test functions and test classes. When applied it will create :class:`MarkInfo` objects which may be @@ -133,8 +191,7 @@ holder = MarkInfo(self.markname, self.args, self.kwargs) setattr(func, self.markname, holder) else: - holder.kwargs.update(self.kwargs) - holder.args += self.args + holder.add(self.args, self.kwargs) return func kw = self.kwargs.copy() kw.update(kwargs) @@ -150,27 +207,20 @@ self.args = args #: keyword argument dictionary, empty if nothing specified self.kwargs = kwargs + self._arglist = [(args, kwargs.copy())] def __repr__(self): return "" % ( self.name, self.args, self.kwargs) -def pytest_itemcollected(item): - if not isinstance(item, pytest.Function): - return - try: - func = item.obj.__func__ - except AttributeError: - func = getattr(item.obj, 'im_func', item.obj) - pyclasses = (pytest.Class, pytest.Module) - for node in item.listchain(): - if isinstance(node, pyclasses): - marker = getattr(node.obj, 'pytestmark', None) - if marker is not None: - if isinstance(marker, list): - for mark in marker: - mark(func) - else: - marker(func) - node = node.parent - item.keywords.update(py.builtin._getfuncdict(func)) + def add(self, args, kwargs): + """ add a MarkInfo with the given args and kwargs. """ + self._arglist.append((args, kwargs)) + self.args += args + self.kwargs.update(kwargs) + + def __iter__(self): + """ yield MarkInfo objects each relating to a marking-call. """ + for args, kwargs in self._arglist: + yield MarkInfo(self.name, args, kwargs) + diff --git a/_pytest/monkeypatch.py b/_pytest/monkeypatch.py --- a/_pytest/monkeypatch.py +++ b/_pytest/monkeypatch.py @@ -13,6 +13,7 @@ monkeypatch.setenv(name, value, prepend=False) monkeypatch.delenv(name, value, raising=True) monkeypatch.syspath_prepend(path) + monkeypatch.chdir(path) All modifications will be undone after the requesting test function has finished. The ``raising`` @@ -30,6 +31,7 @@ def __init__(self): self._setattr = [] self._setitem = [] + self._cwd = None def setattr(self, obj, name, value, raising=True): """ set attribute ``name`` on ``obj`` to ``value``, by default @@ -83,6 +85,17 @@ self._savesyspath = sys.path[:] sys.path.insert(0, str(path)) + def chdir(self, path): + """ change the current working directory to the specified path + path can be a string or a py.path.local object + """ + if self._cwd is None: + self._cwd = os.getcwd() + if hasattr(path, "chdir"): + path.chdir() + else: + os.chdir(path) + def undo(self): """ undo previous changes. This call consumes the undo stack. Calling it a second time has no effect unless @@ -95,9 +108,17 @@ self._setattr[:] = [] for dictionary, name, value in self._setitem: if value is notset: - del dictionary[name] + try: + del dictionary[name] + except KeyError: + pass # was already deleted, so we have the desired state else: dictionary[name] = value self._setitem[:] = [] if hasattr(self, '_savesyspath'): sys.path[:] = self._savesyspath + del self._savesyspath + + if self._cwd is not None: + os.chdir(self._cwd) + self._cwd = None diff --git a/_pytest/nose.py b/_pytest/nose.py --- a/_pytest/nose.py +++ b/_pytest/nose.py @@ -13,6 +13,7 @@ call.excinfo = call2.excinfo + at pytest.mark.trylast def pytest_runtest_setup(item): if isinstance(item, (pytest.Function)): if isinstance(item.parent, pytest.Generator): diff --git a/_pytest/pastebin.py b/_pytest/pastebin.py --- a/_pytest/pastebin.py +++ b/_pytest/pastebin.py @@ -38,7 +38,11 @@ del tr._tw.__dict__['write'] def getproxy(): - return py.std.xmlrpclib.ServerProxy(url.xmlrpc).pastes + if sys.version_info < (3, 0): + from xmlrpclib import ServerProxy + else: + from xmlrpc.client import ServerProxy + return ServerProxy(url.xmlrpc).pastes def pytest_terminal_summary(terminalreporter): if terminalreporter.config.option.pastebin != "failed": diff --git a/_pytest/pdb.py b/_pytest/pdb.py --- a/_pytest/pdb.py +++ b/_pytest/pdb.py @@ -19,11 +19,13 @@ class pytestPDB: """ Pseudo PDB that defers to the real pdb. """ item = None + collector = None def set_trace(self): """ invoke PDB set_trace debugging, dropping any IO capturing. """ frame = sys._getframe().f_back - item = getattr(self, 'item', None) + item = self.item or self.collector + if item is not None: capman = item.config.pluginmanager.getplugin("capturemanager") out, err = capman.suspendcapture() @@ -38,6 +40,14 @@ pytestPDB.item = item pytest_runtest_setup = pytest_runtest_call = pytest_runtest_teardown = pdbitem + at pytest.mark.tryfirst +def pytest_make_collect_report(__multicall__, collector): + try: + pytestPDB.collector = collector + return __multicall__.execute() + finally: + pytestPDB.collector = None + def pytest_runtest_makereport(): pytestPDB.item = None @@ -60,7 +70,13 @@ tw.sep(">", "traceback") rep.toterminal(tw) tw.sep(">", "entering PDB") - post_mortem(call.excinfo._excinfo[2]) + # A doctest.UnexpectedException is not useful for post_mortem. + # Use the underlying exception instead: + if isinstance(call.excinfo.value, py.std.doctest.UnexpectedException): + tb = call.excinfo.value.exc_info[2] + else: + tb = call.excinfo._excinfo[2] + post_mortem(tb) rep._pdbshown = True return rep diff --git a/_pytest/pytester.py b/_pytest/pytester.py --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -25,6 +25,7 @@ _pytest_fullpath except NameError: _pytest_fullpath = os.path.abspath(pytest.__file__.rstrip("oc")) + _pytest_fullpath = _pytest_fullpath.replace("$py.class", ".py") def pytest_funcarg___pytest(request): return PytestArg(request) @@ -313,16 +314,6 @@ result.extend(session.genitems(colitem)) return result - def inline_genitems(self, *args): - #config = self.parseconfig(*args) - config = self.parseconfigure(*args) - rec = self.getreportrecorder(config) - session = Session(config) - config.hook.pytest_sessionstart(session=session) - session.perform_collect() - config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK) - return session.items, rec - def runitem(self, source): # used from runner functional tests item = self.getitem(source) @@ -343,64 +334,57 @@ l = list(args) + [p] reprec = self.inline_run(*l) reports = reprec.getreports("pytest_runtest_logreport") - assert len(reports) == 1, reports - return reports[0] + assert len(reports) == 3, reports # setup/call/teardown + return reports[1] + + def inline_genitems(self, *args): + return self.inprocess_run(list(args) + ['--collectonly']) def inline_run(self, *args): - args = ("-s", ) + args # otherwise FD leakage - config = self.parseconfig(*args) - reprec = self.getreportrecorder(config) - #config.pluginmanager.do_configure(config) - config.hook.pytest_cmdline_main(config=config) - #config.pluginmanager.do_unconfigure(config) - return reprec + items, rec = self.inprocess_run(args) + return rec - def config_preparse(self): - config = self.Config() - for plugin in self.plugins: - if isinstance(plugin, str): - config.pluginmanager.import_plugin(plugin) - else: - if isinstance(plugin, dict): - plugin = PseudoPlugin(plugin) - if not config.pluginmanager.isregistered(plugin): - config.pluginmanager.register(plugin) - return config + def inprocess_run(self, args, plugins=None): + rec = [] + items = [] + class Collect: + def pytest_configure(x, config): + rec.append(self.getreportrecorder(config)) + def pytest_itemcollected(self, item): + items.append(item) + if not plugins: + plugins = [] + plugins.append(Collect()) + ret = self.pytestmain(list(args), plugins=[Collect()]) + reprec = rec[0] + reprec.ret = ret + assert len(rec) == 1 + return items, reprec def parseconfig(self, *args): - if not args: - args = (self.tmpdir,) - config = self.config_preparse() - args = list(args) + args = [str(x) for x in args] for x in args: if str(x).startswith('--basetemp'): break else: args.append("--basetemp=%s" % self.tmpdir.dirpath('basetemp')) - config.parse(args) + import _pytest.core + config = _pytest.core._prepareconfig(args, self.plugins) + # the in-process pytest invocation needs to avoid leaking FDs + # so we register a "reset_capturings" callmon the capturing manager + # and make sure it gets called + config._cleanup.append( + config.pluginmanager.getplugin("capturemanager").reset_capturings) + import _pytest.config + self.request.addfinalizer( + lambda: _pytest.config.pytest_unconfigure(config)) return config - def reparseconfig(self, args=None): - """ this is used from tests that want to re-invoke parse(). """ - if not args: - args = [self.tmpdir] - oldconfig = getattr(py.test, 'config', None) - try: - c = py.test.config = self.Config() - c.basetemp = py.path.local.make_numbered_dir(prefix="reparse", - keep=0, rootdir=self.tmpdir, lock_timeout=None) - c.parse(args) - c.pluginmanager.do_configure(c) - self.request.addfinalizer(lambda: c.pluginmanager.do_unconfigure(c)) - return c - finally: - py.test.config = oldconfig - def parseconfigure(self, *args): config = self.parseconfig(*args) config.pluginmanager.do_configure(config) self.request.addfinalizer(lambda: - config.pluginmanager.do_unconfigure(config)) + config.pluginmanager.do_unconfigure(config)) return config def getitem(self, source, funcname="test_func"): @@ -420,7 +404,6 @@ self.makepyfile(__init__ = "#") self.config = config = self.parseconfigure(path, *configargs) node = self.getnode(config, path) - #config.pluginmanager.do_unconfigure(config) return node def collect_by_name(self, modcol, name): @@ -437,9 +420,16 @@ return py.std.subprocess.Popen(cmdargs, stdout=stdout, stderr=stderr, **kw) def pytestmain(self, *args, **kwargs): - ret = pytest.main(*args, **kwargs) - if ret == 2: - raise KeyboardInterrupt() + class ResetCapturing: + @pytest.mark.trylast + def pytest_unconfigure(self, config): + capman = config.pluginmanager.getplugin("capturemanager") + capman.reset_capturings() + plugins = kwargs.setdefault("plugins", []) + rc = ResetCapturing() + plugins.append(rc) + return pytest.main(*args, **kwargs) + def run(self, *cmdargs): return self._run(*cmdargs) @@ -528,6 +518,8 @@ pexpect = py.test.importorskip("pexpect", "2.4") if hasattr(sys, 'pypy_version_info') and '64' in py.std.platform.machine(): pytest.skip("pypy-64 bit not supported") + if sys.platform == "darwin": + pytest.xfail("pexpect does not work reliably on darwin?!") logfile = self.tmpdir.join("spawn.out") child = pexpect.spawn(cmd, logfile=logfile.open("w")) child.timeout = expect_timeout @@ -540,10 +532,6 @@ return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % ( py.io.saferepr(out),) -class PseudoPlugin: - def __init__(self, vars): - self.__dict__.update(vars) - class ReportRecorder(object): def __init__(self, hook): self.hook = hook @@ -565,10 +553,17 @@ def getreports(self, names="pytest_runtest_logreport pytest_collectreport"): return [x.report for x in self.getcalls(names)] - def matchreport(self, inamepart="", names="pytest_runtest_logreport pytest_collectreport", when=None): + def matchreport(self, inamepart="", + names="pytest_runtest_logreport pytest_collectreport", when=None): """ return a testreport whose dotted import path matches """ l = [] for rep in self.getreports(names=names): + try: + if not when and rep.when != "call" and rep.passed: + # setup/teardown passing reports - let's ignore those + continue + except AttributeError: + pass if when and getattr(rep, 'when', None) != when: continue if not inamepart or inamepart in rep.nodeid.split("::"): diff --git a/_pytest/python.py b/_pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -4,6 +4,7 @@ import sys import pytest from py._code.code import TerminalRepr +from _pytest.monkeypatch import monkeypatch import _pytest cutdir = py.path.local(_pytest.__file__).dirpath() @@ -26,6 +27,24 @@ showfuncargs(config) return 0 + +def pytest_generate_tests(metafunc): + try: + param = metafunc.function.parametrize + except AttributeError: + return + for p in param: + metafunc.parametrize(*p.args, **p.kwargs) + +def pytest_configure(config): + config.addinivalue_line("markers", + "parametrize(argnames, argvalues): call a test function multiple " + "times passing in multiple different argument value sets. Example: " + "@parametrize('arg1', [1,2]) would lead to two calls of the decorated " + "test function, one with arg1=1 and another with arg1=2." + ) + + @pytest.mark.trylast def pytest_namespace(): raises.Exception = pytest.fail.Exception @@ -138,6 +157,7 @@ obj = obj.place_as self._fslineno = py.code.getfslineno(obj) + assert isinstance(self._fslineno[1], int), obj return self._fslineno def reportinfo(self): @@ -155,6 +175,7 @@ else: fspath, lineno = self._getfslineno() modpath = self.getmodpath() + assert isinstance(lineno, int) return fspath, lineno, modpath class PyCollectorMixin(PyobjMixin, pytest.Collector): @@ -200,6 +221,7 @@ module = self.getparent(Module).obj clscol = self.getparent(Class) cls = clscol and clscol.obj or None + transfer_markers(funcobj, cls, module) metafunc = Metafunc(funcobj, config=self.config, cls=cls, module=module) gentesthook = self.config.hook.pytest_generate_tests @@ -219,6 +241,19 @@ l.append(function) return l +def transfer_markers(funcobj, cls, mod): + # XXX this should rather be code in the mark plugin or the mark + # plugin should merge with the python plugin. + for holder in (cls, mod): + try: + pytestmark = holder.pytestmark + except AttributeError: + continue + if isinstance(pytestmark, list): + for mark in pytestmark: + mark(funcobj) + else: + pytestmark(funcobj) class Module(pytest.File, PyCollectorMixin): def _getobj(self): @@ -226,13 +261,8 @@ def _importtestmodule(self): # we assume we are only called once per module - from _pytest import assertion - assertion.before_module_import(self) try: - try: - mod = self.fspath.pyimport(ensuresyspath=True) - finally: - assertion.after_module_import(self) + mod = self.fspath.pyimport(ensuresyspath=True) except SyntaxError: excinfo = py.code.ExceptionInfo() raise self.CollectError(excinfo.getrepr(style="short")) @@ -244,7 +274,8 @@ " %s\n" "which is not the same as the test file we want to collect:\n" " %s\n" - "HINT: use a unique basename for your test file modules" + "HINT: remove __pycache__ / .pyc files and/or use a " + "unique basename for your test file modules" % e.args ) #print "imported test module", mod @@ -374,6 +405,7 @@ tw.line() tw.line("%s:%d" % (self.filename, self.firstlineno+1)) + class Generator(FunctionMixin, PyCollectorMixin, pytest.Collector): def collect(self): # test generators are seen as collectors but they also @@ -430,6 +462,7 @@ "yielded functions (deprecated) cannot have funcargs") else: if callspec is not None: + self.callspec = callspec self.funcargs = callspec.funcargs or {} self._genid = callspec.id if hasattr(callspec, "param"): @@ -506,15 +539,59 @@ request._fillfuncargs() _notexists = object() -class CallSpec: - def __init__(self, funcargs, id, param): - self.funcargs = funcargs - self.id = id + +class CallSpec2(object): + def __init__(self, metafunc): + self.metafunc = metafunc + self.funcargs = {} + self._idlist = [] + self.params = {} + self._globalid = _notexists + self._globalid_args = set() + self._globalparam = _notexists + + def copy(self, metafunc): + cs = CallSpec2(self.metafunc) + cs.funcargs.update(self.funcargs) + cs.params.update(self.params) + cs._idlist = list(self._idlist) + cs._globalid = self._globalid + cs._globalid_args = self._globalid_args + cs._globalparam = self._globalparam + return cs + + def _checkargnotcontained(self, arg): + if arg in self.params or arg in self.funcargs: + raise ValueError("duplicate %r" %(arg,)) + + def getparam(self, name): + try: + return self.params[name] + except KeyError: + if self._globalparam is _notexists: + raise ValueError(name) + return self._globalparam + + @property + def id(self): + return "-".join(map(str, filter(None, self._idlist))) + + def setmulti(self, valtype, argnames, valset, id): + for arg,val in zip(argnames, valset): + self._checkargnotcontained(arg) + getattr(self, valtype)[arg] = val + self._idlist.append(id) + + def setall(self, funcargs, id, param): + for x in funcargs: + self._checkargnotcontained(x) + self.funcargs.update(funcargs) + if id is not _notexists: + self._idlist.append(id) if param is not _notexists: - self.param = param - def __repr__(self): - return "" %( - self.id, getattr(self, 'param', '?'), self.funcargs) + assert self._globalparam is _notexists + self._globalparam = param + class Metafunc: def __init__(self, function, config=None, cls=None, module=None): @@ -528,31 +605,71 @@ self._calls = [] self._ids = py.builtin.set() + def parametrize(self, argnames, argvalues, indirect=False, ids=None): + """ Add new invocations to the underlying test function using the list + of argvalues for the given argnames. Parametrization is performed + during the collection phase. If you need to setup expensive resources + you may pass indirect=True and implement a funcarg factory which can + perform the expensive setup just before a test is actually run. + + :arg argnames: an argument name or a list of argument names + + :arg argvalues: a list of values for the argname or a list of tuples of + values for the list of argument names. + + :arg indirect: if True each argvalue corresponding to an argument will + be passed as request.param to its respective funcarg factory so + that it can perform more expensive setups during the setup phase of + a test rather than at collection time. + + :arg ids: list of string ids each corresponding to the argvalues so + that they are part of the test id. If no ids are provided they will + be generated automatically from the argvalues. + """ + if not isinstance(argnames, (tuple, list)): + argnames = (argnames,) + argvalues = [(val,) for val in argvalues] + if not indirect: + #XXX should we also check for the opposite case? + for arg in argnames: + if arg not in self.funcargnames: + raise ValueError("%r has no argument %r" %(self.function, arg)) + valtype = indirect and "params" or "funcargs" + if not ids: + idmaker = IDMaker() + ids = list(map(idmaker, argvalues)) + newcalls = [] + for callspec in self._calls or [CallSpec2(self)]: + for i, valset in enumerate(argvalues): + assert len(valset) == len(argnames) + newcallspec = callspec.copy(self) + newcallspec.setmulti(valtype, argnames, valset, ids[i]) + newcalls.append(newcallspec) + self._calls = newcalls + def addcall(self, funcargs=None, id=_notexists, param=_notexists): - """ add a new call to the underlying test function during the - collection phase of a test run. Note that request.addcall() is - called during the test collection phase prior and independently - to actual test execution. Therefore you should perform setup - of resources in a funcarg factory which can be instrumented - with the ``param``. + """ (deprecated, use parametrize) Add a new call to the underlying + test function during the collection phase of a test run. Note that + request.addcall() is called during the test collection phase prior and + independently to actual test execution. You should only use addcall() + if you need to specify multiple arguments of a test function. :arg funcargs: argument keyword dictionary used when invoking the test function. :arg id: used for reporting and identification purposes. If you - don't supply an `id` the length of the currently - list of calls to the test function will be used. + don't supply an `id` an automatic unique id will be generated. - :arg param: will be exposed to a later funcarg factory invocation - through the ``request.param`` attribute. It allows to - defer test fixture setup activities to when an actual - test is run. + :arg param: a parameter which will be exposed to a later funcarg factory + invocation through the ``request.param`` attribute. """ assert funcargs is None or isinstance(funcargs, dict) if funcargs is not None: for name in funcargs: if name not in self.funcargnames: pytest.fail("funcarg %r not used in this function." % name) + else: + funcargs = {} if id is None: raise ValueError("id=None not allowed") if id is _notexists: @@ -561,11 +678,26 @@ if id in self._ids: raise ValueError("duplicate id %r" % id) self._ids.add(id) - self._calls.append(CallSpec(funcargs, id, param)) + + cs = CallSpec2(self) + cs.setall(funcargs, id, param) + self._calls.append(cs) + +class IDMaker: + def __init__(self): + self.counter = 0 + def __call__(self, valset): + l = [] + for val in valset: + if not isinstance(val, (int, str)): + val = "."+str(self.counter) + self.counter += 1 + l.append(str(val)) + return "-".join(l) class FuncargRequest: """ A request for function arguments from a test function. - + Note that there is an optional ``param`` attribute in case there was an invocation to metafunc.addcall(param=...). If no such call was done in a ``pytest_generate_tests`` @@ -637,7 +769,7 @@ def applymarker(self, marker): - """ apply a marker to a single test function invocation. + """ Apply a marker to a single test function invocation. This method is useful if you don't want to have a keyword/marker on all function invocations. @@ -649,7 +781,7 @@ self._pyfuncitem.keywords[marker.markname] = marker def cached_setup(self, setup, teardown=None, scope="module", extrakey=None): - """ return a testing resource managed by ``setup`` & + """ Return a testing resource managed by ``setup`` & ``teardown`` calls. ``scope`` and ``extrakey`` determine when the ``teardown`` function will be called so that subsequent calls to ``setup`` would recreate the resource. @@ -698,11 +830,18 @@ self._raiselookupfailed(argname) funcargfactory = self._name2factory[argname].pop() oldarg = self._currentarg - self._currentarg = argname + mp = monkeypatch() + mp.setattr(self, '_currentarg', argname) + try: + param = self._pyfuncitem.callspec.getparam(argname) + except (AttributeError, ValueError): + pass + else: + mp.setattr(self, 'param', param, raising=False) try: self._funcargs[argname] = res = funcargfactory(request=self) finally: - self._currentarg = oldarg + mp.undo() return res def _getscopeitem(self, scope): @@ -817,8 +956,7 @@ >>> raises(ZeroDivisionError, f, x=0) - A third possibility is to use a string which which will - be executed:: + A third possibility is to use a string to be executed:: >>> raises(ZeroDivisionError, "f(0)") diff --git a/_pytest/resultlog.py b/_pytest/resultlog.py --- a/_pytest/resultlog.py +++ b/_pytest/resultlog.py @@ -63,6 +63,8 @@ self.write_log_entry(testpath, lettercode, longrepr) def pytest_runtest_logreport(self, report): + if report.when != "call" and report.passed: + return res = self.config.hook.pytest_report_teststatus(report=report) code = res[1] if code == 'x': @@ -89,5 +91,8 @@ self.log_outcome(report, code, longrepr) def pytest_internalerror(self, excrepr): - path = excrepr.reprcrash.path + reprcrash = getattr(excrepr, 'reprcrash', None) + path = getattr(reprcrash, "path", None) + if path is None: + path = "cwd:%s" % py.path.local() self.write_log_entry(path, '!', str(excrepr)) diff --git a/_pytest/runner.py b/_pytest/runner.py --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -1,6 +1,6 @@ """ basic collect and runtest protocol implementations """ -import py, sys +import py, sys, time from py._code.code import TerminalRepr def pytest_namespace(): @@ -14,33 +14,60 @@ # # pytest plugin hooks +def pytest_addoption(parser): + group = parser.getgroup("terminal reporting", "reporting", after="general") + group.addoption('--durations', + action="store", type="int", default=None, metavar="N", + help="show N slowest setup/test durations (N=0 for all)."), + +def pytest_terminal_summary(terminalreporter): + durations = terminalreporter.config.option.durations + if durations is None: + return + tr = terminalreporter + dlist = [] + for replist in tr.stats.values(): + for rep in replist: + if hasattr(rep, 'duration'): + dlist.append(rep) + if not dlist: + return + dlist.sort(key=lambda x: x.duration) + dlist.reverse() + if not durations: + tr.write_sep("=", "slowest test durations") + else: + tr.write_sep("=", "slowest %s test durations" % durations) + dlist = dlist[:durations] + + for rep in dlist: + nodeid = rep.nodeid.replace("::()::", "::") + tr.write_line("%02.2fs %-8s %s" % + (rep.duration, rep.when, nodeid)) + def pytest_sessionstart(session): session._setupstate = SetupState() - -def pytest_sessionfinish(session, exitstatus): - hook = session.config.hook - rep = hook.pytest__teardown_final(session=session) - if rep: - hook.pytest__teardown_final_logerror(session=session, report=rep) - session.exitstatus = 1 +def pytest_sessionfinish(session): + session._setupstate.teardown_all() class NodeInfo: def __init__(self, location): self.location = location -def pytest_runtest_protocol(item): +def pytest_runtest_protocol(item, nextitem): item.ihook.pytest_runtest_logstart( nodeid=item.nodeid, location=item.location, ) - runtestprotocol(item) + runtestprotocol(item, nextitem=nextitem) return True -def runtestprotocol(item, log=True): +def runtestprotocol(item, log=True, nextitem=None): rep = call_and_report(item, "setup", log) reports = [rep] if rep.passed: reports.append(call_and_report(item, "call", log)) - reports.append(call_and_report(item, "teardown", log)) + reports.append(call_and_report(item, "teardown", log, + nextitem=nextitem)) return reports def pytest_runtest_setup(item): @@ -49,16 +76,8 @@ def pytest_runtest_call(item): item.runtest() -def pytest_runtest_teardown(item): - item.session._setupstate.teardown_exact(item) - -def pytest__teardown_final(session): - call = CallInfo(session._setupstate.teardown_all, when="teardown") - if call.excinfo: - ntraceback = call.excinfo.traceback .cut(excludepath=py._pydir) - call.excinfo.traceback = ntraceback.filter() - longrepr = call.excinfo.getrepr(funcargs=True) - return TeardownErrorReport(longrepr) +def pytest_runtest_teardown(item, nextitem): + item.session._setupstate.teardown_exact(item, nextitem) def pytest_report_teststatus(report): if report.when in ("setup", "teardown"): @@ -74,18 +93,18 @@ # # Implementation -def call_and_report(item, when, log=True): - call = call_runtest_hook(item, when) +def call_and_report(item, when, log=True, **kwds): + call = call_runtest_hook(item, when, **kwds) hook = item.ihook report = hook.pytest_runtest_makereport(item=item, call=call) - if log and (when == "call" or not report.passed): + if log: hook.pytest_runtest_logreport(report=report) return report -def call_runtest_hook(item, when): +def call_runtest_hook(item, when, **kwds): hookname = "pytest_runtest_" + when ihook = getattr(item.ihook, hookname) - return CallInfo(lambda: ihook(item=item), when=when) + return CallInfo(lambda: ihook(item=item, **kwds), when=when) class CallInfo: """ Result/Exception info a function invocation. """ @@ -95,12 +114,16 @@ #: context of invocation: one of "setup", "call", #: "teardown", "memocollect" self.when = when + self.start = time.time() try: - self.result = func() - except KeyboardInterrupt: - raise - except: - self.excinfo = py.code.ExceptionInfo() + try: + self.result = func() + except KeyboardInterrupt: + raise + except: + self.excinfo = py.code.ExceptionInfo() + finally: + self.stop = time.time() def __repr__(self): if self.excinfo: @@ -120,6 +143,10 @@ return s class BaseReport(object): + + def __init__(self, **kw): + self.__dict__.update(kw) + def toterminal(self, out): longrepr = self.longrepr if hasattr(self, 'node'): @@ -139,6 +166,7 @@ def pytest_runtest_makereport(item, call): when = call.when + duration = call.stop-call.start keywords = dict([(x,1) for x in item.keywords]) excinfo = call.excinfo if not call.excinfo: @@ -160,14 +188,15 @@ else: # exception in setup or teardown longrepr = item._repr_failure_py(excinfo) return TestReport(item.nodeid, item.location, - keywords, outcome, longrepr, when) + keywords, outcome, longrepr, when, + duration=duration) class TestReport(BaseReport): """ Basic test report object (also used for setup and teardown calls if they fail). """ def __init__(self, nodeid, location, - keywords, outcome, longrepr, when): + keywords, outcome, longrepr, when, sections=(), duration=0, **extra): #: normalized collection node id self.nodeid = nodeid @@ -179,16 +208,25 @@ #: a name -> value dictionary containing all keywords and #: markers associated with a test invocation. self.keywords = keywords - + #: test outcome, always one of "passed", "failed", "skipped". self.outcome = outcome #: None or a failure representation. self.longrepr = longrepr - + #: one of 'setup', 'call', 'teardown' to indicate runtest phase. self.when = when + #: list of (secname, data) extra information which needs to + #: marshallable + self.sections = list(sections) + + #: time it took to run just the test + self.duration = duration + + self.__dict__.update(extra) + def __repr__(self): return "" % ( self.nodeid, self.when, self.outcome) @@ -196,8 +234,10 @@ class TeardownErrorReport(BaseReport): outcome = "failed" when = "teardown" - def __init__(self, longrepr): + def __init__(self, longrepr, **extra): self.longrepr = longrepr + self.sections = [] + self.__dict__.update(extra) def pytest_make_collect_report(collector): call = CallInfo(collector._memocollect, "memocollect") @@ -219,11 +259,13 @@ getattr(call, 'result', None)) class CollectReport(BaseReport): - def __init__(self, nodeid, outcome, longrepr, result): + def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra): self.nodeid = nodeid self.outcome = outcome self.longrepr = longrepr self.result = result or [] + self.sections = list(sections) + self.__dict__.update(extra) @property def location(self): @@ -277,20 +319,22 @@ self._teardown_with_finalization(None) assert not self._finalizers - def teardown_exact(self, item): - if self.stack and item == self.stack[-1]: + def teardown_exact(self, item, nextitem): + needed_collectors = nextitem and nextitem.listchain() or [] + self._teardown_towards(needed_collectors) + + def _teardown_towards(self, needed_collectors): + while self.stack: + if self.stack == needed_collectors[:len(self.stack)]: + break self._pop_and_teardown() - else: - self._callfinalizers(item) def prepare(self, colitem): """ setup objects along the collector chain to the test-method and teardown previously setup objects.""" needed_collectors = colitem.listchain() - while self.stack: - if self.stack == needed_collectors[:len(self.stack)]: - break - self._pop_and_teardown() + self._teardown_towards(needed_collectors) + # check if the last collection node has raised an error for col in self.stack: if hasattr(col, '_prepare_exc'): diff --git a/_pytest/skipping.py b/_pytest/skipping.py --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -9,6 +9,21 @@ action="store_true", dest="runxfail", default=False, help="run tests even if they are marked xfail") +def pytest_configure(config): + config.addinivalue_line("markers", + "skipif(*conditions): skip the given test function if evaluation " + "of all conditions has a True value. Evaluation happens within the " + "module global context. Example: skipif('sys.platform == \"win32\"') " + "skips the test if we are on the win32 platform. " + ) + config.addinivalue_line("markers", + "xfail(*conditions, reason=None, run=True): mark the the test function " + "as an expected failure. Optionally specify a reason and run=False " + "if you don't even want to execute the test function. Any positional " + "condition strings will be evaluated (like with skipif) and if one is " + "False the marker will not be applied." + ) + def pytest_namespace(): return dict(xfail=xfail) @@ -117,6 +132,14 @@ def pytest_runtest_makereport(__multicall__, item, call): if not isinstance(item, pytest.Function): return + # unitttest special case, see setting of _unexpectedsuccess + if hasattr(item, '_unexpectedsuccess'): + rep = __multicall__.execute() + if rep.when == "call": + # we need to translate into how py.test encodes xpass + rep.keywords['xfail'] = "reason: " + item._unexpectedsuccess + rep.outcome = "failed" + return rep if not (call.excinfo and call.excinfo.errisinstance(py.test.xfail.Exception)): evalxfail = getattr(item, '_evalxfail', None) @@ -169,21 +192,23 @@ elif char == "X": show_xpassed(terminalreporter, lines) elif char in "fF": - show_failed(terminalreporter, lines) + show_simple(terminalreporter, lines, 'failed', "FAIL %s") elif char in "sS": show_skipped(terminalreporter, lines) + elif char == "E": + show_simple(terminalreporter, lines, 'error', "ERROR %s") if lines: tr._tw.sep("=", "short test summary info") for line in lines: tr._tw.line(line) -def show_failed(terminalreporter, lines): +def show_simple(terminalreporter, lines, stat, format): tw = terminalreporter._tw - failed = terminalreporter.stats.get("failed") + failed = terminalreporter.stats.get(stat) if failed: for rep in failed: pos = rep.nodeid - lines.append("FAIL %s" %(pos, )) + lines.append(format %(pos, )) def show_xfailed(terminalreporter, lines): xfailed = terminalreporter.stats.get("xfailed") diff --git a/_pytest/terminal.py b/_pytest/terminal.py --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -15,7 +15,7 @@ group._addoption('-r', action="store", dest="reportchars", default=None, metavar="chars", help="show extra test summary info as specified by chars (f)ailed, " - "(s)skipped, (x)failed, (X)passed.") + "(E)error, (s)skipped, (x)failed, (X)passed.") group._addoption('-l', '--showlocals', action="store_true", dest="showlocals", default=False, help="show locals in tracebacks (disabled by default).") @@ -43,7 +43,8 @@ pass else: stdout = os.fdopen(newfd, stdout.mode, 1) - config._toclose = stdout + config._cleanup.append(lambda: stdout.close()) + reporter = TerminalReporter(config, stdout) config.pluginmanager.register(reporter, 'terminalreporter') if config.option.debug or config.option.traceconfig: @@ -52,11 +53,6 @@ reporter.write_line("[traceconfig] " + msg) config.trace.root.setprocessor("pytest:config", mywriter) -def pytest_unconfigure(config): - if hasattr(config, '_toclose'): - #print "closing", config._toclose, config._toclose.fileno() - config._toclose.close() - def getreportopt(config): reportopts = "" optvalue = config.option.report @@ -165,9 +161,6 @@ def pytest_deselected(self, items): self.stats.setdefault('deselected', []).extend(items) - def pytest__teardown_final_logerror(self, report): - self.stats.setdefault("error", []).append(report) - def pytest_runtest_logstart(self, nodeid, location): # ensure that the path is printed before the # 1st test of a module starts running @@ -259,7 +252,7 @@ msg = "platform %s -- Python %s" % (sys.platform, verinfo) if hasattr(sys, 'pypy_version_info'): verinfo = ".".join(map(str, sys.pypy_version_info[:3])) - msg += "[pypy-%s]" % verinfo + msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3]) msg += " -- pytest-%s" % (py.test.__version__) if self.verbosity > 0 or self.config.option.debug or \ getattr(self.config.option, 'pastebin', None): @@ -289,10 +282,18 @@ # we take care to leave out Instances aka () # because later versions are going to get rid of them anyway if self.config.option.verbose < 0: - for item in items: - nodeid = item.nodeid - nodeid = nodeid.replace("::()::", "::") - self._tw.line(nodeid) + if self.config.option.verbose < -1: + counts = {} + for item in items: + name = item.nodeid.split('::', 1)[0] + counts[name] = counts.get(name, 0) + 1 + for name, count in sorted(counts.items()): + self._tw.line("%s: %d" % (name, count)) + else: + for item in items: + nodeid = item.nodeid + nodeid = nodeid.replace("::()::", "::") + self._tw.line(nodeid) return stack = [] indent = "" @@ -318,12 +319,17 @@ self.config.hook.pytest_terminal_summary(terminalreporter=self) if exitstatus == 2: self._report_keyboardinterrupt() + del self._keyboardinterrupt_memo self.summary_deselected() self.summary_stats() def pytest_keyboard_interrupt(self, excinfo): self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True) + def pytest_unconfigure(self): + if hasattr(self, '_keyboardinterrupt_memo'): + self._report_keyboardinterrupt() + def _report_keyboardinterrupt(self): excrepr = self._keyboardinterrupt_memo msg = excrepr.reprcrash.message @@ -388,7 +394,7 @@ else: msg = self._getfailureheadline(rep) self.write_sep("_", msg) - rep.toterminal(self._tw) + self._outrep_summary(rep) def summary_errors(self): if self.config.option.tbstyle != "no": @@ -406,7 +412,15 @@ elif rep.when == "teardown": msg = "ERROR at teardown of " + msg self.write_sep("_", msg) - rep.toterminal(self._tw) + self._outrep_summary(rep) + + def _outrep_summary(self, rep): + rep.toterminal(self._tw) + for secname, content in rep.sections: + self._tw.sep("-", secname) + if content[-1:] == "\n": + content = content[:-1] + self._tw.line(content) def summary_stats(self): session_duration = py.std.time.time() - self._sessionstarttime @@ -417,9 +431,10 @@ keys.append(key) parts = [] for key in keys: - val = self.stats.get(key, None) - if val: - parts.append("%d %s" %(len(val), key)) + if key: # setup/teardown reports have an empty key, ignore them + val = self.stats.get(key, None) + if val: + parts.append("%d %s" %(len(val), key)) line = ", ".join(parts) # XXX coloring msg = "%s in %.2f seconds" %(line, session_duration) @@ -430,8 +445,15 @@ def summary_deselected(self): if 'deselected' in self.stats: + l = [] + k = self.config.option.keyword + if k: + l.append("-k%s" % k) + m = self.config.option.markexpr + if m: + l.append("-m %r" % m) self.write_sep("=", "%d tests deselected by %r" %( - len(self.stats['deselected']), self.config.option.keyword), bold=True) + len(self.stats['deselected']), " ".join(l)), bold=True) def repr_pythonversion(v=None): if v is None: diff --git a/_pytest/tmpdir.py b/_pytest/tmpdir.py --- a/_pytest/tmpdir.py +++ b/_pytest/tmpdir.py @@ -46,7 +46,7 @@ def finish(self): self.trace("finish") - + def pytest_configure(config): mp = monkeypatch() t = TempdirHandler(config) @@ -64,5 +64,5 @@ name = request._pyfuncitem.name name = py.std.re.sub("[\W]", "_", name) x = request.config._tmpdirhandler.mktemp(name, numbered=True) - return x.realpath() + return x diff --git a/_pytest/unittest.py b/_pytest/unittest.py --- a/_pytest/unittest.py +++ b/_pytest/unittest.py @@ -2,6 +2,9 @@ import pytest, py import sys, pdb +# for transfering markers +from _pytest.python import transfer_markers + def pytest_pycollect_makeitem(collector, name, obj): unittest = sys.modules.get('unittest') if unittest is None: @@ -19,7 +22,14 @@ class UnitTestCase(pytest.Class): def collect(self): loader = py.std.unittest.TestLoader() + module = self.getparent(pytest.Module).obj + cls = self.obj for name in loader.getTestCaseNames(self.obj): + x = getattr(self.obj, name) + funcobj = getattr(x, 'im_func', x) + transfer_markers(funcobj, cls, module) + if hasattr(funcobj, 'todo'): + pytest.mark.xfail(reason=str(funcobj.todo))(funcobj) yield TestCaseFunction(name, parent=self) def setup(self): @@ -37,15 +47,13 @@ class TestCaseFunction(pytest.Function): _excinfo = None - def __init__(self, name, parent): - super(TestCaseFunction, self).__init__(name, parent) - if hasattr(self._obj, 'todo'): - getattr(self._obj, 'im_func', self._obj).xfail = \ - pytest.mark.xfail(reason=str(self._obj.todo)) - def setup(self): self._testcase = self.parent.obj(self.name) self._obj = getattr(self._testcase, self.name) + if hasattr(self._testcase, 'skip'): + pytest.skip(self._testcase.skip) + if hasattr(self._obj, 'skip'): + pytest.skip(self._obj.skip) if hasattr(self._testcase, 'setup_method'): self._testcase.setup_method(self._obj) @@ -83,28 +91,37 @@ self._addexcinfo(rawexcinfo) def addFailure(self, testcase, rawexcinfo): self._addexcinfo(rawexcinfo) + def addSkip(self, testcase, reason): try: pytest.skip(reason) except pytest.skip.Exception: self._addexcinfo(sys.exc_info()) - def addExpectedFailure(self, testcase, rawexcinfo, reason): + + def addExpectedFailure(self, testcase, rawexcinfo, reason=""): try: pytest.xfail(str(reason)) except pytest.xfail.Exception: self._addexcinfo(sys.exc_info()) - def addUnexpectedSuccess(self, testcase, reason): - pass + + def addUnexpectedSuccess(self, testcase, reason=""): + self._unexpectedsuccess = reason + def addSuccess(self, testcase): pass + def stopTest(self, testcase): pass + def runtest(self): self._testcase(result=self) def _prunetraceback(self, excinfo): pytest.Function._prunetraceback(self, excinfo) - excinfo.traceback = excinfo.traceback.filter(lambda x:not x.frame.f_globals.get('__unittest')) + traceback = excinfo.traceback.filter( + lambda x:not x.frame.f_globals.get('__unittest')) + if traceback: + excinfo.traceback = traceback @pytest.mark.tryfirst def pytest_runtest_makereport(item, call): @@ -120,14 +137,19 @@ ut = sys.modules['twisted.python.failure'] Failure__init__ = ut.Failure.__init__.im_func check_testcase_implements_trial_reporter() - def excstore(self, exc_value=None, exc_type=None, exc_tb=None): + def excstore(self, exc_value=None, exc_type=None, exc_tb=None, + captureVars=None): if exc_value is None: self._rawexcinfo = sys.exc_info() else: if exc_type is None: exc_type = type(exc_value) self._rawexcinfo = (exc_type, exc_value, exc_tb) - Failure__init__(self, exc_value, exc_type, exc_tb) + try: + Failure__init__(self, exc_value, exc_type, exc_tb, + captureVars=captureVars) + except TypeError: + Failure__init__(self, exc_value, exc_type, exc_tb) ut.Failure.__init__ = excstore try: return __multicall__.execute() diff --git a/ctypes_configure/cbuild.py b/ctypes_configure/cbuild.py --- a/ctypes_configure/cbuild.py +++ b/ctypes_configure/cbuild.py @@ -206,8 +206,9 @@ cfiles += eci.separate_module_files include_dirs = list(eci.include_dirs) library_dirs = list(eci.library_dirs) - if sys.platform == 'darwin': # support Fink & Darwinports - for s in ('/sw/', '/opt/local/'): + if (sys.platform == 'darwin' or # support Fink & Darwinports + sys.platform.startswith('freebsd')): + for s in ('/sw/', '/opt/local/', '/usr/local/'): if s + 'include' not in include_dirs and \ os.path.exists(s + 'include'): include_dirs.append(s + 'include') @@ -380,9 +381,9 @@ self.link_extra += ['-pthread'] if sys.platform == 'win32': self.link_extra += ['/DEBUG'] # generate .pdb file - if sys.platform == 'darwin': - # support Fink & Darwinports - for s in ('/sw/', '/opt/local/'): + if (sys.platform == 'darwin' or # support Fink & Darwinports + sys.platform.startswith('freebsd')): + for s in ('/sw/', '/opt/local/', '/usr/local/'): if s + 'include' not in self.include_dirs and \ os.path.exists(s + 'include'): self.include_dirs.append(s + 'include') @@ -395,7 +396,6 @@ self.outputfilename = py.path.local(cfilenames[0]).new(ext=ext) else: self.outputfilename = py.path.local(outputfilename) - self.eci = eci def build(self, noerr=False): basename = self.outputfilename.new(ext='') @@ -436,7 +436,7 @@ old = cfile.dirpath().chdir() try: res = compiler.compile([cfile.basename], - include_dirs=self.eci.include_dirs, + include_dirs=self.include_dirs, extra_preargs=self.compile_extra) assert len(res) == 1 cobjfile = py.path.local(res[0]) @@ -445,9 +445,9 @@ finally: old.chdir() compiler.link_executable(objects, str(self.outputfilename), - libraries=self.eci.libraries, + libraries=self.libraries, extra_preargs=self.link_extra, - library_dirs=self.eci.library_dirs) + library_dirs=self.library_dirs) def build_executable(*args, **kwds): noerr = kwds.pop('noerr', False) diff --git a/dotviewer/graphparse.py b/dotviewer/graphparse.py --- a/dotviewer/graphparse.py +++ b/dotviewer/graphparse.py @@ -93,6 +93,7 @@ return result def parse_plain(graph_id, plaincontent, links={}, fixedfont=False): + plaincontent = plaincontent.replace('\r\n', '\n') # fix Windows EOL lines = plaincontent.splitlines(True) for i in range(len(lines)-2, -1, -1): if lines[i].endswith('\\\n'): # line ending in '\' diff --git a/lib-python/2.7/BaseHTTPServer.py b/lib-python/2.7/BaseHTTPServer.py --- a/lib-python/2.7/BaseHTTPServer.py +++ b/lib-python/2.7/BaseHTTPServer.py @@ -310,7 +310,13 @@ """ try: - self.raw_requestline = self.rfile.readline() + self.raw_requestline = self.rfile.readline(65537) + if len(self.raw_requestline) > 65536: + self.requestline = '' + self.request_version = '' + self.command = '' + self.send_error(414) + return if not self.raw_requestline: self.close_connection = 1 return diff --git a/lib-python/2.7/ConfigParser.py b/lib-python/2.7/ConfigParser.py --- a/lib-python/2.7/ConfigParser.py +++ b/lib-python/2.7/ConfigParser.py @@ -545,6 +545,38 @@ if isinstance(val, list): options[name] = '\n'.join(val) +import UserDict as _UserDict + +class _Chainmap(_UserDict.DictMixin): + """Combine multiple mappings for successive lookups. + + For example, to emulate Python's normal lookup sequence: + + import __builtin__ + pylookup = _Chainmap(locals(), globals(), vars(__builtin__)) + """ + + def __init__(self, *maps): + self._maps = maps + + def __getitem__(self, key): + for mapping in self._maps: + try: + return mapping[key] + except KeyError: + pass + raise KeyError(key) + + def keys(self): + result = [] + seen = set() + for mapping in self_maps: + for key in mapping: + if key not in seen: + result.append(key) + seen.add(key) + return result + class ConfigParser(RawConfigParser): def get(self, section, option, raw=False, vars=None): @@ -559,16 +591,18 @@ The section DEFAULT is special. """ - d = self._defaults.copy() + sectiondict = {} try: - d.update(self._sections[section]) + sectiondict = self._sections[section] except KeyError: if section != DEFAULTSECT: raise NoSectionError(section) # Update with the entry specific variables + vardict = {} if vars: for key, value in vars.items(): - d[self.optionxform(key)] = value + vardict[self.optionxform(key)] = value + d = _Chainmap(vardict, sectiondict, self._defaults) option = self.optionxform(option) try: value = d[option] diff --git a/lib-python/2.7/Cookie.py b/lib-python/2.7/Cookie.py --- a/lib-python/2.7/Cookie.py +++ b/lib-python/2.7/Cookie.py @@ -258,6 +258,11 @@ '\033' : '\\033', '\034' : '\\034', '\035' : '\\035', '\036' : '\\036', '\037' : '\\037', + # Because of the way browsers really handle cookies (as opposed + # to what the RFC says) we also encode , and ; + + ',' : '\\054', ';' : '\\073', + '"' : '\\"', '\\' : '\\\\', '\177' : '\\177', '\200' : '\\200', '\201' : '\\201', diff --git a/lib-python/2.7/HTMLParser.py b/lib-python/2.7/HTMLParser.py --- a/lib-python/2.7/HTMLParser.py +++ b/lib-python/2.7/HTMLParser.py @@ -26,7 +26,7 @@ tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*') attrfind = re.compile( r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*' - r'(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~@]*))?') + r'(\'[^\']*\'|"[^"]*"|[^\s"\'=<>`]*))?') locatestarttagend = re.compile(r""" <[a-zA-Z][-.a-zA-Z0-9:_]* # tag name @@ -99,7 +99,7 @@ markupbase.ParserBase.reset(self) def feed(self, data): - """Feed data to the parser. + r"""Feed data to the parser. Call this as often as you want, with as little or as much text as you want (may include '\n'). @@ -367,13 +367,16 @@ return s def replaceEntities(s): s = s.groups()[0] - if s[0] == "#": - s = s[1:] - if s[0] in ['x','X']: - c = int(s[1:], 16) - else: - c = int(s) - return unichr(c) + try: + if s[0] == "#": + s = s[1:] + if s[0] in ['x','X']: + c = int(s[1:], 16) + else: + c = int(s) + return unichr(c) + except ValueError: + return '&#'+s+';' else: # Cannot use name2codepoint directly, because HTMLParser supports apos, # which is not part of HTML 4 diff --git a/lib-python/2.7/SimpleHTTPServer.py b/lib-python/2.7/SimpleHTTPServer.py --- a/lib-python/2.7/SimpleHTTPServer.py +++ b/lib-python/2.7/SimpleHTTPServer.py @@ -15,6 +15,7 @@ import BaseHTTPServer import urllib import cgi +import sys import shutil import mimetypes try: @@ -131,7 +132,8 @@ length = f.tell() f.seek(0) self.send_response(200) - self.send_header("Content-type", "text/html") + encoding = sys.getfilesystemencoding() + self.send_header("Content-type", "text/html; charset=%s" % encoding) self.send_header("Content-Length", str(length)) self.end_headers() return f diff --git a/lib-python/2.7/SimpleXMLRPCServer.py b/lib-python/2.7/SimpleXMLRPCServer.py --- a/lib-python/2.7/SimpleXMLRPCServer.py +++ b/lib-python/2.7/SimpleXMLRPCServer.py @@ -246,7 +246,7 @@ marshalled data. For backwards compatibility, a dispatch function can be provided as an argument (see comment in SimpleXMLRPCRequestHandler.do_POST) but overriding the - existing method through subclassing is the prefered means + existing method through subclassing is the preferred means of changing method dispatch behavior. """ @@ -486,7 +486,10 @@ L = [] while size_remaining: chunk_size = min(size_remaining, max_chunk_size) - L.append(self.rfile.read(chunk_size)) + chunk = self.rfile.read(chunk_size) + if not chunk: + break + L.append(chunk) size_remaining -= len(L[-1]) data = ''.join(L) diff --git a/lib-python/2.7/SocketServer.py b/lib-python/2.7/SocketServer.py --- a/lib-python/2.7/SocketServer.py +++ b/lib-python/2.7/SocketServer.py @@ -675,7 +675,7 @@ # A timeout to apply to the request socket, if not None. timeout = None - # Disable nagle algoritm for this socket, if True. + # Disable nagle algorithm for this socket, if True. # Use only when wbufsize != 0, to avoid small packets. disable_nagle_algorithm = False diff --git a/lib-python/2.7/StringIO.py b/lib-python/2.7/StringIO.py --- a/lib-python/2.7/StringIO.py +++ b/lib-python/2.7/StringIO.py @@ -266,6 +266,7 @@ 8th bit) will cause a UnicodeError to be raised when getvalue() is called. """ + _complain_ifclosed(self.closed) if self.buflist: self.buf += ''.join(self.buflist) self.buflist = [] diff --git a/lib-python/2.7/UserDict.py b/lib-python/2.7/UserDict.py --- a/lib-python/2.7/UserDict.py +++ b/lib-python/2.7/UserDict.py @@ -80,8 +80,12 @@ def __iter__(self): return iter(self.data) -import _abcoll -_abcoll.MutableMapping.register(IterableUserDict) +try: + import _abcoll +except ImportError: + pass # e.g. no '_weakref' module on this pypy +else: + _abcoll.MutableMapping.register(IterableUserDict) class DictMixin: diff --git a/lib-python/2.7/_abcoll.py b/lib-python/2.7/_abcoll.py --- a/lib-python/2.7/_abcoll.py +++ b/lib-python/2.7/_abcoll.py @@ -82,7 +82,7 @@ @classmethod def __subclasshook__(cls, C): if cls is Iterator: - if _hasattr(C, "next"): + if _hasattr(C, "next") and _hasattr(C, "__iter__"): return True return NotImplemented diff --git a/lib-python/2.7/_pyio.py b/lib-python/2.7/_pyio.py --- a/lib-python/2.7/_pyio.py +++ b/lib-python/2.7/_pyio.py @@ -16,6 +16,7 @@ import io from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END) +from errno import EINTR __metaclass__ = type @@ -559,7 +560,11 @@ if not data: break res += data - return bytes(res) + if res: + return bytes(res) + else: + # b'' or None + return data def readinto(self, b): """Read up to len(b) bytes into b. @@ -678,7 +683,7 @@ """ def __init__(self, raw): - self.raw = raw + self._raw = raw ### Positioning ### @@ -722,8 +727,8 @@ if self.raw is None: raise ValueError("raw stream already detached") self.flush() - raw = self.raw - self.raw = None + raw = self._raw + self._raw = None return raw ### Inquiries ### @@ -738,6 +743,10 @@ return self.raw.writable() @property + def raw(self): + return self._raw + + @property def closed(self): return self.raw.closed @@ -933,7 +942,12 @@ current_size = 0 while True: # Read until EOF or until read() would block. - chunk = self.raw.read() + try: + chunk = self.raw.read() + except IOError as e: + if e.errno != EINTR: + raise + continue if chunk in empty_values: nodata_val = chunk break @@ -952,7 +966,12 @@ chunks = [buf[pos:]] wanted = max(self.buffer_size, n) while avail < n: - chunk = self.raw.read(wanted) + try: + chunk = self.raw.read(wanted) + except IOError as e: + if e.errno != EINTR: + raise + continue if chunk in empty_values: nodata_val = chunk break @@ -981,7 +1000,14 @@ have = len(self._read_buf) - self._read_pos if have < want or have <= 0: to_read = self.buffer_size - have - current = self.raw.read(to_read) + while True: + try: + current = self.raw.read(to_read) + except IOError as e: + if e.errno != EINTR: + raise + continue + break if current: self._read_buf = self._read_buf[self._read_pos:] + current self._read_pos = 0 @@ -1088,7 +1114,12 @@ written = 0 try: while self._write_buf: - n = self.raw.write(self._write_buf) + try: + n = self.raw.write(self._write_buf) + except IOError as e: + if e.errno != EINTR: + raise + continue if n > len(self._write_buf) or n < 0: raise IOError("write() returned incorrect number of bytes") del self._write_buf[:n] @@ -1456,7 +1487,7 @@ if not isinstance(errors, basestring): raise ValueError("invalid errors: %r" % errors) - self.buffer = buffer + self._buffer = buffer self._line_buffering = line_buffering self._encoding = encoding self._errors = errors @@ -1511,6 +1542,10 @@ def line_buffering(self): return self._line_buffering + @property + def buffer(self): + return self._buffer + def seekable(self): return self._seekable @@ -1724,8 +1759,8 @@ if self.buffer is None: raise ValueError("buffer is already detached") self.flush() - buffer = self.buffer - self.buffer = None + buffer = self._buffer + self._buffer = None return buffer def seek(self, cookie, whence=0): diff --git a/lib-python/2.7/_threading_local.py b/lib-python/2.7/_threading_local.py --- a/lib-python/2.7/_threading_local.py +++ b/lib-python/2.7/_threading_local.py @@ -155,7 +155,7 @@ object.__setattr__(self, '_local__args', (args, kw)) object.__setattr__(self, '_local__lock', RLock()) - if (args or kw) and (cls.__init__ is object.__init__): + if (args or kw) and (cls.__init__ == object.__init__): raise TypeError("Initialization arguments are not supported") # We need to create the thread dict in anticipation of diff --git a/lib-python/2.7/_weakrefset.py b/lib-python/2.7/_weakrefset.py --- a/lib-python/2.7/_weakrefset.py +++ b/lib-python/2.7/_weakrefset.py @@ -66,7 +66,11 @@ return sum(x() is not None for x in self.data) def __contains__(self, item): - return ref(item) in self.data + try: + wr = ref(item) + except TypeError: + return False + return wr in self.data def __reduce__(self): return (self.__class__, (list(self),), diff --git a/lib-python/2.7/anydbm.py b/lib-python/2.7/anydbm.py --- a/lib-python/2.7/anydbm.py +++ b/lib-python/2.7/anydbm.py @@ -29,17 +29,8 @@ list = d.keys() # return a list of all existing keys (slow!) Future versions may change the order in which implementations are -tested for existence, add interfaces to other dbm-like +tested for existence, and add interfaces to other dbm-like implementations. - -The open function has an optional second argument. This can be 'r', -for read-only access, 'w', for read-write access of an existing -database, 'c' for read-write access to a new or existing database, and -'n' for read-write access to a new database. The default is 'r'. - -Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it -only if it doesn't exist; and 'n' always creates a new database. - """ class error(Exception): @@ -63,7 +54,18 @@ error = tuple(_errors) -def open(file, flag = 'r', mode = 0666): +def open(file, flag='r', mode=0666): + """Open or create database at path given by *file*. + + Optional argument *flag* can be 'r' (default) for read-only access, 'w' + for read-write access of an existing database, 'c' for read-write access + to a new or existing database, and 'n' for read-write access to a new + database. + + Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it + only if it doesn't exist; and 'n' always creates a new database. + """ + # guess the type of an existing database from whichdb import whichdb result=whichdb(file) diff --git a/lib-python/2.7/argparse.py b/lib-python/2.7/argparse.py --- a/lib-python/2.7/argparse.py +++ b/lib-python/2.7/argparse.py @@ -82,6 +82,7 @@ ] +import collections as _collections import copy as _copy import os as _os import re as _re @@ -1037,7 +1038,7 @@ self._prog_prefix = prog self._parser_class = parser_class - self._name_parser_map = {} + self._name_parser_map = _collections.OrderedDict() self._choices_actions = [] super(_SubParsersAction, self).__init__( @@ -1080,7 +1081,7 @@ parser = self._name_parser_map[parser_name] except KeyError: tup = parser_name, ', '.join(self._name_parser_map) - msg = _('unknown parser %r (choices: %s)' % tup) + msg = _('unknown parser %r (choices: %s)') % tup raise ArgumentError(self, msg) # parse all the remaining options into the namespace @@ -1109,7 +1110,7 @@ the builtin open() function. """ - def __init__(self, mode='r', bufsize=None): + def __init__(self, mode='r', bufsize=-1): self._mode = mode self._bufsize = bufsize @@ -1121,18 +1122,19 @@ elif 'w' in self._mode: return _sys.stdout else: - msg = _('argument "-" with mode %r' % self._mode) + msg = _('argument "-" with mode %r') % self._mode raise ValueError(msg) # all other arguments are used as file names - if self._bufsize: + try: return open(string, self._mode, self._bufsize) - else: - return open(string, self._mode) + except IOError as e: + message = _("can't open '%s': %s") + raise ArgumentTypeError(message % (string, e)) def __repr__(self): - args = [self._mode, self._bufsize] - args_str = ', '.join([repr(arg) for arg in args if arg is not None]) + args = self._mode, self._bufsize + args_str = ', '.join(repr(arg) for arg in args if arg != -1) return '%s(%s)' % (type(self).__name__, args_str) # =========================== @@ -1275,13 +1277,20 @@ # create the action object, and add it to the parser action_class = self._pop_action_class(kwargs) if not _callable(action_class): - raise ValueError('unknown action "%s"' % action_class) + raise ValueError('unknown action "%s"' % (action_class,)) action = action_class(**kwargs) # raise an error if the action type is not callable type_func = self._registry_get('type', action.type, action.type) if not _callable(type_func): - raise ValueError('%r is not callable' % type_func) + raise ValueError('%r is not callable' % (type_func,)) + + # raise an error if the metavar does not match the type + if hasattr(self, "_get_formatter"): + try: + self._get_formatter()._format_args(action, None) + except TypeError: + raise ValueError("length of metavar tuple does not match nargs") return self._add_action(action) @@ -1481,6 +1490,7 @@ self._defaults = container._defaults self._has_negative_number_optionals = \ container._has_negative_number_optionals + self._mutually_exclusive_groups = container._mutually_exclusive_groups def _add_action(self, action): action = super(_ArgumentGroup, self)._add_action(action) diff --git a/lib-python/2.7/ast.py b/lib-python/2.7/ast.py --- a/lib-python/2.7/ast.py +++ b/lib-python/2.7/ast.py @@ -29,12 +29,12 @@ from _ast import __version__ -def parse(expr, filename='', mode='exec'): +def parse(source, filename='', mode='exec'): """ - Parse an expression into an AST node. - Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST). + Parse the source into an AST node. + Equivalent to compile(source, filename, mode, PyCF_ONLY_AST). """ - return compile(expr, filename, mode, PyCF_ONLY_AST) + return compile(source, filename, mode, PyCF_ONLY_AST) def literal_eval(node_or_string): @@ -152,8 +152,6 @@ Increment the line number of each node in the tree starting at *node* by *n*. This is useful to "move code" to a different location in a file. """ - if 'lineno' in node._attributes: - node.lineno = getattr(node, 'lineno', 0) + n for child in walk(node): if 'lineno' in child._attributes: child.lineno = getattr(child, 'lineno', 0) + n @@ -204,9 +202,9 @@ def walk(node): """ - Recursively yield all child nodes of *node*, in no specified order. This is - useful if you only want to modify nodes in place and don't care about the - context. + Recursively yield all descendant nodes in the tree starting at *node* + (including *node* itself), in no specified order. This is useful if you + only want to modify nodes in place and don't care about the context. """ from collections import deque todo = deque([node]) diff --git a/lib-python/2.7/asyncore.py b/lib-python/2.7/asyncore.py --- a/lib-python/2.7/asyncore.py +++ b/lib-python/2.7/asyncore.py @@ -54,7 +54,11 @@ import os from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \ - ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, errorcode + ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \ + errorcode + +_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE, + EBADF)) try: socket_map @@ -109,7 +113,7 @@ if flags & (select.POLLHUP | select.POLLERR | select.POLLNVAL): obj.handle_close() except socket.error, e: - if e.args[0] not in (EBADF, ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED): + if e.args[0] not in _DISCONNECTED: obj.handle_error() else: obj.handle_close() @@ -353,7 +357,7 @@ except TypeError: return None except socket.error as why: - if why.args[0] in (EWOULDBLOCK, ECONNABORTED): + if why.args[0] in (EWOULDBLOCK, ECONNABORTED, EAGAIN): return None else: raise @@ -367,7 +371,7 @@ except socket.error, why: if why.args[0] == EWOULDBLOCK: return 0 - elif why.args[0] in (ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED): + elif why.args[0] in _DISCONNECTED: self.handle_close() return 0 else: @@ -385,7 +389,7 @@ return data except socket.error, why: # winsock sometimes throws ENOTCONN - if why.args[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED]: + if why.args[0] in _DISCONNECTED: self.handle_close() return '' else: diff --git a/lib-python/2.7/bdb.py b/lib-python/2.7/bdb.py --- a/lib-python/2.7/bdb.py +++ b/lib-python/2.7/bdb.py @@ -250,6 +250,12 @@ list.append(lineno) bp = Breakpoint(filename, lineno, temporary, cond, funcname) + def _prune_breaks(self, filename, lineno): + if (filename, lineno) not in Breakpoint.bplist: + self.breaks[filename].remove(lineno) + if not self.breaks[filename]: + del self.breaks[filename] + def clear_break(self, filename, lineno): filename = self.canonic(filename) if not filename in self.breaks: @@ -261,10 +267,7 @@ # pair, then remove the breaks entry for bp in Breakpoint.bplist[filename, lineno][:]: bp.deleteMe() - if (filename, lineno) not in Breakpoint.bplist: - self.breaks[filename].remove(lineno) - if not self.breaks[filename]: - del self.breaks[filename] + self._prune_breaks(filename, lineno) def clear_bpbynumber(self, arg): try: @@ -277,7 +280,8 @@ return 'Breakpoint number (%d) out of range' % number if not bp: return 'Breakpoint (%d) already deleted' % number - self.clear_break(bp.file, bp.line) + bp.deleteMe() + self._prune_breaks(bp.file, bp.line) def clear_all_file_breaks(self, filename): filename = self.canonic(filename) diff --git a/lib-python/2.7/collections.py b/lib-python/2.7/collections.py --- a/lib-python/2.7/collections.py +++ b/lib-python/2.7/collections.py @@ -6,59 +6,38 @@ __all__ += _abcoll.__all__ from _collections import deque, defaultdict -from operator import itemgetter as _itemgetter, eq as _eq +from operator import itemgetter as _itemgetter from keyword import iskeyword as _iskeyword import sys as _sys import heapq as _heapq -from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, \ - ifilter as _ifilter, imap as _imap +from itertools import repeat as _repeat, chain as _chain, starmap as _starmap + try: - from thread import get_ident + from thread import get_ident as _get_ident except ImportError: - from dummy_thread import get_ident - -def _recursive_repr(user_function): - 'Decorator to make a repr function return "..." for a recursive call' - repr_running = set() - - def wrapper(self): - key = id(self), get_ident() - if key in repr_running: - return '...' - repr_running.add(key) - try: - result = user_function(self) - finally: - repr_running.discard(key) - return result - - # Can't use functools.wraps() here because of bootstrap issues - wrapper.__module__ = getattr(user_function, '__module__') - wrapper.__doc__ = getattr(user_function, '__doc__') - wrapper.__name__ = getattr(user_function, '__name__') - return wrapper + from dummy_thread import get_ident as _get_ident ################################################################################ ### OrderedDict ################################################################################ -class OrderedDict(dict, MutableMapping): +class OrderedDict(dict): 'Dictionary that remembers insertion order' # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. - # Big-O running times for all methods are the same as for regular dictionaries. + # Big-O running times for all methods are the same as regular dictionaries. - # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The internal self.__map dict maps keys to links in a doubly linked list. # The circular doubly linked list starts and ends with a sentinel element. # The sentinel element never gets deleted (this simplifies the algorithm). # Each link is stored as a list of length three: [PREV, NEXT, KEY]. def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for - regular dictionaries, but keyword arguments are not recommended - because their insertion order is arbitrary. + '''Initialize an ordered dictionary. The signature is the same as + regular dictionaries, but keyword arguments are not recommended because + their insertion order is arbitrary. ''' if len(args) > 1: @@ -66,17 +45,15 @@ try: self.__root except AttributeError: - self.__root = root = [None, None, None] # sentinel node - PREV = 0 - NEXT = 1 - root[PREV] = root[NEXT] = root + self.__root = root = [] # sentinel node + root[:] = [root, root, None] self.__map = {} - self.update(*args, **kwds) + self.__update(*args, **kwds) def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__): 'od.__setitem__(i, y) <==> od[i]=y' - # Setting a new item creates a new link which goes at the end of the linked - # list, and the inherited dictionary is updated with the new key/value pair. + # Setting a new item creates a new link at the end of the linked list, + # and the inherited dictionary is updated with the new key/value pair. if key not in self: root = self.__root last = root[PREV] @@ -85,65 +62,160 @@ def __delitem__(self, key, PREV=0, NEXT=1, dict_delitem=dict.__delitem__): 'od.__delitem__(y) <==> del od[y]' - # Deleting an existing item uses self.__map to find the link which is - # then removed by updating the links in the predecessor and successor nodes. + # Deleting an existing item uses self.__map to find the link which gets + # removed by updating the links in the predecessor and successor nodes. dict_delitem(self, key) - link = self.__map.pop(key) - link_prev = link[PREV] - link_next = link[NEXT] + link_prev, link_next, key = self.__map.pop(key) link_prev[NEXT] = link_next link_next[PREV] = link_prev - def __iter__(self, NEXT=1, KEY=2): + def __iter__(self): 'od.__iter__() <==> iter(od)' # Traverse the linked list in order. + NEXT, KEY = 1, 2 root = self.__root curr = root[NEXT] while curr is not root: yield curr[KEY] curr = curr[NEXT] - def __reversed__(self, PREV=0, KEY=2): + def __reversed__(self): 'od.__reversed__() <==> reversed(od)' # Traverse the linked list in reverse order. + PREV, KEY = 0, 2 root = self.__root curr = root[PREV] while curr is not root: yield curr[KEY] curr = curr[PREV] + def clear(self): + 'od.clear() -> None. Remove all items from od.' + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + dict.clear(self) + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) pairs in od' + for k in self: + yield (k, self[k]) + + update = MutableMapping.update + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding + value. If key is not found, d is returned if given, otherwise KeyError + is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + key = next(reversed(self) if last else iter(self)) + value = self.pop(key) + return key, value + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + def __reduce__(self): 'Return state information for pickling' items = [[k, self[k]] for k in self] - tmp = self.__map, self.__root - del self.__map, self.__root inst_dict = vars(self).copy() - self.__map, self.__root = tmp + for k in vars(OrderedDict()): + inst_dict.pop(k, None) if inst_dict: return (self.__class__, (items,), inst_dict) return self.__class__, (items,) - def clear(self): - 'od.clear() -> None. Remove all items from od.' - try: - for node in self.__map.itervalues(): - del node[:] - self.__root[:] = [self.__root, self.__root, None] - self.__map.clear() - except AttributeError: - pass - dict.clear(self) + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) - setdefault = MutableMapping.setdefault - update = MutableMapping.update - pop = MutableMapping.pop - keys = MutableMapping.keys - values = MutableMapping.values - items = MutableMapping.items - iterkeys = MutableMapping.iterkeys - itervalues = MutableMapping.itervalues - iteritems = MutableMapping.iteritems - __ne__ = MutableMapping.__ne__ + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S. + If not specified, the value defaults to None. + + ''' + self = cls() + for key in iterable: + self[key] = value + return self + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + 'od.__ne__(y) <==> od!=y' + return not self == other + + # -- the following methods support python 3.x style dictionary views -- def viewkeys(self): "od.viewkeys() -> a set-like object providing a view on od's keys" @@ -157,49 +229,6 @@ "od.viewitems() -> a set-like object providing a view on od's items" return ItemsView(self) - def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. - Pairs are returned in LIFO order if last is true or FIFO order if false. - - ''' - if not self: - raise KeyError('dictionary is empty') - key = next(reversed(self) if last else iter(self)) - value = self.pop(key) - return key, value - - @_recursive_repr - def __repr__(self): - 'od.__repr__() <==> repr(od)' - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - - def copy(self): - 'od.copy() -> a shallow copy of od' - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S - and values equal to v (which defaults to None). - - ''' - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive - while comparison to a regular mapping is order-insensitive. - - ''' - if isinstance(other, OrderedDict): - return len(self)==len(other) and \ - all(_imap(_eq, self.iteritems(), other.iteritems())) - return dict.__eq__(self, other) - ################################################################################ ### namedtuple @@ -328,16 +357,16 @@ or multiset. Elements are stored as dictionary keys and their counts are stored as dictionary values. - >>> c = Counter('abracadabra') # count elements from a string + >>> c = Counter('abcdeabcdabcaba') # count elements from a string >>> c.most_common(3) # three most common elements - [('a', 5), ('r', 2), ('b', 2)] + [('a', 5), ('b', 4), ('c', 3)] >>> sorted(c) # list all unique elements - ['a', 'b', 'c', 'd', 'r'] + ['a', 'b', 'c', 'd', 'e'] >>> ''.join(sorted(c.elements())) # list elements with repetitions - 'aaaaabbcdrr' + 'aaaaabbbbcccdde' >>> sum(c.values()) # total of all counts - 11 + 15 >>> c['a'] # count of letter 'a' 5 @@ -345,8 +374,8 @@ ... c[elem] += 1 # by adding 1 to each element's count >>> c['a'] # now there are seven 'a' 7 - >>> del c['r'] # remove all 'r' - >>> c['r'] # now there are zero 'r' + >>> del c['b'] # remove all 'b' + >>> c['b'] # now there are zero 'b' 0 >>> d = Counter('simsalabim') # make another counter @@ -385,6 +414,7 @@ >>> c = Counter(a=4, b=2) # a new counter from keyword args ''' + super(Counter, self).__init__() self.update(iterable, **kwds) def __missing__(self, key): @@ -396,8 +426,8 @@ '''List the n most common elements and their counts from the most common to the least. If n is None, then list all element counts. - >>> Counter('abracadabra').most_common(3) - [('a', 5), ('r', 2), ('b', 2)] + >>> Counter('abcdeabcdabcaba').most_common(3) + [('a', 5), ('b', 4), ('c', 3)] ''' # Emulate Bag.sortedByCount from Smalltalk @@ -463,7 +493,7 @@ for elem, count in iterable.iteritems(): self[elem] = self_get(elem, 0) + count else: - dict.update(self, iterable) # fast path when counter is empty + super(Counter, self).update(iterable) # fast path when counter is empty else: self_get = self.get for elem in iterable: @@ -499,13 +529,16 @@ self.subtract(kwds) def copy(self): - 'Like dict.copy() but returns a Counter instance instead of a dict.' - return Counter(self) + 'Return a shallow copy.' + return self.__class__(self) + + def __reduce__(self): + return self.__class__, (dict(self),) def __delitem__(self, elem): 'Like dict.__delitem__() but does not raise KeyError for missing values.' if elem in self: - dict.__delitem__(self, elem) + super(Counter, self).__delitem__(elem) def __repr__(self): if not self: @@ -532,10 +565,13 @@ if not isinstance(other, Counter): return NotImplemented result = Counter() - for elem in set(self) | set(other): - newcount = self[elem] + other[elem] + for elem, count in self.items(): + newcount = count + other[elem] if newcount > 0: result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count > 0: + result[elem] = count return result def __sub__(self, other): @@ -548,10 +584,13 @@ if not isinstance(other, Counter): return NotImplemented result = Counter() - for elem in set(self) | set(other): - newcount = self[elem] - other[elem] + for elem, count in self.items(): + newcount = count - other[elem] if newcount > 0: result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count < 0: + result[elem] = 0 - count return result def __or__(self, other): @@ -564,11 +603,14 @@ if not isinstance(other, Counter): return NotImplemented result = Counter() - for elem in set(self) | set(other): - p, q = self[elem], other[elem] - newcount = q if p < q else p + for elem, count in self.items(): + other_count = other[elem] + newcount = other_count if count < other_count else count if newcount > 0: result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count > 0: + result[elem] = count return result def __and__(self, other): @@ -581,11 +623,9 @@ if not isinstance(other, Counter): return NotImplemented result = Counter() - if len(self) < len(other): - self, other = other, self - for elem in _ifilter(self.__contains__, other): - p, q = self[elem], other[elem] - newcount = p if p < q else q + for elem, count in self.items(): + other_count = other[elem] + newcount = count if count < other_count else other_count if newcount > 0: result[elem] = newcount return result diff --git a/lib-python/2.7/compileall.py b/lib-python/2.7/compileall.py --- a/lib-python/2.7/compileall.py +++ b/lib-python/2.7/compileall.py @@ -9,7 +9,6 @@ packages -- for now, you'll have to deal with packages separately.) See module py_compile for details of the actual byte-compilation. - """ import os import sys @@ -31,7 +30,6 @@ directory name that will show up in error messages) force: if 1, force compilation, even if timestamps are up-to-date quiet: if 1, be quiet during compilation - """ if not quiet: print 'Listing', dir, '...' @@ -61,15 +59,16 @@ return success def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0): - """Byte-compile file. - file: the file to byte-compile + """Byte-compile one file. + + Arguments (only fullname is required): + + fullname: the file to byte-compile ddir: if given, purported directory name (this is the directory name that will show up in error messages) force: if 1, force compilation, even if timestamps are up-to-date quiet: if 1, be quiet during compilation - """ - success = 1 name = os.path.basename(fullname) if ddir is not None: @@ -120,7 +119,6 @@ maxlevels: max recursion level (default 0) force: as for compile_dir() (default 0) quiet: as for compile_dir() (default 0) - """ success = 1 for dir in sys.path: diff --git a/lib-python/2.7/csv.py b/lib-python/2.7/csv.py --- a/lib-python/2.7/csv.py +++ b/lib-python/2.7/csv.py @@ -281,7 +281,7 @@ an all or nothing approach, so we allow for small variations in this number. 1) build a table of the frequency of each character on every line. - 2) build a table of freqencies of this frequency (meta-frequency?), + 2) build a table of frequencies of this frequency (meta-frequency?), e.g. 'x occurred 5 times in 10 rows, 6 times in 1000 rows, 7 times in 2 rows' 3) use the mode of the meta-frequency to determine the /expected/ diff --git a/lib-python/2.7/ctypes/__init__.py b/lib-python/2.7/ctypes/__init__.py --- a/lib-python/2.7/ctypes/__init__.py +++ b/lib-python/2.7/ctypes/__init__.py @@ -7,6 +7,7 @@ __version__ = "1.1.0" +import _ffi from _ctypes import Union, Structure, Array from _ctypes import _Pointer from _ctypes import CFuncPtr as _CFuncPtr @@ -350,16 +351,17 @@ self._FuncPtr = _FuncPtr if handle is None: - self._handle = _dlopen(self._name, mode) + self._handle = _ffi.CDLL(name, mode) else: self._handle = handle def __repr__(self): - return "<%s '%s', handle %x at %x>" % \ + return "<%s '%s', handle %r at %x>" % \ (self.__class__.__name__, self._name, - (self._handle & (_sys.maxint*2 + 1)), + (self._handle), id(self) & (_sys.maxint*2 + 1)) + def __getattr__(self, name): if name.startswith('__') and name.endswith('__'): raise AttributeError(name) @@ -487,9 +489,12 @@ _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI return CFunctionType -_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr) def cast(obj, typ): - return _cast(obj, obj, typ) + try: + c_void_p.from_param(obj) + except TypeError, e: + raise ArgumentError(str(e)) + return _cast_addr(obj, obj, typ) _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) def string_at(ptr, size=-1): diff --git a/lib-python/2.7/ctypes/test/__init__.py b/lib-python/2.7/ctypes/test/__init__.py --- a/lib-python/2.7/ctypes/test/__init__.py +++ b/lib-python/2.7/ctypes/test/__init__.py @@ -206,3 +206,16 @@ result = unittest.TestResult() test(result) return result + +def xfail(method): + """ + Poor's man xfail: remove it when all the failures have been fixed + """ + def new_method(self, *args, **kwds): + try: + method(self, *args, **kwds) + except: + pass + else: + self.assertTrue(False, "DID NOT RAISE") + return new_method diff --git a/lib-python/2.7/ctypes/test/test_arrays.py b/lib-python/2.7/ctypes/test/test_arrays.py --- a/lib-python/2.7/ctypes/test/test_arrays.py +++ b/lib-python/2.7/ctypes/test/test_arrays.py @@ -1,12 +1,23 @@ import unittest from ctypes import * +from test.test_support import impl_detail formats = "bBhHiIlLqQfd" +# c_longdouble commented out for PyPy, look at the commend in test_longdouble formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \ - c_long, c_ulonglong, c_float, c_double, c_longdouble + c_long, c_ulonglong, c_float, c_double #, c_longdouble class ArrayTestCase(unittest.TestCase): + + @impl_detail('long double not supported by PyPy', pypy=False) + def test_longdouble(self): + """ + This test is empty. It's just here to remind that we commented out + c_longdouble in "formats". If pypy will ever supports c_longdouble, we + should kill this test and uncomment c_longdouble inside formats. + """ + def test_simple(self): # create classes holding simple numeric types, and check # various properties. @@ -37,7 +48,7 @@ values = [ia[i] for i in range(len(init))] self.assertEqual(values, [0] * len(init)) - # Too many in itializers should be caught + # Too many initializers should be caught self.assertRaises(IndexError, int_array, *range(alen*2)) CharArray = ARRAY(c_char, 3) diff --git a/lib-python/2.7/ctypes/test/test_as_parameter.py b/lib-python/2.7/ctypes/test/test_as_parameter.py --- a/lib-python/2.7/ctypes/test/test_as_parameter.py +++ b/lib-python/2.7/ctypes/test/test_as_parameter.py @@ -187,6 +187,18 @@ self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + def test_recursive_as_param(self): + from ctypes import c_int + + class A(object): + pass + + a = A() + a._as_parameter_ = a + with self.assertRaises(RuntimeError): + c_int.from_param(a) + + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class AsParamWrapper(object): diff --git a/lib-python/2.7/ctypes/test/test_bitfields.py b/lib-python/2.7/ctypes/test/test_bitfields.py --- a/lib-python/2.7/ctypes/test/test_bitfields.py +++ b/lib-python/2.7/ctypes/test/test_bitfields.py @@ -115,17 +115,21 @@ def test_nonint_types(self): # bit fields are not allowed on non-integer types. result = self.fail_fields(("a", c_char_p, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char_p')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) result = self.fail_fields(("a", c_void_p, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_void_p')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) if c_int != c_long: result = self.fail_fields(("a", POINTER(c_int), 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type LP_c_int')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) result = self.fail_fields(("a", c_char, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) try: c_wchar @@ -133,13 +137,15 @@ pass else: result = self.fail_fields(("a", c_wchar, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_wchar')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) class Dummy(Structure): _fields_ = [] result = self.fail_fields(("a", Dummy, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type Dummy')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) def test_single_bitfield_size(self): for c_typ in int_types: diff --git a/lib-python/2.7/ctypes/test/test_byteswap.py b/lib-python/2.7/ctypes/test/test_byteswap.py --- a/lib-python/2.7/ctypes/test/test_byteswap.py +++ b/lib-python/2.7/ctypes/test/test_byteswap.py @@ -2,6 +2,7 @@ from binascii import hexlify from ctypes import * +from ctypes.test import xfail def bin(s): return hexlify(memoryview(s)).upper() @@ -21,6 +22,7 @@ setattr(bits, "i%s" % i, 1) dump(bits) + @xfail def test_endian_short(self): if sys.byteorder == "little": self.assertTrue(c_short.__ctype_le__ is c_short) @@ -48,6 +50,7 @@ self.assertEqual(bin(s), "3412") self.assertEqual(s.value, 0x1234) + @xfail def test_endian_int(self): if sys.byteorder == "little": self.assertTrue(c_int.__ctype_le__ is c_int) @@ -76,6 +79,7 @@ self.assertEqual(bin(s), "78563412") self.assertEqual(s.value, 0x12345678) + @xfail def test_endian_longlong(self): if sys.byteorder == "little": self.assertTrue(c_longlong.__ctype_le__ is c_longlong) @@ -104,6 +108,7 @@ self.assertEqual(bin(s), "EFCDAB9078563412") self.assertEqual(s.value, 0x1234567890ABCDEF) + @xfail def test_endian_float(self): if sys.byteorder == "little": self.assertTrue(c_float.__ctype_le__ is c_float) @@ -122,6 +127,7 @@ self.assertAlmostEqual(s.value, math.pi, 6) self.assertEqual(bin(struct.pack(">f", math.pi)), bin(s)) + @xfail def test_endian_double(self): if sys.byteorder == "little": self.assertTrue(c_double.__ctype_le__ is c_double) @@ -149,6 +155,7 @@ self.assertTrue(c_char.__ctype_le__ is c_char) self.assertTrue(c_char.__ctype_be__ is c_char) + @xfail def test_struct_fields_1(self): if sys.byteorder == "little": base = BigEndianStructure @@ -198,6 +205,7 @@ pass self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)]) + @xfail def test_struct_fields_2(self): # standard packing in struct uses no alignment. # So, we have to align using pad bytes. @@ -221,6 +229,7 @@ s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) self.assertEqual(bin(s1), bin(s2)) + @xfail def test_unaligned_nonnative_struct_fields(self): if sys.byteorder == "little": base = BigEndianStructure diff --git a/lib-python/2.7/ctypes/test/test_callbacks.py b/lib-python/2.7/ctypes/test/test_callbacks.py --- a/lib-python/2.7/ctypes/test/test_callbacks.py +++ b/lib-python/2.7/ctypes/test/test_callbacks.py @@ -1,5 +1,6 @@ import unittest from ctypes import * +from ctypes.test import xfail import _ctypes_test class Callbacks(unittest.TestCase): @@ -98,6 +99,7 @@ ## self.check_type(c_char_p, "abc") ## self.check_type(c_char_p, "def") + @xfail def test_pyobject(self): o = () from sys import getrefcount as grc @@ -206,6 +208,42 @@ windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0) + def test_callback_register_int(self): + # Issue #8275: buggy handling of callback args under Win64 + # NOTE: should be run on release builds as well + dll = CDLL(_ctypes_test.__file__) + CALLBACK = CFUNCTYPE(c_int, c_int, c_int, c_int, c_int, c_int) + # All this function does is call the callback with its args squared + func = dll._testfunc_cbk_reg_int + func.argtypes = (c_int, c_int, c_int, c_int, c_int, CALLBACK) + func.restype = c_int + + def callback(a, b, c, d, e): + return a + b + c + d + e + + result = func(2, 3, 4, 5, 6, CALLBACK(callback)) + self.assertEqual(result, callback(2*2, 3*3, 4*4, 5*5, 6*6)) + + def test_callback_register_double(self): + # Issue #8275: buggy handling of callback args under Win64 + # NOTE: should be run on release builds as well + dll = CDLL(_ctypes_test.__file__) + CALLBACK = CFUNCTYPE(c_double, c_double, c_double, c_double, + c_double, c_double) + # All this function does is call the callback with its args squared + func = dll._testfunc_cbk_reg_double + func.argtypes = (c_double, c_double, c_double, + c_double, c_double, CALLBACK) + func.restype = c_double + + def callback(a, b, c, d, e): + return a + b + c + d + e + + result = func(1.1, 2.2, 3.3, 4.4, 5.5, CALLBACK(callback)) + self.assertEqual(result, + callback(1.1*1.1, 2.2*2.2, 3.3*3.3, 4.4*4.4, 5.5*5.5)) + + ################################################################ if __name__ == '__main__': diff --git a/lib-python/2.7/ctypes/test/test_cfuncs.py b/lib-python/2.7/ctypes/test/test_cfuncs.py --- a/lib-python/2.7/ctypes/test/test_cfuncs.py +++ b/lib-python/2.7/ctypes/test/test_cfuncs.py @@ -3,8 +3,8 @@ import unittest from ctypes import * - import _ctypes_test +from test.test_support import impl_detail class CFunctions(unittest.TestCase): _dll = CDLL(_ctypes_test.__file__) @@ -158,12 +158,14 @@ self.assertEqual(self._dll.tf_bd(0, 42.), 14.) self.assertEqual(self.S(), 42) + @impl_detail('long double not supported by PyPy', pypy=False) def test_longdouble(self): self._dll.tf_D.restype = c_longdouble self._dll.tf_D.argtypes = (c_longdouble,) self.assertEqual(self._dll.tf_D(42.), 14.) self.assertEqual(self.S(), 42) - + + @impl_detail('long double not supported by PyPy', pypy=False) def test_longdouble_plus(self): self._dll.tf_bD.restype = c_longdouble self._dll.tf_bD.argtypes = (c_byte, c_longdouble) diff --git a/lib-python/2.7/ctypes/test/test_delattr.py b/lib-python/2.7/ctypes/test/test_delattr.py --- a/lib-python/2.7/ctypes/test/test_delattr.py +++ b/lib-python/2.7/ctypes/test/test_delattr.py @@ -6,15 +6,15 @@ class TestCase(unittest.TestCase): def test_simple(self): - self.assertRaises(TypeError, + self.assertRaises((TypeError, AttributeError), delattr, c_int(42), "value") def test_chararray(self): - self.assertRaises(TypeError, + self.assertRaises((TypeError, AttributeError), delattr, (c_char * 5)(), "value") def test_struct(self): - self.assertRaises(TypeError, + self.assertRaises((TypeError, AttributeError), delattr, X(), "foo") if __name__ == "__main__": diff --git a/lib-python/2.7/ctypes/test/test_frombuffer.py b/lib-python/2.7/ctypes/test/test_frombuffer.py --- a/lib-python/2.7/ctypes/test/test_frombuffer.py +++ b/lib-python/2.7/ctypes/test/test_frombuffer.py @@ -2,6 +2,7 @@ import array import gc import unittest +from ctypes.test import xfail class X(Structure): _fields_ = [("c_int", c_int)] @@ -10,6 +11,7 @@ self._init_called = True class Test(unittest.TestCase): + @xfail def test_fom_buffer(self): a = array.array("i", range(16)) x = (c_int * 16).from_buffer(a) @@ -35,6 +37,7 @@ self.assertRaises(TypeError, (c_char * 16).from_buffer, "a" * 16) + @xfail def test_fom_buffer_with_offset(self): a = array.array("i", range(16)) x = (c_int * 15).from_buffer(a, sizeof(c_int)) @@ -43,6 +46,7 @@ self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a, sizeof(c_int))) self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 * sizeof(c_int))) + @xfail def test_from_buffer_copy(self): a = array.array("i", range(16)) x = (c_int * 16).from_buffer_copy(a) @@ -67,6 +71,7 @@ x = (c_char * 16).from_buffer_copy("a" * 16) self.assertEqual(x[:], "a" * 16) + @xfail def test_fom_buffer_copy_with_offset(self): a = array.array("i", range(16)) x = (c_int * 15).from_buffer_copy(a, sizeof(c_int)) diff --git a/lib-python/2.7/ctypes/test/test_functions.py b/lib-python/2.7/ctypes/test/test_functions.py --- a/lib-python/2.7/ctypes/test/test_functions.py +++ b/lib-python/2.7/ctypes/test/test_functions.py @@ -7,6 +7,8 @@ from ctypes import * import sys, unittest +from ctypes.test import xfail +from test.test_support import impl_detail try: WINFUNCTYPE @@ -116,7 +118,7 @@ self.assertEqual(result, 21) self.assertEqual(type(result), int) - # You cannot assing character format codes as restype any longer + # You cannot assign character format codes as restype any longer self.assertRaises(TypeError, setattr, f, "restype", "i") def test_floatresult(self): @@ -143,6 +145,7 @@ self.assertEqual(result, -21) self.assertEqual(type(result), float) + @impl_detail('long double not supported by PyPy', pypy=False) def test_longdoubleresult(self): f = dll._testfunc_D_bhilfD f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble] @@ -393,6 +396,7 @@ self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + @xfail def test_sf1651235(self): # see http://www.python.org/sf/1651235 diff --git a/lib-python/2.7/ctypes/test/test_init.py b/lib-python/2.7/ctypes/test/test_init.py --- a/lib-python/2.7/ctypes/test/test_init.py +++ b/lib-python/2.7/ctypes/test/test_init.py @@ -27,7 +27,7 @@ self.assertEqual((y.x.a, y.x.b), (0, 0)) self.assertEqual(y.x.new_was_called, False) - # But explicitely creating an X structure calls __new__ and __init__, of course. + # But explicitly creating an X structure calls __new__ and __init__, of course. x = X() self.assertEqual((x.a, x.b), (9, 12)) self.assertEqual(x.new_was_called, True) diff --git a/lib-python/2.7/ctypes/test/test_internals.py b/lib-python/2.7/ctypes/test/test_internals.py --- a/lib-python/2.7/ctypes/test/test_internals.py +++ b/lib-python/2.7/ctypes/test/test_internals.py @@ -33,7 +33,13 @@ refcnt = grc(s) cs = c_char_p(s) self.assertEqual(refcnt + 1, grc(s)) - self.assertSame(cs._objects, s) + try: + # Moving gcs need to allocate a nonmoving buffer + cs._objects._obj + except AttributeError: + self.assertSame(cs._objects, s) + else: + self.assertSame(cs._objects._obj, s) def test_simple_struct(self): class X(Structure): diff --git a/lib-python/2.7/ctypes/test/test_libc.py b/lib-python/2.7/ctypes/test/test_libc.py --- a/lib-python/2.7/ctypes/test/test_libc.py +++ b/lib-python/2.7/ctypes/test/test_libc.py @@ -25,5 +25,14 @@ lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort)) self.assertEqual(chars.raw, " ,,aaaadmmmnpppsss\x00") + def SKIPPED_test_no_more_xfail(self): + # We decided to not explicitly support the whole ctypes-2.7 + # and instead go for a case-by-case, demand-driven approach. + # So this test is skipped instead of failing. + import socket + import ctypes.test + self.assertTrue(not hasattr(ctypes.test, 'xfail'), + "You should incrementally grep for '@xfail' and remove them, they are real failures") + if __name__ == "__main__": unittest.main() diff --git a/lib-python/2.7/ctypes/test/test_loading.py b/lib-python/2.7/ctypes/test/test_loading.py --- a/lib-python/2.7/ctypes/test/test_loading.py +++ b/lib-python/2.7/ctypes/test/test_loading.py @@ -2,7 +2,7 @@ import sys, unittest import os from ctypes.util import find_library -from ctypes.test import is_resource_enabled +from ctypes.test import is_resource_enabled, xfail libc_name = None if os.name == "nt": @@ -75,6 +75,7 @@ self.assertRaises(AttributeError, dll.__getitem__, 1234) if os.name == "nt": + @xfail def test_1703286_A(self): from _ctypes import LoadLibrary, FreeLibrary # On winXP 64-bit, advapi32 loads at an address that does @@ -85,6 +86,7 @@ handle = LoadLibrary("advapi32") FreeLibrary(handle) + @xfail def test_1703286_B(self): # Since on winXP 64-bit advapi32 loads like described # above, the (arbitrarily selected) CloseEventLog function diff --git a/lib-python/2.7/ctypes/test/test_macholib.py b/lib-python/2.7/ctypes/test/test_macholib.py --- a/lib-python/2.7/ctypes/test/test_macholib.py +++ b/lib-python/2.7/ctypes/test/test_macholib.py @@ -52,7 +52,6 @@ '/usr/lib/libSystem.B.dylib') result = find_lib('z') - self.assertTrue(result.startswith('/usr/lib/libz.1')) self.assertTrue(result.endswith('.dylib')) self.assertEqual(find_lib('IOKit'), diff --git a/lib-python/2.7/ctypes/test/test_numbers.py b/lib-python/2.7/ctypes/test/test_numbers.py --- a/lib-python/2.7/ctypes/test/test_numbers.py +++ b/lib-python/2.7/ctypes/test/test_numbers.py @@ -1,6 +1,7 @@ from ctypes import * import unittest import struct +from ctypes.test import xfail def valid_ranges(*types): # given a sequence of numeric types, collect their _type_ @@ -89,12 +90,14 @@ ## self.assertRaises(ValueError, t, l-1) ## self.assertRaises(ValueError, t, h+1) + @xfail def test_from_param(self): # the from_param class method attribute always # returns PyCArgObject instances for t in signed_types + unsigned_types + float_types: self.assertEqual(ArgType, type(t.from_param(0))) + @xfail def test_byref(self): # calling byref returns also a PyCArgObject instance for t in signed_types + unsigned_types + float_types + bool_types: @@ -102,6 +105,7 @@ self.assertEqual(ArgType, type(parm)) + @xfail def test_floats(self): # c_float and c_double can be created from # Python int, long and float @@ -115,6 +119,7 @@ self.assertEqual(t(2L).value, 2.0) self.assertEqual(t(f).value, 2.0) + @xfail def test_integers(self): class FloatLike(object): def __float__(self): @@ -157,7 +162,7 @@ def test_int_from_address(self): from array import array for t in signed_types + unsigned_types: - # the array module doesn't suppport all format codes + # the array module doesn't support all format codes # (no 'q' or 'Q') try: array(t._type_) diff --git a/lib-python/2.7/ctypes/test/test_objects.py b/lib-python/2.7/ctypes/test/test_objects.py --- a/lib-python/2.7/ctypes/test/test_objects.py +++ b/lib-python/2.7/ctypes/test/test_objects.py @@ -22,7 +22,7 @@ >>> array[4] = 'foo bar' >>> array._objects -{'4': 'foo bar'} +{'4': } >>> array[4] 'foo bar' >>> @@ -47,9 +47,9 @@ >>> x.array[0] = 'spam spam spam' >>> x._objects -{'0:2': 'spam spam spam'} +{'0:2': } >>> x.array._b_base_._objects -{'0:2': 'spam spam spam'} +{'0:2': } >>> ''' diff --git a/lib-python/2.7/ctypes/test/test_parameters.py b/lib-python/2.7/ctypes/test/test_parameters.py --- a/lib-python/2.7/ctypes/test/test_parameters.py +++ b/lib-python/2.7/ctypes/test/test_parameters.py @@ -1,5 +1,7 @@ import unittest, sys +from ctypes.test import xfail + class SimpleTypesTestCase(unittest.TestCase): def setUp(self): @@ -49,6 +51,7 @@ self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc") # XXX Replace by c_char_p tests + @xfail def test_cstrings(self): from ctypes import c_char_p, byref @@ -86,7 +89,10 @@ pa = c_wchar_p.from_param(c_wchar_p(u"123")) self.assertEqual(type(pa), c_wchar_p) + if sys.platform == "win32": + test_cw_strings = xfail(test_cw_strings) + @xfail def test_int_pointers(self): from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer LPINT = POINTER(c_int) diff --git a/lib-python/2.7/ctypes/test/test_pep3118.py b/lib-python/2.7/ctypes/test/test_pep3118.py --- a/lib-python/2.7/ctypes/test/test_pep3118.py +++ b/lib-python/2.7/ctypes/test/test_pep3118.py @@ -1,6 +1,7 @@ import unittest from ctypes import * import re, sys +from ctypes.test import xfail if sys.byteorder == "little": THIS_ENDIAN = "<" @@ -19,6 +20,7 @@ class Test(unittest.TestCase): + @xfail def test_native_types(self): for tp, fmt, shape, itemtp in native_types: ob = tp() @@ -46,6 +48,7 @@ print(tp) raise + @xfail def test_endian_types(self): for tp, fmt, shape, itemtp in endian_types: ob = tp() diff --git a/lib-python/2.7/ctypes/test/test_pickling.py b/lib-python/2.7/ctypes/test/test_pickling.py --- a/lib-python/2.7/ctypes/test/test_pickling.py +++ b/lib-python/2.7/ctypes/test/test_pickling.py @@ -3,6 +3,7 @@ from ctypes import * import _ctypes_test dll = CDLL(_ctypes_test.__file__) +from ctypes.test import xfail class X(Structure): _fields_ = [("a", c_int), ("b", c_double)] @@ -21,6 +22,7 @@ def loads(self, item): return pickle.loads(item) + @xfail def test_simple(self): for src in [ c_int(42), @@ -31,6 +33,7 @@ self.assertEqual(memoryview(src).tobytes(), memoryview(dst).tobytes()) + @xfail def test_struct(self): X.init_called = 0 @@ -49,6 +52,7 @@ self.assertEqual(memoryview(y).tobytes(), memoryview(x).tobytes()) + @xfail def test_unpickable(self): # ctypes objects that are pointers or contain pointers are # unpickable. @@ -66,6 +70,7 @@ ]: self.assertRaises(ValueError, lambda: self.dumps(item)) + @xfail def test_wchar(self): pickle.dumps(c_char("x")) # Issue 5049 diff --git a/lib-python/2.7/ctypes/test/test_python_api.py b/lib-python/2.7/ctypes/test/test_python_api.py --- a/lib-python/2.7/ctypes/test/test_python_api.py +++ b/lib-python/2.7/ctypes/test/test_python_api.py @@ -1,6 +1,6 @@ from ctypes import * import unittest, sys -from ctypes.test import is_resource_enabled +from ctypes.test import is_resource_enabled, xfail ################################################################ # This section should be moved into ctypes\__init__.py, when it's ready. @@ -17,6 +17,7 @@ class PythonAPITestCase(unittest.TestCase): + @xfail def test_PyString_FromStringAndSize(self): PyString_FromStringAndSize = pythonapi.PyString_FromStringAndSize @@ -25,6 +26,7 @@ self.assertEqual(PyString_FromStringAndSize("abcdefghi", 3), "abc") + @xfail def test_PyString_FromString(self): pythonapi.PyString_FromString.restype = py_object pythonapi.PyString_FromString.argtypes = (c_char_p,) @@ -56,6 +58,7 @@ del res self.assertEqual(grc(42), ref42) + @xfail def test_PyObj_FromPtr(self): s = "abc def ghi jkl" ref = grc(s) @@ -81,6 +84,7 @@ # not enough arguments self.assertRaises(TypeError, PyOS_snprintf, buf) + @xfail def test_pyobject_repr(self): self.assertEqual(repr(py_object()), "py_object()") self.assertEqual(repr(py_object(42)), "py_object(42)") diff --git a/lib-python/2.7/ctypes/test/test_refcounts.py b/lib-python/2.7/ctypes/test/test_refcounts.py --- a/lib-python/2.7/ctypes/test/test_refcounts.py +++ b/lib-python/2.7/ctypes/test/test_refcounts.py @@ -90,6 +90,7 @@ return a * b * 2 f = proto(func) + gc.collect() a = sys.getrefcount(ctypes.c_int) f(1, 2) self.assertEqual(sys.getrefcount(ctypes.c_int), a) diff --git a/lib-python/2.7/ctypes/test/test_stringptr.py b/lib-python/2.7/ctypes/test/test_stringptr.py --- a/lib-python/2.7/ctypes/test/test_stringptr.py +++ b/lib-python/2.7/ctypes/test/test_stringptr.py @@ -2,11 +2,13 @@ from ctypes import * import _ctypes_test +from ctypes.test import xfail lib = CDLL(_ctypes_test.__file__) class StringPtrTestCase(unittest.TestCase): + @xfail def test__POINTER_c_char(self): class X(Structure): _fields_ = [("str", POINTER(c_char))] @@ -27,6 +29,7 @@ self.assertRaises(TypeError, setattr, x, "str", "Hello, World") + @xfail def test__c_char_p(self): class X(Structure): _fields_ = [("str", c_char_p)] diff --git a/lib-python/2.7/ctypes/test/test_strings.py b/lib-python/2.7/ctypes/test/test_strings.py --- a/lib-python/2.7/ctypes/test/test_strings.py +++ b/lib-python/2.7/ctypes/test/test_strings.py @@ -31,8 +31,9 @@ buf.value = "Hello, World" self.assertEqual(buf.value, "Hello, World") - self.assertRaises(TypeError, setattr, buf, "value", memoryview("Hello, World")) - self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) + if test_support.check_impl_detail(): + self.assertRaises(TypeError, setattr, buf, "value", memoryview("Hello, World")) + self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) self.assertRaises(ValueError, setattr, buf, "raw", memoryview("x" * 100)) def test_c_buffer_raw(self, memoryview=memoryview): @@ -40,7 +41,8 @@ buf.raw = memoryview("Hello, World") self.assertEqual(buf.value, "Hello, World") - self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) + if test_support.check_impl_detail(): + self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) self.assertRaises(ValueError, setattr, buf, "raw", memoryview("x" * 100)) def test_c_buffer_deprecated(self): diff --git a/lib-python/2.7/ctypes/test/test_structures.py b/lib-python/2.7/ctypes/test/test_structures.py --- a/lib-python/2.7/ctypes/test/test_structures.py +++ b/lib-python/2.7/ctypes/test/test_structures.py @@ -194,8 +194,8 @@ self.assertEqual(X.b.offset, min(8, longlong_align)) - d = {"_fields_": [("a", "b"), - ("b", "q")], + d = {"_fields_": [("a", c_byte), + ("b", c_longlong)], "_pack_": -1} self.assertRaises(ValueError, type(Structure), "X", (Structure,), d) diff --git a/lib-python/2.7/ctypes/test/test_varsize_struct.py b/lib-python/2.7/ctypes/test/test_varsize_struct.py --- a/lib-python/2.7/ctypes/test/test_varsize_struct.py +++ b/lib-python/2.7/ctypes/test/test_varsize_struct.py @@ -1,7 +1,9 @@ from ctypes import * import unittest +from ctypes.test import xfail class VarSizeTest(unittest.TestCase): + @xfail def test_resize(self): class X(Structure): _fields_ = [("item", c_int), diff --git a/lib-python/2.7/ctypes/test/test_win32.py b/lib-python/2.7/ctypes/test/test_win32.py --- a/lib-python/2.7/ctypes/test/test_win32.py +++ b/lib-python/2.7/ctypes/test/test_win32.py @@ -17,7 +17,7 @@ # ValueError: Procedure probably called with not enough arguments (4 bytes missing) self.assertRaises(ValueError, IsWindow) - # This one should succeeed... + # This one should succeed... self.assertEqual(0, IsWindow(0)) # ValueError: Procedure probably called with too many arguments (8 bytes in excess) diff --git a/lib-python/2.7/ctypes/util.py b/lib-python/2.7/ctypes/util.py --- a/lib-python/2.7/ctypes/util.py +++ b/lib-python/2.7/ctypes/util.py @@ -72,8 +72,8 @@ return name if os.name == "posix" and sys.platform == "darwin": - from ctypes.macholib.dyld import dyld_find as _dyld_find def find_library(name): + from ctypes.macholib.dyld import dyld_find as _dyld_find possible = ['lib%s.dylib' % name, '%s.dylib' % name, '%s.framework/%s' % (name, name)] diff --git a/lib-python/2.7/curses/wrapper.py b/lib-python/2.7/curses/wrapper.py --- a/lib-python/2.7/curses/wrapper.py +++ b/lib-python/2.7/curses/wrapper.py @@ -43,7 +43,8 @@ return func(stdscr, *args, **kwds) finally: # Set everything back to normal - stdscr.keypad(0) - curses.echo() - curses.nocbreak() - curses.endwin() + if 'stdscr' in locals(): + stdscr.keypad(0) + curses.echo() + curses.nocbreak() + curses.endwin() diff --git a/lib-python/2.7/decimal.py b/lib-python/2.7/decimal.py --- a/lib-python/2.7/decimal.py +++ b/lib-python/2.7/decimal.py @@ -1068,14 +1068,16 @@ if ans: return ans - if not self: - # -Decimal('0') is Decimal('0'), not Decimal('-0') + if context is None: + context = getcontext() + + if not self and context.rounding != ROUND_FLOOR: + # -Decimal('0') is Decimal('0'), not Decimal('-0'), except + # in ROUND_FLOOR rounding mode. ans = self.copy_abs() else: ans = self.copy_negate() - if context is None: - context = getcontext() return ans._fix(context) def __pos__(self, context=None): @@ -1088,14 +1090,15 @@ if ans: return ans - if not self: - # + (-0) = 0 + if context is None: + context = getcontext() + + if not self and context.rounding != ROUND_FLOOR: + # + (-0) = 0, except in ROUND_FLOOR rounding mode. ans = self.copy_abs() else: ans = Decimal(self) - if context is None: - context = getcontext() return ans._fix(context) def __abs__(self, round=True, context=None): @@ -1680,7 +1683,7 @@ self = _dec_from_triple(self._sign, '1', exp_min-1) digits = 0 rounding_method = self._pick_rounding_function[context.rounding] - changed = getattr(self, rounding_method)(digits) + changed = rounding_method(self, digits) coeff = self._int[:digits] or '0' if changed > 0: coeff = str(int(coeff)+1) @@ -1720,8 +1723,6 @@ # here self was representable to begin with; return unchanged return Decimal(self) - _pick_rounding_function = {} - # for each of the rounding functions below: # self is a finite, nonzero Decimal # prec is an integer satisfying 0 <= prec < len(self._int) @@ -1788,6 +1789,17 @@ else: return -self._round_down(prec) + _pick_rounding_function = dict( + ROUND_DOWN = _round_down, + ROUND_UP = _round_up, + ROUND_HALF_UP = _round_half_up, + ROUND_HALF_DOWN = _round_half_down, + ROUND_HALF_EVEN = _round_half_even, + ROUND_CEILING = _round_ceiling, + ROUND_FLOOR = _round_floor, + ROUND_05UP = _round_05up, + ) + def fma(self, other, third, context=None): """Fused multiply-add. @@ -2492,8 +2504,8 @@ if digits < 0: self = _dec_from_triple(self._sign, '1', exp-1) digits = 0 - this_function = getattr(self, self._pick_rounding_function[rounding]) - changed = this_function(digits) + this_function = self._pick_rounding_function[rounding] + changed = this_function(self, digits) coeff = self._int[:digits] or '0' if changed == 1: coeff = str(int(coeff)+1) @@ -3705,18 +3717,6 @@ ##### Context class ####################################################### - -# get rounding method function: -rounding_functions = [name for name in Decimal.__dict__.keys() - if name.startswith('_round_')] -for name in rounding_functions: - # name is like _round_half_even, goes to the global ROUND_HALF_EVEN value. - globalname = name[1:].upper() - val = globals()[globalname] - Decimal._pick_rounding_function[val] = name - -del name, val, globalname, rounding_functions - class _ContextManager(object): """Context manager class to support localcontext(). @@ -5990,7 +5990,7 @@ def _format_align(sign, body, spec): """Given an unpadded, non-aligned numeric string 'body' and sign - string 'sign', add padding and aligment conforming to the given + string 'sign', add padding and alignment conforming to the given format specifier dictionary 'spec' (as produced by parse_format_specifier). diff --git a/lib-python/2.7/difflib.py b/lib-python/2.7/difflib.py --- a/lib-python/2.7/difflib.py +++ b/lib-python/2.7/difflib.py @@ -1140,6 +1140,21 @@ return ch in ws +######################################################################## +### Unified Diff +######################################################################## + +def _format_range_unified(start, stop): + 'Convert range to the "ed" format' + # Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning = start + 1 # lines start numbering with one + length = stop - start + if length == 1: + return '{}'.format(beginning) + if not length: + beginning -= 1 # empty ranges begin at line just before the range + return '{},{}'.format(beginning, length) + def unified_diff(a, b, fromfile='', tofile='', fromfiledate='', tofiledate='', n=3, lineterm='\n'): r""" @@ -1184,25 +1199,45 @@ started = False for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n): if not started: - fromdate = '\t%s' % fromfiledate if fromfiledate else '' - todate = '\t%s' % tofiledate if tofiledate else '' - yield '--- %s%s%s' % (fromfile, fromdate, lineterm) - yield '+++ %s%s%s' % (tofile, todate, lineterm) started = True - i1, i2, j1, j2 = group[0][1], group[-1][2], group[0][3], group[-1][4] - yield "@@ -%d,%d +%d,%d @@%s" % (i1+1, i2-i1, j1+1, j2-j1, lineterm) + fromdate = '\t{}'.format(fromfiledate) if fromfiledate else '' + todate = '\t{}'.format(tofiledate) if tofiledate else '' + yield '--- {}{}{}'.format(fromfile, fromdate, lineterm) + yield '+++ {}{}{}'.format(tofile, todate, lineterm) + + first, last = group[0], group[-1] + file1_range = _format_range_unified(first[1], last[2]) + file2_range = _format_range_unified(first[3], last[4]) + yield '@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm) + for tag, i1, i2, j1, j2 in group: if tag == 'equal': for line in a[i1:i2]: yield ' ' + line continue - if tag == 'replace' or tag == 'delete': + if tag in ('replace', 'delete'): for line in a[i1:i2]: yield '-' + line - if tag == 'replace' or tag == 'insert': + if tag in ('replace', 'insert'): for line in b[j1:j2]: yield '+' + line + +######################################################################## +### Context Diff +######################################################################## + +def _format_range_context(start, stop): + 'Convert range to the "ed" format' + # Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning = start + 1 # lines start numbering with one + length = stop - start + if not length: + beginning -= 1 # empty ranges begin at line just before the range + if length <= 1: + return '{}'.format(beginning) + return '{},{}'.format(beginning, beginning + length - 1) + # See http://www.unix.org/single_unix_specification/ def context_diff(a, b, fromfile='', tofile='', fromfiledate='', tofiledate='', n=3, lineterm='\n'): @@ -1247,38 +1282,36 @@ four """ + prefix = dict(insert='+ ', delete='- ', replace='! ', equal=' ') started = False - prefixmap = {'insert':'+ ', 'delete':'- ', 'replace':'! ', 'equal':' '} for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n): if not started: - fromdate = '\t%s' % fromfiledate if fromfiledate else '' - todate = '\t%s' % tofiledate if tofiledate else '' - yield '*** %s%s%s' % (fromfile, fromdate, lineterm) - yield '--- %s%s%s' % (tofile, todate, lineterm) started = True + fromdate = '\t{}'.format(fromfiledate) if fromfiledate else '' + todate = '\t{}'.format(tofiledate) if tofiledate else '' + yield '*** {}{}{}'.format(fromfile, fromdate, lineterm) + yield '--- {}{}{}'.format(tofile, todate, lineterm) - yield '***************%s' % (lineterm,) - if group[-1][2] - group[0][1] >= 2: - yield '*** %d,%d ****%s' % (group[0][1]+1, group[-1][2], lineterm) - else: - yield '*** %d ****%s' % (group[-1][2], lineterm) - visiblechanges = [e for e in group if e[0] in ('replace', 'delete')] - if visiblechanges: + first, last = group[0], group[-1] + yield '***************' + lineterm + + file1_range = _format_range_context(first[1], last[2]) + yield '*** {} ****{}'.format(file1_range, lineterm) + + if any(tag in ('replace', 'delete') for tag, _, _, _, _ in group): for tag, i1, i2, _, _ in group: if tag != 'insert': for line in a[i1:i2]: - yield prefixmap[tag] + line + yield prefix[tag] + line - if group[-1][4] - group[0][3] >= 2: - yield '--- %d,%d ----%s' % (group[0][3]+1, group[-1][4], lineterm) - else: - yield '--- %d ----%s' % (group[-1][4], lineterm) - visiblechanges = [e for e in group if e[0] in ('replace', 'insert')] - if visiblechanges: + file2_range = _format_range_context(first[3], last[4]) + yield '--- {} ----{}'.format(file2_range, lineterm) + + if any(tag in ('replace', 'insert') for tag, _, _, _, _ in group): for tag, _, _, j1, j2 in group: if tag != 'delete': for line in b[j1:j2]: - yield prefixmap[tag] + line + yield prefix[tag] + line def ndiff(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK): r""" @@ -1714,7 +1747,7 @@ line = line.replace(' ','\0') # expand tabs into spaces line = line.expandtabs(self._tabsize) - # relace spaces from expanded tabs back into tab characters + # replace spaces from expanded tabs back into tab characters # (we'll replace them with markup after we do differencing) line = line.replace(' ','\t') return line.replace('\0',' ').rstrip('\n') diff --git a/lib-python/2.7/distutils/__init__.py b/lib-python/2.7/distutils/__init__.py --- a/lib-python/2.7/distutils/__init__.py +++ b/lib-python/2.7/distutils/__init__.py @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "2.7.1" +__version__ = "2.7.2" #--end constants-- diff --git a/lib-python/2.7/distutils/archive_util.py b/lib-python/2.7/distutils/archive_util.py --- a/lib-python/2.7/distutils/archive_util.py +++ b/lib-python/2.7/distutils/archive_util.py @@ -121,7 +121,7 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0): """Create a zip file from all the files under 'base_dir'. - The output zip file will be named 'base_dir' + ".zip". Uses either the + The output zip file will be named 'base_name' + ".zip". Uses either the "zipfile" Python module (if available) or the InfoZIP "zip" utility (if installed and found on the default search path). If neither tool is available, raises DistutilsExecError. Returns the name of the output zip diff --git a/lib-python/2.7/distutils/cmd.py b/lib-python/2.7/distutils/cmd.py --- a/lib-python/2.7/distutils/cmd.py +++ b/lib-python/2.7/distutils/cmd.py @@ -377,7 +377,7 @@ dry_run=self.dry_run) def move_file (self, src, dst, level=1): - """Move a file respectin dry-run flag.""" + """Move a file respecting dry-run flag.""" return file_util.move_file(src, dst, dry_run = self.dry_run) def spawn (self, cmd, search_path=1, level=1): diff --git a/lib-python/2.7/distutils/command/bdist_wininst.py b/lib-python/2.7/distutils/command/bdist_wininst.py --- a/lib-python/2.7/distutils/command/bdist_wininst.py +++ b/lib-python/2.7/distutils/command/bdist_wininst.py @@ -298,7 +298,8 @@ bitmaplen, # number of bytes in bitmap ) file.write(header) - file.write(open(arcname, "rb").read()) + with open(arcname, "rb") as arcfile: + file.write(arcfile.read()) # create_exe() diff --git a/lib-python/2.7/distutils/command/build_ext.py b/lib-python/2.7/distutils/command/build_ext.py --- a/lib-python/2.7/distutils/command/build_ext.py +++ b/lib-python/2.7/distutils/command/build_ext.py @@ -184,7 +184,7 @@ # the 'libs' directory is for binary installs - we assume that # must be the *native* platform. But we don't really support # cross-compiling via a binary install anyway, so we let it go. - self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs')) + self.library_dirs.append(os.path.join(sys.exec_prefix, 'include')) if self.debug: self.build_temp = os.path.join(self.build_temp, "Debug") else: @@ -192,8 +192,13 @@ # Append the source distribution include and library directories, # this allows distutils on windows to work in the source tree - self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC')) - if MSVC_VERSION == 9: + if 0: + # pypy has no PC directory + self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC')) + if 1: + # pypy has no PCBuild directory + pass + elif MSVC_VERSION == 9: # Use the .lib files for the correct architecture if self.plat_name == 'win32': suffix = '' @@ -207,7 +212,7 @@ elif MSVC_VERSION == 8: self.library_dirs.append(os.path.join(sys.exec_prefix, - 'PC', 'VS8.0', 'win32release')) + 'PC', 'VS8.0')) elif MSVC_VERSION == 7: self.library_dirs.append(os.path.join(sys.exec_prefix, 'PC', 'VS7.1')) @@ -695,24 +700,14 @@ shared extension. On most platforms, this is just 'ext.libraries'; on Windows and OS/2, we add the Python library (eg. python20.dll). """ - # The python library is always needed on Windows. For MSVC, this - # is redundant, since the library is mentioned in a pragma in - # pyconfig.h that MSVC groks. The other Windows compilers all seem - # to need it mentioned explicitly, though, so that's what we do. - # Append '_d' to the python import library on debug builds. + # The python library is always needed on Windows. if sys.platform == "win32": - from distutils.msvccompiler import MSVCCompiler - if not isinstance(self.compiler, MSVCCompiler): - template = "python%d%d" - if self.debug: - template = template + '_d' - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - # don't extend ext.libraries, it may be shared with other - # extensions, it is a reference to the original list - return ext.libraries + [pythonlib] - else: - return ext.libraries + template = "python%d%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] elif sys.platform == "os2emx": # EMX/GCC requires the python library explicitly, and I # believe VACPP does as well (though not confirmed) - AIM Apr01 diff --git a/lib-python/2.7/distutils/command/install.py b/lib-python/2.7/distutils/command/install.py --- a/lib-python/2.7/distutils/command/install.py +++ b/lib-python/2.7/distutils/command/install.py @@ -83,6 +83,13 @@ 'scripts': '$userbase/bin', 'data' : '$userbase', }, + 'pypy': { + 'purelib': '$base/site-packages', + 'platlib': '$base/site-packages', + 'headers': '$base/include', + 'scripts': '$base/bin', + 'data' : '$base', + }, } # The keys to an installation scheme; if any new types of files are to be @@ -467,6 +474,8 @@ def select_scheme (self, name): # it's the caller's problem if they supply a bad name! + if hasattr(sys, 'pypy_version_info'): + name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: attrname = 'install_' + key diff --git a/lib-python/2.7/distutils/command/sdist.py b/lib-python/2.7/distutils/command/sdist.py --- a/lib-python/2.7/distutils/command/sdist.py +++ b/lib-python/2.7/distutils/command/sdist.py @@ -306,17 +306,20 @@ rstrip_ws=1, collapse_join=1) - while 1: - line = template.readline() - if line is None: # end of file - break + try: + while 1: + line = template.readline() + if line is None: # end of file + break - try: - self.filelist.process_template_line(line) - except DistutilsTemplateError, msg: - self.warn("%s, line %d: %s" % (template.filename, - template.current_line, - msg)) + try: + self.filelist.process_template_line(line) + except DistutilsTemplateError, msg: + self.warn("%s, line %d: %s" % (template.filename, + template.current_line, + msg)) + finally: + template.close() def prune_file_list(self): """Prune off branches that might slip into the file list as created diff --git a/lib-python/2.7/distutils/command/upload.py b/lib-python/2.7/distutils/command/upload.py --- a/lib-python/2.7/distutils/command/upload.py +++ b/lib-python/2.7/distutils/command/upload.py @@ -176,6 +176,9 @@ result = urlopen(request) status = result.getcode() reason = result.msg + if self.show_response: + msg = '\n'.join(('-' * 75, r.read(), '-' * 75)) + self.announce(msg, log.INFO) except socket.error, e: self.announce(str(e), log.ERROR) return @@ -189,6 +192,3 @@ else: self.announce('Upload failed (%s): %s' % (status, reason), log.ERROR) - if self.show_response: - msg = '\n'.join(('-' * 75, r.read(), '-' * 75)) - self.announce(msg, log.INFO) diff --git a/lib-python/2.7/distutils/cygwinccompiler.py b/lib-python/2.7/distutils/cygwinccompiler.py --- a/lib-python/2.7/distutils/cygwinccompiler.py +++ b/lib-python/2.7/distutils/cygwinccompiler.py @@ -75,6 +75,9 @@ elif msc_ver == '1500': # VS2008 / MSVC 9.0 return ['msvcr90'] + elif msc_ver == '1600': + # VS2010 / MSVC 10.0 + return ['msvcr100'] else: raise ValueError("Unknown MS Compiler version %s " % msc_ver) diff --git a/lib-python/2.7/distutils/msvc9compiler.py b/lib-python/2.7/distutils/msvc9compiler.py --- a/lib-python/2.7/distutils/msvc9compiler.py +++ b/lib-python/2.7/distutils/msvc9compiler.py @@ -648,6 +648,7 @@ temp_manifest = os.path.join( build_temp, os.path.basename(output_filename) + ".manifest") + ld_args.append('/MANIFEST') ld_args.append('/MANIFESTFILE:' + temp_manifest) if extra_preargs: diff --git a/lib-python/2.7/distutils/spawn.py b/lib-python/2.7/distutils/spawn.py --- a/lib-python/2.7/distutils/spawn.py +++ b/lib-python/2.7/distutils/spawn.py @@ -58,7 +58,6 @@ def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0): executable = cmd[0] - cmd = _nt_quote_args(cmd) if search_path: # either we find one or it stays the same executable = find_executable(executable) or executable @@ -66,7 +65,8 @@ if not dry_run: # spawn for NT requires a full path to the .exe try: - rc = os.spawnv(os.P_WAIT, executable, cmd) + import subprocess + rc = subprocess.call(cmd) except OSError, exc: # this seems to happen when the command isn't found raise DistutilsExecError, \ diff --git a/lib-python/2.7/distutils/sysconfig.py b/lib-python/2.7/distutils/sysconfig.py --- a/lib-python/2.7/distutils/sysconfig.py +++ b/lib-python/2.7/distutils/sysconfig.py @@ -9,563 +9,21 @@ Email: """ -__revision__ = "$Id$" +__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $" -import os -import re -import string import sys -from distutils.errors import DistutilsPlatformError -# These are needed in a couple of spots, so just compute them once. -PREFIX = os.path.normpath(sys.prefix) -EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +# The content of this file is redirected from +# sysconfig_cpython or sysconfig_pypy. -# Path to the base directory of the project. On Windows the binary may -# live in project/PCBuild9. If we're dealing with an x64 Windows build, -# it'll live in project/PCbuild/amd64. -project_base = os.path.dirname(os.path.abspath(sys.executable)) -if os.name == "nt" and "pcbuild" in project_base[-8:].lower(): - project_base = os.path.abspath(os.path.join(project_base, os.path.pardir)) -# PC/VS7.1 -if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower(): - project_base = os.path.abspath(os.path.join(project_base, os.path.pardir, - os.path.pardir)) -# PC/AMD64 -if os.name == "nt" and "\\pcbuild\\amd64" in project_base[-14:].lower(): - project_base = os.path.abspath(os.path.join(project_base, os.path.pardir, - os.path.pardir)) +if '__pypy__' in sys.builtin_module_names: + from distutils.sysconfig_pypy import * + from distutils.sysconfig_pypy import _config_vars # needed by setuptools + from distutils.sysconfig_pypy import _variable_rx # read_setup_file() +else: + from distutils.sysconfig_cpython import * + from distutils.sysconfig_cpython import _config_vars # needed by setuptools + from distutils.sysconfig_cpython import _variable_rx # read_setup_file() -# python_build: (Boolean) if true, we're either building Python or -# building an extension with an un-installed Python, so we use -# different (hard-wired) directories. -# Setup.local is available for Makefile builds including VPATH builds, -# Setup.dist is available on Windows -def _python_build(): - for fn in ("Setup.dist", "Setup.local"): - if os.path.isfile(os.path.join(project_base, "Modules", fn)): - return True - return False -python_build = _python_build() - -def get_python_version(): - """Return a string containing the major and minor Python version, - leaving off the patchlevel. Sample return values could be '1.5' - or '2.2'. - """ - return sys.version[:3] - - -def get_python_inc(plat_specific=0, prefix=None): - """Return the directory containing installed Python header files. - - If 'plat_specific' is false (the default), this is the path to the - non-platform-specific header files, i.e. Python.h and so on; - otherwise, this is the path to platform-specific header files - (namely pyconfig.h). - - If 'prefix' is supplied, use it instead of sys.prefix or - sys.exec_prefix -- i.e., ignore 'plat_specific'. - """ - if prefix is None: - prefix = plat_specific and EXEC_PREFIX or PREFIX - - if os.name == "posix": - if python_build: - buildir = os.path.dirname(sys.executable) - if plat_specific: - # python.h is located in the buildir - inc_dir = buildir - else: - # the source dir is relative to the buildir - srcdir = os.path.abspath(os.path.join(buildir, - get_config_var('srcdir'))) - # Include is located in the srcdir - inc_dir = os.path.join(srcdir, "Include") - return inc_dir - return os.path.join(prefix, "include", "python" + get_python_version()) - elif os.name == "nt": - return os.path.join(prefix, "include") - elif os.name == "os2": - return os.path.join(prefix, "Include") - else: - raise DistutilsPlatformError( - "I don't know where Python installs its C header files " - "on platform '%s'" % os.name) - - -def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): - """Return the directory containing the Python library (standard or - site additions). - - If 'plat_specific' is true, return the directory containing - platform-specific modules, i.e. any module from a non-pure-Python - module distribution; otherwise, return the platform-shared library - directory. If 'standard_lib' is true, return the directory - containing standard Python library modules; otherwise, return the - directory for site-specific modules. - - If 'prefix' is supplied, use it instead of sys.prefix or - sys.exec_prefix -- i.e., ignore 'plat_specific'. - """ - if prefix is None: - prefix = plat_specific and EXEC_PREFIX or PREFIX - - if os.name == "posix": - libpython = os.path.join(prefix, - "lib", "python" + get_python_version()) - if standard_lib: - return libpython - else: - return os.path.join(libpython, "site-packages") - - elif os.name == "nt": - if standard_lib: - return os.path.join(prefix, "Lib") - else: - if get_python_version() < "2.2": - return prefix - else: - return os.path.join(prefix, "Lib", "site-packages") - - elif os.name == "os2": - if standard_lib: - return os.path.join(prefix, "Lib") - else: - return os.path.join(prefix, "Lib", "site-packages") - - else: - raise DistutilsPlatformError( - "I don't know where Python installs its library " - "on platform '%s'" % os.name) - - -def customize_compiler(compiler): - """Do any platform-specific customization of a CCompiler instance. - - Mainly needed on Unix, so we can plug in the information that - varies across Unices and is stored in Python's Makefile. - """ - if compiler.compiler_type == "unix": - (cc, cxx, opt, cflags, ccshared, ldshared, so_ext) = \ - get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', - 'CCSHARED', 'LDSHARED', 'SO') - - if 'CC' in os.environ: - cc = os.environ['CC'] - if 'CXX' in os.environ: - cxx = os.environ['CXX'] - if 'LDSHARED' in os.environ: - ldshared = os.environ['LDSHARED'] - if 'CPP' in os.environ: - cpp = os.environ['CPP'] - else: - cpp = cc + " -E" # not always - if 'LDFLAGS' in os.environ: - ldshared = ldshared + ' ' + os.environ['LDFLAGS'] - if 'CFLAGS' in os.environ: - cflags = opt + ' ' + os.environ['CFLAGS'] - ldshared = ldshared + ' ' + os.environ['CFLAGS'] - if 'CPPFLAGS' in os.environ: - cpp = cpp + ' ' + os.environ['CPPFLAGS'] - cflags = cflags + ' ' + os.environ['CPPFLAGS'] - ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] - - cc_cmd = cc + ' ' + cflags - compiler.set_executables( - preprocessor=cpp, - compiler=cc_cmd, - compiler_so=cc_cmd + ' ' + ccshared, - compiler_cxx=cxx, - linker_so=ldshared, - linker_exe=cc) - - compiler.shared_lib_extension = so_ext - - -def get_config_h_filename(): - """Return full pathname of installed pyconfig.h file.""" - if python_build: - if os.name == "nt": - inc_dir = os.path.join(project_base, "PC") - else: - inc_dir = project_base - else: - inc_dir = get_python_inc(plat_specific=1) - if get_python_version() < '2.2': - config_h = 'config.h' - else: - # The name of the config.h file changed in 2.2 - config_h = 'pyconfig.h' - return os.path.join(inc_dir, config_h) - - -def get_makefile_filename(): - """Return full pathname of installed Makefile from the Python build.""" - if python_build: - return os.path.join(os.path.dirname(sys.executable), "Makefile") - lib_dir = get_python_lib(plat_specific=1, standard_lib=1) - return os.path.join(lib_dir, "config", "Makefile") - - -def parse_config_h(fp, g=None): - """Parse a config.h-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - if g is None: - g = {} - define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") - undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") - # - while 1: - line = fp.readline() - if not line: - break - m = define_rx.match(line) - if m: - n, v = m.group(1, 2) - try: v = int(v) - except ValueError: pass - g[n] = v - else: - m = undef_rx.match(line) - if m: - g[m.group(1)] = 0 - return g - - -# Regexes needed for parsing Makefile (and similar syntaxes, -# like old-style Setup files). -_variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") -_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") -_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") - -def parse_makefile(fn, g=None): - """Parse a Makefile-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - from distutils.text_file import TextFile - fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1) - - if g is None: - g = {} - done = {} - notdone = {} - - while 1: - line = fp.readline() - if line is None: # eof - break - m = _variable_rx.match(line) - if m: - n, v = m.group(1, 2) - v = v.strip() - # `$$' is a literal `$' in make - tmpv = v.replace('$$', '') - - if "$" in tmpv: - notdone[n] = v - else: - try: - v = int(v) - except ValueError: - # insert literal `$' - done[n] = v.replace('$$', '$') - else: - done[n] = v - - # do variable interpolation here - while notdone: - for name in notdone.keys(): - value = notdone[name] - m = _findvar1_rx.search(value) or _findvar2_rx.search(value) - if m: - n = m.group(1) - found = True - if n in done: - item = str(done[n]) - elif n in notdone: - # get it on a subsequent round - found = False - elif n in os.environ: - # do it like make: fall back to environment - item = os.environ[n] - else: - done[n] = item = "" - if found: - after = value[m.end():] - value = value[:m.start()] + item + after - if "$" in after: - notdone[name] = value - else: - try: value = int(value) - except ValueError: - done[name] = value.strip() - else: - done[name] = value - del notdone[name] - else: - # bogus variable reference; just drop it since we can't deal - del notdone[name] - - fp.close() - - # strip spurious spaces - for k, v in done.items(): - if isinstance(v, str): - done[k] = v.strip() - - # save the results in the global dictionary - g.update(done) - return g - - -def expand_makefile_vars(s, vars): - """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in - 'string' according to 'vars' (a dictionary mapping variable names to - values). Variables not present in 'vars' are silently expanded to the - empty string. The variable values in 'vars' should not contain further - variable expansions; if 'vars' is the output of 'parse_makefile()', - you're fine. Returns a variable-expanded version of 's'. - """ - - # This algorithm does multiple expansion, so if vars['foo'] contains - # "${bar}", it will expand ${foo} to ${bar}, and then expand - # ${bar}... and so forth. This is fine as long as 'vars' comes from - # 'parse_makefile()', which takes care of such expansions eagerly, - # according to make's variable expansion semantics. - - while 1: - m = _findvar1_rx.search(s) or _findvar2_rx.search(s) - if m: - (beg, end) = m.span() - s = s[0:beg] + vars.get(m.group(1)) + s[end:] - else: - break - return s - - -_config_vars = None - -def _init_posix(): - """Initialize the module as appropriate for POSIX systems.""" - g = {} - # load the installed Makefile: - try: - filename = get_makefile_filename() - parse_makefile(filename, g) - except IOError, msg: - my_msg = "invalid Python installation: unable to open %s" % filename - if hasattr(msg, "strerror"): - my_msg = my_msg + " (%s)" % msg.strerror - - raise DistutilsPlatformError(my_msg) - - # load the installed pyconfig.h: - try: - filename = get_config_h_filename() - parse_config_h(file(filename), g) - except IOError, msg: - my_msg = "invalid Python installation: unable to open %s" % filename - if hasattr(msg, "strerror"): - my_msg = my_msg + " (%s)" % msg.strerror - - raise DistutilsPlatformError(my_msg) - - # On MacOSX we need to check the setting of the environment variable - # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so - # it needs to be compatible. - # If it isn't set we set it to the configure-time value - if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in g: - cfg_target = g['MACOSX_DEPLOYMENT_TARGET'] - cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '') - if cur_target == '': - cur_target = cfg_target - os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target) - elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')): - my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure' - % (cur_target, cfg_target)) - raise DistutilsPlatformError(my_msg) - - # On AIX, there are wrong paths to the linker scripts in the Makefile - # -- these paths are relative to the Python source, but when installed - # the scripts are in another directory. - if python_build: - g['LDSHARED'] = g['BLDSHARED'] - - elif get_python_version() < '2.1': - # The following two branches are for 1.5.2 compatibility. - if sys.platform == 'aix4': # what about AIX 3.x ? - # Linker script is in the config directory, not in Modules as the - # Makefile says. - python_lib = get_python_lib(standard_lib=1) - ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix') - python_exp = os.path.join(python_lib, 'config', 'python.exp') - - g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp) - - elif sys.platform == 'beos': - # Linker script is in the config directory. In the Makefile it is - # relative to the srcdir, which after installation no longer makes - # sense. - python_lib = get_python_lib(standard_lib=1) - linkerscript_path = string.split(g['LDSHARED'])[0] - linkerscript_name = os.path.basename(linkerscript_path) - linkerscript = os.path.join(python_lib, 'config', - linkerscript_name) - - # XXX this isn't the right place to do this: adding the Python - # library to the link, if needed, should be in the "build_ext" - # command. (It's also needed for non-MS compilers on Windows, and - # it's taken care of for them by the 'build_ext.get_libraries()' - # method.) - g['LDSHARED'] = ("%s -L%s/lib -lpython%s" % - (linkerscript, PREFIX, get_python_version())) - - global _config_vars - _config_vars = g - - -def _init_nt(): - """Initialize the module as appropriate for NT""" - g = {} - # set basic install directories - g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) - g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) - - # XXX hmmm.. a normal install puts include files here - g['INCLUDEPY'] = get_python_inc(plat_specific=0) - - g['SO'] = '.pyd' - g['EXE'] = ".exe" - g['VERSION'] = get_python_version().replace(".", "") - g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable)) - - global _config_vars - _config_vars = g - - -def _init_os2(): - """Initialize the module as appropriate for OS/2""" - g = {} - # set basic install directories - g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) - g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) - - # XXX hmmm.. a normal install puts include files here - g['INCLUDEPY'] = get_python_inc(plat_specific=0) - - g['SO'] = '.pyd' - g['EXE'] = ".exe" - - global _config_vars - _config_vars = g - - -def get_config_vars(*args): - """With no arguments, return a dictionary of all configuration - variables relevant for the current platform. Generally this includes - everything needed to build extensions and install both pure modules and - extensions. On Unix, this means every variable defined in Python's - installed Makefile; on Windows and Mac OS it's a much smaller set. - - With arguments, return a list of values that result from looking up - each argument in the configuration variable dictionary. - """ - global _config_vars - if _config_vars is None: - func = globals().get("_init_" + os.name) - if func: - func() - else: - _config_vars = {} - - # Normalized versions of prefix and exec_prefix are handy to have; - # in fact, these are the standard versions used most places in the - # Distutils. - _config_vars['prefix'] = PREFIX - _config_vars['exec_prefix'] = EXEC_PREFIX - - if sys.platform == 'darwin': - kernel_version = os.uname()[2] # Kernel version (8.4.3) - major_version = int(kernel_version.split('.')[0]) - - if major_version < 8: - # On Mac OS X before 10.4, check if -arch and -isysroot - # are in CFLAGS or LDFLAGS and remove them if they are. - # This is needed when building extensions on a 10.3 system - # using a universal build of python. - for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - flags = _config_vars[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = re.sub('-isysroot [^ \t]*', ' ', flags) - _config_vars[key] = flags - - else: - - # Allow the user to override the architecture flags using - # an environment variable. - # NOTE: This name was introduced by Apple in OSX 10.5 and - # is used by several scripting languages distributed with - # that OS release. - - if 'ARCHFLAGS' in os.environ: - arch = os.environ['ARCHFLAGS'] - for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - - flags = _config_vars[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = flags + ' ' + arch - _config_vars[key] = flags - - # If we're on OSX 10.5 or later and the user tries to - # compiles an extension using an SDK that is not present - # on the current machine it is better to not use an SDK - # than to fail. - # - # The major usecase for this is users using a Python.org - # binary installer on OSX 10.6: that installer uses - # the 10.4u SDK, but that SDK is not installed by default - # when you install Xcode. - # - m = re.search('-isysroot\s+(\S+)', _config_vars['CFLAGS']) - if m is not None: - sdk = m.group(1) - if not os.path.exists(sdk): - for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - - flags = _config_vars[key] - flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags) - _config_vars[key] = flags - - if args: - vals = [] - for name in args: - vals.append(_config_vars.get(name)) - return vals - else: - return _config_vars - -def get_config_var(name): - """Return the value of a single variable using the dictionary - returned by 'get_config_vars()'. Equivalent to - get_config_vars().get(name) - """ - return get_config_vars().get(name) diff --git a/lib-python/2.7/distutils/sysconfig_cpython.py b/lib-python/2.7/distutils/sysconfig_cpython.py new file mode 100644 --- /dev/null +++ b/lib-python/2.7/distutils/sysconfig_cpython.py @@ -0,0 +1,571 @@ +"""Provide access to Python's configuration information. The specific +configuration variables available depend heavily on the platform and +configuration. The values may be retrieved using +get_config_var(name), and the list of variables is available via +get_config_vars().keys(). Additional convenience functions are also +available. + +Written by: Fred L. Drake, Jr. +Email: +""" + +__revision__ = "$Id$" + +import os +import re +import string +import sys + +from distutils.errors import DistutilsPlatformError + +# These are needed in a couple of spots, so just compute them once. +PREFIX = os.path.normpath(sys.prefix) +EXEC_PREFIX = os.path.normpath(sys.exec_prefix) + +# Path to the base directory of the project. On Windows the binary may +# live in project/PCBuild9. If we're dealing with an x64 Windows build, +# it'll live in project/PCbuild/amd64. +project_base = os.path.dirname(os.path.abspath(sys.executable)) +if os.name == "nt" and "pcbuild" in project_base[-8:].lower(): + project_base = os.path.abspath(os.path.join(project_base, os.path.pardir)) +# PC/VS7.1 +if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower(): + project_base = os.path.abspath(os.path.join(project_base, os.path.pardir, + os.path.pardir)) +# PC/AMD64 +if os.name == "nt" and "\\pcbuild\\amd64" in project_base[-14:].lower(): + project_base = os.path.abspath(os.path.join(project_base, os.path.pardir, + os.path.pardir)) + +# python_build: (Boolean) if true, we're either building Python or +# building an extension with an un-installed Python, so we use +# different (hard-wired) directories. +# Setup.local is available for Makefile builds including VPATH builds, +# Setup.dist is available on Windows +def _python_build(): + for fn in ("Setup.dist", "Setup.local"): + if os.path.isfile(os.path.join(project_base, "Modules", fn)): + return True + return False +python_build = _python_build() + + +def get_python_version(): + """Return a string containing the major and minor Python version, + leaving off the patchlevel. Sample return values could be '1.5' + or '2.2'. + """ + return sys.version[:3] + + +def get_python_inc(plat_specific=0, prefix=None): + """Return the directory containing installed Python header files. + + If 'plat_specific' is false (the default), this is the path to the + non-platform-specific header files, i.e. Python.h and so on; + otherwise, this is the path to platform-specific header files + (namely pyconfig.h). + + If 'prefix' is supplied, use it instead of sys.prefix or + sys.exec_prefix -- i.e., ignore 'plat_specific'. + """ + if prefix is None: + prefix = plat_specific and EXEC_PREFIX or PREFIX + + if os.name == "posix": + if python_build: + buildir = os.path.dirname(sys.executable) + if plat_specific: + # python.h is located in the buildir + inc_dir = buildir + else: + # the source dir is relative to the buildir + srcdir = os.path.abspath(os.path.join(buildir, + get_config_var('srcdir'))) + # Include is located in the srcdir + inc_dir = os.path.join(srcdir, "Include") + return inc_dir + return os.path.join(prefix, "include", "python" + get_python_version()) + elif os.name == "nt": + return os.path.join(prefix, "include") + elif os.name == "os2": + return os.path.join(prefix, "Include") + else: + raise DistutilsPlatformError( + "I don't know where Python installs its C header files " + "on platform '%s'" % os.name) + + +def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): + """Return the directory containing the Python library (standard or + site additions). + + If 'plat_specific' is true, return the directory containing + platform-specific modules, i.e. any module from a non-pure-Python + module distribution; otherwise, return the platform-shared library + directory. If 'standard_lib' is true, return the directory + containing standard Python library modules; otherwise, return the + directory for site-specific modules. + + If 'prefix' is supplied, use it instead of sys.prefix or + sys.exec_prefix -- i.e., ignore 'plat_specific'. + """ + if prefix is None: + prefix = plat_specific and EXEC_PREFIX or PREFIX + + if os.name == "posix": + libpython = os.path.join(prefix, + "lib", "python" + get_python_version()) + if standard_lib: + return libpython + else: + return os.path.join(libpython, "site-packages") + + elif os.name == "nt": + if standard_lib: + return os.path.join(prefix, "Lib") + else: + if get_python_version() < "2.2": + return prefix + else: + return os.path.join(prefix, "Lib", "site-packages") + + elif os.name == "os2": + if standard_lib: + return os.path.join(prefix, "Lib") + else: + return os.path.join(prefix, "Lib", "site-packages") + + else: + raise DistutilsPlatformError( + "I don't know where Python installs its library " + "on platform '%s'" % os.name) + + +def customize_compiler(compiler): + """Do any platform-specific customization of a CCompiler instance. + + Mainly needed on Unix, so we can plug in the information that + varies across Unices and is stored in Python's Makefile. + """ + if compiler.compiler_type == "unix": + (cc, cxx, opt, cflags, ccshared, ldshared, so_ext) = \ + get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', + 'CCSHARED', 'LDSHARED', 'SO') + + if 'CC' in os.environ: + cc = os.environ['CC'] + if 'CXX' in os.environ: + cxx = os.environ['CXX'] + if 'LDSHARED' in os.environ: + ldshared = os.environ['LDSHARED'] + if 'CPP' in os.environ: + cpp = os.environ['CPP'] + else: + cpp = cc + " -E" # not always + if 'LDFLAGS' in os.environ: + ldshared = ldshared + ' ' + os.environ['LDFLAGS'] + if 'CFLAGS' in os.environ: + cflags = opt + ' ' + os.environ['CFLAGS'] + ldshared = ldshared + ' ' + os.environ['CFLAGS'] + if 'CPPFLAGS' in os.environ: + cpp = cpp + ' ' + os.environ['CPPFLAGS'] + cflags = cflags + ' ' + os.environ['CPPFLAGS'] + ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] + + cc_cmd = cc + ' ' + cflags + compiler.set_executables( + preprocessor=cpp, + compiler=cc_cmd, + compiler_so=cc_cmd + ' ' + ccshared, + compiler_cxx=cxx, + linker_so=ldshared, + linker_exe=cc) + + compiler.shared_lib_extension = so_ext + + +def get_config_h_filename(): + """Return full pathname of installed pyconfig.h file.""" + if python_build: + if os.name == "nt": + inc_dir = os.path.join(project_base, "PC") + else: + inc_dir = project_base + else: + inc_dir = get_python_inc(plat_specific=1) + if get_python_version() < '2.2': + config_h = 'config.h' + else: + # The name of the config.h file changed in 2.2 + config_h = 'pyconfig.h' + return os.path.join(inc_dir, config_h) + + +def get_makefile_filename(): + """Return full pathname of installed Makefile from the Python build.""" + if python_build: + return os.path.join(os.path.dirname(sys.executable), "Makefile") + lib_dir = get_python_lib(plat_specific=1, standard_lib=1) + return os.path.join(lib_dir, "config", "Makefile") + + +def parse_config_h(fp, g=None): + """Parse a config.h-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + if g is None: + g = {} + define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") + undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") + # + while 1: + line = fp.readline() + if not line: + break + m = define_rx.match(line) + if m: + n, v = m.group(1, 2) + try: v = int(v) + except ValueError: pass + g[n] = v + else: + m = undef_rx.match(line) + if m: + g[m.group(1)] = 0 + return g + + +# Regexes needed for parsing Makefile (and similar syntaxes, +# like old-style Setup files). +_variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") +_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") +_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") + +def parse_makefile(fn, g=None): + """Parse a Makefile-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + from distutils.text_file import TextFile + fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1) + + if g is None: + g = {} + done = {} + notdone = {} + + while 1: + line = fp.readline() + if line is None: # eof + break + m = _variable_rx.match(line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # do variable interpolation here + while notdone: + for name in notdone.keys(): + value = notdone[name] + m = _findvar1_rx.search(value) or _findvar2_rx.search(value) + if m: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + else: + done[n] = item = "" + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + del notdone[name] + else: + # bogus variable reference; just drop it since we can't deal + del notdone[name] + + fp.close() + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + g.update(done) + return g + + +def expand_makefile_vars(s, vars): + """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in + 'string' according to 'vars' (a dictionary mapping variable names to + values). Variables not present in 'vars' are silently expanded to the + empty string. The variable values in 'vars' should not contain further + variable expansions; if 'vars' is the output of 'parse_makefile()', + you're fine. Returns a variable-expanded version of 's'. + """ + + # This algorithm does multiple expansion, so if vars['foo'] contains + # "${bar}", it will expand ${foo} to ${bar}, and then expand + # ${bar}... and so forth. This is fine as long as 'vars' comes from + # 'parse_makefile()', which takes care of such expansions eagerly, + # according to make's variable expansion semantics. + + while 1: + m = _findvar1_rx.search(s) or _findvar2_rx.search(s) + if m: + (beg, end) = m.span() + s = s[0:beg] + vars.get(m.group(1)) + s[end:] + else: + break + return s + + +_config_vars = None + +def _init_posix(): + """Initialize the module as appropriate for POSIX systems.""" + g = {} + # load the installed Makefile: + try: + filename = get_makefile_filename() + parse_makefile(filename, g) + except IOError, msg: + my_msg = "invalid Python installation: unable to open %s" % filename + if hasattr(msg, "strerror"): + my_msg = my_msg + " (%s)" % msg.strerror + + raise DistutilsPlatformError(my_msg) + + # load the installed pyconfig.h: + try: + filename = get_config_h_filename() + parse_config_h(file(filename), g) + except IOError, msg: + my_msg = "invalid Python installation: unable to open %s" % filename + if hasattr(msg, "strerror"): + my_msg = my_msg + " (%s)" % msg.strerror + + raise DistutilsPlatformError(my_msg) + + # On MacOSX we need to check the setting of the environment variable + # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so + # it needs to be compatible. + # If it isn't set we set it to the configure-time value + if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in g: + cfg_target = g['MACOSX_DEPLOYMENT_TARGET'] + cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '') + if cur_target == '': + cur_target = cfg_target + os.environ['MACOSX_DEPLOYMENT_TARGET'] = cfg_target + elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')): + my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure' + % (cur_target, cfg_target)) + raise DistutilsPlatformError(my_msg) + + # On AIX, there are wrong paths to the linker scripts in the Makefile + # -- these paths are relative to the Python source, but when installed + # the scripts are in another directory. + if python_build: + g['LDSHARED'] = g['BLDSHARED'] + + elif get_python_version() < '2.1': + # The following two branches are for 1.5.2 compatibility. + if sys.platform == 'aix4': # what about AIX 3.x ? + # Linker script is in the config directory, not in Modules as the + # Makefile says. + python_lib = get_python_lib(standard_lib=1) + ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix') + python_exp = os.path.join(python_lib, 'config', 'python.exp') + + g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp) + + elif sys.platform == 'beos': + # Linker script is in the config directory. In the Makefile it is + # relative to the srcdir, which after installation no longer makes + # sense. + python_lib = get_python_lib(standard_lib=1) + linkerscript_path = string.split(g['LDSHARED'])[0] + linkerscript_name = os.path.basename(linkerscript_path) + linkerscript = os.path.join(python_lib, 'config', + linkerscript_name) + + # XXX this isn't the right place to do this: adding the Python + # library to the link, if needed, should be in the "build_ext" + # command. (It's also needed for non-MS compilers on Windows, and + # it's taken care of for them by the 'build_ext.get_libraries()' + # method.) + g['LDSHARED'] = ("%s -L%s/lib -lpython%s" % + (linkerscript, PREFIX, get_python_version())) + + global _config_vars + _config_vars = g + + +def _init_nt(): + """Initialize the module as appropriate for NT""" + g = {} + # set basic install directories + g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) + g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) + + # XXX hmmm.. a normal install puts include files here + g['INCLUDEPY'] = get_python_inc(plat_specific=0) + + g['SO'] = '.pyd' + g['EXE'] = ".exe" + g['VERSION'] = get_python_version().replace(".", "") + g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable)) + + global _config_vars + _config_vars = g + + +def _init_os2(): + """Initialize the module as appropriate for OS/2""" + g = {} + # set basic install directories + g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) + g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) + + # XXX hmmm.. a normal install puts include files here + g['INCLUDEPY'] = get_python_inc(plat_specific=0) + + g['SO'] = '.pyd' + g['EXE'] = ".exe" + + global _config_vars + _config_vars = g + + +def get_config_vars(*args): + """With no arguments, return a dictionary of all configuration + variables relevant for the current platform. Generally this includes + everything needed to build extensions and install both pure modules and + extensions. On Unix, this means every variable defined in Python's + installed Makefile; on Windows and Mac OS it's a much smaller set. + + With arguments, return a list of values that result from looking up + each argument in the configuration variable dictionary. + """ + global _config_vars + if _config_vars is None: + func = globals().get("_init_" + os.name) + if func: + func() + else: + _config_vars = {} + + # Normalized versions of prefix and exec_prefix are handy to have; + # in fact, these are the standard versions used most places in the + # Distutils. + _config_vars['prefix'] = PREFIX + _config_vars['exec_prefix'] = EXEC_PREFIX + + if sys.platform == 'darwin': + kernel_version = os.uname()[2] # Kernel version (8.4.3) + major_version = int(kernel_version.split('.')[0]) + + if major_version < 8: + # On Mac OS X before 10.4, check if -arch and -isysroot + # are in CFLAGS or LDFLAGS and remove them if they are. + # This is needed when building extensions on a 10.3 system + # using a universal build of python. + for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + flags = _config_vars[key] + flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = re.sub('-isysroot [^ \t]*', ' ', flags) + _config_vars[key] = flags + + else: + + # Allow the user to override the architecture flags using + # an environment variable. + # NOTE: This name was introduced by Apple in OSX 10.5 and + # is used by several scripting languages distributed with + # that OS release. + + if 'ARCHFLAGS' in os.environ: + arch = os.environ['ARCHFLAGS'] + for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _config_vars[key] + flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = flags + ' ' + arch + _config_vars[key] = flags + + # If we're on OSX 10.5 or later and the user tries to + # compiles an extension using an SDK that is not present + # on the current machine it is better to not use an SDK + # than to fail. + # + # The major usecase for this is users using a Python.org + # binary installer on OSX 10.6: that installer uses + # the 10.4u SDK, but that SDK is not installed by default + # when you install Xcode. + # + m = re.search('-isysroot\s+(\S+)', _config_vars['CFLAGS']) + if m is not None: + sdk = m.group(1) + if not os.path.exists(sdk): + for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _config_vars[key] + flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags) + _config_vars[key] = flags + + if args: + vals = [] + for name in args: + vals.append(_config_vars.get(name)) + return vals + else: + return _config_vars + +def get_config_var(name): + """Return the value of a single variable using the dictionary + returned by 'get_config_vars()'. Equivalent to + get_config_vars().get(name) + """ + return get_config_vars().get(name) diff --git a/lib-python/modified-2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py rename from lib-python/modified-2.7/distutils/sysconfig_pypy.py rename to lib-python/2.7/distutils/sysconfig_pypy.py --- a/lib-python/modified-2.7/distutils/sysconfig_pypy.py +++ b/lib-python/2.7/distutils/sysconfig_pypy.py @@ -60,6 +60,7 @@ g['EXE'] = "" g['SO'] = _get_so_extension() or ".so" g['SOABI'] = g['SO'].rsplit('.')[0] + g['LIBDIR'] = os.path.join(sys.prefix, 'lib') global _config_vars _config_vars = g diff --git a/lib-python/2.7/distutils/tests/__init__.py b/lib-python/2.7/distutils/tests/__init__.py --- a/lib-python/2.7/distutils/tests/__init__.py +++ b/lib-python/2.7/distutils/tests/__init__.py @@ -15,9 +15,10 @@ import os import sys import unittest +from test.test_support import run_unittest -here = os.path.dirname(__file__) +here = os.path.dirname(__file__) or os.curdir def test_suite(): @@ -32,4 +33,4 @@ if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_archive_util.py b/lib-python/2.7/distutils/tests/test_archive_util.py --- a/lib-python/2.7/distutils/tests/test_archive_util.py +++ b/lib-python/2.7/distutils/tests/test_archive_util.py @@ -12,7 +12,7 @@ ARCHIVE_FORMATS) from distutils.spawn import find_executable, spawn from distutils.tests import support -from test.test_support import check_warnings +from test.test_support import check_warnings, run_unittest try: import grp @@ -281,4 +281,4 @@ return unittest.makeSuite(ArchiveUtilTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_bdist_msi.py b/lib-python/2.7/distutils/tests/test_bdist_msi.py --- a/lib-python/2.7/distutils/tests/test_bdist_msi.py +++ b/lib-python/2.7/distutils/tests/test_bdist_msi.py @@ -11,7 +11,7 @@ support.LoggingSilencer, unittest.TestCase): - def test_minial(self): + def test_minimal(self): # minimal test XXX need more tests from distutils.command.bdist_msi import bdist_msi pkg_pth, dist = self.create_dist() diff --git a/lib-python/2.7/distutils/tests/test_build.py b/lib-python/2.7/distutils/tests/test_build.py --- a/lib-python/2.7/distutils/tests/test_build.py +++ b/lib-python/2.7/distutils/tests/test_build.py @@ -2,6 +2,7 @@ import unittest import os import sys +from test.test_support import run_unittest from distutils.command.build import build from distutils.tests import support @@ -51,4 +52,4 @@ return unittest.makeSuite(BuildTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_build_clib.py b/lib-python/2.7/distutils/tests/test_build_clib.py --- a/lib-python/2.7/distutils/tests/test_build_clib.py +++ b/lib-python/2.7/distutils/tests/test_build_clib.py @@ -3,6 +3,8 @@ import os import sys +from test.test_support import run_unittest + from distutils.command.build_clib import build_clib from distutils.errors import DistutilsSetupError from distutils.tests import support @@ -140,4 +142,4 @@ return unittest.makeSuite(BuildCLibTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_build_ext.py b/lib-python/2.7/distutils/tests/test_build_ext.py --- a/lib-python/2.7/distutils/tests/test_build_ext.py +++ b/lib-python/2.7/distutils/tests/test_build_ext.py @@ -3,12 +3,13 @@ import tempfile import shutil from StringIO import StringIO +import textwrap from distutils.core import Extension, Distribution from distutils.command.build_ext import build_ext from distutils import sysconfig from distutils.tests import support -from distutils.errors import DistutilsSetupError +from distutils.errors import DistutilsSetupError, CompileError import unittest from test import test_support @@ -292,7 +293,7 @@ finally: os.chdir(old_wd) self.assertTrue(os.path.exists(so_file)) - self.assertEqual(os.path.splitext(so_file)[-1], + self.assertEqual(so_file[so_file.index(os.path.extsep):], sysconfig.get_config_var('SO')) so_dir = os.path.dirname(so_file) self.assertEqual(so_dir, other_tmp_dir) @@ -301,7 +302,7 @@ cmd.run() so_file = cmd.get_outputs()[0] self.assertTrue(os.path.exists(so_file)) - self.assertEqual(os.path.splitext(so_file)[-1], + self.assertEqual(so_file[so_file.index(os.path.extsep):], sysconfig.get_config_var('SO')) so_dir = os.path.dirname(so_file) self.assertEqual(so_dir, cmd.build_lib) @@ -430,6 +431,59 @@ wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext) self.assertEqual(ext_path, wanted) + @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX') + def test_deployment_target(self): + self._try_compile_deployment_target() + + orig_environ = os.environ + os.environ = orig_environ.copy() + self.addCleanup(setattr, os, 'environ', orig_environ) + + os.environ['MACOSX_DEPLOYMENT_TARGET']='10.1' + self._try_compile_deployment_target() + + + def _try_compile_deployment_target(self): + deptarget_c = os.path.join(self.tmp_dir, 'deptargetmodule.c') + + with open(deptarget_c, 'w') as fp: + fp.write(textwrap.dedent('''\ + #include + + int dummy; + + #if TARGET != MAC_OS_X_VERSION_MIN_REQUIRED + #error "Unexpected target" + #endif + + ''')) + + target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') + target = tuple(map(int, target.split('.'))) + target = '%02d%01d0' % target + + deptarget_ext = Extension( + 'deptarget', + [deptarget_c], + extra_compile_args=['-DTARGET=%s'%(target,)], + ) + dist = Distribution({ + 'name': 'deptarget', + 'ext_modules': [deptarget_ext] + }) + dist.package_dir = self.tmp_dir + cmd = build_ext(dist) + cmd.build_lib = self.tmp_dir + cmd.build_temp = self.tmp_dir + + try: + old_stdout = sys.stdout + cmd.ensure_finalized() + cmd.run() + + except CompileError: + self.fail("Wrong deployment target during compilation") + def test_suite(): return unittest.makeSuite(BuildExtTestCase) diff --git a/lib-python/2.7/distutils/tests/test_build_py.py b/lib-python/2.7/distutils/tests/test_build_py.py --- a/lib-python/2.7/distutils/tests/test_build_py.py +++ b/lib-python/2.7/distutils/tests/test_build_py.py @@ -10,13 +10,14 @@ from distutils.errors import DistutilsFileError from distutils.tests import support +from test.test_support import run_unittest class BuildPyTestCase(support.TempdirManager, support.LoggingSilencer, unittest.TestCase): - def _setup_package_data(self): + def test_package_data(self): sources = self.mkdtemp() f = open(os.path.join(sources, "__init__.py"), "w") try: @@ -56,20 +57,15 @@ self.assertEqual(len(cmd.get_outputs()), 3) pkgdest = os.path.join(destination, "pkg") files = os.listdir(pkgdest) - return files + self.assertIn("__init__.py", files) + self.assertIn("README.txt", files) + # XXX even with -O, distutils writes pyc, not pyo; bug? + if sys.dont_write_bytecode: + self.assertNotIn("__init__.pyc", files) + else: + self.assertIn("__init__.pyc", files) - def test_package_data(self): - files = self._setup_package_data() - self.assertTrue("__init__.py" in files) - self.assertTrue("README.txt" in files) - - @unittest.skipIf(sys.flags.optimize >= 2, - "pyc files are not written with -O2 and above") - def test_package_data_pyc(self): - files = self._setup_package_data() - self.assertTrue("__init__.pyc" in files) - - def test_empty_package_dir (self): + def test_empty_package_dir(self): # See SF 1668596/1720897. cwd = os.getcwd() @@ -117,10 +113,10 @@ finally: sys.dont_write_bytecode = old_dont_write_bytecode - self.assertTrue('byte-compiling is disabled' in self.logs[0][1]) + self.assertIn('byte-compiling is disabled', self.logs[0][1]) def test_suite(): return unittest.makeSuite(BuildPyTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_build_scripts.py b/lib-python/2.7/distutils/tests/test_build_scripts.py --- a/lib-python/2.7/distutils/tests/test_build_scripts.py +++ b/lib-python/2.7/distutils/tests/test_build_scripts.py @@ -8,6 +8,7 @@ import sysconfig from distutils.tests import support +from test.test_support import run_unittest class BuildScriptsTestCase(support.TempdirManager, @@ -108,4 +109,4 @@ return unittest.makeSuite(BuildScriptsTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_check.py b/lib-python/2.7/distutils/tests/test_check.py --- a/lib-python/2.7/distutils/tests/test_check.py +++ b/lib-python/2.7/distutils/tests/test_check.py @@ -1,5 +1,6 @@ """Tests for distutils.command.check.""" import unittest +from test.test_support import run_unittest from distutils.command.check import check, HAS_DOCUTILS from distutils.tests import support @@ -95,4 +96,4 @@ return unittest.makeSuite(CheckTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_clean.py b/lib-python/2.7/distutils/tests/test_clean.py --- a/lib-python/2.7/distutils/tests/test_clean.py +++ b/lib-python/2.7/distutils/tests/test_clean.py @@ -6,6 +6,7 @@ from distutils.command.clean import clean from distutils.tests import support +from test.test_support import run_unittest class cleanTestCase(support.TempdirManager, support.LoggingSilencer, @@ -38,7 +39,7 @@ self.assertTrue(not os.path.exists(path), '%s was not removed' % path) - # let's run the command again (should spit warnings but suceed) + # let's run the command again (should spit warnings but succeed) cmd.all = 1 cmd.ensure_finalized() cmd.run() @@ -47,4 +48,4 @@ return unittest.makeSuite(cleanTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_cmd.py b/lib-python/2.7/distutils/tests/test_cmd.py --- a/lib-python/2.7/distutils/tests/test_cmd.py +++ b/lib-python/2.7/distutils/tests/test_cmd.py @@ -99,7 +99,7 @@ def test_ensure_dirname(self): cmd = self.cmd - cmd.option1 = os.path.dirname(__file__) + cmd.option1 = os.path.dirname(__file__) or os.curdir cmd.ensure_dirname('option1') cmd.option2 = 'xxx' self.assertRaises(DistutilsOptionError, cmd.ensure_dirname, 'option2') diff --git a/lib-python/2.7/distutils/tests/test_config.py b/lib-python/2.7/distutils/tests/test_config.py --- a/lib-python/2.7/distutils/tests/test_config.py +++ b/lib-python/2.7/distutils/tests/test_config.py @@ -11,6 +11,7 @@ from distutils.log import WARN from distutils.tests import support +from test.test_support import run_unittest PYPIRC = """\ [distutils] @@ -119,4 +120,4 @@ return unittest.makeSuite(PyPIRCCommandTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_config_cmd.py b/lib-python/2.7/distutils/tests/test_config_cmd.py --- a/lib-python/2.7/distutils/tests/test_config_cmd.py +++ b/lib-python/2.7/distutils/tests/test_config_cmd.py @@ -2,6 +2,7 @@ import unittest import os import sys +from test.test_support import run_unittest from distutils.command.config import dump_file, config from distutils.tests import support @@ -86,4 +87,4 @@ return unittest.makeSuite(ConfigTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_core.py b/lib-python/2.7/distutils/tests/test_core.py --- a/lib-python/2.7/distutils/tests/test_core.py +++ b/lib-python/2.7/distutils/tests/test_core.py @@ -6,7 +6,7 @@ import shutil import sys import test.test_support -from test.test_support import captured_stdout +from test.test_support import captured_stdout, run_unittest import unittest from distutils.tests import support @@ -105,4 +105,4 @@ return unittest.makeSuite(CoreTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_dep_util.py b/lib-python/2.7/distutils/tests/test_dep_util.py --- a/lib-python/2.7/distutils/tests/test_dep_util.py +++ b/lib-python/2.7/distutils/tests/test_dep_util.py @@ -6,6 +6,7 @@ from distutils.dep_util import newer, newer_pairwise, newer_group from distutils.errors import DistutilsFileError from distutils.tests import support +from test.test_support import run_unittest class DepUtilTestCase(support.TempdirManager, unittest.TestCase): @@ -77,4 +78,4 @@ return unittest.makeSuite(DepUtilTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_dir_util.py b/lib-python/2.7/distutils/tests/test_dir_util.py --- a/lib-python/2.7/distutils/tests/test_dir_util.py +++ b/lib-python/2.7/distutils/tests/test_dir_util.py @@ -10,6 +10,7 @@ from distutils import log from distutils.tests import support +from test.test_support import run_unittest class DirUtilTestCase(support.TempdirManager, unittest.TestCase): @@ -112,4 +113,4 @@ return unittest.makeSuite(DirUtilTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_dist.py b/lib-python/2.7/distutils/tests/test_dist.py --- a/lib-python/2.7/distutils/tests/test_dist.py +++ b/lib-python/2.7/distutils/tests/test_dist.py @@ -11,7 +11,7 @@ from distutils.dist import Distribution, fix_help_options, DistributionMetadata from distutils.cmd import Command import distutils.dist -from test.test_support import TESTFN, captured_stdout +from test.test_support import TESTFN, captured_stdout, run_unittest from distutils.tests import support class test_dist(Command): @@ -433,4 +433,4 @@ return suite if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_file_util.py b/lib-python/2.7/distutils/tests/test_file_util.py --- a/lib-python/2.7/distutils/tests/test_file_util.py +++ b/lib-python/2.7/distutils/tests/test_file_util.py @@ -6,6 +6,7 @@ from distutils.file_util import move_file, write_file, copy_file from distutils import log from distutils.tests import support +from test.test_support import run_unittest class FileUtilTestCase(support.TempdirManager, unittest.TestCase): @@ -77,4 +78,4 @@ return unittest.makeSuite(FileUtilTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_filelist.py b/lib-python/2.7/distutils/tests/test_filelist.py --- a/lib-python/2.7/distutils/tests/test_filelist.py +++ b/lib-python/2.7/distutils/tests/test_filelist.py @@ -1,7 +1,7 @@ """Tests for distutils.filelist.""" from os.path import join import unittest -from test.test_support import captured_stdout +from test.test_support import captured_stdout, run_unittest from distutils.filelist import glob_to_re, FileList from distutils import debug @@ -82,4 +82,4 @@ return unittest.makeSuite(FileListTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_install.py b/lib-python/2.7/distutils/tests/test_install.py --- a/lib-python/2.7/distutils/tests/test_install.py +++ b/lib-python/2.7/distutils/tests/test_install.py @@ -2,6 +2,9 @@ import os import unittest +from test import test_support + +from test.test_support import run_unittest from distutils.command.install import install from distutils.core import Distribution @@ -38,18 +41,19 @@ expected = os.path.normpath(expected) self.assertEqual(got, expected) - libdir = os.path.join(destination, "lib", "python") - check_path(cmd.install_lib, libdir) - check_path(cmd.install_platlib, libdir) - check_path(cmd.install_purelib, libdir) - check_path(cmd.install_headers, - os.path.join(destination, "include", "python", "foopkg")) - check_path(cmd.install_scripts, os.path.join(destination, "bin")) - check_path(cmd.install_data, destination) + if test_support.check_impl_detail(): + libdir = os.path.join(destination, "lib", "python") + check_path(cmd.install_lib, libdir) + check_path(cmd.install_platlib, libdir) + check_path(cmd.install_purelib, libdir) + check_path(cmd.install_headers, + os.path.join(destination, "include", "python", "foopkg")) + check_path(cmd.install_scripts, os.path.join(destination, "bin")) + check_path(cmd.install_data, destination) def test_suite(): return unittest.makeSuite(InstallTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_install_data.py b/lib-python/2.7/distutils/tests/test_install_data.py --- a/lib-python/2.7/distutils/tests/test_install_data.py +++ b/lib-python/2.7/distutils/tests/test_install_data.py @@ -6,6 +6,7 @@ from distutils.command.install_data import install_data from distutils.tests import support +from test.test_support import run_unittest class InstallDataTestCase(support.TempdirManager, support.LoggingSilencer, @@ -73,4 +74,4 @@ return unittest.makeSuite(InstallDataTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_install_headers.py b/lib-python/2.7/distutils/tests/test_install_headers.py --- a/lib-python/2.7/distutils/tests/test_install_headers.py +++ b/lib-python/2.7/distutils/tests/test_install_headers.py @@ -6,6 +6,7 @@ from distutils.command.install_headers import install_headers from distutils.tests import support +from test.test_support import run_unittest class InstallHeadersTestCase(support.TempdirManager, support.LoggingSilencer, @@ -37,4 +38,4 @@ return unittest.makeSuite(InstallHeadersTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_install_lib.py b/lib-python/2.7/distutils/tests/test_install_lib.py --- a/lib-python/2.7/distutils/tests/test_install_lib.py +++ b/lib-python/2.7/distutils/tests/test_install_lib.py @@ -7,6 +7,7 @@ from distutils.extension import Extension from distutils.tests import support from distutils.errors import DistutilsOptionError +from test.test_support import run_unittest class InstallLibTestCase(support.TempdirManager, support.LoggingSilencer, @@ -103,4 +104,4 @@ return unittest.makeSuite(InstallLibTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_install_scripts.py b/lib-python/2.7/distutils/tests/test_install_scripts.py --- a/lib-python/2.7/distutils/tests/test_install_scripts.py +++ b/lib-python/2.7/distutils/tests/test_install_scripts.py @@ -7,6 +7,7 @@ from distutils.core import Distribution from distutils.tests import support +from test.test_support import run_unittest class InstallScriptsTestCase(support.TempdirManager, @@ -78,4 +79,4 @@ return unittest.makeSuite(InstallScriptsTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_msvc9compiler.py b/lib-python/2.7/distutils/tests/test_msvc9compiler.py --- a/lib-python/2.7/distutils/tests/test_msvc9compiler.py +++ b/lib-python/2.7/distutils/tests/test_msvc9compiler.py @@ -5,6 +5,7 @@ from distutils.errors import DistutilsPlatformError from distutils.tests import support +from test.test_support import run_unittest _MANIFEST = """\ @@ -137,4 +138,4 @@ return unittest.makeSuite(msvc9compilerTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_register.py b/lib-python/2.7/distutils/tests/test_register.py --- a/lib-python/2.7/distutils/tests/test_register.py +++ b/lib-python/2.7/distutils/tests/test_register.py @@ -7,7 +7,7 @@ import urllib2 import warnings -from test.test_support import check_warnings +from test.test_support import check_warnings, run_unittest from distutils.command import register as register_module from distutils.command.register import register @@ -138,7 +138,7 @@ # let's see what the server received : we should # have 2 similar requests - self.assertTrue(self.conn.reqs, 2) + self.assertEqual(len(self.conn.reqs), 2) req1 = dict(self.conn.reqs[0].headers) req2 = dict(self.conn.reqs[1].headers) self.assertEqual(req2['Content-length'], req1['Content-length']) @@ -168,7 +168,7 @@ del register_module.raw_input # we should have send a request - self.assertTrue(self.conn.reqs, 1) + self.assertEqual(len(self.conn.reqs), 1) req = self.conn.reqs[0] headers = dict(req.headers) self.assertEqual(headers['Content-length'], '608') @@ -186,7 +186,7 @@ del register_module.raw_input # we should have send a request - self.assertTrue(self.conn.reqs, 1) + self.assertEqual(len(self.conn.reqs), 1) req = self.conn.reqs[0] headers = dict(req.headers) self.assertEqual(headers['Content-length'], '290') @@ -258,4 +258,4 @@ return unittest.makeSuite(RegisterTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_sdist.py b/lib-python/2.7/distutils/tests/test_sdist.py --- a/lib-python/2.7/distutils/tests/test_sdist.py +++ b/lib-python/2.7/distutils/tests/test_sdist.py @@ -24,11 +24,9 @@ import tempfile import warnings -from test.test_support import check_warnings -from test.test_support import captured_stdout +from test.test_support import captured_stdout, check_warnings, run_unittest -from distutils.command.sdist import sdist -from distutils.command.sdist import show_formats +from distutils.command.sdist import sdist, show_formats from distutils.core import Distribution from distutils.tests.test_config import PyPIRCCommandTestCase from distutils.errors import DistutilsExecError, DistutilsOptionError @@ -372,7 +370,7 @@ # adding a file self.write_file((self.tmp_dir, 'somecode', 'doc2.txt'), '#') - # make sure build_py is reinitinialized, like a fresh run + # make sure build_py is reinitialized, like a fresh run build_py = dist.get_command_obj('build_py') build_py.finalized = False build_py.ensure_finalized() @@ -390,6 +388,7 @@ self.assertEqual(len(manifest2), 6) self.assertIn('doc2.txt', manifest2[-1]) + @unittest.skipUnless(zlib, "requires zlib") def test_manifest_marker(self): # check that autogenerated MANIFESTs have a marker dist, cmd = self.get_cmd() @@ -406,6 +405,7 @@ self.assertEqual(manifest[0], '# file GENERATED by distutils, do NOT edit') + @unittest.skipUnless(zlib, "requires zlib") def test_manual_manifest(self): # check that a MANIFEST without a marker is left alone dist, cmd = self.get_cmd() @@ -426,4 +426,4 @@ return unittest.makeSuite(SDistTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_spawn.py b/lib-python/2.7/distutils/tests/test_spawn.py --- a/lib-python/2.7/distutils/tests/test_spawn.py +++ b/lib-python/2.7/distutils/tests/test_spawn.py @@ -2,7 +2,7 @@ import unittest import os import time -from test.test_support import captured_stdout +from test.test_support import captured_stdout, run_unittest from distutils.spawn import _nt_quote_args from distutils.spawn import spawn, find_executable @@ -57,4 +57,4 @@ return unittest.makeSuite(SpawnTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_text_file.py b/lib-python/2.7/distutils/tests/test_text_file.py --- a/lib-python/2.7/distutils/tests/test_text_file.py +++ b/lib-python/2.7/distutils/tests/test_text_file.py @@ -3,6 +3,7 @@ import unittest from distutils.text_file import TextFile from distutils.tests import support +from test.test_support import run_unittest TEST_DATA = """# test file @@ -103,4 +104,4 @@ return unittest.makeSuite(TextFileTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_unixccompiler.py b/lib-python/2.7/distutils/tests/test_unixccompiler.py --- a/lib-python/2.7/distutils/tests/test_unixccompiler.py +++ b/lib-python/2.7/distutils/tests/test_unixccompiler.py @@ -1,6 +1,7 @@ """Tests for distutils.unixccompiler.""" import sys import unittest +from test.test_support import run_unittest from distutils import sysconfig from distutils.unixccompiler import UnixCCompiler @@ -126,4 +127,4 @@ return unittest.makeSuite(UnixCCompilerTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_upload.py b/lib-python/2.7/distutils/tests/test_upload.py --- a/lib-python/2.7/distutils/tests/test_upload.py +++ b/lib-python/2.7/distutils/tests/test_upload.py @@ -1,14 +1,13 @@ +# -*- encoding: utf8 -*- """Tests for distutils.command.upload.""" -# -*- encoding: utf8 -*- -import sys import os import unittest +from test.test_support import run_unittest from distutils.command import upload as upload_mod from distutils.command.upload import upload from distutils.core import Distribution -from distutils.tests import support from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase PYPIRC_LONG_PASSWORD = """\ @@ -129,4 +128,4 @@ return unittest.makeSuite(uploadTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_util.py b/lib-python/2.7/distutils/tests/test_util.py --- a/lib-python/2.7/distutils/tests/test_util.py +++ b/lib-python/2.7/distutils/tests/test_util.py @@ -1,6 +1,7 @@ """Tests for distutils.util.""" import sys import unittest +from test.test_support import run_unittest from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError from distutils.util import byte_compile @@ -21,4 +22,4 @@ return unittest.makeSuite(UtilTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_version.py b/lib-python/2.7/distutils/tests/test_version.py --- a/lib-python/2.7/distutils/tests/test_version.py +++ b/lib-python/2.7/distutils/tests/test_version.py @@ -2,6 +2,7 @@ import unittest from distutils.version import LooseVersion from distutils.version import StrictVersion +from test.test_support import run_unittest class VersionTestCase(unittest.TestCase): @@ -67,4 +68,4 @@ return unittest.makeSuite(VersionTestCase) if __name__ == "__main__": - unittest.main(defaultTest="test_suite") + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/tests/test_versionpredicate.py b/lib-python/2.7/distutils/tests/test_versionpredicate.py --- a/lib-python/2.7/distutils/tests/test_versionpredicate.py +++ b/lib-python/2.7/distutils/tests/test_versionpredicate.py @@ -4,6 +4,10 @@ import distutils.versionpredicate import doctest +from test.test_support import run_unittest def test_suite(): return doctest.DocTestSuite(distutils.versionpredicate) + +if __name__ == '__main__': + run_unittest(test_suite()) diff --git a/lib-python/2.7/distutils/unixccompiler.py b/lib-python/2.7/distutils/unixccompiler.py --- a/lib-python/2.7/distutils/unixccompiler.py +++ b/lib-python/2.7/distutils/unixccompiler.py @@ -125,7 +125,22 @@ } if sys.platform[:6] == "darwin": + import platform + if platform.machine() == 'i386': + if platform.architecture()[0] == '32bit': + arch = 'i386' + else: + arch = 'x86_64' + else: + # just a guess + arch = platform.machine() executables['ranlib'] = ["ranlib"] + executables['linker_so'] += ['-undefined', 'dynamic_lookup'] + + for k, v in executables.iteritems(): + if v and v[0] == 'cc': + v += ['-arch', arch] + # Needed for the filename generation methods provided by the base # class, CCompiler. NB. whoever instantiates/uses a particular @@ -309,7 +324,7 @@ # On OSX users can specify an alternate SDK using # '-isysroot', calculate the SDK root if it is specified # (and use it further on) - cflags = sysconfig.get_config_var('CFLAGS') + cflags = sysconfig.get_config_var('CFLAGS') or '' m = re.search(r'-isysroot\s+(\S+)', cflags) if m is None: sysroot = '/' diff --git a/lib-python/2.7/distutils/util.py b/lib-python/2.7/distutils/util.py --- a/lib-python/2.7/distutils/util.py +++ b/lib-python/2.7/distutils/util.py @@ -97,9 +97,7 @@ from distutils.sysconfig import get_config_vars cfgvars = get_config_vars() - macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET') - if not macver: - macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') + macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') if 1: # Always calculate the release of the running machine, diff --git a/lib-python/2.7/doctest.py b/lib-python/2.7/doctest.py --- a/lib-python/2.7/doctest.py +++ b/lib-python/2.7/doctest.py @@ -1217,7 +1217,7 @@ # Process each example. for examplenum, example in enumerate(test.examples): - # If REPORT_ONLY_FIRST_FAILURE is set, then supress + # If REPORT_ONLY_FIRST_FAILURE is set, then suppress # reporting after the first failure. quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and failures > 0) @@ -2186,7 +2186,7 @@ caller can catch the errors and initiate post-mortem debugging. The DocTestCase provides a debug method that raises - UnexpectedException errors if there is an unexepcted + UnexpectedException errors if there is an unexpected exception: >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', diff --git a/lib-python/2.7/email/charset.py b/lib-python/2.7/email/charset.py --- a/lib-python/2.7/email/charset.py +++ b/lib-python/2.7/email/charset.py @@ -209,7 +209,7 @@ input_charset = unicode(input_charset, 'ascii') except UnicodeError: raise errors.CharsetError(input_charset) - input_charset = input_charset.lower() + input_charset = input_charset.lower().encode('ascii') # Set the input charset after filtering through the aliases and/or codecs if not (input_charset in ALIASES or input_charset in CHARSETS): try: diff --git a/lib-python/2.7/email/generator.py b/lib-python/2.7/email/generator.py --- a/lib-python/2.7/email/generator.py +++ b/lib-python/2.7/email/generator.py @@ -202,18 +202,13 @@ g = self.clone(s) g.flatten(part, unixfrom=False) msgtexts.append(s.getvalue()) - # Now make sure the boundary we've selected doesn't appear in any of - # the message texts. - alltext = NL.join(msgtexts) # BAW: What about boundaries that are wrapped in double-quotes? - boundary = msg.get_boundary(failobj=_make_boundary(alltext)) - # If we had to calculate a new boundary because the body text - # contained that string, set the new boundary. We don't do it - # unconditionally because, while set_boundary() preserves order, it - # doesn't preserve newlines/continuations in headers. This is no big - # deal in practice, but turns out to be inconvenient for the unittest - # suite. - if msg.get_boundary() != boundary: + boundary = msg.get_boundary() + if not boundary: + # Create a boundary that doesn't appear in any of the + # message texts. + alltext = NL.join(msgtexts) + boundary = _make_boundary(alltext) msg.set_boundary(boundary) # If there's a preamble, write it out, with a trailing CRLF if msg.preamble is not None: @@ -292,7 +287,7 @@ _FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]' class DecodedGenerator(Generator): - """Generator a text representation of a message. + """Generates a text representation of a message. Like the Generator base class, except that non-text parts are substituted with a format string representing the part. diff --git a/lib-python/2.7/email/header.py b/lib-python/2.7/email/header.py --- a/lib-python/2.7/email/header.py +++ b/lib-python/2.7/email/header.py @@ -47,6 +47,10 @@ # For use with .match() fcre = re.compile(r'[\041-\176]+:$') +# Find a header embedded in a putative header value. Used to check for +# header injection attack. +_embeded_header = re.compile(r'\n[^ \t]+:') + # Helpers @@ -403,7 +407,11 @@ newchunks += self._split(s, charset, targetlen, splitchars) lastchunk, lastcharset = newchunks[-1] lastlen = lastcharset.encoded_header_len(lastchunk) - return self._encode_chunks(newchunks, maxlinelen) + value = self._encode_chunks(newchunks, maxlinelen) + if _embeded_header.search(value): + raise HeaderParseError("header value appears to contain " + "an embedded header: {!r}".format(value)) + return value diff --git a/lib-python/2.7/email/message.py b/lib-python/2.7/email/message.py --- a/lib-python/2.7/email/message.py +++ b/lib-python/2.7/email/message.py @@ -38,7 +38,9 @@ def _formatparam(param, value=None, quote=True): """Convenience function to format and return a key=value pair. - This will quote the value if needed or if quote is true. + This will quote the value if needed or if quote is true. If value is a + three tuple (charset, language, value), it will be encoded according + to RFC2231 rules. """ if value is not None and len(value) > 0: # A tuple is used for RFC 2231 encoded parameter values where items @@ -97,7 +99,7 @@ objects, otherwise it is a string. Message objects implement part of the `mapping' interface, which assumes - there is exactly one occurrance of the header per message. Some headers + there is exactly one occurrence of the header per message. Some headers do in fact appear multiple times (e.g. Received) and for those headers, you must use the explicit API to set or get all the headers. Not all of the mapping methods are implemented. @@ -286,7 +288,7 @@ Return None if the header is missing instead of raising an exception. Note that if the header appeared multiple times, exactly which - occurrance gets returned is undefined. Use get_all() to get all + occurrence gets returned is undefined. Use get_all() to get all the values matching a header field name. """ return self.get(name) @@ -389,7 +391,10 @@ name is the header field to add. keyword arguments can be used to set additional parameters for the header field, with underscores converted to dashes. Normally the parameter will be added as key="value" unless - value is None, in which case only the key will be added. + value is None, in which case only the key will be added. If a + parameter value contains non-ASCII characters it must be specified as a + three-tuple of (charset, language, value), in which case it will be + encoded according to RFC2231 rules. Example: diff --git a/lib-python/2.7/email/mime/application.py b/lib-python/2.7/email/mime/application.py --- a/lib-python/2.7/email/mime/application.py +++ b/lib-python/2.7/email/mime/application.py @@ -17,7 +17,7 @@ _encoder=encoders.encode_base64, **_params): """Create an application/* type MIME document. - _data is a string containing the raw applicatoin data. + _data is a string containing the raw application data. _subtype is the MIME content type subtype, defaulting to 'octet-stream'. diff --git a/lib-python/2.7/email/test/data/msg_26.txt b/lib-python/2.7/email/test/data/msg_26.txt --- a/lib-python/2.7/email/test/data/msg_26.txt +++ b/lib-python/2.7/email/test/data/msg_26.txt @@ -42,4 +42,4 @@ MzMAAAAACH97tzAAAAALu3c3gAAAAAAL+7tzDABAu7f7cAAAAAAACA+3MA7EQAv/sIAA AAAAAAAIAAAAAAAAAIAAAAAA ---1618492860--2051301190--113853680-- +--1618492860--2051301190--113853680-- \ No newline at end of file diff --git a/lib-python/2.7/email/test/test_email.py b/lib-python/2.7/email/test/test_email.py --- a/lib-python/2.7/email/test/test_email.py +++ b/lib-python/2.7/email/test/test_email.py @@ -179,6 +179,17 @@ self.assertRaises(Errors.HeaderParseError, msg.set_boundary, 'BOUNDARY') + def test_make_boundary(self): + msg = MIMEMultipart('form-data') + # Note that when the boundary gets created is an implementation + # detail and might change. + self.assertEqual(msg.items()[0][1], 'multipart/form-data') + # Trigger creation of boundary + msg.as_string() + self.assertEqual(msg.items()[0][1][:33], + 'multipart/form-data; boundary="==') + # XXX: there ought to be tests of the uniqueness of the boundary, too. + def test_message_rfc822_only(self): # Issue 7970: message/rfc822 not in multipart parsed by # HeaderParser caused an exception when flattened. @@ -542,6 +553,17 @@ msg.set_charset(u'us-ascii') self.assertEqual('us-ascii', msg.get_content_charset()) + # Issue 5871: reject an attempt to embed a header inside a header value + # (header injection attack). + def test_embeded_header_via_Header_rejected(self): + msg = Message() + msg['Dummy'] = Header('dummy\nX-Injected-Header: test') + self.assertRaises(Errors.HeaderParseError, msg.as_string) + + def test_embeded_header_via_string_rejected(self): + msg = Message() + msg['Dummy'] = 'dummy\nX-Injected-Header: test' + self.assertRaises(Errors.HeaderParseError, msg.as_string) # Test the email.Encoders module @@ -3113,6 +3135,28 @@ s = 'Subject: =?EUC-KR?B?CSixpLDtKSC/7Liuvsax4iC6uLmwMcijIKHaILzSwd/H0SC8+LCjwLsgv7W/+Mj3I ?=' raises(Errors.HeaderParseError, decode_header, s) + # Issue 1078919 + def test_ascii_add_header(self): + msg = Message() + msg.add_header('Content-Disposition', 'attachment', + filename='bud.gif') + self.assertEqual('attachment; filename="bud.gif"', + msg['Content-Disposition']) + + def test_nonascii_add_header_via_triple(self): + msg = Message() + msg.add_header('Content-Disposition', 'attachment', + filename=('iso-8859-1', '', 'Fu\xdfballer.ppt')) + self.assertEqual( + 'attachment; filename*="iso-8859-1\'\'Fu%DFballer.ppt"', + msg['Content-Disposition']) + + def test_encode_unaliased_charset(self): + # Issue 1379416: when the charset has no output conversion, + # output was accidentally getting coerced to unicode. + res = Header('abc','iso-8859-2').encode() + self.assertEqual(res, '=?iso-8859-2?q?abc?=') + self.assertIsInstance(res, str) # Test RFC 2231 header parameters (en/de)coding diff --git a/lib-python/2.7/ftplib.py b/lib-python/2.7/ftplib.py --- a/lib-python/2.7/ftplib.py +++ b/lib-python/2.7/ftplib.py @@ -599,7 +599,7 @@ Usage example: >>> from ftplib import FTP_TLS >>> ftps = FTP_TLS('ftp.python.org') - >>> ftps.login() # login anonimously previously securing control channel + >>> ftps.login() # login anonymously previously securing control channel '230 Guest login ok, access restrictions apply.' >>> ftps.prot_p() # switch to secure data connection '200 Protection level set to P' diff --git a/lib-python/2.7/functools.py b/lib-python/2.7/functools.py --- a/lib-python/2.7/functools.py +++ b/lib-python/2.7/functools.py @@ -53,17 +53,17 @@ def total_ordering(cls): """Class decorator that fills in missing ordering methods""" convert = { - '__lt__': [('__gt__', lambda self, other: other < self), - ('__le__', lambda self, other: not other < self), + '__lt__': [('__gt__', lambda self, other: not (self < other or self == other)), + ('__le__', lambda self, other: self < other or self == other), ('__ge__', lambda self, other: not self < other)], - '__le__': [('__ge__', lambda self, other: other <= self), - ('__lt__', lambda self, other: not other <= self), + '__le__': [('__ge__', lambda self, other: not self <= other or self == other), + ('__lt__', lambda self, other: self <= other and not self == other), ('__gt__', lambda self, other: not self <= other)], - '__gt__': [('__lt__', lambda self, other: other > self), - ('__ge__', lambda self, other: not other > self), + '__gt__': [('__lt__', lambda self, other: not (self > other or self == other)), + ('__ge__', lambda self, other: self > other or self == other), ('__le__', lambda self, other: not self > other)], - '__ge__': [('__le__', lambda self, other: other >= self), - ('__gt__', lambda self, other: not other >= self), + '__ge__': [('__le__', lambda self, other: (not self >= other) or self == other), + ('__gt__', lambda self, other: self >= other and not self == other), ('__lt__', lambda self, other: not self >= other)] } roots = set(dir(cls)) & set(convert) @@ -80,6 +80,7 @@ def cmp_to_key(mycmp): """Convert a cmp= function into a key= function""" class K(object): + __slots__ = ['obj'] def __init__(self, obj, *args): self.obj = obj def __lt__(self, other): diff --git a/lib-python/2.7/getpass.py b/lib-python/2.7/getpass.py --- a/lib-python/2.7/getpass.py +++ b/lib-python/2.7/getpass.py @@ -62,7 +62,7 @@ try: old = termios.tcgetattr(fd) # a copy to save new = old[:] - new[3] &= ~(termios.ECHO|termios.ISIG) # 3 == 'lflags' + new[3] &= ~termios.ECHO # 3 == 'lflags' tcsetattr_flags = termios.TCSAFLUSH if hasattr(termios, 'TCSASOFT'): tcsetattr_flags |= termios.TCSASOFT diff --git a/lib-python/2.7/gettext.py b/lib-python/2.7/gettext.py --- a/lib-python/2.7/gettext.py +++ b/lib-python/2.7/gettext.py @@ -316,7 +316,7 @@ # Note: we unconditionally convert both msgids and msgstrs to # Unicode using the character encoding specified in the charset # parameter of the Content-Type header. The gettext documentation - # strongly encourages msgids to be us-ascii, but some appliations + # strongly encourages msgids to be us-ascii, but some applications # require alternative encodings (e.g. Zope's ZCML and ZPT). For # traditional gettext applications, the msgid conversion will # cause no problems since us-ascii should always be a subset of diff --git a/lib-python/2.7/hashlib.py b/lib-python/2.7/hashlib.py --- a/lib-python/2.7/hashlib.py +++ b/lib-python/2.7/hashlib.py @@ -64,26 +64,29 @@ def __get_builtin_constructor(name): - if name in ('SHA1', 'sha1'): - import _sha - return _sha.new - elif name in ('MD5', 'md5'): - import _md5 - return _md5.new - elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): - import _sha256 - bs = name[3:] - if bs == '256': - return _sha256.sha256 - elif bs == '224': - return _sha256.sha224 - elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): - import _sha512 - bs = name[3:] - if bs == '512': - return _sha512.sha512 - elif bs == '384': - return _sha512.sha384 + try: + if name in ('SHA1', 'sha1'): + import _sha + return _sha.new + elif name in ('MD5', 'md5'): + import _md5 + return _md5.new + elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): + import _sha256 + bs = name[3:] + if bs == '256': + return _sha256.sha256 + elif bs == '224': + return _sha256.sha224 + elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): + import _sha512 + bs = name[3:] + if bs == '512': + return _sha512.sha512 + elif bs == '384': + return _sha512.sha384 + except ImportError: + pass # no extension module, this hash is unsupported. raise ValueError('unsupported hash type %s' % name) diff --git a/lib-python/2.7/heapq.py b/lib-python/2.7/heapq.py --- a/lib-python/2.7/heapq.py +++ b/lib-python/2.7/heapq.py @@ -133,6 +133,11 @@ from operator import itemgetter import bisect +def cmp_lt(x, y): + # Use __lt__ if available; otherwise, try __le__. + # In Py3.x, only __lt__ will be called. + return (x < y) if hasattr(x, '__lt__') else (not y <= x) + def heappush(heap, item): """Push item onto heap, maintaining the heap invariant.""" heap.append(item) @@ -167,13 +172,13 @@ def heappushpop(heap, item): """Fast version of a heappush followed by a heappop.""" - if heap and heap[0] < item: + if heap and cmp_lt(heap[0], item): item, heap[0] = heap[0], item _siftup(heap, 0) return item def heapify(x): - """Transform list into a heap, in-place, in O(len(heap)) time.""" + """Transform list into a heap, in-place, in O(len(x)) time.""" n = len(x) # Transform bottom-up. The largest index there's any point to looking at # is the largest with a child index in-range, so must have 2*i + 1 < n, @@ -188,6 +193,8 @@ Equivalent to: sorted(iterable, reverse=True)[:n] """ + if n < 0: # for consistency with the c impl + return [] it = iter(iterable) result = list(islice(it, n)) if not result: @@ -204,6 +211,8 @@ Equivalent to: sorted(iterable)[:n] """ + if n < 0: # for consistency with the c impl + return [] if hasattr(iterable, '__len__') and n * 10 <= len(iterable): # For smaller values of n, the bisect method is faster than a minheap. # It is also memory efficient, consuming only n elements of space. @@ -215,11 +224,10 @@ pop = result.pop los = result[-1] # los --> Largest of the nsmallest for elem in it: - if los <= elem: - continue - insort(result, elem) - pop() - los = result[-1] + if cmp_lt(elem, los): + insort(result, elem) + pop() + los = result[-1] return result # An alternative approach manifests the whole iterable in memory but # saves comparisons by heapifying all at once. Also, saves time @@ -240,7 +248,7 @@ while pos > startpos: parentpos = (pos - 1) >> 1 parent = heap[parentpos] - if newitem < parent: + if cmp_lt(newitem, parent): heap[pos] = parent pos = parentpos continue @@ -295,7 +303,7 @@ while childpos < endpos: # Set childpos to index of smaller child. rightpos = childpos + 1 - if rightpos < endpos and not heap[childpos] < heap[rightpos]: + if rightpos < endpos and not cmp_lt(heap[childpos], heap[rightpos]): childpos = rightpos # Move the smaller child up. heap[pos] = heap[childpos] @@ -364,7 +372,7 @@ return [min(chain(head, it))] return [min(chain(head, it), key=key)] - # When n>=size, it's faster to use sort() + # When n>=size, it's faster to use sorted() try: size = len(iterable) except (TypeError, AttributeError): @@ -402,7 +410,7 @@ return [max(chain(head, it))] return [max(chain(head, it), key=key)] - # When n>=size, it's faster to use sort() + # When n>=size, it's faster to use sorted() try: size = len(iterable) except (TypeError, AttributeError): diff --git a/lib-python/2.7/httplib.py b/lib-python/2.7/httplib.py --- a/lib-python/2.7/httplib.py +++ b/lib-python/2.7/httplib.py @@ -212,6 +212,9 @@ # maximal amount of data to read at one time in _safe_read MAXAMOUNT = 1048576 +# maximal line length when calling readline(). +_MAXLINE = 65536 + class HTTPMessage(mimetools.Message): def addheader(self, key, value): @@ -274,7 +277,9 @@ except IOError: startofline = tell = None self.seekable = 0 - line = self.fp.readline() + line = self.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("header line") if not line: self.status = 'EOF in headers' break @@ -404,7 +409,10 @@ break # skip the header from the 100 response while True: - skip = self.fp.readline().strip() + skip = self.fp.readline(_MAXLINE + 1) + if len(skip) > _MAXLINE: + raise LineTooLong("header line") + skip = skip.strip() if not skip: break if self.debuglevel > 0: @@ -563,7 +571,9 @@ value = [] while True: if chunk_left is None: - line = self.fp.readline() + line = self.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("chunk size") i = line.find(';') if i >= 0: line = line[:i] # strip chunk-extensions @@ -598,7 +608,9 @@ # read and discard trailer up to the CRLF terminator ### note: we shouldn't have any trailers! while True: - line = self.fp.readline() + line = self.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("trailer line") if not line: # a vanishingly small number of sites EOF without # sending the trailer @@ -730,7 +742,9 @@ raise socket.error("Tunnel connection failed: %d %s" % (code, message.strip())) while True: - line = response.fp.readline() + line = response.fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong("header line") if line == '\r\n': break @@ -790,7 +804,7 @@ del self._buffer[:] # If msg and message_body are sent in a single send() call, # it will avoid performance problems caused by the interaction - # between delayed ack and the Nagle algorithim. + # between delayed ack and the Nagle algorithm. if isinstance(message_body, str): msg += message_body message_body = None @@ -1010,7 +1024,11 @@ kwds["buffering"] = True; response = self.response_class(*args, **kwds) - response.begin() + try: + response.begin() + except: + response.close() + raise assert response.will_close != _UNKNOWN self.__state = _CS_IDLE @@ -1233,6 +1251,11 @@ self.args = line, self.line = line +class LineTooLong(HTTPException): + def __init__(self, line_type): + HTTPException.__init__(self, "got more than %d bytes when reading %s" + % (_MAXLINE, line_type)) + # for backwards compatibility error = HTTPException diff --git a/lib-python/2.7/idlelib/Bindings.py b/lib-python/2.7/idlelib/Bindings.py --- a/lib-python/2.7/idlelib/Bindings.py +++ b/lib-python/2.7/idlelib/Bindings.py @@ -98,14 +98,6 @@ # menu del menudefs[-1][1][0:2] - menudefs.insert(0, - ('application', [ - ('About IDLE', '<>'), - None, - ('_Preferences....', '<>'), - ])) - - default_keydefs = idleConf.GetCurrentKeySet() del sys diff --git a/lib-python/2.7/idlelib/Delegator.py b/lib-python/2.7/idlelib/Delegator.py --- a/lib-python/2.7/idlelib/Delegator.py +++ b/lib-python/2.7/idlelib/Delegator.py @@ -12,6 +12,14 @@ self.__cache[name] = attr return attr + def __nonzero__(self): + # this is needed for PyPy: else, if self.delegate is None, the + # __getattr__ above picks NoneType.__nonzero__, which returns + # False. Thus, bool(Delegator()) is False as well, but it's not what + # we want. On CPython, bool(Delegator()) is True because NoneType + # does not have __nonzero__ + return True + def resetcache(self): for key in self.__cache.keys(): try: diff --git a/lib-python/2.7/idlelib/EditorWindow.py b/lib-python/2.7/idlelib/EditorWindow.py --- a/lib-python/2.7/idlelib/EditorWindow.py +++ b/lib-python/2.7/idlelib/EditorWindow.py @@ -48,6 +48,21 @@ path = module.__path__ except AttributeError: raise ImportError, 'No source for module ' + module.__name__ + if descr[2] != imp.PY_SOURCE: + # If all of the above fails and didn't raise an exception,fallback + # to a straight import which can find __init__.py in a package. + m = __import__(fullname) + try: + filename = m.__file__ + except AttributeError: + pass + else: + file = None + base, ext = os.path.splitext(filename) + if ext == '.pyc': + ext = '.py' + filename = base + ext + descr = filename, None, imp.PY_SOURCE return file, filename, descr class EditorWindow(object): @@ -102,8 +117,8 @@ self.top = top = WindowList.ListedToplevel(root, menu=self.menubar) if flist: self.tkinter_vars = flist.vars - #self.top.instance_dict makes flist.inversedict avalable to - #configDialog.py so it can access all EditorWindow instaces + #self.top.instance_dict makes flist.inversedict available to + #configDialog.py so it can access all EditorWindow instances self.top.instance_dict = flist.inversedict else: self.tkinter_vars = {} # keys: Tkinter event names @@ -136,6 +151,14 @@ if macosxSupport.runningAsOSXApp(): # Command-W on editorwindows doesn't work without this. text.bind('<>', self.close_event) + # Some OS X systems have only one mouse button, + # so use control-click for pulldown menus there. + # (Note, AquaTk defines <2> as the right button if + # present and the Tk Text widget already binds <2>.) + text.bind("",self.right_menu_event) + else: + # Elsewhere, use right-click for pulldown menus. + text.bind("<3>",self.right_menu_event) text.bind("<>", self.cut) text.bind("<>", self.copy) text.bind("<>", self.paste) @@ -154,7 +177,6 @@ text.bind("<>", self.find_selection_event) text.bind("<>", self.replace_event) text.bind("<>", self.goto_line_event) - text.bind("<3>", self.right_menu_event) text.bind("<>",self.smart_backspace_event) text.bind("<>",self.newline_and_indent_event) text.bind("<>",self.smart_indent_event) @@ -300,13 +322,13 @@ return "break" def home_callback(self, event): - if (event.state & 12) != 0 and event.keysym == "Home": - # state&1==shift, state&4==control, state&8==alt - return # ; fall back to class binding - + if (event.state & 4) != 0 and event.keysym == "Home": + # state&4==Control. If , use the Tk binding. + return if self.text.index("iomark") and \ self.text.compare("iomark", "<=", "insert lineend") and \ self.text.compare("insert linestart", "<=", "iomark"): + # In Shell on input line, go to just after prompt insertpt = int(self.text.index("iomark").split(".")[1]) else: line = self.text.get("insert linestart", "insert lineend") @@ -315,30 +337,27 @@ break else: insertpt=len(line) - lineat = int(self.text.index("insert").split('.')[1]) - if insertpt == lineat: insertpt = 0 - dest = "insert linestart+"+str(insertpt)+"c" - if (event.state&1) == 0: - # shift not pressed + # shift was not pressed self.text.tag_remove("sel", "1.0", "end") else: if not self.text.index("sel.first"): - self.text.mark_set("anchor","insert") - + self.text.mark_set("my_anchor", "insert") # there was no previous selection + else: + if self.text.compare(self.text.index("sel.first"), "<", self.text.index("insert")): + self.text.mark_set("my_anchor", "sel.first") # extend back + else: + self.text.mark_set("my_anchor", "sel.last") # extend forward first = self.text.index(dest) - last = self.text.index("anchor") - + last = self.text.index("my_anchor") if self.text.compare(first,">",last): first,last = last,first - self.text.tag_remove("sel", "1.0", "end") self.text.tag_add("sel", first, last) - self.text.mark_set("insert", dest) self.text.see("insert") return "break" @@ -385,7 +404,7 @@ menudict[name] = menu = Menu(mbar, name=name) mbar.add_cascade(label=label, menu=menu, underline=underline) - if macosxSupport.runningAsOSXApp(): + if macosxSupport.isCarbonAquaTk(self.root): # Insert the application menu menudict['application'] = menu = Menu(mbar, name='apple') mbar.add_cascade(label='IDLE', menu=menu) @@ -445,7 +464,11 @@ def python_docs(self, event=None): if sys.platform[:3] == 'win': - os.startfile(self.help_url) + try: + os.startfile(self.help_url) + except WindowsError as why: + tkMessageBox.showerror(title='Document Start Failure', + message=str(why), parent=self.text) else: webbrowser.open(self.help_url) return "break" @@ -740,9 +763,13 @@ "Create a callback with the helpfile value frozen at definition time" def display_extra_help(helpfile=helpfile): if not helpfile.startswith(('www', 'http')): - url = os.path.normpath(helpfile) + helpfile = os.path.normpath(helpfile) if sys.platform[:3] == 'win': - os.startfile(helpfile) + try: + os.startfile(helpfile) + except WindowsError as why: + tkMessageBox.showerror(title='Document Start Failure', + message=str(why), parent=self.text) else: webbrowser.open(helpfile) return display_extra_help @@ -1526,7 +1553,12 @@ def get_accelerator(keydefs, eventname): keylist = keydefs.get(eventname) - if not keylist: + # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5 + # if not keylist: + if (not keylist) or (macosxSupport.runningAsOSXApp() and eventname in { + "<>", + "<>", + "<>"}): return "" s = keylist[0] s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s) diff --git a/lib-python/2.7/idlelib/FileList.py b/lib-python/2.7/idlelib/FileList.py --- a/lib-python/2.7/idlelib/FileList.py +++ b/lib-python/2.7/idlelib/FileList.py @@ -43,7 +43,7 @@ def new(self, filename=None): return self.EditorWindow(self, filename) - def close_all_callback(self, event): + def close_all_callback(self, *args, **kwds): for edit in self.inversedict.keys(): reply = edit.close() if reply == "cancel": diff --git a/lib-python/2.7/idlelib/FormatParagraph.py b/lib-python/2.7/idlelib/FormatParagraph.py --- a/lib-python/2.7/idlelib/FormatParagraph.py +++ b/lib-python/2.7/idlelib/FormatParagraph.py @@ -54,7 +54,7 @@ # If the block ends in a \n, we dont want the comment # prefix inserted after it. (Im not sure it makes sense to # reformat a comment block that isnt made of complete - # lines, but whatever!) Can't think of a clean soltution, + # lines, but whatever!) Can't think of a clean solution, # so we hack away block_suffix = "" if not newdata[-1]: diff --git a/lib-python/2.7/idlelib/HISTORY.txt b/lib-python/2.7/idlelib/HISTORY.txt --- a/lib-python/2.7/idlelib/HISTORY.txt +++ b/lib-python/2.7/idlelib/HISTORY.txt @@ -13,7 +13,7 @@ - New tarball released as a result of the 'revitalisation' of the IDLEfork project. -- This release requires python 2.1 or better. Compatability with earlier +- This release requires python 2.1 or better. Compatibility with earlier versions of python (especially ancient ones like 1.5x) is no longer a priority in IDLEfork development. diff --git a/lib-python/2.7/idlelib/IOBinding.py b/lib-python/2.7/idlelib/IOBinding.py --- a/lib-python/2.7/idlelib/IOBinding.py +++ b/lib-python/2.7/idlelib/IOBinding.py @@ -320,17 +320,20 @@ return "yes" message = "Do you want to save %s before closing?" % ( self.filename or "this untitled document") - m = tkMessageBox.Message( - title="Save On Close", - message=message, - icon=tkMessageBox.QUESTION, - type=tkMessageBox.YESNOCANCEL, - master=self.text) - reply = m.show() - if reply == "yes": + confirm = tkMessageBox.askyesnocancel( + title="Save On Close", + message=message, + default=tkMessageBox.YES, + master=self.text) + if confirm: + reply = "yes" self.save(None) if not self.get_saved(): reply = "cancel" + elif confirm is None: + reply = "cancel" + else: + reply = "no" self.text.focus_set() return reply @@ -339,7 +342,7 @@ self.save_as(event) else: if self.writefile(self.filename): - self.set_saved(1) + self.set_saved(True) try: self.editwin.store_file_breaks() except AttributeError: # may be a PyShell @@ -465,15 +468,12 @@ self.text.insert("end-1c", "\n") def print_window(self, event): - m = tkMessageBox.Message( - title="Print", - message="Print to Default Printer", - icon=tkMessageBox.QUESTION, - type=tkMessageBox.OKCANCEL, - default=tkMessageBox.OK, - master=self.text) - reply = m.show() - if reply != tkMessageBox.OK: + confirm = tkMessageBox.askokcancel( + title="Print", + message="Print to Default Printer", + default=tkMessageBox.OK, + master=self.text) + if not confirm: self.text.focus_set() return "break" tempfilename = None @@ -488,8 +488,8 @@ if not self.writefile(tempfilename): os.unlink(tempfilename) return "break" - platform=os.name - printPlatform=1 + platform = os.name + printPlatform = True if platform == 'posix': #posix platform command = idleConf.GetOption('main','General', 'print-command-posix') @@ -497,7 +497,7 @@ elif platform == 'nt': #win32 platform command = idleConf.GetOption('main','General','print-command-win') else: #no printing for this platform - printPlatform=0 + printPlatform = False if printPlatform: #we can try to print for this platform command = command % filename pipe = os.popen(command, "r") @@ -511,7 +511,7 @@ output = "Printing command: %s\n" % repr(command) + output tkMessageBox.showerror("Print status", output, master=self.text) else: #no printing for this platform - message="Printing is not enabled for this platform: %s" % platform + message = "Printing is not enabled for this platform: %s" % platform tkMessageBox.showinfo("Print status", message, master=self.text) if tempfilename: os.unlink(tempfilename) diff --git a/lib-python/2.7/idlelib/NEWS.txt b/lib-python/2.7/idlelib/NEWS.txt --- a/lib-python/2.7/idlelib/NEWS.txt +++ b/lib-python/2.7/idlelib/NEWS.txt @@ -1,3 +1,18 @@ +What's New in IDLE 2.7.2? +======================= + +*Release date: 29-May-2011* + +- Issue #6378: Further adjust idle.bat to start associated Python + +- Issue #11896: Save on Close failed despite selecting "Yes" in dialog. + +- toggle failing on Tk 8.5, causing IDLE exits and strange selection + behavior. Issue 4676. Improve selection extension behaviour. + +- toggle non-functional when NumLock set on Windows. Issue 3851. + + What's New in IDLE 2.7? ======================= @@ -21,7 +36,7 @@ - Tk 8.5 Text widget requires 'wordprocessor' tabstyle attr to handle mixed space/tab properly. Issue 5129, patch by Guilherme Polo. - + - Issue #3549: On MacOS the preferences menu was not present diff --git a/lib-python/2.7/idlelib/PyShell.py b/lib-python/2.7/idlelib/PyShell.py --- a/lib-python/2.7/idlelib/PyShell.py +++ b/lib-python/2.7/idlelib/PyShell.py @@ -1432,6 +1432,13 @@ shell.interp.prepend_syspath(script) shell.interp.execfile(script) + # Check for problematic OS X Tk versions and print a warning message + # in the IDLE shell window; this is less intrusive than always opening + # a separate window. + tkversionwarning = macosxSupport.tkVersionWarning(root) + if tkversionwarning: + shell.interp.runcommand(''.join(("print('", tkversionwarning, "')"))) + root.mainloop() root.destroy() diff --git a/lib-python/2.7/idlelib/ScriptBinding.py b/lib-python/2.7/idlelib/ScriptBinding.py --- a/lib-python/2.7/idlelib/ScriptBinding.py +++ b/lib-python/2.7/idlelib/ScriptBinding.py @@ -26,6 +26,7 @@ from idlelib import PyShell from idlelib.configHandler import idleConf +from idlelib import macosxSupport IDENTCHARS = string.ascii_letters + string.digits + "_" @@ -53,6 +54,9 @@ self.flist = self.editwin.flist self.root = self.editwin.root + if macosxSupport.runningAsOSXApp(): + self.editwin.text_frame.bind('<>', self._run_module_event) + def check_module_event(self, event): filename = self.getfilename() if not filename: @@ -166,6 +170,19 @@ interp.runcode(code) return 'break' + if macosxSupport.runningAsOSXApp(): + # Tk-Cocoa in MacOSX is broken until at least + # Tk 8.5.9, and without this rather + # crude workaround IDLE would hang when a user + # tries to run a module using the keyboard shortcut + # (the menu item works fine). + _run_module_event = run_module_event + + def run_module_event(self, event): + self.editwin.text_frame.after(200, + lambda: self.editwin.text_frame.event_generate('<>')) + return 'break' + def getfilename(self): """Get source filename. If not saved, offer to save (or create) file @@ -184,9 +201,9 @@ if autosave and filename: self.editwin.io.save(None) else: - reply = self.ask_save_dialog() + confirm = self.ask_save_dialog() self.editwin.text.focus_set() - if reply == "ok": + if confirm: self.editwin.io.save(None) filename = self.editwin.io.filename else: @@ -195,13 +212,11 @@ def ask_save_dialog(self): msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?" - mb = tkMessageBox.Message(title="Save Before Run or Check", - message=msg, - icon=tkMessageBox.QUESTION, - type=tkMessageBox.OKCANCEL, - default=tkMessageBox.OK, - master=self.editwin.text) - return mb.show() + confirm = tkMessageBox.askokcancel(title="Save Before Run or Check", + message=msg, + default=tkMessageBox.OK, + master=self.editwin.text) + return confirm def errorbox(self, title, message): # XXX This should really be a function of EditorWindow... diff --git a/lib-python/2.7/idlelib/config-keys.def b/lib-python/2.7/idlelib/config-keys.def --- a/lib-python/2.7/idlelib/config-keys.def +++ b/lib-python/2.7/idlelib/config-keys.def @@ -176,7 +176,7 @@ redo = close-window = restart-shell = -save-window-as-file = +save-window-as-file = close-all-windows = view-restart = tabify-region = @@ -208,7 +208,7 @@ open-module = find-selection = python-context-help = -save-copy-of-window-as-file = +save-copy-of-window-as-file = open-window-from-file = python-docs = diff --git a/lib-python/2.7/idlelib/extend.txt b/lib-python/2.7/idlelib/extend.txt --- a/lib-python/2.7/idlelib/extend.txt +++ b/lib-python/2.7/idlelib/extend.txt @@ -18,7 +18,7 @@ An IDLE extension class is instantiated with a single argument, `editwin', an EditorWindow instance. The extension cannot assume much -about this argument, but it is guarateed to have the following instance +about this argument, but it is guaranteed to have the following instance variables: text a Text instance (a widget) diff --git a/lib-python/2.7/idlelib/idle.bat b/lib-python/2.7/idlelib/idle.bat --- a/lib-python/2.7/idlelib/idle.bat +++ b/lib-python/2.7/idlelib/idle.bat @@ -1,4 +1,4 @@ @echo off rem Start IDLE using the appropriate Python interpreter set CURRDIR=%~dp0 -start "%CURRDIR%..\..\pythonw.exe" "%CURRDIR%idle.pyw" %1 %2 %3 %4 %5 %6 %7 %8 %9 +start "IDLE" "%CURRDIR%..\..\pythonw.exe" "%CURRDIR%idle.pyw" %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/lib-python/2.7/idlelib/idlever.py b/lib-python/2.7/idlelib/idlever.py --- a/lib-python/2.7/idlelib/idlever.py +++ b/lib-python/2.7/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "2.7.1" +IDLE_VERSION = "2.7.2" diff --git a/lib-python/2.7/idlelib/macosxSupport.py b/lib-python/2.7/idlelib/macosxSupport.py --- a/lib-python/2.7/idlelib/macosxSupport.py +++ b/lib-python/2.7/idlelib/macosxSupport.py @@ -4,6 +4,7 @@ """ import sys import Tkinter +from os import path _appbundle = None @@ -19,10 +20,41 @@ _appbundle = (sys.platform == 'darwin' and '.app' in sys.executable) return _appbundle +_carbonaquatk = None + +def isCarbonAquaTk(root): + """ + Returns True if IDLE is using a Carbon Aqua Tk (instead of the + newer Cocoa Aqua Tk). + """ + global _carbonaquatk + if _carbonaquatk is None: + _carbonaquatk = (runningAsOSXApp() and + 'aqua' in root.tk.call('tk', 'windowingsystem') and + 'AppKit' not in root.tk.call('winfo', 'server', '.')) + return _carbonaquatk + +def tkVersionWarning(root): + """ + Returns a string warning message if the Tk version in use appears to + be one known to cause problems with IDLE. The Apple Cocoa-based Tk 8.5 + that was shipped with Mac OS X 10.6. + """ + + if (runningAsOSXApp() and + ('AppKit' in root.tk.call('winfo', 'server', '.')) and + (root.tk.call('info', 'patchlevel') == '8.5.7') ): + return (r"WARNING: The version of Tcl/Tk (8.5.7) in use may" + r" be unstable.\n" + r"Visit http://www.python.org/download/mac/tcltk/" + r" for current information.") + else: + return False + def addOpenEventSupport(root, flist): """ - This ensures that the application will respont to open AppleEvents, which - makes is feaseable to use IDLE as the default application for python files. + This ensures that the application will respond to open AppleEvents, which + makes is feasible to use IDLE as the default application for python files. """ def doOpenFile(*args): for fn in args: @@ -79,9 +111,6 @@ WindowList.add_windows_to_menu(menu) WindowList.register_callback(postwindowsmenu) - menudict['application'] = menu = Menu(menubar, name='apple') - menubar.add_cascade(label='IDLE', menu=menu) - def about_dialog(event=None): from idlelib import aboutDialog aboutDialog.AboutDialog(root, 'About IDLE') @@ -91,41 +120,45 @@ root.instance_dict = flist.inversedict configDialog.ConfigDialog(root, 'Settings') + def help_dialog(event=None): + from idlelib import textView + fn = path.join(path.abspath(path.dirname(__file__)), 'help.txt') + textView.view_file(root, 'Help', fn) root.bind('<>', about_dialog) root.bind('<>', config_dialog) + root.createcommand('::tk::mac::ShowPreferences', config_dialog) if flist: root.bind('<>', flist.close_all_callback) + # The binding above doesn't reliably work on all versions of Tk + # on MacOSX. Adding command definition below does seem to do the + # right thing for now. + root.createcommand('exit', flist.close_all_callback) - ###check if Tk version >= 8.4.14; if so, use hard-coded showprefs binding - tkversion = root.tk.eval('info patchlevel') - # Note: we cannot check if the string tkversion >= '8.4.14', because - # the string '8.4.7' is greater than the string '8.4.14'. - if tuple(map(int, tkversion.split('.'))) >= (8, 4, 14): - Bindings.menudefs[0] = ('application', [ + if isCarbonAquaTk(root): + # for Carbon AquaTk, replace the default Tk apple menu + menudict['application'] = menu = Menu(menubar, name='apple') + menubar.add_cascade(label='IDLE', menu=menu) + Bindings.menudefs.insert(0, + ('application', [ ('About IDLE', '<>'), - None, - ]) - root.createcommand('::tk::mac::ShowPreferences', config_dialog) + None, + ])) + tkversion = root.tk.eval('info patchlevel') + if tuple(map(int, tkversion.split('.'))) < (8, 4, 14): + # for earlier AquaTk versions, supply a Preferences menu item + Bindings.menudefs[0][1].append( + ('_Preferences....', '<>'), + ) else: - for mname, entrylist in Bindings.menudefs: - menu = menudict.get(mname) - if not menu: - continue - else: - for entry in entrylist: - if not entry: - menu.add_separator() - else: - label, eventname = entry - underline, label = prepstr(label) - accelerator = get_accelerator(Bindings.default_keydefs, - eventname) - def command(text=root, eventname=eventname): - text.event_generate(eventname) - menu.add_command(label=label, underline=underline, - command=command, accelerator=accelerator) + # assume Cocoa AquaTk + # replace default About dialog with About IDLE one + root.createcommand('tkAboutDialog', about_dialog) + # replace default "Help" item in Help menu + root.createcommand('::tk::mac::ShowHelp', help_dialog) + # remove redundant "IDLE Help" from menu + del Bindings.menudefs[-1][1][0] def setupApp(root, flist): """ diff --git a/lib-python/2.7/imaplib.py b/lib-python/2.7/imaplib.py --- a/lib-python/2.7/imaplib.py +++ b/lib-python/2.7/imaplib.py @@ -1158,28 +1158,17 @@ self.port = port self.sock = socket.create_connection((host, port)) self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile) + self.file = self.sslobj.makefile('rb') def read(self, size): """Read 'size' bytes from remote.""" - # sslobj.read() sometimes returns < size bytes - chunks = [] - read = 0 - while read < size: - data = self.sslobj.read(min(size-read, 16384)) - read += len(data) - chunks.append(data) - - return ''.join(chunks) + return self.file.read(size) def readline(self): """Read line from remote.""" - line = [] - while 1: - char = self.sslobj.read(1) - line.append(char) - if char in ("\n", ""): return ''.join(line) + return self.file.readline() def send(self, data): @@ -1195,6 +1184,7 @@ def shutdown(self): """Close I/O established in "open".""" + self.file.close() self.sock.close() @@ -1321,9 +1311,10 @@ 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12} def Internaldate2tuple(resp): - """Convert IMAP4 INTERNALDATE to UT. + """Parse an IMAP4 INTERNALDATE string. - Returns Python time module tuple. + Return corresponding local time. The return value is a + time.struct_time instance or None if the string has wrong format. """ mo = InternalDate.match(resp) @@ -1390,9 +1381,14 @@ def Time2Internaldate(date_time): - """Convert 'date_time' to IMAP4 INTERNALDATE representation. + """Convert date_time to IMAP4 INTERNALDATE representation. - Return string in form: '"DD-Mmm-YYYY HH:MM:SS +HHMM"' + Return string in form: '"DD-Mmm-YYYY HH:MM:SS +HHMM"'. The + date_time argument can be a number (int or float) representing + seconds since epoch (as returned by time.time()), a 9-tuple + representing local time (as returned by time.localtime()), or a + double-quoted string. In the last case, it is assumed to already + be in the correct format. """ if isinstance(date_time, (int, float)): diff --git a/lib-python/2.7/inspect.py b/lib-python/2.7/inspect.py --- a/lib-python/2.7/inspect.py +++ b/lib-python/2.7/inspect.py @@ -746,8 +746,15 @@ 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" if not iscode(co): - raise TypeError('{!r} is not a code object'.format(co)) + if hasattr(len, 'func_code') and type(co) is type(len.func_code): + # PyPy extension: built-in function objects have a func_code too. + # There is no co_code on it, but co_argcount and co_varnames and + # co_flags are present. + pass + else: + raise TypeError('{!r} is not a code object'.format(co)) + code = getattr(co, 'co_code', '') nargs = co.co_argcount names = co.co_varnames args = list(names[:nargs]) @@ -757,12 +764,12 @@ for i in range(nargs): if args[i][:1] in ('', '.'): stack, remain, count = [], [], [] - while step < len(co.co_code): - op = ord(co.co_code[step]) + while step < len(code): + op = ord(code[step]) step = step + 1 if op >= dis.HAVE_ARGUMENT: opname = dis.opname[op] - value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256 + value = ord(code[step]) + ord(code[step+1])*256 step = step + 2 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): remain.append(value) @@ -809,7 +816,9 @@ if ismethod(func): func = func.im_func - if not isfunction(func): + if not (isfunction(func) or + isbuiltin(func) and hasattr(func, 'func_code')): + # PyPy extension: this works for built-in functions too raise TypeError('{!r} is not a Python function'.format(func)) args, varargs, varkw = getargs(func.func_code) return ArgSpec(args, varargs, varkw, func.func_defaults) @@ -943,8 +952,14 @@ f_name, 'at most' if defaults else 'exactly', num_args, 'arguments' if num_args > 1 else 'argument', num_total)) elif num_args == 0 and num_total: - raise TypeError('%s() takes no arguments (%d given)' % - (f_name, num_total)) + if varkw: + if num_pos: + # XXX: We should use num_pos, but Python also uses num_total: + raise TypeError('%s() takes exactly 0 arguments ' + '(%d given)' % (f_name, num_total)) + else: + raise TypeError('%s() takes no argument (%d given)' % + (f_name, num_total)) for arg in args: if isinstance(arg, str) and arg in named: if is_assigned(arg): diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -4,7 +4,7 @@ import sys import struct -from json.scanner import make_scanner +from json import scanner try: from _json import scanstring as c_scanstring except ImportError: @@ -161,6 +161,12 @@ nextchar = s[end:end + 1] # Trivial empty object if nextchar == '}': + if object_pairs_hook is not None: + result = object_pairs_hook(pairs) + return result, end + pairs = {} + if object_hook is not None: + pairs = object_hook(pairs) return pairs, end + 1 elif nextchar != '"': raise ValueError(errmsg("Expecting property name", s, end)) @@ -350,7 +356,7 @@ self.parse_object = JSONObject self.parse_array = JSONArray self.parse_string = scanstring - self.scan_once = make_scanner(self) + self.scan_once = scanner.make_scanner(self) def decode(self, s, _w=WHITESPACE.match): """Return the Python representation of ``s`` (a ``str`` or ``unicode`` diff --git a/lib-python/2.7/json/encoder.py b/lib-python/2.7/json/encoder.py --- a/lib-python/2.7/json/encoder.py +++ b/lib-python/2.7/json/encoder.py @@ -2,14 +2,7 @@ """ import re -try: - from _json import encode_basestring_ascii as c_encode_basestring_ascii -except ImportError: - c_encode_basestring_ascii = None -try: - from _json import make_encoder as c_make_encoder -except ImportError: - c_make_encoder = None +from __pypy__.builders import StringBuilder, UnicodeBuilder ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]') ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') @@ -24,23 +17,22 @@ '\t': '\\t', } for i in range(0x20): - ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) - #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) + ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) # Assume this produces an infinity on all machines (probably not guaranteed) INFINITY = float('1e66666') FLOAT_REPR = repr -def encode_basestring(s): +def raw_encode_basestring(s): """Return a JSON representation of a Python string """ def replace(match): return ESCAPE_DCT[match.group(0)] - return '"' + ESCAPE.sub(replace, s) + '"' + return ESCAPE.sub(replace, s) +encode_basestring = lambda s: '"' + raw_encode_basestring(s) + '"' - -def py_encode_basestring_ascii(s): +def raw_encode_basestring_ascii(s): """Return an ASCII-only JSON representation of a Python string """ @@ -53,21 +45,19 @@ except KeyError: n = ord(s) if n < 0x10000: - return '\\u{0:04x}'.format(n) - #return '\\u%04x' % (n,) + return '\\u%04x' % (n,) else: # surrogate pair n -= 0x10000 s1 = 0xd800 | ((n >> 10) & 0x3ff) s2 = 0xdc00 | (n & 0x3ff) - return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) - #return '\\u%04x\\u%04x' % (s1, s2) - return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' + return '\\u%04x\\u%04x' % (s1, s2) + if ESCAPE_ASCII.search(s): + return str(ESCAPE_ASCII.sub(replace, s)) + return s +encode_basestring_ascii = lambda s: '"' + raw_encode_basestring_ascii(s) + '"' -encode_basestring_ascii = ( - c_encode_basestring_ascii or py_encode_basestring_ascii) - class JSONEncoder(object): """Extensible JSON encoder for Python data structures. @@ -147,6 +137,17 @@ self.skipkeys = skipkeys self.ensure_ascii = ensure_ascii + if ensure_ascii: + self.encoder = raw_encode_basestring_ascii + else: + self.encoder = raw_encode_basestring + if encoding != 'utf-8': + orig_encoder = self.encoder + def encoder(o): + if isinstance(o, str): + o = o.decode(encoding) + return orig_encoder(o) + self.encoder = encoder self.check_circular = check_circular self.allow_nan = allow_nan self.sort_keys = sort_keys @@ -184,24 +185,126 @@ '{"foo": ["bar", "baz"]}' """ - # This is for extremely simple cases and benchmarks. + if self.check_circular: + markers = {} + else: + markers = None + if self.ensure_ascii: + builder = StringBuilder() + else: + builder = UnicodeBuilder() + self._encode(o, markers, builder, 0) + return builder.build() + + def _emit_indent(self, builder, _current_indent_level): + if self.indent is not None: + _current_indent_level += 1 + newline_indent = '\n' + (' ' * (self.indent * + _current_indent_level)) + separator = self.item_separator + newline_indent + builder.append(newline_indent) + else: + separator = self.item_separator + return separator, _current_indent_level + + def _emit_unindent(self, builder, _current_indent_level): + if self.indent is not None: + builder.append('\n') + builder.append(' ' * (self.indent * (_current_indent_level - 1))) + + def _encode(self, o, markers, builder, _current_indent_level): if isinstance(o, basestring): - if isinstance(o, str): - _encoding = self.encoding - if (_encoding is not None - and not (_encoding == 'utf-8')): - o = o.decode(_encoding) - if self.ensure_ascii: - return encode_basestring_ascii(o) + builder.append('"') + builder.append(self.encoder(o)) + builder.append('"') + elif o is None: + builder.append('null') + elif o is True: + builder.append('true') + elif o is False: + builder.append('false') + elif isinstance(o, (int, long)): + builder.append(str(o)) + elif isinstance(o, float): + builder.append(self._floatstr(o)) + elif isinstance(o, (list, tuple)): + if not o: + builder.append('[]') + return + self._encode_list(o, markers, builder, _current_indent_level) + elif isinstance(o, dict): + if not o: + builder.append('{}') + return + self._encode_dict(o, markers, builder, _current_indent_level) + else: + self._mark_markers(markers, o) + res = self.default(o) + self._encode(res, markers, builder, _current_indent_level) + self._remove_markers(markers, o) + return res + + def _encode_list(self, l, markers, builder, _current_indent_level): + self._mark_markers(markers, l) + builder.append('[') + first = True + separator, _current_indent_level = self._emit_indent(builder, + _current_indent_level) + for elem in l: + if first: + first = False else: - return encode_basestring(o) - # This doesn't pass the iterator directly to ''.join() because the - # exceptions aren't as detailed. The list call should be roughly - # equivalent to the PySequence_Fast that ''.join() would do. - chunks = self.iterencode(o, _one_shot=True) - if not isinstance(chunks, (list, tuple)): - chunks = list(chunks) - return ''.join(chunks) + builder.append(separator) + self._encode(elem, markers, builder, _current_indent_level) + del elem # XXX grumble + self._emit_unindent(builder, _current_indent_level) + builder.append(']') + self._remove_markers(markers, l) + + def _encode_dict(self, d, markers, builder, _current_indent_level): + self._mark_markers(markers, d) + first = True + builder.append('{') + separator, _current_indent_level = self._emit_indent(builder, + _current_indent_level) + if self.sort_keys: + items = sorted(d.items(), key=lambda kv: kv[0]) + else: + items = d.iteritems() + + for key, v in items: + if first: + first = False + else: + builder.append(separator) + if isinstance(key, basestring): + pass + # JavaScript is weakly typed for these, so it makes sense to + # also allow them. Many encoders seem to do something like this. + elif isinstance(key, float): + key = self._floatstr(key) + elif key is True: + key = 'true' + elif key is False: + key = 'false' + elif key is None: + key = 'null' + elif isinstance(key, (int, long)): + key = str(key) + elif self.skipkeys: + continue + else: + raise TypeError("key " + repr(key) + " is not a string") + builder.append('"') + builder.append(self.encoder(key)) + builder.append('"') + builder.append(self.key_separator) + self._encode(v, markers, builder, _current_indent_level) + del key + del v # XXX grumble + self._emit_unindent(builder, _current_indent_level) + builder.append('}') + self._remove_markers(markers, d) def iterencode(self, o, _one_shot=False): """Encode the given object and yield each string @@ -217,86 +320,54 @@ markers = {} else: markers = None - if self.ensure_ascii: - _encoder = encode_basestring_ascii + return self._iterencode(o, markers, 0) + + def _floatstr(self, o): + # Check for specials. Note that this type of test is processor + # and/or platform-specific, so do tests which don't depend on the + # internals. + + if o != o: + text = 'NaN' + elif o == INFINITY: + text = 'Infinity' + elif o == -INFINITY: + text = '-Infinity' else: - _encoder = encode_basestring - if self.encoding != 'utf-8': - def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): - if isinstance(o, str): - o = o.decode(_encoding) - return _orig_encoder(o) + return FLOAT_REPR(o) - def floatstr(o, allow_nan=self.allow_nan, - _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY): - # Check for specials. Note that this type of test is processor - # and/or platform-specific, so do tests which don't depend on the - # internals. + if not self.allow_nan: + raise ValueError( + "Out of range float values are not JSON compliant: " + + repr(o)) - if o != o: - text = 'NaN' - elif o == _inf: - text = 'Infinity' - elif o == _neginf: - text = '-Infinity' - else: - return _repr(o) + return text - if not allow_nan: - raise ValueError( - "Out of range float values are not JSON compliant: " + - repr(o)) + def _mark_markers(self, markers, o): + if markers is not None: + if id(o) in markers: + raise ValueError("Circular reference detected") + markers[id(o)] = None - return text + def _remove_markers(self, markers, o): + if markers is not None: + del markers[id(o)] - - if (_one_shot and c_make_encoder is not None - and not self.indent and not self.sort_keys): - _iterencode = c_make_encoder( - markers, self.default, _encoder, self.indent, - self.key_separator, self.item_separator, self.sort_keys, - self.skipkeys, self.allow_nan) - else: - _iterencode = _make_iterencode( - markers, self.default, _encoder, self.indent, floatstr, - self.key_separator, self.item_separator, self.sort_keys, - self.skipkeys, _one_shot) - return _iterencode(o, 0) - -def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, - _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot, - ## HACK: hand-optimized bytecode; turn globals into locals - ValueError=ValueError, - basestring=basestring, - dict=dict, - float=float, - id=id, - int=int, - isinstance=isinstance, - list=list, - long=long, - str=str, - tuple=tuple, - ): - - def _iterencode_list(lst, _current_indent_level): + def _iterencode_list(self, lst, markers, _current_indent_level): if not lst: yield '[]' return - if markers is not None: - markerid = id(lst) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = lst + self._mark_markers(markers, lst) buf = '[' - if _indent is not None: + if self.indent is not None: _current_indent_level += 1 - newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) - separator = _item_separator + newline_indent + newline_indent = '\n' + (' ' * (self.indent * + _current_indent_level)) + separator = self.item_separator + newline_indent buf += newline_indent else: newline_indent = None - separator = _item_separator + separator = self.item_separator first = True for value in lst: if first: @@ -304,7 +375,7 @@ else: buf = separator if isinstance(value, basestring): - yield buf + _encoder(value) + yield buf + '"' + self.encoder(value) + '"' elif value is None: yield buf + 'null' elif value is True: @@ -314,44 +385,43 @@ elif isinstance(value, (int, long)): yield buf + str(value) elif isinstance(value, float): - yield buf + _floatstr(value) + yield buf + self._floatstr(value) else: yield buf if isinstance(value, (list, tuple)): - chunks = _iterencode_list(value, _current_indent_level) + chunks = self._iterencode_list(value, markers, + _current_indent_level) elif isinstance(value, dict): - chunks = _iterencode_dict(value, _current_indent_level) + chunks = self._iterencode_dict(value, markers, + _current_indent_level) else: - chunks = _iterencode(value, _current_indent_level) + chunks = self._iterencode(value, markers, + _current_indent_level) for chunk in chunks: yield chunk if newline_indent is not None: _current_indent_level -= 1 - yield '\n' + (' ' * (_indent * _current_indent_level)) + yield '\n' + (' ' * (self.indent * _current_indent_level)) yield ']' - if markers is not None: - del markers[markerid] + self._remove_markers(markers, lst) - def _iterencode_dict(dct, _current_indent_level): + def _iterencode_dict(self, dct, markers, _current_indent_level): if not dct: yield '{}' return - if markers is not None: - markerid = id(dct) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = dct + self._mark_markers(markers, dct) yield '{' - if _indent is not None: + if self.indent is not None: _current_indent_level += 1 - newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) - item_separator = _item_separator + newline_indent + newline_indent = '\n' + (' ' * (self.indent * + _current_indent_level)) + item_separator = self.item_separator + newline_indent yield newline_indent else: newline_indent = None - item_separator = _item_separator + item_separator = self.item_separator first = True - if _sort_keys: + if self.sort_keys: items = sorted(dct.items(), key=lambda kv: kv[0]) else: items = dct.iteritems() @@ -361,7 +431,7 @@ # JavaScript is weakly typed for these, so it makes sense to # also allow them. Many encoders seem to do something like this. elif isinstance(key, float): - key = _floatstr(key) + key = self._floatstr(key) elif key is True: key = 'true' elif key is False: @@ -370,7 +440,7 @@ key = 'null' elif isinstance(key, (int, long)): key = str(key) - elif _skipkeys: + elif self.skipkeys: continue else: raise TypeError("key " + repr(key) + " is not a string") @@ -378,10 +448,10 @@ first = False else: yield item_separator - yield _encoder(key) - yield _key_separator + yield '"' + self.encoder(key) + '"' + yield self.key_separator if isinstance(value, basestring): - yield _encoder(value) + yield '"' + self.encoder(value) + '"' elif value is None: yield 'null' elif value is True: @@ -391,26 +461,28 @@ elif isinstance(value, (int, long)): yield str(value) elif isinstance(value, float): - yield _floatstr(value) + yield self._floatstr(value) else: if isinstance(value, (list, tuple)): - chunks = _iterencode_list(value, _current_indent_level) + chunks = self._iterencode_list(value, markers, + _current_indent_level) elif isinstance(value, dict): - chunks = _iterencode_dict(value, _current_indent_level) + chunks = self._iterencode_dict(value, markers, + _current_indent_level) else: - chunks = _iterencode(value, _current_indent_level) + chunks = self._iterencode(value, markers, + _current_indent_level) for chunk in chunks: yield chunk if newline_indent is not None: _current_indent_level -= 1 - yield '\n' + (' ' * (_indent * _current_indent_level)) + yield '\n' + (' ' * (self.indent * _current_indent_level)) yield '}' - if markers is not None: - del markers[markerid] + self._remove_markers(markers, dct) - def _iterencode(o, _current_indent_level): + def _iterencode(self, o, markers, _current_indent_level): if isinstance(o, basestring): - yield _encoder(o) + yield '"' + self.encoder(o) + '"' elif o is None: yield 'null' elif o is True: @@ -420,23 +492,19 @@ elif isinstance(o, (int, long)): yield str(o) elif isinstance(o, float): - yield _floatstr(o) + yield self._floatstr(o) elif isinstance(o, (list, tuple)): - for chunk in _iterencode_list(o, _current_indent_level): + for chunk in self._iterencode_list(o, markers, + _current_indent_level): yield chunk elif isinstance(o, dict): - for chunk in _iterencode_dict(o, _current_indent_level): + for chunk in self._iterencode_dict(o, markers, + _current_indent_level): yield chunk else: - if markers is not None: - markerid = id(o) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = o - o = _default(o) - for chunk in _iterencode(o, _current_indent_level): + self._mark_markers(markers, o) + obj = self.default(o) + for chunk in self._iterencode(obj, markers, + _current_indent_level): yield chunk - if markers is not None: - del markers[markerid] - - return _iterencode + self._remove_markers(markers, o) diff --git a/lib-python/2.7/json/tests/__init__.py b/lib-python/2.7/json/tests/__init__.py --- a/lib-python/2.7/json/tests/__init__.py +++ b/lib-python/2.7/json/tests/__init__.py @@ -1,7 +1,46 @@ import os import sys +import json +import doctest import unittest -import doctest + +from test import test_support + +# import json with and without accelerations +cjson = test_support.import_fresh_module('json', fresh=['_json']) +pyjson = test_support.import_fresh_module('json', blocked=['_json']) + +# create two base classes that will be used by the other tests +class PyTest(unittest.TestCase): + json = pyjson + loads = staticmethod(pyjson.loads) + dumps = staticmethod(pyjson.dumps) + + at unittest.skipUnless(cjson, 'requires _json') +class CTest(unittest.TestCase): + if cjson is not None: + json = cjson + loads = staticmethod(cjson.loads) + dumps = staticmethod(cjson.dumps) + +# test PyTest and CTest checking if the functions come from the right module +class TestPyTest(PyTest): + def test_pyjson(self): + self.assertEqual(self.json.scanner.make_scanner.__module__, + 'json.scanner') + self.assertEqual(self.json.decoder.scanstring.__module__, + 'json.decoder') + self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__, + 'json.encoder') + +class TestCTest(CTest): + def test_cjson(self): + self.assertEqual(self.json.scanner.make_scanner.__module__, '_json') + self.assertEqual(self.json.decoder.scanstring.__module__, '_json') + self.assertEqual(self.json.encoder.c_make_encoder.__module__, '_json') + self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__, + '_json') + here = os.path.dirname(__file__) @@ -17,12 +56,11 @@ return suite def additional_tests(): - import json - import json.encoder - import json.decoder suite = unittest.TestSuite() for mod in (json, json.encoder, json.decoder): suite.addTest(doctest.DocTestSuite(mod)) + suite.addTest(TestPyTest('test_pyjson')) + suite.addTest(TestCTest('test_cjson')) return suite def main(): diff --git a/lib-python/2.7/json/tests/test_check_circular.py b/lib-python/2.7/json/tests/test_check_circular.py --- a/lib-python/2.7/json/tests/test_check_circular.py +++ b/lib-python/2.7/json/tests/test_check_circular.py @@ -1,30 +1,34 @@ -from unittest import TestCase -import json +from json.tests import PyTest, CTest + def default_iterable(obj): return list(obj) -class TestCheckCircular(TestCase): +class TestCheckCircular(object): def test_circular_dict(self): dct = {} dct['a'] = dct - self.assertRaises(ValueError, json.dumps, dct) + self.assertRaises(ValueError, self.dumps, dct) def test_circular_list(self): lst = [] lst.append(lst) - self.assertRaises(ValueError, json.dumps, lst) + self.assertRaises(ValueError, self.dumps, lst) def test_circular_composite(self): dct2 = {} dct2['a'] = [] dct2['a'].append(dct2) - self.assertRaises(ValueError, json.dumps, dct2) + self.assertRaises(ValueError, self.dumps, dct2) def test_circular_default(self): - json.dumps([set()], default=default_iterable) - self.assertRaises(TypeError, json.dumps, [set()]) + self.dumps([set()], default=default_iterable) + self.assertRaises(TypeError, self.dumps, [set()]) def test_circular_off_default(self): - json.dumps([set()], default=default_iterable, check_circular=False) - self.assertRaises(TypeError, json.dumps, [set()], check_circular=False) + self.dumps([set()], default=default_iterable, check_circular=False) + self.assertRaises(TypeError, self.dumps, [set()], check_circular=False) + + +class TestPyCheckCircular(TestCheckCircular, PyTest): pass +class TestCCheckCircular(TestCheckCircular, CTest): pass diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -1,18 +1,17 @@ import decimal -from unittest import TestCase from StringIO import StringIO +from collections import OrderedDict +from json.tests import PyTest, CTest -import json -from collections import OrderedDict -class TestDecode(TestCase): +class TestDecode(object): def test_decimal(self): - rval = json.loads('1.1', parse_float=decimal.Decimal) + rval = self.loads('1.1', parse_float=decimal.Decimal) self.assertTrue(isinstance(rval, decimal.Decimal)) self.assertEqual(rval, decimal.Decimal('1.1')) def test_float(self): - rval = json.loads('1', parse_int=float) + rval = self.loads('1', parse_int=float) self.assertTrue(isinstance(rval, float)) self.assertEqual(rval, 1.0) @@ -20,22 +19,32 @@ # Several optimizations were made that skip over calls to # the whitespace regex, so this test is designed to try and # exercise the uncommon cases. The array cases are already covered. - rval = json.loads('{ "key" : "value" , "k":"v" }') + rval = self.loads('{ "key" : "value" , "k":"v" }') self.assertEqual(rval, {"key":"value", "k":"v"}) + def test_empty_objects(self): + self.assertEqual(self.loads('{}'), {}) + self.assertEqual(self.loads('[]'), []) + self.assertEqual(self.loads('""'), u"") + self.assertIsInstance(self.loads('""'), unicode) + def test_object_pairs_hook(self): s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), ("qrt", 5), ("pad", 6), ("hoy", 7)] - self.assertEqual(json.loads(s), eval(s)) - self.assertEqual(json.loads(s, object_pairs_hook=lambda x: x), p) - self.assertEqual(json.load(StringIO(s), - object_pairs_hook=lambda x: x), p) - od = json.loads(s, object_pairs_hook=OrderedDict) + self.assertEqual(self.loads(s), eval(s)) + self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p) + self.assertEqual(self.json.load(StringIO(s), + object_pairs_hook=lambda x: x), p) + od = self.loads(s, object_pairs_hook=OrderedDict) self.assertEqual(od, OrderedDict(p)) self.assertEqual(type(od), OrderedDict) # the object_pairs_hook takes priority over the object_hook - self.assertEqual(json.loads(s, + self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + + +class TestPyDecode(TestDecode, PyTest): pass +class TestCDecode(TestDecode, CTest): pass diff --git a/lib-python/2.7/json/tests/test_default.py b/lib-python/2.7/json/tests/test_default.py --- a/lib-python/2.7/json/tests/test_default.py +++ b/lib-python/2.7/json/tests/test_default.py @@ -1,9 +1,12 @@ -from unittest import TestCase +from json.tests import PyTest, CTest -import json -class TestDefault(TestCase): +class TestDefault(object): def test_default(self): self.assertEqual( - json.dumps(type, default=repr), - json.dumps(repr(type))) + self.dumps(type, default=repr), + self.dumps(repr(type))) + + +class TestPyDefault(TestDefault, PyTest): pass +class TestCDefault(TestDefault, CTest): pass diff --git a/lib-python/2.7/json/tests/test_dump.py b/lib-python/2.7/json/tests/test_dump.py --- a/lib-python/2.7/json/tests/test_dump.py +++ b/lib-python/2.7/json/tests/test_dump.py @@ -1,21 +1,23 @@ -from unittest import TestCase from cStringIO import StringIO +from json.tests import PyTest, CTest -import json -class TestDump(TestCase): +class TestDump(object): def test_dump(self): sio = StringIO() - json.dump({}, sio) + self.json.dump({}, sio) self.assertEqual(sio.getvalue(), '{}') def test_dumps(self): - self.assertEqual(json.dumps({}), '{}') + self.assertEqual(self.dumps({}), '{}') def test_encode_truefalse(self): - self.assertEqual(json.dumps( + self.assertEqual(self.dumps( {True: False, False: True}, sort_keys=True), '{"false": true, "true": false}') - self.assertEqual(json.dumps( + self.assertEqual(self.dumps( {2: 3.0, 4.0: 5L, False: 1, 6L: True}, sort_keys=True), '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') + +class TestPyDump(TestDump, PyTest): pass +class TestCDump(TestDump, CTest): pass diff --git a/lib-python/2.7/json/tests/test_encode_basestring_ascii.py b/lib-python/2.7/json/tests/test_encode_basestring_ascii.py --- a/lib-python/2.7/json/tests/test_encode_basestring_ascii.py +++ b/lib-python/2.7/json/tests/test_encode_basestring_ascii.py @@ -1,8 +1,6 @@ -from unittest import TestCase +from collections import OrderedDict +from json.tests import PyTest, CTest -import json.encoder -from json import dumps -from collections import OrderedDict CASES = [ (u'/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"'), @@ -23,19 +21,11 @@ (u'\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), ] -class TestEncodeBaseStringAscii(TestCase): - def test_py_encode_basestring_ascii(self): - self._test_encode_basestring_ascii(json.encoder.py_encode_basestring_ascii) - - def test_c_encode_basestring_ascii(self): - if not json.encoder.c_encode_basestring_ascii: - return - self._test_encode_basestring_ascii(json.encoder.c_encode_basestring_ascii) - - def _test_encode_basestring_ascii(self, encode_basestring_ascii): - fname = encode_basestring_ascii.__name__ +class TestEncodeBasestringAscii(object): + def test_encode_basestring_ascii(self): + fname = self.json.encoder.encode_basestring_ascii.__name__ for input_string, expect in CASES: - result = encode_basestring_ascii(input_string) + result = self.json.encoder.encode_basestring_ascii(input_string) self.assertEqual(result, expect, '{0!r} != {1!r} for {2}({3!r})'.format( result, expect, fname, input_string)) @@ -43,5 +33,9 @@ def test_ordered_dict(self): # See issue 6105 items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)] - s = json.dumps(OrderedDict(items)) + s = self.dumps(OrderedDict(items)) self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}') + + +class TestPyEncodeBasestringAscii(TestEncodeBasestringAscii, PyTest): pass +class TestCEncodeBasestringAscii(TestEncodeBasestringAscii, CTest): pass diff --git a/lib-python/2.7/json/tests/test_fail.py b/lib-python/2.7/json/tests/test_fail.py --- a/lib-python/2.7/json/tests/test_fail.py +++ b/lib-python/2.7/json/tests/test_fail.py @@ -1,6 +1,4 @@ -from unittest import TestCase - -import json +from json.tests import PyTest, CTest # Fri Dec 30 18:57:26 2005 JSONDOCS = [ @@ -61,15 +59,15 @@ 18: "spec doesn't specify any nesting limitations", } -class TestFail(TestCase): +class TestFail(object): def test_failures(self): for idx, doc in enumerate(JSONDOCS): idx = idx + 1 if idx in SKIPS: - json.loads(doc) + self.loads(doc) continue try: - json.loads(doc) + self.loads(doc) except ValueError: pass else: @@ -79,7 +77,11 @@ data = {'a' : 1, (1, 2) : 2} #This is for c encoder - self.assertRaises(TypeError, json.dumps, data) + self.assertRaises(TypeError, self.dumps, data) #This is for python encoder - self.assertRaises(TypeError, json.dumps, data, indent=True) + self.assertRaises(TypeError, self.dumps, data, indent=True) + + +class TestPyFail(TestFail, PyTest): pass +class TestCFail(TestFail, CTest): pass diff --git a/lib-python/2.7/json/tests/test_float.py b/lib-python/2.7/json/tests/test_float.py --- a/lib-python/2.7/json/tests/test_float.py +++ b/lib-python/2.7/json/tests/test_float.py @@ -1,19 +1,22 @@ import math -from unittest import TestCase +from json.tests import PyTest, CTest -import json -class TestFloat(TestCase): +class TestFloat(object): def test_floats(self): for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]: - self.assertEqual(float(json.dumps(num)), num) - self.assertEqual(json.loads(json.dumps(num)), num) - self.assertEqual(json.loads(unicode(json.dumps(num))), num) + self.assertEqual(float(self.dumps(num)), num) + self.assertEqual(self.loads(self.dumps(num)), num) + self.assertEqual(self.loads(unicode(self.dumps(num))), num) def test_ints(self): for num in [1, 1L, 1<<32, 1<<64]: - self.assertEqual(json.dumps(num), str(num)) - self.assertEqual(int(json.dumps(num)), num) - self.assertEqual(json.loads(json.dumps(num)), num) - self.assertEqual(json.loads(unicode(json.dumps(num))), num) + self.assertEqual(self.dumps(num), str(num)) + self.assertEqual(int(self.dumps(num)), num) + self.assertEqual(self.loads(self.dumps(num)), num) + self.assertEqual(self.loads(unicode(self.dumps(num))), num) + + +class TestPyFloat(TestFloat, PyTest): pass +class TestCFloat(TestFloat, CTest): pass diff --git a/lib-python/2.7/json/tests/test_indent.py b/lib-python/2.7/json/tests/test_indent.py --- a/lib-python/2.7/json/tests/test_indent.py +++ b/lib-python/2.7/json/tests/test_indent.py @@ -1,9 +1,9 @@ -from unittest import TestCase +import textwrap +from StringIO import StringIO +from json.tests import PyTest, CTest -import json -import textwrap -class TestIndent(TestCase): +class TestIndent(object): def test_indent(self): h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', {'nifty': 87}, {'field': 'yes', 'morefield': False} ] @@ -30,12 +30,31 @@ ]""") - d1 = json.dumps(h) - d2 = json.dumps(h, indent=2, sort_keys=True, separators=(',', ': ')) + d1 = self.dumps(h) + d2 = self.dumps(h, indent=2, sort_keys=True, separators=(',', ': ')) - h1 = json.loads(d1) - h2 = json.loads(d2) + h1 = self.loads(d1) + h2 = self.loads(d2) self.assertEqual(h1, h) self.assertEqual(h2, h) self.assertEqual(d2, expect) + + def test_indent0(self): + h = {3: 1} + def check(indent, expected): + d1 = self.dumps(h, indent=indent) + self.assertEqual(d1, expected) From noreply at buildbot.pypy.org Tue Jun 5 09:58:59 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:58:59 +0200 (CEST) Subject: [pypy-commit] pypy stm-thread: Remove the hand-waving uncertainty of gcsource, and instead Message-ID: <20120605075859.3BFD41C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-thread Changeset: r55306:62c2fc45c3a8 Date: 2012-06-04 16:51 +0200 http://bitbucket.org/pypy/pypy/changeset/62c2fc45c3a8/ Log: Remove the hand-waving uncertainty of gcsource, and instead assume that it is able to find *all* calls to functions with a GC arg or result. Tentative: this should be true because external calls and callbacks are always with functions with no GC argument. diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py --- a/pypy/translator/c/genc.py +++ b/pypy/translator/c/genc.py @@ -134,6 +134,9 @@ if self.config.translation.stm: from pypy.translator.stm import transform + self.getentrypointptr() # build the wrapper first + # ^^ this is needed to make sure we see the no-GC wrapper function + # calling the GC entrypoint function. transformer = transform.STMTransformer(self.translator) transformer.transform() diff --git a/pypy/translator/stm/gcsource.py b/pypy/translator/stm/gcsource.py --- a/pypy/translator/stm/gcsource.py +++ b/pypy/translator/stm/gcsource.py @@ -1,4 +1,4 @@ -from pypy.objspace.flow.model import Variable +from pypy.objspace.flow.model import Variable, Constant from pypy.rpython.lltypesystem import lltype, rclass from pypy.translator.simplify import get_graph @@ -25,23 +25,23 @@ # We don't have to worry about external calls and callbacks. # This works by assuming that each graph's calls are fully tracked # by the last argument to 'indirect_call'. Graphs for which we don't - # find any call like this are assumed to be called 'from the outside' - # passing any random arguments to it. + # find any call like this are assumed to be not called at all, e.g. + # as a result of having been inlined everywhere. resultlist = [] - was_a_callee = set() # def call(graph, args, result): inputargs = graph.getargs() assert len(args) == len(inputargs) for v1, v2 in zip(args, inputargs): - if is_gc(v2): - assert is_gc(v1) + ig = is_gc(v1) + assert ig is is_gc(v2) + if ig: resultlist.append((v1, v2)) - if is_gc(result): - v = graph.getreturnvar() - assert is_gc(v) + v = graph.getreturnvar() + ig = is_gc(result) + assert ig is is_gc(v) + if ig: resultlist.append((v, result)) - was_a_callee.add(graph) # for graph in translator.graphs: for block in graph.iterblocks(): @@ -61,6 +61,14 @@ continue # if op.opname == 'indirect_call': + # any GC argument or result? + for v in op.args[:-1]: + if is_gc(v): + break + else: + if not is_gc(op.result): + continue # no: ignore the indirect_call + # tographs = op.args[-1].value if tographs is not None: for tograph in tographs: @@ -79,34 +87,21 @@ if is_instantiate: resultlist.append(('instantiate', op.result)) continue + # + raise Exception("%r: unknown targets, passing GC " + "arguments or result" % (op,)) # if is_gc(op.result): resultlist.append((op, op.result)) # for link in block.exits: for v1, v2 in zip(link.args, link.target.inputargs): - if is_gc(v2): - assert is_gc(v1) + ig = is_gc(v2) + assert ig is is_gc(v1) + if ig: if v1 is link.last_exc_value: v1 = 'last_exc_value' resultlist.append((v1, v2)) - # - # also add as a callee the graphs that are explicitly callees in the - # callgraph. Useful because some graphs may end up not being called - # any more, if they were inlined. - was_originally_a_callee = set() - for _, graph in translator.callgraph.itervalues(): - was_originally_a_callee.add(graph) - # - for graph in translator.graphs: - if graph not in was_a_callee: - if graph in was_originally_a_callee: - src = 'originally_a_callee' - else: - src = 'unknown' - for v in graph.getargs(): - if is_gc(v): - resultlist.append((src, v)) return resultlist @@ -130,13 +125,13 @@ return set_of_variables def _backpropagate(self, variable): + if isinstance(variable, Constant): + return set([variable]), set() result = set() pending = [variable] seen = set(pending) for v2 in pending: - # we get a KeyError here if 'variable' is not found, - # or if one of the preceeding variables is not found - for v1 in self._backmapping[v2]: + for v1 in self._backmapping.get(v2, ()): if isinstance(v1, Variable): if v1 not in seen: seen.add(v1) diff --git a/pypy/translator/stm/localtracker.py b/pypy/translator/stm/localtracker.py --- a/pypy/translator/stm/localtracker.py +++ b/pypy/translator/stm/localtracker.py @@ -41,17 +41,7 @@ return True def _could_be_local(self, variable): - try: - srcs = self.gsrc[variable] - except KeyError: - if isinstance(variable, Constant): - srcs = [variable] - else: - # XXX we shouldn't get here, but we do translating the whole - # pypy. We should investigate at some point. In the meantime - # returning False is always safe. - self.reason = 'variable not in gsrc!' - return False + srcs = self.gsrc[variable] for src in srcs: if isinstance(src, SpaceOperation): if src.opname in RETURNS_LOCAL_POINTER: @@ -66,8 +56,6 @@ return False elif src == 'instantiate': pass - elif src == 'originally_a_callee': - pass elif isinstance(src, str): self.reason = src return False diff --git a/pypy/translator/stm/test/test_gcsource.py b/pypy/translator/stm/test/test_gcsource.py --- a/pypy/translator/stm/test/test_gcsource.py +++ b/pypy/translator/stm/test/test_gcsource.py @@ -115,7 +115,7 @@ gsrc = gcsource(main, [lltype.Ptr(lltype.GcStruct('S'))]) v_result = gsrc.translator.graphs[0].getreturnvar() s = gsrc[v_result] - assert list(s) == ['unknown'] + assert list(s) == [] def test_exception(): class FooError(Exception): From noreply at buildbot.pypy.org Tue Jun 5 09:59:06 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:59:06 +0200 (CEST) Subject: [pypy-commit] pypy stm-thread: The next thing to re-optimize: withmethodcache Message-ID: <20120605075906.235711C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-thread Changeset: r55307:34f9f1965cf7 Date: 2012-06-04 18:19 +0200 http://bitbucket.org/pypy/pypy/changeset/34f9f1965cf7/ Log: The next thing to re-optimize: withmethodcache diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -411,7 +411,7 @@ # otherwise, we get all the time spurious transaction conflicts. # For now we have one per transaction: the following field is # set when we start a transaction, and cleared just before - # committing. + # committing. XXX lies cache = space.getexecutioncontext()._methodcache else: cache = space.fromcache(MethodCache) From noreply at buildbot.pypy.org Tue Jun 5 09:59:18 2012 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 5 Jun 2012 09:59:18 +0200 (CEST) Subject: [pypy-commit] pypy release-1.9.x: merge default Message-ID: <20120605075918.A62C41C003C@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-1.9.x Changeset: r55308:426d5143ea79 Date: 2012-06-04 19:04 +0200 http://bitbucket.org/pypy/pypy/changeset/426d5143ea79/ Log: merge default diff too long, truncating to 10000 out of 220791 lines diff --git a/_pytest/__init__.py b/_pytest/__init__.py --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.1.0.dev4' +__version__ = '2.2.4.dev2' diff --git a/_pytest/assertion/__init__.py b/_pytest/assertion/__init__.py --- a/_pytest/assertion/__init__.py +++ b/_pytest/assertion/__init__.py @@ -2,35 +2,25 @@ support for presenting detailed information in failing assertions. """ import py -import imp -import marshal -import struct import sys import pytest from _pytest.monkeypatch import monkeypatch -from _pytest.assertion import reinterpret, util - -try: - from _pytest.assertion.rewrite import rewrite_asserts -except ImportError: - rewrite_asserts = None -else: - import ast +from _pytest.assertion import util def pytest_addoption(parser): group = parser.getgroup("debugconfig") - group.addoption('--assertmode', action="store", dest="assertmode", - choices=("on", "old", "off", "default"), default="default", - metavar="on|old|off", + group.addoption('--assert', action="store", dest="assertmode", + choices=("rewrite", "reinterp", "plain",), + default="rewrite", metavar="MODE", help="""control assertion debugging tools. -'off' performs no assertion debugging. -'old' reinterprets the expressions in asserts to glean information. -'on' (the default) rewrites the assert statements in test modules to provide -sub-expression results.""") +'plain' performs no assertion debugging. +'reinterp' reinterprets assert statements after they failed to provide assertion expression information. +'rewrite' (the default) rewrites assert statements in test modules on import +to provide assert expression information. """) group.addoption('--no-assert', action="store_true", default=False, - dest="noassert", help="DEPRECATED equivalent to --assertmode=off") + dest="noassert", help="DEPRECATED equivalent to --assert=plain") group.addoption('--nomagic', action="store_true", default=False, - dest="nomagic", help="DEPRECATED equivalent to --assertmode=off") + dest="nomagic", help="DEPRECATED equivalent to --assert=plain") class AssertionState: """State for the assertion plugin.""" @@ -40,89 +30,90 @@ self.trace = config.trace.root.get("assertion") def pytest_configure(config): - warn_about_missing_assertion() mode = config.getvalue("assertmode") if config.getvalue("noassert") or config.getvalue("nomagic"): - if mode not in ("off", "default"): - raise pytest.UsageError("assertion options conflict") - mode = "off" - elif mode == "default": - mode = "on" - if mode != "off": - def callbinrepr(op, left, right): - hook_result = config.hook.pytest_assertrepr_compare( - config=config, op=op, left=left, right=right) - for new_expl in hook_result: - if new_expl: - return '\n~'.join(new_expl) + mode = "plain" + if mode == "rewrite": + try: + import ast + except ImportError: + mode = "reinterp" + else: + if sys.platform.startswith('java'): + mode = "reinterp" + if mode != "plain": + _load_modules(mode) m = monkeypatch() config._cleanup.append(m.undo) m.setattr(py.builtin.builtins, 'AssertionError', reinterpret.AssertionError) - m.setattr(util, '_reprcompare', callbinrepr) - if mode == "on" and rewrite_asserts is None: - mode = "old" + hook = None + if mode == "rewrite": + hook = rewrite.AssertionRewritingHook() + sys.meta_path.append(hook) + warn_about_missing_assertion(mode) config._assertstate = AssertionState(config, mode) + config._assertstate.hook = hook config._assertstate.trace("configured with mode set to %r" % (mode,)) -def _write_pyc(co, source_path): - if hasattr(imp, "cache_from_source"): - # Handle PEP 3147 pycs. - pyc = py.path.local(imp.cache_from_source(str(source_path))) - pyc.ensure() - else: - pyc = source_path + "c" - mtime = int(source_path.mtime()) - fp = pyc.open("wb") - try: - fp.write(imp.get_magic()) - fp.write(struct.pack(" 0 and - item.identifier != "__future__"): + elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or + item.module != "__future__"): lineno = item.lineno break pos += 1 @@ -118,9 +357,9 @@ for alias in aliases] mod.body[pos:pos] = imports # Collect asserts. - nodes = collections.deque([mod]) + nodes = [mod] while nodes: - node = nodes.popleft() + node = nodes.pop() for name, field in ast.iter_fields(node): if isinstance(field, list): new = [] @@ -143,7 +382,7 @@ """Get a new variable.""" # Use a character invalid in python identifiers to avoid clashing. name = "@py_assert" + str(next(self.variable_counter)) - self.variables.add(name) + self.variables.append(name) return name def assign(self, expr): @@ -198,7 +437,8 @@ # There's already a message. Don't mess with it. return [assert_] self.statements = [] - self.variables = set() + self.cond_chain = () + self.variables = [] self.variable_counter = itertools.count() self.stack = [] self.on_failure = [] @@ -220,11 +460,11 @@ else: raise_ = ast.Raise(exc, None, None) body.append(raise_) - # Delete temporary variables. - names = [ast.Name(name, ast.Del()) for name in self.variables] - if names: - delete = ast.Delete(names) - self.statements.append(delete) + # Clear temporary variables by setting them to None. + if self.variables: + variables = [ast.Name(name, ast.Store()) for name in self.variables] + clear = ast.Assign(variables, ast.Name("None", ast.Load())) + self.statements.append(clear) # Fix line numbers. for stmt in self.statements: set_location(stmt, assert_.lineno, assert_.col_offset) @@ -240,21 +480,38 @@ return name, self.explanation_param(expr) def visit_BoolOp(self, boolop): - operands = [] - explanations = [] + res_var = self.variable() + expl_list = self.assign(ast.List([], ast.Load())) + app = ast.Attribute(expl_list, "append", ast.Load()) + is_or = int(isinstance(boolop.op, ast.Or)) + body = save = self.statements + fail_save = self.on_failure + levels = len(boolop.values) - 1 self.push_format_context() - for operand in boolop.values: - res, explanation = self.visit(operand) - operands.append(res) - explanations.append(explanation) - expls = ast.Tuple([ast.Str(expl) for expl in explanations], ast.Load()) - is_or = ast.Num(isinstance(boolop.op, ast.Or)) - expl_template = self.helper("format_boolop", - ast.Tuple(operands, ast.Load()), expls, - is_or) + # Process each operand, short-circuting if needed. + for i, v in enumerate(boolop.values): + if i: + fail_inner = [] + self.on_failure.append(ast.If(cond, fail_inner, [])) + self.on_failure = fail_inner + self.push_format_context() + res, expl = self.visit(v) + body.append(ast.Assign([ast.Name(res_var, ast.Store())], res)) + expl_format = self.pop_format_context(ast.Str(expl)) + call = ast.Call(app, [expl_format], [], None, None) + self.on_failure.append(ast.Expr(call)) + if i < levels: + cond = res + if is_or: + cond = ast.UnaryOp(ast.Not(), cond) + inner = [] + self.statements.append(ast.If(cond, inner, [])) + self.statements = body = inner + self.statements = save + self.on_failure = fail_save + expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or)) expl = self.pop_format_context(expl_template) - res = self.assign(ast.BoolOp(boolop.op, operands)) - return res, self.explanation_param(expl) + return ast.Name(res_var, ast.Load()), self.explanation_param(expl) def visit_UnaryOp(self, unary): pattern = unary_map[unary.op.__class__] @@ -288,7 +545,7 @@ new_star, expl = self.visit(call.starargs) arg_expls.append("*" + expl) if call.kwargs: - new_kwarg, expl = self.visit(call.kwarg) + new_kwarg, expl = self.visit(call.kwargs) arg_expls.append("**" + expl) expl = "%s(%s)" % (func_expl, ', '.join(arg_expls)) new_call = ast.Call(new_func, new_args, new_kwargs, new_star, new_kwarg) diff --git a/_pytest/assertion/util.py b/_pytest/assertion/util.py --- a/_pytest/assertion/util.py +++ b/_pytest/assertion/util.py @@ -2,6 +2,7 @@ import py +BuiltinAssertionError = py.builtin.builtins.AssertionError # The _reprcompare attribute on the util module is used by the new assertion # interpretation code and assertion rewriter to detect this plugin was diff --git a/_pytest/capture.py b/_pytest/capture.py --- a/_pytest/capture.py +++ b/_pytest/capture.py @@ -11,22 +11,22 @@ group._addoption('-s', action="store_const", const="no", dest="capture", help="shortcut for --capture=no.") + at pytest.mark.tryfirst +def pytest_cmdline_parse(pluginmanager, args): + # we want to perform capturing already for plugin/conftest loading + if '-s' in args or "--capture=no" in args: + method = "no" + elif hasattr(os, 'dup') and '--capture=sys' not in args: + method = "fd" + else: + method = "sys" + capman = CaptureManager(method) + pluginmanager.register(capman, "capturemanager") + def addouterr(rep, outerr): - repr = getattr(rep, 'longrepr', None) - if not hasattr(repr, 'addsection'): - return for secname, content in zip(["out", "err"], outerr): if content: - repr.addsection("Captured std%s" % secname, content.rstrip()) - -def pytest_unconfigure(config): - # registered in config.py during early conftest.py loading - capman = config.pluginmanager.getplugin('capturemanager') - while capman._method2capture: - name, cap = capman._method2capture.popitem() - # XXX logging module may wants to close it itself on process exit - # otherwise we could do finalization here and call "reset()". - cap.suspend() + rep.sections.append(("Captured std%s" % secname, content)) class NoCapture: def startall(self): @@ -39,8 +39,9 @@ return "", "" class CaptureManager: - def __init__(self): + def __init__(self, defaultmethod=None): self._method2capture = {} + self._defaultmethod = defaultmethod def _maketempfile(self): f = py.std.tempfile.TemporaryFile() @@ -65,14 +66,6 @@ else: raise ValueError("unknown capturing method: %r" % method) - def _getmethod_preoptionparse(self, args): - if '-s' in args or "--capture=no" in args: - return "no" - elif hasattr(os, 'dup') and '--capture=sys' not in args: - return "fd" - else: - return "sys" - def _getmethod(self, config, fspath): if config.option.capture: method = config.option.capture @@ -85,16 +78,22 @@ method = "sys" return method + def reset_capturings(self): + for name, cap in self._method2capture.items(): + cap.reset() + def resumecapture_item(self, item): method = self._getmethod(item.config, item.fspath) if not hasattr(item, 'outerr'): item.outerr = ('', '') # we accumulate outerr on the item return self.resumecapture(method) - def resumecapture(self, method): + def resumecapture(self, method=None): if hasattr(self, '_capturing'): raise ValueError("cannot resume, already capturing with %r" % (self._capturing,)) + if method is None: + method = self._defaultmethod cap = self._method2capture.get(method) self._capturing = method if cap is None: @@ -164,17 +163,6 @@ def pytest_runtest_teardown(self, item): self.resumecapture_item(item) - def pytest__teardown_final(self, __multicall__, session): - method = self._getmethod(session.config, None) - self.resumecapture(method) - try: - rep = __multicall__.execute() - finally: - outerr = self.suspendcapture() - if rep: - addouterr(rep, outerr) - return rep - def pytest_keyboard_interrupt(self, excinfo): if hasattr(self, '_capturing'): self.suspendcapture() diff --git a/_pytest/config.py b/_pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -8,13 +8,15 @@ def pytest_cmdline_parse(pluginmanager, args): config = Config(pluginmanager) config.parse(args) - if config.option.debug: - config.trace.root.setwriter(sys.stderr.write) return config def pytest_unconfigure(config): - for func in config._cleanup: - func() + while 1: + try: + fin = config._cleanup.pop() + except IndexError: + break + fin() class Parser: """ Parser for command line arguments. """ @@ -81,6 +83,7 @@ self._inidict[name] = (help, type, default) self._ininames.append(name) + class OptionGroup: def __init__(self, name, description="", parser=None): self.name = name @@ -256,11 +259,14 @@ self.hook = self.pluginmanager.hook self._inicache = {} self._cleanup = [] - + @classmethod def fromdictargs(cls, option_dict, args): """ constructor useable for subprocesses. """ config = cls() + # XXX slightly crude way to initialize capturing + import _pytest.capture + _pytest.capture.pytest_cmdline_parse(config.pluginmanager, args) config._preparse(args, addopts=False) config.option.__dict__.update(option_dict) for x in config.option.plugins: @@ -285,11 +291,10 @@ def _setinitialconftest(self, args): # capture output during conftest init (#issue93) - from _pytest.capture import CaptureManager - capman = CaptureManager() - self.pluginmanager.register(capman, 'capturemanager') - # will be unregistered in capture.py's unconfigure() - capman.resumecapture(capman._getmethod_preoptionparse(args)) + # XXX introduce load_conftest hook to avoid needing to know + # about capturing plugin here + capman = self.pluginmanager.getplugin("capturemanager") + capman.resumecapture() try: try: self._conftest.setinitial(args) @@ -334,6 +339,7 @@ # Note that this can only be called once per testing process. assert not hasattr(self, 'args'), ( "can only parse cmdline args at most once per Config object") + self._origargs = args self._preparse(args) self._parser.hints.extend(self.pluginmanager._hints) args = self._parser.parse_setoption(args, self.option) @@ -341,6 +347,14 @@ args.append(py.std.os.getcwd()) self.args = args + def addinivalue_line(self, name, line): + """ add a line to an ini-file option. The option must have been + declared but might not yet be set in which case the line becomes the + the first line in its value. """ + x = self.getini(name) + assert isinstance(x, list) + x.append(line) # modifies the cached list inline + def getini(self, name): """ return configuration value from an ini file. If the specified name hasn't been registered through a prior ``parse.addini`` @@ -422,7 +436,7 @@ def getcfg(args, inibasenames): - args = [x for x in args if str(x)[0] != "-"] + args = [x for x in args if not str(x).startswith("-")] if not args: args = [py.path.local()] for arg in args: diff --git a/_pytest/core.py b/_pytest/core.py --- a/_pytest/core.py +++ b/_pytest/core.py @@ -16,11 +16,10 @@ "junitxml resultlog doctest").split() class TagTracer: - def __init__(self, prefix="[pytest] "): + def __init__(self): self._tag2proc = {} self.writer = None self.indent = 0 - self.prefix = prefix def get(self, name): return TagTracerSub(self, (name,)) @@ -30,7 +29,7 @@ if args: indent = " " * self.indent content = " ".join(map(str, args)) - self.writer("%s%s%s\n" %(self.prefix, indent, content)) + self.writer("%s%s [%s]\n" %(indent, content, ":".join(tags))) try: self._tag2proc[tags](tags, args) except KeyError: @@ -212,6 +211,14 @@ self.register(mod, modname) self.consider_module(mod) + def pytest_configure(self, config): + config.addinivalue_line("markers", + "tryfirst: mark a hook implementation function such that the " + "plugin machinery will try to call it first/as early as possible.") + config.addinivalue_line("markers", + "trylast: mark a hook implementation function such that the " + "plugin machinery will try to call it last/as late as possible.") + def pytest_plugin_registered(self, plugin): import pytest dic = self.call_plugin(plugin, "pytest_namespace", {}) or {} @@ -432,10 +439,7 @@ def _preloadplugins(): _preinit.append(PluginManager(load=True)) -def main(args=None, plugins=None): - """ returned exit code integer, after an in-process testing run - with the given command line arguments, preloading an optional list - of passed in plugin objects. """ +def _prepareconfig(args=None, plugins=None): if args is None: args = sys.argv[1:] elif isinstance(args, py.path.local): @@ -449,13 +453,19 @@ else: # subsequent calls to main will create a fresh instance _pluginmanager = PluginManager(load=True) hook = _pluginmanager.hook + if plugins: + for plugin in plugins: + _pluginmanager.register(plugin) + return hook.pytest_cmdline_parse( + pluginmanager=_pluginmanager, args=args) + +def main(args=None, plugins=None): + """ returned exit code integer, after an in-process testing run + with the given command line arguments, preloading an optional list + of passed in plugin objects. """ try: - if plugins: - for plugin in plugins: - _pluginmanager.register(plugin) - config = hook.pytest_cmdline_parse( - pluginmanager=_pluginmanager, args=args) - exitstatus = hook.pytest_cmdline_main(config=config) + config = _prepareconfig(args, plugins) + exitstatus = config.hook.pytest_cmdline_main(config=config) except UsageError: e = sys.exc_info()[1] sys.stderr.write("ERROR: %s\n" %(e.args[0],)) diff --git a/_pytest/helpconfig.py b/_pytest/helpconfig.py --- a/_pytest/helpconfig.py +++ b/_pytest/helpconfig.py @@ -1,7 +1,7 @@ """ version info, help messages, tracing configuration. """ import py import pytest -import inspect, sys +import os, inspect, sys from _pytest.core import varnames def pytest_addoption(parser): @@ -18,7 +18,29 @@ help="trace considerations of conftest.py files."), group.addoption('--debug', action="store_true", dest="debug", default=False, - help="generate and show internal debugging information.") + help="store internal tracing debug information in 'pytestdebug.log'.") + + +def pytest_cmdline_parse(__multicall__): + config = __multicall__.execute() + if config.option.debug: + path = os.path.abspath("pytestdebug.log") + f = open(path, 'w') + config._debugfile = f + f.write("versions pytest-%s, py-%s, python-%s\ncwd=%s\nargs=%s\n\n" %( + pytest.__version__, py.__version__, ".".join(map(str, sys.version_info)), + os.getcwd(), config._origargs)) + config.trace.root.setwriter(f.write) + sys.stderr.write("writing pytestdebug information to %s\n" % path) + return config + + at pytest.mark.trylast +def pytest_unconfigure(config): + if hasattr(config, '_debugfile'): + config._debugfile.close() + sys.stderr.write("wrote pytestdebug information to %s\n" % + config._debugfile.name) + config.trace.root.setwriter(None) def pytest_cmdline_main(config): @@ -34,6 +56,7 @@ elif config.option.help: config.pluginmanager.do_configure(config) showhelp(config) + config.pluginmanager.do_unconfigure(config) return 0 def showhelp(config): @@ -91,7 +114,7 @@ verinfo = getpluginversioninfo(config) if verinfo: lines.extend(verinfo) - + if config.option.traceconfig: lines.append("active plugins:") plugins = [] diff --git a/_pytest/hookspec.py b/_pytest/hookspec.py --- a/_pytest/hookspec.py +++ b/_pytest/hookspec.py @@ -121,16 +121,23 @@ def pytest_itemstart(item, node=None): """ (deprecated, use pytest_runtest_logstart). """ -def pytest_runtest_protocol(item): - """ implements the standard runtest_setup/call/teardown protocol including - capturing exceptions and calling reporting hooks on the results accordingly. +def pytest_runtest_protocol(item, nextitem): + """ implements the runtest_setup/call/teardown protocol for + the given test item, including capturing exceptions and calling + reporting hooks. + + :arg item: test item for which the runtest protocol is performed. + + :arg nexitem: the scheduled-to-be-next test item (or None if this + is the end my friend). This argument is passed on to + :py:func:`pytest_runtest_teardown`. :return boolean: True if no further hook implementations should be invoked. """ pytest_runtest_protocol.firstresult = True def pytest_runtest_logstart(nodeid, location): - """ signal the start of a test run. """ + """ signal the start of running a single test item. """ def pytest_runtest_setup(item): """ called before ``pytest_runtest_call(item)``. """ @@ -138,8 +145,14 @@ def pytest_runtest_call(item): """ called to execute the test ``item``. """ -def pytest_runtest_teardown(item): - """ called after ``pytest_runtest_call``. """ +def pytest_runtest_teardown(item, nextitem): + """ called after ``pytest_runtest_call``. + + :arg nexitem: the scheduled-to-be-next test item (None if no further + test item is scheduled). This argument can be used to + perform exact teardowns, i.e. calling just enough finalizers + so that nextitem only needs to call setup-functions. + """ def pytest_runtest_makereport(item, call): """ return a :py:class:`_pytest.runner.TestReport` object @@ -149,15 +162,8 @@ pytest_runtest_makereport.firstresult = True def pytest_runtest_logreport(report): - """ process item test report. """ - -# special handling for final teardown - somewhat internal for now -def pytest__teardown_final(session): - """ called before test session finishes. """ -pytest__teardown_final.firstresult = True - -def pytest__teardown_final_logerror(report, session): - """ called if runtest_teardown_final failed. """ + """ process a test setup/call/teardown report relating to + the respective phase of executing a test. """ # ------------------------------------------------------------------------- # test session related hooks diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -25,21 +25,39 @@ long = int +class Junit(py.xml.Namespace): + pass + + # We need to get the subset of the invalid unicode ranges according to # XML 1.0 which are valid in this python build. Hence we calculate # this dynamically instead of hardcoding it. The spec range of valid # chars is: Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] # | [#x10000-#x10FFFF] -_illegal_unichrs = [(0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x19), - (0xD800, 0xDFFF), (0xFDD0, 0xFFFF)] -_illegal_ranges = [unicode("%s-%s") % (unichr(low), unichr(high)) - for (low, high) in _illegal_unichrs +_legal_chars = (0x09, 0x0A, 0x0d) +_legal_ranges = ( + (0x20, 0xD7FF), + (0xE000, 0xFFFD), + (0x10000, 0x10FFFF), +) +_legal_xml_re = [unicode("%s-%s") % (unichr(low), unichr(high)) + for (low, high) in _legal_ranges if low < sys.maxunicode] -illegal_xml_re = re.compile(unicode('[%s]') % - unicode('').join(_illegal_ranges)) -del _illegal_unichrs -del _illegal_ranges +_legal_xml_re = [unichr(x) for x in _legal_chars] + _legal_xml_re +illegal_xml_re = re.compile(unicode('[^%s]') % + unicode('').join(_legal_xml_re)) +del _legal_chars +del _legal_ranges +del _legal_xml_re +def bin_xml_escape(arg): + def repl(matchobj): + i = ord(matchobj.group()) + if i <= 0xFF: + return unicode('#x%02X') % i + else: + return unicode('#x%04X') % i + return illegal_xml_re.sub(repl, py.xml.escape(arg)) def pytest_addoption(parser): group = parser.getgroup("terminal reporting") @@ -68,117 +86,97 @@ logfile = os.path.expanduser(os.path.expandvars(logfile)) self.logfile = os.path.normpath(logfile) self.prefix = prefix - self.test_logs = [] + self.tests = [] self.passed = self.skipped = 0 self.failed = self.errors = 0 - self._durations = {} def _opentestcase(self, report): names = report.nodeid.split("::") names[0] = names[0].replace("/", '.') - names = tuple(names) - d = {'time': self._durations.pop(report.nodeid, "0")} names = [x.replace(".py", "") for x in names if x != "()"] classnames = names[:-1] if self.prefix: classnames.insert(0, self.prefix) - d['classname'] = ".".join(classnames) - d['name'] = py.xml.escape(names[-1]) - attrs = ['%s="%s"' % item for item in sorted(d.items())] - self.test_logs.append("\n" % " ".join(attrs)) + self.tests.append(Junit.testcase( + classname=".".join(classnames), + name=names[-1], + time=getattr(report, 'duration', 0) + )) - def _closetestcase(self): - self.test_logs.append("") - - def appendlog(self, fmt, *args): - def repl(matchobj): - i = ord(matchobj.group()) - if i <= 0xFF: - return unicode('#x%02X') % i - else: - return unicode('#x%04X') % i - args = tuple([illegal_xml_re.sub(repl, py.xml.escape(arg)) - for arg in args]) - self.test_logs.append(fmt % args) + def append(self, obj): + self.tests[-1].append(obj) def append_pass(self, report): self.passed += 1 - self._opentestcase(report) - self._closetestcase() def append_failure(self, report): - self._opentestcase(report) #msg = str(report.longrepr.reprtraceback.extraline) if "xfail" in report.keywords: - self.appendlog( - '') + self.append( + Junit.skipped(message="xfail-marked test passes unexpectedly")) self.skipped += 1 else: - self.appendlog('%s', - report.longrepr) + sec = dict(report.sections) + fail = Junit.failure(message="test failure") + fail.append(str(report.longrepr)) + self.append(fail) + for name in ('out', 'err'): + content = sec.get("Captured std%s" % name) + if content: + tag = getattr(Junit, 'system-'+name) + self.append(tag(bin_xml_escape(content))) self.failed += 1 - self._closetestcase() def append_collect_failure(self, report): - self._opentestcase(report) #msg = str(report.longrepr.reprtraceback.extraline) - self.appendlog('%s', - report.longrepr) - self._closetestcase() + self.append(Junit.failure(str(report.longrepr), + message="collection failure")) self.errors += 1 def append_collect_skipped(self, report): - self._opentestcase(report) #msg = str(report.longrepr.reprtraceback.extraline) - self.appendlog('%s', - report.longrepr) - self._closetestcase() + self.append(Junit.skipped(str(report.longrepr), + message="collection skipped")) self.skipped += 1 def append_error(self, report): - self._opentestcase(report) - self.appendlog('%s', - report.longrepr) - self._closetestcase() + self.append(Junit.error(str(report.longrepr), + message="test setup failure")) self.errors += 1 def append_skipped(self, report): - self._opentestcase(report) if "xfail" in report.keywords: - self.appendlog( - '%s', - report.keywords['xfail']) + self.append(Junit.skipped(str(report.keywords['xfail']), + message="expected test failure")) else: filename, lineno, skipreason = report.longrepr if skipreason.startswith("Skipped: "): skipreason = skipreason[9:] - self.appendlog('%s', - skipreason, "%s:%s: %s" % report.longrepr, - ) - self._closetestcase() + self.append( + Junit.skipped("%s:%s: %s" % report.longrepr, + type="pytest.skip", + message=skipreason + )) self.skipped += 1 def pytest_runtest_logreport(self, report): if report.passed: - self.append_pass(report) + if report.when == "call": # ignore setup/teardown + self._opentestcase(report) + self.append_pass(report) elif report.failed: + self._opentestcase(report) if report.when != "call": self.append_error(report) else: self.append_failure(report) elif report.skipped: + self._opentestcase(report) self.append_skipped(report) - def pytest_runtest_call(self, item, __multicall__): - start = time.time() - try: - return __multicall__.execute() - finally: - self._durations[item.nodeid] = time.time() - start - def pytest_collectreport(self, report): if not report.passed: + self._opentestcase(report) if report.failed: self.append_collect_failure(report) else: @@ -187,10 +185,11 @@ def pytest_internalerror(self, excrepr): self.errors += 1 data = py.xml.escape(excrepr) - self.test_logs.append( - '\n' - ' ' - '%s' % data) + self.tests.append( + Junit.testcase( + Junit.error(data, message="internal error"), + classname="pytest", + name="internal")) def pytest_sessionstart(self, session): self.suite_start_time = time.time() @@ -204,17 +203,17 @@ suite_stop_time = time.time() suite_time_delta = suite_stop_time - self.suite_start_time numtests = self.passed + self.failed + logfile.write('') - logfile.write('') - logfile.writelines(self.test_logs) - logfile.write('') + logfile.write(Junit.testsuite( + self.tests, + name="", + errors=self.errors, + failures=self.failed, + skips=self.skipped, + tests=numtests, + time="%.3f" % suite_time_delta, + ).unicode(indent=0)) logfile.close() def pytest_terminal_summary(self, terminalreporter): diff --git a/_pytest/main.py b/_pytest/main.py --- a/_pytest/main.py +++ b/_pytest/main.py @@ -2,7 +2,7 @@ import py import pytest, _pytest -import os, sys +import os, sys, imp tracebackcutdir = py.path.local(_pytest.__file__).dirpath() # exitcodes for the command line @@ -11,6 +11,8 @@ EXIT_INTERRUPTED = 2 EXIT_INTERNALERROR = 3 +name_re = py.std.re.compile("^[a-zA-Z_]\w*$") + def pytest_addoption(parser): parser.addini("norecursedirs", "directory patterns to avoid for recursion", type="args", default=('.*', 'CVS', '_darcs', '{arch}')) @@ -27,6 +29,9 @@ action="store", type="int", dest="maxfail", default=0, help="exit after first num failures or errors.") + group._addoption('--strict', action="store_true", + help="run pytest in strict mode, warnings become errors.") + group = parser.getgroup("collect", "collection") group.addoption('--collectonly', action="store_true", dest="collectonly", @@ -48,7 +53,7 @@ def pytest_namespace(): collect = dict(Item=Item, Collector=Collector, File=File, Session=Session) return dict(collect=collect) - + def pytest_configure(config): py.test.config = config # compatibiltiy if config.option.exitfirst: @@ -77,11 +82,11 @@ session.exitstatus = EXIT_INTERNALERROR if excinfo.errisinstance(SystemExit): sys.stderr.write("mainloop: caught Spurious SystemExit!\n") + if initstate >= 2: + config.hook.pytest_sessionfinish(session=session, + exitstatus=session.exitstatus or (session._testsfailed and 1)) if not session.exitstatus and session._testsfailed: session.exitstatus = EXIT_TESTSFAILED - if initstate >= 2: - config.hook.pytest_sessionfinish(session=session, - exitstatus=session.exitstatus) if initstate >= 1: config.pluginmanager.do_unconfigure(config) return session.exitstatus @@ -101,8 +106,12 @@ def pytest_runtestloop(session): if session.config.option.collectonly: return True - for item in session.session.items: - item.config.hook.pytest_runtest_protocol(item=item) + for i, item in enumerate(session.items): + try: + nextitem = session.items[i+1] + except IndexError: + nextitem = None + item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem) if session.shouldstop: raise session.Interrupted(session.shouldstop) return True @@ -132,7 +141,7 @@ return getattr(pytest, name) return property(fget, None, None, "deprecated attribute %r, use pytest.%s" % (name,name)) - + class Node(object): """ base class for all Nodes in the collection tree. Collector subclasses have children, Items are terminal nodes.""" @@ -143,13 +152,13 @@ #: the parent collector node. self.parent = parent - + #: the test config object self.config = config or parent.config #: the collection this node is part of self.session = session or parent.session - + #: filesystem path where this node was collected from self.fspath = getattr(parent, 'fspath', None) self.ihook = self.session.gethookproxy(self.fspath) @@ -224,13 +233,13 @@ def listchain(self): """ return list of all parent collectors up to self, starting from root of collection tree. """ - l = [self] - while 1: - x = l[0] - if x.parent is not None: # and x.parent.parent is not None: - l.insert(0, x.parent) - else: - return l + chain = [] + item = self + while item is not None: + chain.append(item) + item = item.parent + chain.reverse() + return chain def listnames(self): return [x.name for x in self.listchain()] @@ -325,6 +334,8 @@ """ a basic test invocation item. Note that for a single function there might be multiple test invocation items. """ + nextitem = None + def reportinfo(self): return self.fspath, None, "" @@ -399,6 +410,7 @@ self._notfound = [] self._initialpaths = set() self._initialparts = [] + self.items = items = [] for arg in args: parts = self._parsearg(arg) self._initialparts.append(parts) @@ -414,7 +426,6 @@ if not genitems: return rep.result else: - self.items = items = [] if rep.passed: for node in rep.result: self.items.extend(self.genitems(node)) @@ -469,16 +480,29 @@ return True def _tryconvertpyarg(self, x): - try: - mod = __import__(x, None, None, ['__doc__']) - except (ValueError, ImportError): - return x - p = py.path.local(mod.__file__) - if p.purebasename == "__init__": - p = p.dirpath() - else: - p = p.new(basename=p.purebasename+".py") - return str(p) + mod = None + path = [os.path.abspath('.')] + sys.path + for name in x.split('.'): + # ignore anything that's not a proper name here + # else something like --pyargs will mess up '.' + # since imp.find_module will actually sometimes work for it + # but it's supposed to be considered a filesystem path + # not a package + if name_re.match(name) is None: + return x + try: + fd, mod, type_ = imp.find_module(name, path) + except ImportError: + return x + else: + if fd is not None: + fd.close() + + if type_[2] != imp.PKG_DIRECTORY: + path = [os.path.dirname(mod)] + else: + path = [mod] + return mod def _parsearg(self, arg): """ return (fspath, names) tuple after checking the file exists. """ @@ -496,7 +520,7 @@ raise pytest.UsageError(msg + arg) parts[0] = path return parts - + def matchnodes(self, matching, names): self.trace("matchnodes", matching, names) self.trace.root.indent += 1 diff --git a/_pytest/mark.py b/_pytest/mark.py --- a/_pytest/mark.py +++ b/_pytest/mark.py @@ -14,12 +14,37 @@ "Terminate expression with ':' to make the first match match " "all subsequent tests (usually file-order). ") + group._addoption("-m", + action="store", dest="markexpr", default="", metavar="MARKEXPR", + help="only run tests matching given mark expression. " + "example: -m 'mark1 and not mark2'." + ) + + group.addoption("--markers", action="store_true", help= + "show markers (builtin, plugin and per-project ones).") + + parser.addini("markers", "markers for test functions", 'linelist') + +def pytest_cmdline_main(config): + if config.option.markers: + config.pluginmanager.do_configure(config) + tw = py.io.TerminalWriter() + for line in config.getini("markers"): + name, rest = line.split(":", 1) + tw.write("@pytest.mark.%s:" % name, bold=True) + tw.line(rest) + tw.line() + config.pluginmanager.do_unconfigure(config) + return 0 +pytest_cmdline_main.tryfirst = True + def pytest_collection_modifyitems(items, config): keywordexpr = config.option.keyword - if not keywordexpr: + matchexpr = config.option.markexpr + if not keywordexpr and not matchexpr: return selectuntil = False - if keywordexpr[-1] == ":": + if keywordexpr[-1:] == ":": selectuntil = True keywordexpr = keywordexpr[:-1] @@ -29,21 +54,38 @@ if keywordexpr and skipbykeyword(colitem, keywordexpr): deselected.append(colitem) else: - remaining.append(colitem) if selectuntil: keywordexpr = None + if matchexpr: + if not matchmark(colitem, matchexpr): + deselected.append(colitem) + continue + remaining.append(colitem) if deselected: config.hook.pytest_deselected(items=deselected) items[:] = remaining +class BoolDict: + def __init__(self, mydict): + self._mydict = mydict + def __getitem__(self, name): + return name in self._mydict + +def matchmark(colitem, matchexpr): + return eval(matchexpr, {}, BoolDict(colitem.obj.__dict__)) + +def pytest_configure(config): + if config.option.strict: + pytest.mark._config = config + def skipbykeyword(colitem, keywordexpr): """ return True if they given keyword expression means to skip this collector/item. """ if not keywordexpr: return - + itemkeywords = getkeywords(colitem) for key in filter(None, keywordexpr.split()): eor = key[:1] == '-' @@ -77,15 +119,31 @@ @py.test.mark.slowtest def test_function(): pass - + will set a 'slowtest' :class:`MarkInfo` object on the ``test_function`` object. """ def __getattr__(self, name): if name[0] == "_": raise AttributeError(name) + if hasattr(self, '_config'): + self._check(name) return MarkDecorator(name) + def _check(self, name): + try: + if name in self._markers: + return + except AttributeError: + pass + self._markers = l = set() + for line in self._config.getini("markers"): + beginning = line.split(":", 1) + x = beginning[0].split("(", 1)[0] + l.add(x) + if name not in self._markers: + raise AttributeError("%r not a registered marker" % (name,)) + class MarkDecorator: """ A decorator for test functions and test classes. When applied it will create :class:`MarkInfo` objects which may be @@ -133,8 +191,7 @@ holder = MarkInfo(self.markname, self.args, self.kwargs) setattr(func, self.markname, holder) else: - holder.kwargs.update(self.kwargs) - holder.args += self.args + holder.add(self.args, self.kwargs) return func kw = self.kwargs.copy() kw.update(kwargs) @@ -150,27 +207,20 @@ self.args = args #: keyword argument dictionary, empty if nothing specified self.kwargs = kwargs + self._arglist = [(args, kwargs.copy())] def __repr__(self): return "" % ( self.name, self.args, self.kwargs) -def pytest_itemcollected(item): - if not isinstance(item, pytest.Function): - return - try: - func = item.obj.__func__ - except AttributeError: - func = getattr(item.obj, 'im_func', item.obj) - pyclasses = (pytest.Class, pytest.Module) - for node in item.listchain(): - if isinstance(node, pyclasses): - marker = getattr(node.obj, 'pytestmark', None) - if marker is not None: - if isinstance(marker, list): - for mark in marker: - mark(func) - else: - marker(func) - node = node.parent - item.keywords.update(py.builtin._getfuncdict(func)) + def add(self, args, kwargs): + """ add a MarkInfo with the given args and kwargs. """ + self._arglist.append((args, kwargs)) + self.args += args + self.kwargs.update(kwargs) + + def __iter__(self): + """ yield MarkInfo objects each relating to a marking-call. """ + for args, kwargs in self._arglist: + yield MarkInfo(self.name, args, kwargs) + diff --git a/_pytest/monkeypatch.py b/_pytest/monkeypatch.py --- a/_pytest/monkeypatch.py +++ b/_pytest/monkeypatch.py @@ -13,6 +13,7 @@ monkeypatch.setenv(name, value, prepend=False) monkeypatch.delenv(name, value, raising=True) monkeypatch.syspath_prepend(path) + monkeypatch.chdir(path) All modifications will be undone after the requesting test function has finished. The ``raising`` @@ -30,6 +31,7 @@ def __init__(self): self._setattr = [] self._setitem = [] + self._cwd = None def setattr(self, obj, name, value, raising=True): """ set attribute ``name`` on ``obj`` to ``value``, by default @@ -83,6 +85,17 @@ self._savesyspath = sys.path[:] sys.path.insert(0, str(path)) + def chdir(self, path): + """ change the current working directory to the specified path + path can be a string or a py.path.local object + """ + if self._cwd is None: + self._cwd = os.getcwd() + if hasattr(path, "chdir"): + path.chdir() + else: + os.chdir(path) + def undo(self): """ undo previous changes. This call consumes the undo stack. Calling it a second time has no effect unless @@ -95,9 +108,17 @@ self._setattr[:] = [] for dictionary, name, value in self._setitem: if value is notset: - del dictionary[name] + try: + del dictionary[name] + except KeyError: + pass # was already deleted, so we have the desired state else: dictionary[name] = value self._setitem[:] = [] if hasattr(self, '_savesyspath'): sys.path[:] = self._savesyspath + del self._savesyspath + + if self._cwd is not None: + os.chdir(self._cwd) + self._cwd = None diff --git a/_pytest/nose.py b/_pytest/nose.py --- a/_pytest/nose.py +++ b/_pytest/nose.py @@ -13,6 +13,7 @@ call.excinfo = call2.excinfo + at pytest.mark.trylast def pytest_runtest_setup(item): if isinstance(item, (pytest.Function)): if isinstance(item.parent, pytest.Generator): diff --git a/_pytest/pastebin.py b/_pytest/pastebin.py --- a/_pytest/pastebin.py +++ b/_pytest/pastebin.py @@ -38,7 +38,11 @@ del tr._tw.__dict__['write'] def getproxy(): - return py.std.xmlrpclib.ServerProxy(url.xmlrpc).pastes + if sys.version_info < (3, 0): + from xmlrpclib import ServerProxy + else: + from xmlrpc.client import ServerProxy + return ServerProxy(url.xmlrpc).pastes def pytest_terminal_summary(terminalreporter): if terminalreporter.config.option.pastebin != "failed": diff --git a/_pytest/pdb.py b/_pytest/pdb.py --- a/_pytest/pdb.py +++ b/_pytest/pdb.py @@ -19,11 +19,13 @@ class pytestPDB: """ Pseudo PDB that defers to the real pdb. """ item = None + collector = None def set_trace(self): """ invoke PDB set_trace debugging, dropping any IO capturing. """ frame = sys._getframe().f_back - item = getattr(self, 'item', None) + item = self.item or self.collector + if item is not None: capman = item.config.pluginmanager.getplugin("capturemanager") out, err = capman.suspendcapture() @@ -38,6 +40,14 @@ pytestPDB.item = item pytest_runtest_setup = pytest_runtest_call = pytest_runtest_teardown = pdbitem + at pytest.mark.tryfirst +def pytest_make_collect_report(__multicall__, collector): + try: + pytestPDB.collector = collector + return __multicall__.execute() + finally: + pytestPDB.collector = None + def pytest_runtest_makereport(): pytestPDB.item = None @@ -60,7 +70,13 @@ tw.sep(">", "traceback") rep.toterminal(tw) tw.sep(">", "entering PDB") - post_mortem(call.excinfo._excinfo[2]) + # A doctest.UnexpectedException is not useful for post_mortem. + # Use the underlying exception instead: + if isinstance(call.excinfo.value, py.std.doctest.UnexpectedException): + tb = call.excinfo.value.exc_info[2] + else: + tb = call.excinfo._excinfo[2] + post_mortem(tb) rep._pdbshown = True return rep diff --git a/_pytest/pytester.py b/_pytest/pytester.py --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -25,6 +25,7 @@ _pytest_fullpath except NameError: _pytest_fullpath = os.path.abspath(pytest.__file__.rstrip("oc")) + _pytest_fullpath = _pytest_fullpath.replace("$py.class", ".py") def pytest_funcarg___pytest(request): return PytestArg(request) @@ -313,16 +314,6 @@ result.extend(session.genitems(colitem)) return result - def inline_genitems(self, *args): - #config = self.parseconfig(*args) - config = self.parseconfigure(*args) - rec = self.getreportrecorder(config) - session = Session(config) - config.hook.pytest_sessionstart(session=session) - session.perform_collect() - config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK) - return session.items, rec - def runitem(self, source): # used from runner functional tests item = self.getitem(source) @@ -343,64 +334,57 @@ l = list(args) + [p] reprec = self.inline_run(*l) reports = reprec.getreports("pytest_runtest_logreport") - assert len(reports) == 1, reports - return reports[0] + assert len(reports) == 3, reports # setup/call/teardown + return reports[1] + + def inline_genitems(self, *args): + return self.inprocess_run(list(args) + ['--collectonly']) def inline_run(self, *args): - args = ("-s", ) + args # otherwise FD leakage - config = self.parseconfig(*args) - reprec = self.getreportrecorder(config) - #config.pluginmanager.do_configure(config) - config.hook.pytest_cmdline_main(config=config) - #config.pluginmanager.do_unconfigure(config) - return reprec + items, rec = self.inprocess_run(args) + return rec - def config_preparse(self): - config = self.Config() - for plugin in self.plugins: - if isinstance(plugin, str): - config.pluginmanager.import_plugin(plugin) - else: - if isinstance(plugin, dict): - plugin = PseudoPlugin(plugin) - if not config.pluginmanager.isregistered(plugin): - config.pluginmanager.register(plugin) - return config + def inprocess_run(self, args, plugins=None): + rec = [] + items = [] + class Collect: + def pytest_configure(x, config): + rec.append(self.getreportrecorder(config)) + def pytest_itemcollected(self, item): + items.append(item) + if not plugins: + plugins = [] + plugins.append(Collect()) + ret = self.pytestmain(list(args), plugins=[Collect()]) + reprec = rec[0] + reprec.ret = ret + assert len(rec) == 1 + return items, reprec def parseconfig(self, *args): - if not args: - args = (self.tmpdir,) - config = self.config_preparse() - args = list(args) + args = [str(x) for x in args] for x in args: if str(x).startswith('--basetemp'): break else: args.append("--basetemp=%s" % self.tmpdir.dirpath('basetemp')) - config.parse(args) + import _pytest.core + config = _pytest.core._prepareconfig(args, self.plugins) + # the in-process pytest invocation needs to avoid leaking FDs + # so we register a "reset_capturings" callmon the capturing manager + # and make sure it gets called + config._cleanup.append( + config.pluginmanager.getplugin("capturemanager").reset_capturings) + import _pytest.config + self.request.addfinalizer( + lambda: _pytest.config.pytest_unconfigure(config)) return config - def reparseconfig(self, args=None): - """ this is used from tests that want to re-invoke parse(). """ - if not args: - args = [self.tmpdir] - oldconfig = getattr(py.test, 'config', None) - try: - c = py.test.config = self.Config() - c.basetemp = py.path.local.make_numbered_dir(prefix="reparse", - keep=0, rootdir=self.tmpdir, lock_timeout=None) - c.parse(args) - c.pluginmanager.do_configure(c) - self.request.addfinalizer(lambda: c.pluginmanager.do_unconfigure(c)) - return c - finally: - py.test.config = oldconfig - def parseconfigure(self, *args): config = self.parseconfig(*args) config.pluginmanager.do_configure(config) self.request.addfinalizer(lambda: - config.pluginmanager.do_unconfigure(config)) + config.pluginmanager.do_unconfigure(config)) return config def getitem(self, source, funcname="test_func"): @@ -420,7 +404,6 @@ self.makepyfile(__init__ = "#") self.config = config = self.parseconfigure(path, *configargs) node = self.getnode(config, path) - #config.pluginmanager.do_unconfigure(config) return node def collect_by_name(self, modcol, name): @@ -437,9 +420,16 @@ return py.std.subprocess.Popen(cmdargs, stdout=stdout, stderr=stderr, **kw) def pytestmain(self, *args, **kwargs): - ret = pytest.main(*args, **kwargs) - if ret == 2: - raise KeyboardInterrupt() + class ResetCapturing: + @pytest.mark.trylast + def pytest_unconfigure(self, config): + capman = config.pluginmanager.getplugin("capturemanager") + capman.reset_capturings() + plugins = kwargs.setdefault("plugins", []) + rc = ResetCapturing() + plugins.append(rc) + return pytest.main(*args, **kwargs) + def run(self, *cmdargs): return self._run(*cmdargs) @@ -528,6 +518,8 @@ pexpect = py.test.importorskip("pexpect", "2.4") if hasattr(sys, 'pypy_version_info') and '64' in py.std.platform.machine(): pytest.skip("pypy-64 bit not supported") + if sys.platform == "darwin": + pytest.xfail("pexpect does not work reliably on darwin?!") logfile = self.tmpdir.join("spawn.out") child = pexpect.spawn(cmd, logfile=logfile.open("w")) child.timeout = expect_timeout @@ -540,10 +532,6 @@ return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % ( py.io.saferepr(out),) -class PseudoPlugin: - def __init__(self, vars): - self.__dict__.update(vars) - class ReportRecorder(object): def __init__(self, hook): self.hook = hook @@ -565,10 +553,17 @@ def getreports(self, names="pytest_runtest_logreport pytest_collectreport"): return [x.report for x in self.getcalls(names)] - def matchreport(self, inamepart="", names="pytest_runtest_logreport pytest_collectreport", when=None): + def matchreport(self, inamepart="", + names="pytest_runtest_logreport pytest_collectreport", when=None): """ return a testreport whose dotted import path matches """ l = [] for rep in self.getreports(names=names): + try: + if not when and rep.when != "call" and rep.passed: + # setup/teardown passing reports - let's ignore those + continue + except AttributeError: + pass if when and getattr(rep, 'when', None) != when: continue if not inamepart or inamepart in rep.nodeid.split("::"): diff --git a/_pytest/python.py b/_pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -4,6 +4,7 @@ import sys import pytest from py._code.code import TerminalRepr +from _pytest.monkeypatch import monkeypatch import _pytest cutdir = py.path.local(_pytest.__file__).dirpath() @@ -26,6 +27,24 @@ showfuncargs(config) return 0 + +def pytest_generate_tests(metafunc): + try: + param = metafunc.function.parametrize + except AttributeError: + return + for p in param: + metafunc.parametrize(*p.args, **p.kwargs) + +def pytest_configure(config): + config.addinivalue_line("markers", + "parametrize(argnames, argvalues): call a test function multiple " + "times passing in multiple different argument value sets. Example: " + "@parametrize('arg1', [1,2]) would lead to two calls of the decorated " + "test function, one with arg1=1 and another with arg1=2." + ) + + @pytest.mark.trylast def pytest_namespace(): raises.Exception = pytest.fail.Exception @@ -138,6 +157,7 @@ obj = obj.place_as self._fslineno = py.code.getfslineno(obj) + assert isinstance(self._fslineno[1], int), obj return self._fslineno def reportinfo(self): @@ -155,6 +175,7 @@ else: fspath, lineno = self._getfslineno() modpath = self.getmodpath() + assert isinstance(lineno, int) return fspath, lineno, modpath class PyCollectorMixin(PyobjMixin, pytest.Collector): @@ -200,6 +221,7 @@ module = self.getparent(Module).obj clscol = self.getparent(Class) cls = clscol and clscol.obj or None + transfer_markers(funcobj, cls, module) metafunc = Metafunc(funcobj, config=self.config, cls=cls, module=module) gentesthook = self.config.hook.pytest_generate_tests @@ -219,6 +241,19 @@ l.append(function) return l +def transfer_markers(funcobj, cls, mod): + # XXX this should rather be code in the mark plugin or the mark + # plugin should merge with the python plugin. + for holder in (cls, mod): + try: + pytestmark = holder.pytestmark + except AttributeError: + continue + if isinstance(pytestmark, list): + for mark in pytestmark: + mark(funcobj) + else: + pytestmark(funcobj) class Module(pytest.File, PyCollectorMixin): def _getobj(self): @@ -226,13 +261,8 @@ def _importtestmodule(self): # we assume we are only called once per module - from _pytest import assertion - assertion.before_module_import(self) try: - try: - mod = self.fspath.pyimport(ensuresyspath=True) - finally: - assertion.after_module_import(self) + mod = self.fspath.pyimport(ensuresyspath=True) except SyntaxError: excinfo = py.code.ExceptionInfo() raise self.CollectError(excinfo.getrepr(style="short")) @@ -244,7 +274,8 @@ " %s\n" "which is not the same as the test file we want to collect:\n" " %s\n" - "HINT: use a unique basename for your test file modules" + "HINT: remove __pycache__ / .pyc files and/or use a " + "unique basename for your test file modules" % e.args ) #print "imported test module", mod @@ -374,6 +405,7 @@ tw.line() tw.line("%s:%d" % (self.filename, self.firstlineno+1)) + class Generator(FunctionMixin, PyCollectorMixin, pytest.Collector): def collect(self): # test generators are seen as collectors but they also @@ -430,6 +462,7 @@ "yielded functions (deprecated) cannot have funcargs") else: if callspec is not None: + self.callspec = callspec self.funcargs = callspec.funcargs or {} self._genid = callspec.id if hasattr(callspec, "param"): @@ -506,15 +539,59 @@ request._fillfuncargs() _notexists = object() -class CallSpec: - def __init__(self, funcargs, id, param): - self.funcargs = funcargs - self.id = id + +class CallSpec2(object): + def __init__(self, metafunc): + self.metafunc = metafunc + self.funcargs = {} + self._idlist = [] + self.params = {} + self._globalid = _notexists + self._globalid_args = set() + self._globalparam = _notexists + + def copy(self, metafunc): + cs = CallSpec2(self.metafunc) + cs.funcargs.update(self.funcargs) + cs.params.update(self.params) + cs._idlist = list(self._idlist) + cs._globalid = self._globalid + cs._globalid_args = self._globalid_args + cs._globalparam = self._globalparam + return cs + + def _checkargnotcontained(self, arg): + if arg in self.params or arg in self.funcargs: + raise ValueError("duplicate %r" %(arg,)) + + def getparam(self, name): + try: + return self.params[name] + except KeyError: + if self._globalparam is _notexists: + raise ValueError(name) + return self._globalparam + + @property + def id(self): + return "-".join(map(str, filter(None, self._idlist))) + + def setmulti(self, valtype, argnames, valset, id): + for arg,val in zip(argnames, valset): + self._checkargnotcontained(arg) + getattr(self, valtype)[arg] = val + self._idlist.append(id) + + def setall(self, funcargs, id, param): + for x in funcargs: + self._checkargnotcontained(x) + self.funcargs.update(funcargs) + if id is not _notexists: + self._idlist.append(id) if param is not _notexists: - self.param = param - def __repr__(self): - return "" %( - self.id, getattr(self, 'param', '?'), self.funcargs) + assert self._globalparam is _notexists + self._globalparam = param + class Metafunc: def __init__(self, function, config=None, cls=None, module=None): @@ -528,31 +605,71 @@ self._calls = [] self._ids = py.builtin.set() + def parametrize(self, argnames, argvalues, indirect=False, ids=None): + """ Add new invocations to the underlying test function using the list + of argvalues for the given argnames. Parametrization is performed + during the collection phase. If you need to setup expensive resources + you may pass indirect=True and implement a funcarg factory which can + perform the expensive setup just before a test is actually run. + + :arg argnames: an argument name or a list of argument names + + :arg argvalues: a list of values for the argname or a list of tuples of + values for the list of argument names. + + :arg indirect: if True each argvalue corresponding to an argument will + be passed as request.param to its respective funcarg factory so + that it can perform more expensive setups during the setup phase of + a test rather than at collection time. + + :arg ids: list of string ids each corresponding to the argvalues so + that they are part of the test id. If no ids are provided they will + be generated automatically from the argvalues. + """ + if not isinstance(argnames, (tuple, list)): + argnames = (argnames,) + argvalues = [(val,) for val in argvalues] + if not indirect: + #XXX should we also check for the opposite case? + for arg in argnames: + if arg not in self.funcargnames: + raise ValueError("%r has no argument %r" %(self.function, arg)) + valtype = indirect and "params" or "funcargs" + if not ids: + idmaker = IDMaker() + ids = list(map(idmaker, argvalues)) + newcalls = [] + for callspec in self._calls or [CallSpec2(self)]: + for i, valset in enumerate(argvalues): + assert len(valset) == len(argnames) + newcallspec = callspec.copy(self) + newcallspec.setmulti(valtype, argnames, valset, ids[i]) + newcalls.append(newcallspec) + self._calls = newcalls + def addcall(self, funcargs=None, id=_notexists, param=_notexists): - """ add a new call to the underlying test function during the - collection phase of a test run. Note that request.addcall() is - called during the test collection phase prior and independently - to actual test execution. Therefore you should perform setup - of resources in a funcarg factory which can be instrumented - with the ``param``. + """ (deprecated, use parametrize) Add a new call to the underlying + test function during the collection phase of a test run. Note that + request.addcall() is called during the test collection phase prior and + independently to actual test execution. You should only use addcall() + if you need to specify multiple arguments of a test function. :arg funcargs: argument keyword dictionary used when invoking the test function. :arg id: used for reporting and identification purposes. If you - don't supply an `id` the length of the currently - list of calls to the test function will be used. + don't supply an `id` an automatic unique id will be generated. - :arg param: will be exposed to a later funcarg factory invocation - through the ``request.param`` attribute. It allows to - defer test fixture setup activities to when an actual - test is run. + :arg param: a parameter which will be exposed to a later funcarg factory + invocation through the ``request.param`` attribute. """ assert funcargs is None or isinstance(funcargs, dict) if funcargs is not None: for name in funcargs: if name not in self.funcargnames: pytest.fail("funcarg %r not used in this function." % name) + else: + funcargs = {} if id is None: raise ValueError("id=None not allowed") if id is _notexists: @@ -561,11 +678,26 @@ if id in self._ids: raise ValueError("duplicate id %r" % id) self._ids.add(id) - self._calls.append(CallSpec(funcargs, id, param)) + + cs = CallSpec2(self) + cs.setall(funcargs, id, param) + self._calls.append(cs) + +class IDMaker: + def __init__(self): + self.counter = 0 + def __call__(self, valset): + l = [] + for val in valset: + if not isinstance(val, (int, str)): + val = "."+str(self.counter) + self.counter += 1 + l.append(str(val)) + return "-".join(l) class FuncargRequest: """ A request for function arguments from a test function. - + Note that there is an optional ``param`` attribute in case there was an invocation to metafunc.addcall(param=...). If no such call was done in a ``pytest_generate_tests`` @@ -637,7 +769,7 @@ def applymarker(self, marker): - """ apply a marker to a single test function invocation. + """ Apply a marker to a single test function invocation. This method is useful if you don't want to have a keyword/marker on all function invocations. @@ -649,7 +781,7 @@ self._pyfuncitem.keywords[marker.markname] = marker def cached_setup(self, setup, teardown=None, scope="module", extrakey=None): - """ return a testing resource managed by ``setup`` & + """ Return a testing resource managed by ``setup`` & ``teardown`` calls. ``scope`` and ``extrakey`` determine when the ``teardown`` function will be called so that subsequent calls to ``setup`` would recreate the resource. @@ -698,11 +830,18 @@ self._raiselookupfailed(argname) funcargfactory = self._name2factory[argname].pop() oldarg = self._currentarg - self._currentarg = argname + mp = monkeypatch() + mp.setattr(self, '_currentarg', argname) + try: + param = self._pyfuncitem.callspec.getparam(argname) + except (AttributeError, ValueError): + pass + else: + mp.setattr(self, 'param', param, raising=False) try: self._funcargs[argname] = res = funcargfactory(request=self) finally: - self._currentarg = oldarg + mp.undo() return res def _getscopeitem(self, scope): @@ -817,8 +956,7 @@ >>> raises(ZeroDivisionError, f, x=0) - A third possibility is to use a string which which will - be executed:: + A third possibility is to use a string to be executed:: >>> raises(ZeroDivisionError, "f(0)") diff --git a/_pytest/resultlog.py b/_pytest/resultlog.py --- a/_pytest/resultlog.py +++ b/_pytest/resultlog.py @@ -63,6 +63,8 @@ self.write_log_entry(testpath, lettercode, longrepr) def pytest_runtest_logreport(self, report): + if report.when != "call" and report.passed: + return res = self.config.hook.pytest_report_teststatus(report=report) code = res[1] if code == 'x': @@ -89,5 +91,8 @@ self.log_outcome(report, code, longrepr) def pytest_internalerror(self, excrepr): - path = excrepr.reprcrash.path + reprcrash = getattr(excrepr, 'reprcrash', None) + path = getattr(reprcrash, "path", None) + if path is None: + path = "cwd:%s" % py.path.local() self.write_log_entry(path, '!', str(excrepr)) diff --git a/_pytest/runner.py b/_pytest/runner.py --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -1,6 +1,6 @@ """ basic collect and runtest protocol implementations """ -import py, sys +import py, sys, time from py._code.code import TerminalRepr def pytest_namespace(): @@ -14,33 +14,60 @@ # # pytest plugin hooks +def pytest_addoption(parser): + group = parser.getgroup("terminal reporting", "reporting", after="general") + group.addoption('--durations', + action="store", type="int", default=None, metavar="N", + help="show N slowest setup/test durations (N=0 for all)."), + +def pytest_terminal_summary(terminalreporter): + durations = terminalreporter.config.option.durations + if durations is None: + return + tr = terminalreporter + dlist = [] + for replist in tr.stats.values(): + for rep in replist: + if hasattr(rep, 'duration'): + dlist.append(rep) + if not dlist: + return + dlist.sort(key=lambda x: x.duration) + dlist.reverse() + if not durations: + tr.write_sep("=", "slowest test durations") + else: + tr.write_sep("=", "slowest %s test durations" % durations) + dlist = dlist[:durations] + + for rep in dlist: + nodeid = rep.nodeid.replace("::()::", "::") + tr.write_line("%02.2fs %-8s %s" % + (rep.duration, rep.when, nodeid)) + def pytest_sessionstart(session): session._setupstate = SetupState() - -def pytest_sessionfinish(session, exitstatus): - hook = session.config.hook - rep = hook.pytest__teardown_final(session=session) - if rep: - hook.pytest__teardown_final_logerror(session=session, report=rep) - session.exitstatus = 1 +def pytest_sessionfinish(session): + session._setupstate.teardown_all() class NodeInfo: def __init__(self, location): self.location = location -def pytest_runtest_protocol(item): +def pytest_runtest_protocol(item, nextitem): item.ihook.pytest_runtest_logstart( nodeid=item.nodeid, location=item.location, ) - runtestprotocol(item) + runtestprotocol(item, nextitem=nextitem) return True -def runtestprotocol(item, log=True): +def runtestprotocol(item, log=True, nextitem=None): rep = call_and_report(item, "setup", log) reports = [rep] if rep.passed: reports.append(call_and_report(item, "call", log)) - reports.append(call_and_report(item, "teardown", log)) + reports.append(call_and_report(item, "teardown", log, + nextitem=nextitem)) return reports def pytest_runtest_setup(item): @@ -49,16 +76,8 @@ def pytest_runtest_call(item): item.runtest() -def pytest_runtest_teardown(item): - item.session._setupstate.teardown_exact(item) - -def pytest__teardown_final(session): - call = CallInfo(session._setupstate.teardown_all, when="teardown") - if call.excinfo: - ntraceback = call.excinfo.traceback .cut(excludepath=py._pydir) - call.excinfo.traceback = ntraceback.filter() - longrepr = call.excinfo.getrepr(funcargs=True) - return TeardownErrorReport(longrepr) +def pytest_runtest_teardown(item, nextitem): + item.session._setupstate.teardown_exact(item, nextitem) def pytest_report_teststatus(report): if report.when in ("setup", "teardown"): @@ -74,18 +93,18 @@ # # Implementation -def call_and_report(item, when, log=True): - call = call_runtest_hook(item, when) +def call_and_report(item, when, log=True, **kwds): + call = call_runtest_hook(item, when, **kwds) hook = item.ihook report = hook.pytest_runtest_makereport(item=item, call=call) - if log and (when == "call" or not report.passed): + if log: hook.pytest_runtest_logreport(report=report) return report -def call_runtest_hook(item, when): +def call_runtest_hook(item, when, **kwds): hookname = "pytest_runtest_" + when ihook = getattr(item.ihook, hookname) - return CallInfo(lambda: ihook(item=item), when=when) + return CallInfo(lambda: ihook(item=item, **kwds), when=when) class CallInfo: """ Result/Exception info a function invocation. """ @@ -95,12 +114,16 @@ #: context of invocation: one of "setup", "call", #: "teardown", "memocollect" self.when = when + self.start = time.time() try: - self.result = func() - except KeyboardInterrupt: - raise - except: - self.excinfo = py.code.ExceptionInfo() + try: + self.result = func() + except KeyboardInterrupt: + raise + except: + self.excinfo = py.code.ExceptionInfo() + finally: + self.stop = time.time() def __repr__(self): if self.excinfo: @@ -120,6 +143,10 @@ return s class BaseReport(object): + + def __init__(self, **kw): + self.__dict__.update(kw) + def toterminal(self, out): longrepr = self.longrepr if hasattr(self, 'node'): @@ -139,6 +166,7 @@ def pytest_runtest_makereport(item, call): when = call.when + duration = call.stop-call.start keywords = dict([(x,1) for x in item.keywords]) excinfo = call.excinfo if not call.excinfo: @@ -160,14 +188,15 @@ else: # exception in setup or teardown longrepr = item._repr_failure_py(excinfo) return TestReport(item.nodeid, item.location, - keywords, outcome, longrepr, when) + keywords, outcome, longrepr, when, + duration=duration) class TestReport(BaseReport): """ Basic test report object (also used for setup and teardown calls if they fail). """ def __init__(self, nodeid, location, - keywords, outcome, longrepr, when): + keywords, outcome, longrepr, when, sections=(), duration=0, **extra): #: normalized collection node id self.nodeid = nodeid @@ -179,16 +208,25 @@ #: a name -> value dictionary containing all keywords and #: markers associated with a test invocation. self.keywords = keywords - + #: test outcome, always one of "passed", "failed", "skipped". self.outcome = outcome #: None or a failure representation. self.longrepr = longrepr - + #: one of 'setup', 'call', 'teardown' to indicate runtest phase. self.when = when + #: list of (secname, data) extra information which needs to + #: marshallable + self.sections = list(sections) + + #: time it took to run just the test + self.duration = duration + + self.__dict__.update(extra) + def __repr__(self): return "" % ( self.nodeid, self.when, self.outcome) @@ -196,8 +234,10 @@ class TeardownErrorReport(BaseReport): outcome = "failed" when = "teardown" - def __init__(self, longrepr): + def __init__(self, longrepr, **extra): self.longrepr = longrepr + self.sections = [] + self.__dict__.update(extra) def pytest_make_collect_report(collector): call = CallInfo(collector._memocollect, "memocollect") @@ -219,11 +259,13 @@ getattr(call, 'result', None)) class CollectReport(BaseReport): - def __init__(self, nodeid, outcome, longrepr, result): + def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra): self.nodeid = nodeid self.outcome = outcome self.longrepr = longrepr self.result = result or [] + self.sections = list(sections) + self.__dict__.update(extra) @property def location(self): @@ -277,20 +319,22 @@ self._teardown_with_finalization(None) assert not self._finalizers - def teardown_exact(self, item): - if self.stack and item == self.stack[-1]: + def teardown_exact(self, item, nextitem): + needed_collectors = nextitem and nextitem.listchain() or [] + self._teardown_towards(needed_collectors) + + def _teardown_towards(self, needed_collectors): + while self.stack: + if self.stack == needed_collectors[:len(self.stack)]: + break self._pop_and_teardown() - else: - self._callfinalizers(item) def prepare(self, colitem): """ setup objects along the collector chain to the test-method and teardown previously setup objects.""" needed_collectors = colitem.listchain() - while self.stack: - if self.stack == needed_collectors[:len(self.stack)]: - break - self._pop_and_teardown() + self._teardown_towards(needed_collectors) + # check if the last collection node has raised an error for col in self.stack: if hasattr(col, '_prepare_exc'): diff --git a/_pytest/skipping.py b/_pytest/skipping.py --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -9,6 +9,21 @@ action="store_true", dest="runxfail", default=False, help="run tests even if they are marked xfail") +def pytest_configure(config): + config.addinivalue_line("markers", + "skipif(*conditions): skip the given test function if evaluation " + "of all conditions has a True value. Evaluation happens within the " + "module global context. Example: skipif('sys.platform == \"win32\"') " + "skips the test if we are on the win32 platform. " + ) + config.addinivalue_line("markers", + "xfail(*conditions, reason=None, run=True): mark the the test function " + "as an expected failure. Optionally specify a reason and run=False " + "if you don't even want to execute the test function. Any positional " + "condition strings will be evaluated (like with skipif) and if one is " + "False the marker will not be applied." + ) + def pytest_namespace(): return dict(xfail=xfail) @@ -117,6 +132,14 @@ def pytest_runtest_makereport(__multicall__, item, call): if not isinstance(item, pytest.Function): return + # unitttest special case, see setting of _unexpectedsuccess + if hasattr(item, '_unexpectedsuccess'): + rep = __multicall__.execute() + if rep.when == "call": + # we need to translate into how py.test encodes xpass + rep.keywords['xfail'] = "reason: " + item._unexpectedsuccess + rep.outcome = "failed" + return rep if not (call.excinfo and call.excinfo.errisinstance(py.test.xfail.Exception)): evalxfail = getattr(item, '_evalxfail', None) @@ -169,21 +192,23 @@ elif char == "X": show_xpassed(terminalreporter, lines) elif char in "fF": - show_failed(terminalreporter, lines) + show_simple(terminalreporter, lines, 'failed', "FAIL %s") elif char in "sS": show_skipped(terminalreporter, lines) + elif char == "E": + show_simple(terminalreporter, lines, 'error', "ERROR %s") if lines: tr._tw.sep("=", "short test summary info") for line in lines: tr._tw.line(line) -def show_failed(terminalreporter, lines): +def show_simple(terminalreporter, lines, stat, format): tw = terminalreporter._tw - failed = terminalreporter.stats.get("failed") + failed = terminalreporter.stats.get(stat) if failed: for rep in failed: pos = rep.nodeid - lines.append("FAIL %s" %(pos, )) + lines.append(format %(pos, )) def show_xfailed(terminalreporter, lines): xfailed = terminalreporter.stats.get("xfailed") diff --git a/_pytest/terminal.py b/_pytest/terminal.py --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -15,7 +15,7 @@ group._addoption('-r', action="store", dest="reportchars", default=None, metavar="chars", help="show extra test summary info as specified by chars (f)ailed, " - "(s)skipped, (x)failed, (X)passed.") + "(E)error, (s)skipped, (x)failed, (X)passed.") group._addoption('-l', '--showlocals', action="store_true", dest="showlocals", default=False, help="show locals in tracebacks (disabled by default).") @@ -43,7 +43,8 @@ pass else: stdout = os.fdopen(newfd, stdout.mode, 1) - config._toclose = stdout + config._cleanup.append(lambda: stdout.close()) + reporter = TerminalReporter(config, stdout) config.pluginmanager.register(reporter, 'terminalreporter') if config.option.debug or config.option.traceconfig: @@ -52,11 +53,6 @@ reporter.write_line("[traceconfig] " + msg) config.trace.root.setprocessor("pytest:config", mywriter) -def pytest_unconfigure(config): - if hasattr(config, '_toclose'): - #print "closing", config._toclose, config._toclose.fileno() - config._toclose.close() - def getreportopt(config): reportopts = "" optvalue = config.option.report @@ -165,9 +161,6 @@ def pytest_deselected(self, items): self.stats.setdefault('deselected', []).extend(items) - def pytest__teardown_final_logerror(self, report): - self.stats.setdefault("error", []).append(report) - def pytest_runtest_logstart(self, nodeid, location): # ensure that the path is printed before the # 1st test of a module starts running @@ -259,7 +252,7 @@ msg = "platform %s -- Python %s" % (sys.platform, verinfo) if hasattr(sys, 'pypy_version_info'): verinfo = ".".join(map(str, sys.pypy_version_info[:3])) - msg += "[pypy-%s]" % verinfo + msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3]) msg += " -- pytest-%s" % (py.test.__version__) if self.verbosity > 0 or self.config.option.debug or \ getattr(self.config.option, 'pastebin', None): @@ -289,10 +282,18 @@ # we take care to leave out Instances aka () # because later versions are going to get rid of them anyway if self.config.option.verbose < 0: - for item in items: - nodeid = item.nodeid - nodeid = nodeid.replace("::()::", "::") - self._tw.line(nodeid) + if self.config.option.verbose < -1: + counts = {} + for item in items: + name = item.nodeid.split('::', 1)[0] + counts[name] = counts.get(name, 0) + 1 + for name, count in sorted(counts.items()): + self._tw.line("%s: %d" % (name, count)) + else: + for item in items: + nodeid = item.nodeid + nodeid = nodeid.replace("::()::", "::") + self._tw.line(nodeid) return stack = [] indent = "" @@ -318,12 +319,17 @@ self.config.hook.pytest_terminal_summary(terminalreporter=self) if exitstatus == 2: self._report_keyboardinterrupt() + del self._keyboardinterrupt_memo self.summary_deselected() self.summary_stats() def pytest_keyboard_interrupt(self, excinfo): self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True) + def pytest_unconfigure(self): + if hasattr(self, '_keyboardinterrupt_memo'): + self._report_keyboardinterrupt() + def _report_keyboardinterrupt(self): excrepr = self._keyboardinterrupt_memo msg = excrepr.reprcrash.message @@ -388,7 +394,7 @@ else: msg = self._getfailureheadline(rep) self.write_sep("_", msg) - rep.toterminal(self._tw) + self._outrep_summary(rep) def summary_errors(self): if self.config.option.tbstyle != "no": @@ -406,7 +412,15 @@ elif rep.when == "teardown": msg = "ERROR at teardown of " + msg self.write_sep("_", msg) - rep.toterminal(self._tw) + self._outrep_summary(rep) + + def _outrep_summary(self, rep): + rep.toterminal(self._tw) + for secname, content in rep.sections: + self._tw.sep("-", secname) + if content[-1:] == "\n": + content = content[:-1] + self._tw.line(content) def summary_stats(self): session_duration = py.std.time.time() - self._sessionstarttime @@ -417,9 +431,10 @@ keys.append(key) parts = [] for key in keys: - val = self.stats.get(key, None) - if val: - parts.append("%d %s" %(len(val), key)) + if key: # setup/teardown reports have an empty key, ignore them + val = self.stats.get(key, None) + if val: + parts.append("%d %s" %(len(val), key)) line = ", ".join(parts) # XXX coloring msg = "%s in %.2f seconds" %(line, session_duration) @@ -430,8 +445,15 @@ def summary_deselected(self): if 'deselected' in self.stats: + l = [] + k = self.config.option.keyword + if k: + l.append("-k%s" % k) + m = self.config.option.markexpr + if m: + l.append("-m %r" % m) self.write_sep("=", "%d tests deselected by %r" %( - len(self.stats['deselected']), self.config.option.keyword), bold=True) + len(self.stats['deselected']), " ".join(l)), bold=True) def repr_pythonversion(v=None): if v is None: diff --git a/_pytest/tmpdir.py b/_pytest/tmpdir.py --- a/_pytest/tmpdir.py +++ b/_pytest/tmpdir.py @@ -46,7 +46,7 @@ def finish(self): self.trace("finish") - + def pytest_configure(config): mp = monkeypatch() t = TempdirHandler(config) @@ -64,5 +64,5 @@ name = request._pyfuncitem.name name = py.std.re.sub("[\W]", "_", name) x = request.config._tmpdirhandler.mktemp(name, numbered=True) - return x.realpath() + return x diff --git a/_pytest/unittest.py b/_pytest/unittest.py --- a/_pytest/unittest.py +++ b/_pytest/unittest.py @@ -2,6 +2,9 @@ import pytest, py import sys, pdb +# for transfering markers +from _pytest.python import transfer_markers + def pytest_pycollect_makeitem(collector, name, obj): unittest = sys.modules.get('unittest') if unittest is None: @@ -19,7 +22,14 @@ class UnitTestCase(pytest.Class): def collect(self): loader = py.std.unittest.TestLoader() + module = self.getparent(pytest.Module).obj + cls = self.obj for name in loader.getTestCaseNames(self.obj): + x = getattr(self.obj, name) + funcobj = getattr(x, 'im_func', x) + transfer_markers(funcobj, cls, module) + if hasattr(funcobj, 'todo'): + pytest.mark.xfail(reason=str(funcobj.todo))(funcobj) yield TestCaseFunction(name, parent=self) def setup(self): @@ -37,15 +47,13 @@ class TestCaseFunction(pytest.Function): _excinfo = None - def __init__(self, name, parent): - super(TestCaseFunction, self).__init__(name, parent) - if hasattr(self._obj, 'todo'): - getattr(self._obj, 'im_func', self._obj).xfail = \ - pytest.mark.xfail(reason=str(self._obj.todo)) - def setup(self): self._testcase = self.parent.obj(self.name) self._obj = getattr(self._testcase, self.name) + if hasattr(self._testcase, 'skip'): + pytest.skip(self._testcase.skip) + if hasattr(self._obj, 'skip'): + pytest.skip(self._obj.skip) if hasattr(self._testcase, 'setup_method'): self._testcase.setup_method(self._obj) @@ -83,28 +91,37 @@ self._addexcinfo(rawexcinfo) def addFailure(self, testcase, rawexcinfo): self._addexcinfo(rawexcinfo) + def addSkip(self, testcase, reason): try: pytest.skip(reason) except pytest.skip.Exception: self._addexcinfo(sys.exc_info()) - def addExpectedFailure(self, testcase, rawexcinfo, reason): + + def addExpectedFailure(self, testcase, rawexcinfo, reason=""): try: pytest.xfail(str(reason)) except pytest.xfail.Exception: self._addexcinfo(sys.exc_info()) - def addUnexpectedSuccess(self, testcase, reason): - pass + + def addUnexpectedSuccess(self, testcase, reason=""): + self._unexpectedsuccess = reason + def addSuccess(self, testcase): pass + def stopTest(self, testcase): pass + def runtest(self): self._testcase(result=self) def _prunetraceback(self, excinfo): pytest.Function._prunetraceback(self, excinfo) - excinfo.traceback = excinfo.traceback.filter(lambda x:not x.frame.f_globals.get('__unittest')) + traceback = excinfo.traceback.filter( + lambda x:not x.frame.f_globals.get('__unittest')) + if traceback: + excinfo.traceback = traceback @pytest.mark.tryfirst def pytest_runtest_makereport(item, call): @@ -120,14 +137,19 @@ ut = sys.modules['twisted.python.failure'] Failure__init__ = ut.Failure.__init__.im_func check_testcase_implements_trial_reporter() - def excstore(self, exc_value=None, exc_type=None, exc_tb=None): + def excstore(self, exc_value=None, exc_type=None, exc_tb=None, + captureVars=None): if exc_value is None: self._rawexcinfo = sys.exc_info() else: if exc_type is None: exc_type = type(exc_value) self._rawexcinfo = (exc_type, exc_value, exc_tb) - Failure__init__(self, exc_value, exc_type, exc_tb) + try: + Failure__init__(self, exc_value, exc_type, exc_tb, + captureVars=captureVars) + except TypeError: + Failure__init__(self, exc_value, exc_type, exc_tb) ut.Failure.__init__ = excstore try: return __multicall__.execute() diff --git a/lib-python/2.7/UserDict.py b/lib-python/2.7/UserDict.py --- a/lib-python/2.7/UserDict.py +++ b/lib-python/2.7/UserDict.py @@ -80,8 +80,12 @@ def __iter__(self): return iter(self.data) -import _abcoll -_abcoll.MutableMapping.register(IterableUserDict) +try: + import _abcoll +except ImportError: + pass # e.g. no '_weakref' module on this pypy +else: + _abcoll.MutableMapping.register(IterableUserDict) class DictMixin: diff --git a/lib-python/2.7/_threading_local.py b/lib-python/2.7/_threading_local.py --- a/lib-python/2.7/_threading_local.py +++ b/lib-python/2.7/_threading_local.py @@ -155,7 +155,7 @@ object.__setattr__(self, '_local__args', (args, kw)) object.__setattr__(self, '_local__lock', RLock()) - if (args or kw) and (cls.__init__ is object.__init__): + if (args or kw) and (cls.__init__ == object.__init__): raise TypeError("Initialization arguments are not supported") # We need to create the thread dict in anticipation of diff --git a/lib-python/2.7/ctypes/__init__.py b/lib-python/2.7/ctypes/__init__.py --- a/lib-python/2.7/ctypes/__init__.py +++ b/lib-python/2.7/ctypes/__init__.py @@ -7,6 +7,7 @@ __version__ = "1.1.0" +import _ffi from _ctypes import Union, Structure, Array from _ctypes import _Pointer from _ctypes import CFuncPtr as _CFuncPtr @@ -350,16 +351,17 @@ self._FuncPtr = _FuncPtr if handle is None: - self._handle = _dlopen(self._name, mode) + self._handle = _ffi.CDLL(name, mode) else: self._handle = handle def __repr__(self): - return "<%s '%s', handle %x at %x>" % \ + return "<%s '%s', handle %r at %x>" % \ (self.__class__.__name__, self._name, - (self._handle & (_sys.maxint*2 + 1)), + (self._handle), id(self) & (_sys.maxint*2 + 1)) + def __getattr__(self, name): if name.startswith('__') and name.endswith('__'): raise AttributeError(name) @@ -487,9 +489,12 @@ _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI return CFunctionType -_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr) def cast(obj, typ): - return _cast(obj, obj, typ) + try: + c_void_p.from_param(obj) + except TypeError, e: + raise ArgumentError(str(e)) + return _cast_addr(obj, obj, typ) _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) def string_at(ptr, size=-1): diff --git a/lib-python/2.7/ctypes/test/__init__.py b/lib-python/2.7/ctypes/test/__init__.py --- a/lib-python/2.7/ctypes/test/__init__.py +++ b/lib-python/2.7/ctypes/test/__init__.py @@ -206,3 +206,16 @@ result = unittest.TestResult() test(result) return result + +def xfail(method): + """ + Poor's man xfail: remove it when all the failures have been fixed + """ + def new_method(self, *args, **kwds): + try: + method(self, *args, **kwds) + except: + pass + else: + self.assertTrue(False, "DID NOT RAISE") + return new_method diff --git a/lib-python/2.7/ctypes/test/test_arrays.py b/lib-python/2.7/ctypes/test/test_arrays.py --- a/lib-python/2.7/ctypes/test/test_arrays.py +++ b/lib-python/2.7/ctypes/test/test_arrays.py @@ -1,12 +1,23 @@ import unittest from ctypes import * +from test.test_support import impl_detail formats = "bBhHiIlLqQfd" +# c_longdouble commented out for PyPy, look at the commend in test_longdouble formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \ - c_long, c_ulonglong, c_float, c_double, c_longdouble + c_long, c_ulonglong, c_float, c_double #, c_longdouble class ArrayTestCase(unittest.TestCase): + + @impl_detail('long double not supported by PyPy', pypy=False) + def test_longdouble(self): + """ + This test is empty. It's just here to remind that we commented out + c_longdouble in "formats". If pypy will ever supports c_longdouble, we + should kill this test and uncomment c_longdouble inside formats. + """ + def test_simple(self): # create classes holding simple numeric types, and check # various properties. diff --git a/lib-python/2.7/ctypes/test/test_bitfields.py b/lib-python/2.7/ctypes/test/test_bitfields.py --- a/lib-python/2.7/ctypes/test/test_bitfields.py +++ b/lib-python/2.7/ctypes/test/test_bitfields.py @@ -115,17 +115,21 @@ def test_nonint_types(self): # bit fields are not allowed on non-integer types. result = self.fail_fields(("a", c_char_p, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char_p')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) result = self.fail_fields(("a", c_void_p, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_void_p')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) if c_int != c_long: result = self.fail_fields(("a", POINTER(c_int), 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type LP_c_int')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) result = self.fail_fields(("a", c_char, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) try: c_wchar @@ -133,13 +137,15 @@ pass else: result = self.fail_fields(("a", c_wchar, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_wchar')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) class Dummy(Structure): _fields_ = [] result = self.fail_fields(("a", Dummy, 1)) - self.assertEqual(result, (TypeError, 'bit fields not allowed for type Dummy')) + self.assertEqual(result[0], TypeError) + self.assertIn('bit fields not allowed for type', result[1]) def test_single_bitfield_size(self): for c_typ in int_types: diff --git a/lib-python/2.7/ctypes/test/test_byteswap.py b/lib-python/2.7/ctypes/test/test_byteswap.py --- a/lib-python/2.7/ctypes/test/test_byteswap.py +++ b/lib-python/2.7/ctypes/test/test_byteswap.py @@ -2,6 +2,7 @@ from binascii import hexlify from ctypes import * +from ctypes.test import xfail def bin(s): return hexlify(memoryview(s)).upper() @@ -21,6 +22,7 @@ setattr(bits, "i%s" % i, 1) dump(bits) + @xfail def test_endian_short(self): if sys.byteorder == "little": self.assertTrue(c_short.__ctype_le__ is c_short) @@ -48,6 +50,7 @@ self.assertEqual(bin(s), "3412") self.assertEqual(s.value, 0x1234) + @xfail def test_endian_int(self): if sys.byteorder == "little": self.assertTrue(c_int.__ctype_le__ is c_int) @@ -76,6 +79,7 @@ self.assertEqual(bin(s), "78563412") self.assertEqual(s.value, 0x12345678) + @xfail def test_endian_longlong(self): if sys.byteorder == "little": self.assertTrue(c_longlong.__ctype_le__ is c_longlong) @@ -104,6 +108,7 @@ self.assertEqual(bin(s), "EFCDAB9078563412") self.assertEqual(s.value, 0x1234567890ABCDEF) + @xfail def test_endian_float(self): if sys.byteorder == "little": self.assertTrue(c_float.__ctype_le__ is c_float) @@ -122,6 +127,7 @@ self.assertAlmostEqual(s.value, math.pi, 6) self.assertEqual(bin(struct.pack(">f", math.pi)), bin(s)) + @xfail def test_endian_double(self): if sys.byteorder == "little": self.assertTrue(c_double.__ctype_le__ is c_double) @@ -149,6 +155,7 @@ self.assertTrue(c_char.__ctype_le__ is c_char) self.assertTrue(c_char.__ctype_be__ is c_char) + @xfail def test_struct_fields_1(self): if sys.byteorder == "little": base = BigEndianStructure @@ -198,6 +205,7 @@ pass self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)]) + @xfail def test_struct_fields_2(self): # standard packing in struct uses no alignment. # So, we have to align using pad bytes. @@ -221,6 +229,7 @@ s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) self.assertEqual(bin(s1), bin(s2)) + @xfail def test_unaligned_nonnative_struct_fields(self): if sys.byteorder == "little": base = BigEndianStructure diff --git a/lib-python/2.7/ctypes/test/test_callbacks.py b/lib-python/2.7/ctypes/test/test_callbacks.py --- a/lib-python/2.7/ctypes/test/test_callbacks.py +++ b/lib-python/2.7/ctypes/test/test_callbacks.py @@ -1,5 +1,6 @@ import unittest from ctypes import * +from ctypes.test import xfail import _ctypes_test class Callbacks(unittest.TestCase): @@ -98,6 +99,7 @@ ## self.check_type(c_char_p, "abc") ## self.check_type(c_char_p, "def") + @xfail def test_pyobject(self): o = () from sys import getrefcount as grc diff --git a/lib-python/2.7/ctypes/test/test_cfuncs.py b/lib-python/2.7/ctypes/test/test_cfuncs.py --- a/lib-python/2.7/ctypes/test/test_cfuncs.py +++ b/lib-python/2.7/ctypes/test/test_cfuncs.py @@ -3,8 +3,8 @@ import unittest from ctypes import * - import _ctypes_test +from test.test_support import impl_detail class CFunctions(unittest.TestCase): _dll = CDLL(_ctypes_test.__file__) @@ -158,12 +158,14 @@ self.assertEqual(self._dll.tf_bd(0, 42.), 14.) self.assertEqual(self.S(), 42) + @impl_detail('long double not supported by PyPy', pypy=False) def test_longdouble(self): self._dll.tf_D.restype = c_longdouble self._dll.tf_D.argtypes = (c_longdouble,) self.assertEqual(self._dll.tf_D(42.), 14.) self.assertEqual(self.S(), 42) - + + @impl_detail('long double not supported by PyPy', pypy=False) def test_longdouble_plus(self): self._dll.tf_bD.restype = c_longdouble self._dll.tf_bD.argtypes = (c_byte, c_longdouble) diff --git a/lib-python/2.7/ctypes/test/test_delattr.py b/lib-python/2.7/ctypes/test/test_delattr.py --- a/lib-python/2.7/ctypes/test/test_delattr.py +++ b/lib-python/2.7/ctypes/test/test_delattr.py @@ -6,15 +6,15 @@ class TestCase(unittest.TestCase): def test_simple(self): - self.assertRaises(TypeError, + self.assertRaises((TypeError, AttributeError), delattr, c_int(42), "value") def test_chararray(self): - self.assertRaises(TypeError, + self.assertRaises((TypeError, AttributeError), delattr, (c_char * 5)(), "value") def test_struct(self): - self.assertRaises(TypeError, + self.assertRaises((TypeError, AttributeError), delattr, X(), "foo") if __name__ == "__main__": diff --git a/lib-python/2.7/ctypes/test/test_frombuffer.py b/lib-python/2.7/ctypes/test/test_frombuffer.py --- a/lib-python/2.7/ctypes/test/test_frombuffer.py +++ b/lib-python/2.7/ctypes/test/test_frombuffer.py @@ -2,6 +2,7 @@ import array import gc import unittest +from ctypes.test import xfail class X(Structure): _fields_ = [("c_int", c_int)] @@ -10,6 +11,7 @@ self._init_called = True class Test(unittest.TestCase): + @xfail def test_fom_buffer(self): a = array.array("i", range(16)) x = (c_int * 16).from_buffer(a) @@ -35,6 +37,7 @@ self.assertRaises(TypeError, (c_char * 16).from_buffer, "a" * 16) + @xfail def test_fom_buffer_with_offset(self): a = array.array("i", range(16)) x = (c_int * 15).from_buffer(a, sizeof(c_int)) @@ -43,6 +46,7 @@ self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a, sizeof(c_int))) self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 * sizeof(c_int))) + @xfail def test_from_buffer_copy(self): a = array.array("i", range(16)) x = (c_int * 16).from_buffer_copy(a) @@ -67,6 +71,7 @@ x = (c_char * 16).from_buffer_copy("a" * 16) self.assertEqual(x[:], "a" * 16) + @xfail def test_fom_buffer_copy_with_offset(self): a = array.array("i", range(16)) x = (c_int * 15).from_buffer_copy(a, sizeof(c_int)) diff --git a/lib-python/2.7/ctypes/test/test_functions.py b/lib-python/2.7/ctypes/test/test_functions.py --- a/lib-python/2.7/ctypes/test/test_functions.py +++ b/lib-python/2.7/ctypes/test/test_functions.py @@ -7,6 +7,8 @@ from ctypes import * import sys, unittest +from ctypes.test import xfail +from test.test_support import impl_detail try: WINFUNCTYPE @@ -143,6 +145,7 @@ self.assertEqual(result, -21) self.assertEqual(type(result), float) + @impl_detail('long double not supported by PyPy', pypy=False) def test_longdoubleresult(self): f = dll._testfunc_D_bhilfD f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble] @@ -393,6 +396,7 @@ self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + @xfail def test_sf1651235(self): # see http://www.python.org/sf/1651235 diff --git a/lib-python/2.7/ctypes/test/test_internals.py b/lib-python/2.7/ctypes/test/test_internals.py --- a/lib-python/2.7/ctypes/test/test_internals.py +++ b/lib-python/2.7/ctypes/test/test_internals.py @@ -33,7 +33,13 @@ refcnt = grc(s) cs = c_char_p(s) self.assertEqual(refcnt + 1, grc(s)) - self.assertSame(cs._objects, s) + try: + # Moving gcs need to allocate a nonmoving buffer + cs._objects._obj + except AttributeError: + self.assertSame(cs._objects, s) + else: + self.assertSame(cs._objects._obj, s) def test_simple_struct(self): class X(Structure): diff --git a/lib-python/2.7/ctypes/test/test_libc.py b/lib-python/2.7/ctypes/test/test_libc.py --- a/lib-python/2.7/ctypes/test/test_libc.py +++ b/lib-python/2.7/ctypes/test/test_libc.py @@ -25,5 +25,14 @@ lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort)) self.assertEqual(chars.raw, " ,,aaaadmmmnpppsss\x00") + def SKIPPED_test_no_more_xfail(self): + # We decided to not explicitly support the whole ctypes-2.7 + # and instead go for a case-by-case, demand-driven approach. + # So this test is skipped instead of failing. + import socket + import ctypes.test + self.assertTrue(not hasattr(ctypes.test, 'xfail'), + "You should incrementally grep for '@xfail' and remove them, they are real failures") + if __name__ == "__main__": unittest.main() diff --git a/lib-python/2.7/ctypes/test/test_loading.py b/lib-python/2.7/ctypes/test/test_loading.py --- a/lib-python/2.7/ctypes/test/test_loading.py +++ b/lib-python/2.7/ctypes/test/test_loading.py @@ -2,7 +2,7 @@ import sys, unittest import os from ctypes.util import find_library -from ctypes.test import is_resource_enabled +from ctypes.test import is_resource_enabled, xfail libc_name = None if os.name == "nt": @@ -75,6 +75,7 @@ self.assertRaises(AttributeError, dll.__getitem__, 1234) if os.name == "nt": + @xfail def test_1703286_A(self): from _ctypes import LoadLibrary, FreeLibrary # On winXP 64-bit, advapi32 loads at an address that does @@ -85,6 +86,7 @@ handle = LoadLibrary("advapi32") FreeLibrary(handle) + @xfail def test_1703286_B(self): # Since on winXP 64-bit advapi32 loads like described # above, the (arbitrarily selected) CloseEventLog function diff --git a/lib-python/2.7/ctypes/test/test_macholib.py b/lib-python/2.7/ctypes/test/test_macholib.py --- a/lib-python/2.7/ctypes/test/test_macholib.py +++ b/lib-python/2.7/ctypes/test/test_macholib.py @@ -52,7 +52,6 @@ '/usr/lib/libSystem.B.dylib') result = find_lib('z') - self.assertTrue(result.startswith('/usr/lib/libz.1')) self.assertTrue(result.endswith('.dylib')) self.assertEqual(find_lib('IOKit'), diff --git a/lib-python/2.7/ctypes/test/test_numbers.py b/lib-python/2.7/ctypes/test/test_numbers.py --- a/lib-python/2.7/ctypes/test/test_numbers.py +++ b/lib-python/2.7/ctypes/test/test_numbers.py @@ -1,6 +1,7 @@ from ctypes import * import unittest import struct +from ctypes.test import xfail def valid_ranges(*types): # given a sequence of numeric types, collect their _type_ @@ -89,12 +90,14 @@ ## self.assertRaises(ValueError, t, l-1) ## self.assertRaises(ValueError, t, h+1) + @xfail def test_from_param(self): # the from_param class method attribute always # returns PyCArgObject instances for t in signed_types + unsigned_types + float_types: self.assertEqual(ArgType, type(t.from_param(0))) + @xfail def test_byref(self): # calling byref returns also a PyCArgObject instance for t in signed_types + unsigned_types + float_types + bool_types: @@ -102,6 +105,7 @@ self.assertEqual(ArgType, type(parm)) + @xfail def test_floats(self): # c_float and c_double can be created from # Python int, long and float @@ -115,6 +119,7 @@ self.assertEqual(t(2L).value, 2.0) self.assertEqual(t(f).value, 2.0) + @xfail def test_integers(self): class FloatLike(object): def __float__(self): diff --git a/lib-python/2.7/ctypes/test/test_objects.py b/lib-python/2.7/ctypes/test/test_objects.py --- a/lib-python/2.7/ctypes/test/test_objects.py +++ b/lib-python/2.7/ctypes/test/test_objects.py @@ -22,7 +22,7 @@ >>> array[4] = 'foo bar' >>> array._objects -{'4': 'foo bar'} +{'4': } >>> array[4] 'foo bar' >>> @@ -47,9 +47,9 @@ >>> x.array[0] = 'spam spam spam' >>> x._objects -{'0:2': 'spam spam spam'} +{'0:2': } >>> x.array._b_base_._objects -{'0:2': 'spam spam spam'} +{'0:2': } >>> ''' diff --git a/lib-python/2.7/ctypes/test/test_parameters.py b/lib-python/2.7/ctypes/test/test_parameters.py --- a/lib-python/2.7/ctypes/test/test_parameters.py +++ b/lib-python/2.7/ctypes/test/test_parameters.py @@ -1,5 +1,7 @@ import unittest, sys +from ctypes.test import xfail + class SimpleTypesTestCase(unittest.TestCase): def setUp(self): @@ -49,6 +51,7 @@ self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc") # XXX Replace by c_char_p tests + @xfail def test_cstrings(self): from ctypes import c_char_p, byref @@ -86,7 +89,10 @@ pa = c_wchar_p.from_param(c_wchar_p(u"123")) self.assertEqual(type(pa), c_wchar_p) + if sys.platform == "win32": + test_cw_strings = xfail(test_cw_strings) + @xfail def test_int_pointers(self): from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer LPINT = POINTER(c_int) diff --git a/lib-python/2.7/ctypes/test/test_pep3118.py b/lib-python/2.7/ctypes/test/test_pep3118.py --- a/lib-python/2.7/ctypes/test/test_pep3118.py +++ b/lib-python/2.7/ctypes/test/test_pep3118.py @@ -1,6 +1,7 @@ import unittest from ctypes import * import re, sys +from ctypes.test import xfail if sys.byteorder == "little": THIS_ENDIAN = "<" @@ -19,6 +20,7 @@ class Test(unittest.TestCase): + @xfail def test_native_types(self): for tp, fmt, shape, itemtp in native_types: ob = tp() @@ -46,6 +48,7 @@ print(tp) raise + @xfail def test_endian_types(self): for tp, fmt, shape, itemtp in endian_types: ob = tp() diff --git a/lib-python/2.7/ctypes/test/test_pickling.py b/lib-python/2.7/ctypes/test/test_pickling.py --- a/lib-python/2.7/ctypes/test/test_pickling.py +++ b/lib-python/2.7/ctypes/test/test_pickling.py @@ -3,6 +3,7 @@ from ctypes import * import _ctypes_test dll = CDLL(_ctypes_test.__file__) +from ctypes.test import xfail class X(Structure): _fields_ = [("a", c_int), ("b", c_double)] @@ -21,6 +22,7 @@ def loads(self, item): return pickle.loads(item) + @xfail def test_simple(self): for src in [ c_int(42), @@ -31,6 +33,7 @@ self.assertEqual(memoryview(src).tobytes(), memoryview(dst).tobytes()) + @xfail def test_struct(self): X.init_called = 0 @@ -49,6 +52,7 @@ self.assertEqual(memoryview(y).tobytes(), memoryview(x).tobytes()) + @xfail def test_unpickable(self): # ctypes objects that are pointers or contain pointers are # unpickable. @@ -66,6 +70,7 @@ ]: self.assertRaises(ValueError, lambda: self.dumps(item)) + @xfail def test_wchar(self): pickle.dumps(c_char("x")) # Issue 5049 diff --git a/lib-python/2.7/ctypes/test/test_python_api.py b/lib-python/2.7/ctypes/test/test_python_api.py --- a/lib-python/2.7/ctypes/test/test_python_api.py +++ b/lib-python/2.7/ctypes/test/test_python_api.py @@ -1,6 +1,6 @@ from ctypes import * import unittest, sys -from ctypes.test import is_resource_enabled +from ctypes.test import is_resource_enabled, xfail ################################################################ # This section should be moved into ctypes\__init__.py, when it's ready. @@ -17,6 +17,7 @@ class PythonAPITestCase(unittest.TestCase): + @xfail def test_PyString_FromStringAndSize(self): PyString_FromStringAndSize = pythonapi.PyString_FromStringAndSize @@ -25,6 +26,7 @@ self.assertEqual(PyString_FromStringAndSize("abcdefghi", 3), "abc") + @xfail def test_PyString_FromString(self): pythonapi.PyString_FromString.restype = py_object pythonapi.PyString_FromString.argtypes = (c_char_p,) @@ -56,6 +58,7 @@ del res self.assertEqual(grc(42), ref42) + @xfail def test_PyObj_FromPtr(self): s = "abc def ghi jkl" ref = grc(s) @@ -81,6 +84,7 @@ # not enough arguments self.assertRaises(TypeError, PyOS_snprintf, buf) + @xfail def test_pyobject_repr(self): self.assertEqual(repr(py_object()), "py_object()") self.assertEqual(repr(py_object(42)), "py_object(42)") diff --git a/lib-python/2.7/ctypes/test/test_refcounts.py b/lib-python/2.7/ctypes/test/test_refcounts.py --- a/lib-python/2.7/ctypes/test/test_refcounts.py +++ b/lib-python/2.7/ctypes/test/test_refcounts.py @@ -90,6 +90,7 @@ return a * b * 2 f = proto(func) + gc.collect() a = sys.getrefcount(ctypes.c_int) f(1, 2) self.assertEqual(sys.getrefcount(ctypes.c_int), a) diff --git a/lib-python/2.7/ctypes/test/test_stringptr.py b/lib-python/2.7/ctypes/test/test_stringptr.py --- a/lib-python/2.7/ctypes/test/test_stringptr.py +++ b/lib-python/2.7/ctypes/test/test_stringptr.py @@ -2,11 +2,13 @@ from ctypes import * import _ctypes_test +from ctypes.test import xfail lib = CDLL(_ctypes_test.__file__) class StringPtrTestCase(unittest.TestCase): + @xfail def test__POINTER_c_char(self): class X(Structure): _fields_ = [("str", POINTER(c_char))] @@ -27,6 +29,7 @@ self.assertRaises(TypeError, setattr, x, "str", "Hello, World") + @xfail def test__c_char_p(self): class X(Structure): _fields_ = [("str", c_char_p)] diff --git a/lib-python/2.7/ctypes/test/test_strings.py b/lib-python/2.7/ctypes/test/test_strings.py --- a/lib-python/2.7/ctypes/test/test_strings.py +++ b/lib-python/2.7/ctypes/test/test_strings.py @@ -31,8 +31,9 @@ buf.value = "Hello, World" self.assertEqual(buf.value, "Hello, World") - self.assertRaises(TypeError, setattr, buf, "value", memoryview("Hello, World")) - self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) + if test_support.check_impl_detail(): + self.assertRaises(TypeError, setattr, buf, "value", memoryview("Hello, World")) + self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) self.assertRaises(ValueError, setattr, buf, "raw", memoryview("x" * 100)) def test_c_buffer_raw(self, memoryview=memoryview): @@ -40,7 +41,8 @@ buf.raw = memoryview("Hello, World") self.assertEqual(buf.value, "Hello, World") - self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) + if test_support.check_impl_detail(): + self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) self.assertRaises(ValueError, setattr, buf, "raw", memoryview("x" * 100)) def test_c_buffer_deprecated(self): diff --git a/lib-python/2.7/ctypes/test/test_structures.py b/lib-python/2.7/ctypes/test/test_structures.py --- a/lib-python/2.7/ctypes/test/test_structures.py +++ b/lib-python/2.7/ctypes/test/test_structures.py @@ -194,8 +194,8 @@ self.assertEqual(X.b.offset, min(8, longlong_align)) - d = {"_fields_": [("a", "b"), - ("b", "q")], + d = {"_fields_": [("a", c_byte), + ("b", c_longlong)], "_pack_": -1} self.assertRaises(ValueError, type(Structure), "X", (Structure,), d) diff --git a/lib-python/2.7/ctypes/test/test_varsize_struct.py b/lib-python/2.7/ctypes/test/test_varsize_struct.py --- a/lib-python/2.7/ctypes/test/test_varsize_struct.py +++ b/lib-python/2.7/ctypes/test/test_varsize_struct.py @@ -1,7 +1,9 @@ from ctypes import * import unittest +from ctypes.test import xfail class VarSizeTest(unittest.TestCase): + @xfail def test_resize(self): class X(Structure): _fields_ = [("item", c_int), diff --git a/lib-python/2.7/ctypes/util.py b/lib-python/2.7/ctypes/util.py --- a/lib-python/2.7/ctypes/util.py +++ b/lib-python/2.7/ctypes/util.py @@ -72,8 +72,8 @@ return name if os.name == "posix" and sys.platform == "darwin": - from ctypes.macholib.dyld import dyld_find as _dyld_find def find_library(name): + from ctypes.macholib.dyld import dyld_find as _dyld_find possible = ['lib%s.dylib' % name, '%s.dylib' % name, '%s.framework/%s' % (name, name)] diff --git a/lib-python/2.7/distutils/command/bdist_wininst.py b/lib-python/2.7/distutils/command/bdist_wininst.py --- a/lib-python/2.7/distutils/command/bdist_wininst.py +++ b/lib-python/2.7/distutils/command/bdist_wininst.py @@ -298,7 +298,8 @@ bitmaplen, # number of bytes in bitmap ) file.write(header) - file.write(open(arcname, "rb").read()) + with open(arcname, "rb") as arcfile: + file.write(arcfile.read()) # create_exe() diff --git a/lib-python/2.7/distutils/command/build_ext.py b/lib-python/2.7/distutils/command/build_ext.py --- a/lib-python/2.7/distutils/command/build_ext.py +++ b/lib-python/2.7/distutils/command/build_ext.py @@ -184,7 +184,7 @@ # the 'libs' directory is for binary installs - we assume that # must be the *native* platform. But we don't really support # cross-compiling via a binary install anyway, so we let it go. - self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs')) + self.library_dirs.append(os.path.join(sys.exec_prefix, 'include')) if self.debug: self.build_temp = os.path.join(self.build_temp, "Debug") else: @@ -192,8 +192,13 @@ # Append the source distribution include and library directories, # this allows distutils on windows to work in the source tree - self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC')) - if MSVC_VERSION == 9: + if 0: + # pypy has no PC directory + self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC')) + if 1: + # pypy has no PCBuild directory + pass + elif MSVC_VERSION == 9: # Use the .lib files for the correct architecture if self.plat_name == 'win32': suffix = '' @@ -695,24 +700,14 @@ shared extension. On most platforms, this is just 'ext.libraries'; on Windows and OS/2, we add the Python library (eg. python20.dll). """ - # The python library is always needed on Windows. For MSVC, this - # is redundant, since the library is mentioned in a pragma in - # pyconfig.h that MSVC groks. The other Windows compilers all seem - # to need it mentioned explicitly, though, so that's what we do. - # Append '_d' to the python import library on debug builds. + # The python library is always needed on Windows. if sys.platform == "win32": - from distutils.msvccompiler import MSVCCompiler - if not isinstance(self.compiler, MSVCCompiler): - template = "python%d%d" - if self.debug: - template = template + '_d' - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - # don't extend ext.libraries, it may be shared with other - # extensions, it is a reference to the original list - return ext.libraries + [pythonlib] - else: - return ext.libraries + template = "python%d%d" + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] elif sys.platform == "os2emx": # EMX/GCC requires the python library explicitly, and I # believe VACPP does as well (though not confirmed) - AIM Apr01 diff --git a/lib-python/2.7/distutils/command/install.py b/lib-python/2.7/distutils/command/install.py --- a/lib-python/2.7/distutils/command/install.py +++ b/lib-python/2.7/distutils/command/install.py @@ -83,6 +83,13 @@ 'scripts': '$userbase/bin', 'data' : '$userbase', }, + 'pypy': { + 'purelib': '$base/site-packages', + 'platlib': '$base/site-packages', + 'headers': '$base/include', + 'scripts': '$base/bin', + 'data' : '$base', + }, } # The keys to an installation scheme; if any new types of files are to be @@ -467,6 +474,8 @@ def select_scheme (self, name): # it's the caller's problem if they supply a bad name! + if hasattr(sys, 'pypy_version_info'): + name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: attrname = 'install_' + key diff --git a/lib-python/2.7/distutils/cygwinccompiler.py b/lib-python/2.7/distutils/cygwinccompiler.py --- a/lib-python/2.7/distutils/cygwinccompiler.py +++ b/lib-python/2.7/distutils/cygwinccompiler.py @@ -75,6 +75,9 @@ elif msc_ver == '1500': # VS2008 / MSVC 9.0 return ['msvcr90'] + elif msc_ver == '1600': + # VS2010 / MSVC 10.0 + return ['msvcr100'] else: raise ValueError("Unknown MS Compiler version %s " % msc_ver) diff --git a/lib-python/2.7/distutils/msvc9compiler.py b/lib-python/2.7/distutils/msvc9compiler.py --- a/lib-python/2.7/distutils/msvc9compiler.py +++ b/lib-python/2.7/distutils/msvc9compiler.py @@ -648,6 +648,7 @@ temp_manifest = os.path.join( build_temp, os.path.basename(output_filename) + ".manifest") + ld_args.append('/MANIFEST') ld_args.append('/MANIFESTFILE:' + temp_manifest) if extra_preargs: diff --git a/lib-python/2.7/distutils/spawn.py b/lib-python/2.7/distutils/spawn.py --- a/lib-python/2.7/distutils/spawn.py +++ b/lib-python/2.7/distutils/spawn.py @@ -58,7 +58,6 @@ def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0): executable = cmd[0] - cmd = _nt_quote_args(cmd) if search_path: # either we find one or it stays the same executable = find_executable(executable) or executable @@ -66,7 +65,8 @@ if not dry_run: # spawn for NT requires a full path to the .exe try: - rc = os.spawnv(os.P_WAIT, executable, cmd) + import subprocess + rc = subprocess.call(cmd) except OSError, exc: # this seems to happen when the command isn't found raise DistutilsExecError, \ diff --git a/lib-python/2.7/distutils/sysconfig.py b/lib-python/2.7/distutils/sysconfig.py --- a/lib-python/2.7/distutils/sysconfig.py +++ b/lib-python/2.7/distutils/sysconfig.py @@ -9,563 +9,21 @@ Email: """ -__revision__ = "$Id$" +__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $" -import os -import re -import string import sys -from distutils.errors import DistutilsPlatformError -# These are needed in a couple of spots, so just compute them once. -PREFIX = os.path.normpath(sys.prefix) -EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +# The content of this file is redirected from +# sysconfig_cpython or sysconfig_pypy. -# Path to the base directory of the project. On Windows the binary may -# live in project/PCBuild9. If we're dealing with an x64 Windows build, -# it'll live in project/PCbuild/amd64. -project_base = os.path.dirname(os.path.abspath(sys.executable)) -if os.name == "nt" and "pcbuild" in project_base[-8:].lower(): - project_base = os.path.abspath(os.path.join(project_base, os.path.pardir)) -# PC/VS7.1 -if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower(): - project_base = os.path.abspath(os.path.join(project_base, os.path.pardir, - os.path.pardir)) -# PC/AMD64 -if os.name == "nt" and "\\pcbuild\\amd64" in project_base[-14:].lower(): - project_base = os.path.abspath(os.path.join(project_base, os.path.pardir, - os.path.pardir)) +if '__pypy__' in sys.builtin_module_names: + from distutils.sysconfig_pypy import * + from distutils.sysconfig_pypy import _config_vars # needed by setuptools + from distutils.sysconfig_pypy import _variable_rx # read_setup_file() +else: + from distutils.sysconfig_cpython import * + from distutils.sysconfig_cpython import _config_vars # needed by setuptools + from distutils.sysconfig_cpython import _variable_rx # read_setup_file() -# python_build: (Boolean) if true, we're either building Python or -# building an extension with an un-installed Python, so we use -# different (hard-wired) directories. -# Setup.local is available for Makefile builds including VPATH builds, -# Setup.dist is available on Windows -def _python_build(): - for fn in ("Setup.dist", "Setup.local"): - if os.path.isfile(os.path.join(project_base, "Modules", fn)): - return True - return False -python_build = _python_build() - -def get_python_version(): - """Return a string containing the major and minor Python version, - leaving off the patchlevel. Sample return values could be '1.5' - or '2.2'. - """ - return sys.version[:3] - - -def get_python_inc(plat_specific=0, prefix=None): - """Return the directory containing installed Python header files. - - If 'plat_specific' is false (the default), this is the path to the - non-platform-specific header files, i.e. Python.h and so on; - otherwise, this is the path to platform-specific header files - (namely pyconfig.h). - - If 'prefix' is supplied, use it instead of sys.prefix or - sys.exec_prefix -- i.e., ignore 'plat_specific'. - """ - if prefix is None: - prefix = plat_specific and EXEC_PREFIX or PREFIX - - if os.name == "posix": - if python_build: - buildir = os.path.dirname(sys.executable) - if plat_specific: - # python.h is located in the buildir - inc_dir = buildir - else: - # the source dir is relative to the buildir - srcdir = os.path.abspath(os.path.join(buildir, - get_config_var('srcdir'))) - # Include is located in the srcdir - inc_dir = os.path.join(srcdir, "Include") - return inc_dir - return os.path.join(prefix, "include", "python" + get_python_version()) - elif os.name == "nt": - return os.path.join(prefix, "include") - elif os.name == "os2": - return os.path.join(prefix, "Include") - else: - raise DistutilsPlatformError( - "I don't know where Python installs its C header files " - "on platform '%s'" % os.name) - - -def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): - """Return the directory containing the Python library (standard or - site additions). - - If 'plat_specific' is true, return the directory containing - platform-specific modules, i.e. any module from a non-pure-Python - module distribution; otherwise, return the platform-shared library - directory. If 'standard_lib' is true, return the directory - containing standard Python library modules; otherwise, return the - directory for site-specific modules. - - If 'prefix' is supplied, use it instead of sys.prefix or - sys.exec_prefix -- i.e., ignore 'plat_specific'. - """ - if prefix is None: - prefix = plat_specific and EXEC_PREFIX or PREFIX - - if os.name == "posix": - libpython = os.path.join(prefix, - "lib", "python" + get_python_version()) - if standard_lib: - return libpython - else: - return os.path.join(libpython, "site-packages") - - elif os.name == "nt": - if standard_lib: - return os.path.join(prefix, "Lib") - else: - if get_python_version() < "2.2": - return prefix - else: - return os.path.join(prefix, "Lib", "site-packages") - - elif os.name == "os2": - if standard_lib: - return os.path.join(prefix, "Lib") - else: - return os.path.join(prefix, "Lib", "site-packages") - - else: - raise DistutilsPlatformError( - "I don't know where Python installs its library " - "on platform '%s'" % os.name) - - -def customize_compiler(compiler): - """Do any platform-specific customization of a CCompiler instance. - - Mainly needed on Unix, so we can plug in the information that - varies across Unices and is stored in Python's Makefile. - """ - if compiler.compiler_type == "unix": - (cc, cxx, opt, cflags, ccshared, ldshared, so_ext) = \ - get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', - 'CCSHARED', 'LDSHARED', 'SO') - - if 'CC' in os.environ: - cc = os.environ['CC'] - if 'CXX' in os.environ: - cxx = os.environ['CXX'] - if 'LDSHARED' in os.environ: - ldshared = os.environ['LDSHARED'] - if 'CPP' in os.environ: - cpp = os.environ['CPP'] - else: - cpp = cc + " -E" # not always - if 'LDFLAGS' in os.environ: - ldshared = ldshared + ' ' + os.environ['LDFLAGS'] - if 'CFLAGS' in os.environ: - cflags = opt + ' ' + os.environ['CFLAGS'] - ldshared = ldshared + ' ' + os.environ['CFLAGS'] - if 'CPPFLAGS' in os.environ: - cpp = cpp + ' ' + os.environ['CPPFLAGS'] - cflags = cflags + ' ' + os.environ['CPPFLAGS'] - ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] - - cc_cmd = cc + ' ' + cflags - compiler.set_executables( - preprocessor=cpp, - compiler=cc_cmd, - compiler_so=cc_cmd + ' ' + ccshared, - compiler_cxx=cxx, - linker_so=ldshared, - linker_exe=cc) - - compiler.shared_lib_extension = so_ext - - -def get_config_h_filename(): - """Return full pathname of installed pyconfig.h file.""" - if python_build: - if os.name == "nt": - inc_dir = os.path.join(project_base, "PC") - else: - inc_dir = project_base - else: - inc_dir = get_python_inc(plat_specific=1) - if get_python_version() < '2.2': - config_h = 'config.h' - else: - # The name of the config.h file changed in 2.2 - config_h = 'pyconfig.h' - return os.path.join(inc_dir, config_h) - - -def get_makefile_filename(): - """Return full pathname of installed Makefile from the Python build.""" - if python_build: - return os.path.join(os.path.dirname(sys.executable), "Makefile") - lib_dir = get_python_lib(plat_specific=1, standard_lib=1) - return os.path.join(lib_dir, "config", "Makefile") - - -def parse_config_h(fp, g=None): - """Parse a config.h-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - if g is None: - g = {} - define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") - undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") - # - while 1: - line = fp.readline() - if not line: - break - m = define_rx.match(line) - if m: - n, v = m.group(1, 2) - try: v = int(v) - except ValueError: pass - g[n] = v - else: - m = undef_rx.match(line) - if m: - g[m.group(1)] = 0 - return g - - -# Regexes needed for parsing Makefile (and similar syntaxes, -# like old-style Setup files). -_variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") -_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") -_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") - -def parse_makefile(fn, g=None): - """Parse a Makefile-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - from distutils.text_file import TextFile - fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1) - - if g is None: - g = {} - done = {} - notdone = {} - - while 1: - line = fp.readline() - if line is None: # eof - break - m = _variable_rx.match(line) - if m: - n, v = m.group(1, 2) - v = v.strip() - # `$$' is a literal `$' in make - tmpv = v.replace('$$', '') - - if "$" in tmpv: - notdone[n] = v - else: - try: - v = int(v) - except ValueError: - # insert literal `$' - done[n] = v.replace('$$', '$') - else: - done[n] = v - - # do variable interpolation here - while notdone: - for name in notdone.keys(): - value = notdone[name] - m = _findvar1_rx.search(value) or _findvar2_rx.search(value) - if m: - n = m.group(1) - found = True - if n in done: - item = str(done[n]) - elif n in notdone: - # get it on a subsequent round - found = False - elif n in os.environ: - # do it like make: fall back to environment - item = os.environ[n] - else: - done[n] = item = "" - if found: - after = value[m.end():] - value = value[:m.start()] + item + after - if "$" in after: - notdone[name] = value - else: - try: value = int(value) - except ValueError: - done[name] = value.strip() - else: - done[name] = value - del notdone[name] - else: - # bogus variable reference; just drop it since we can't deal - del notdone[name] - - fp.close() - - # strip spurious spaces - for k, v in done.items(): - if isinstance(v, str): - done[k] = v.strip() - - # save the results in the global dictionary - g.update(done) - return g - - -def expand_makefile_vars(s, vars): - """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in - 'string' according to 'vars' (a dictionary mapping variable names to - values). Variables not present in 'vars' are silently expanded to the - empty string. The variable values in 'vars' should not contain further - variable expansions; if 'vars' is the output of 'parse_makefile()', - you're fine. Returns a variable-expanded version of 's'. - """ - - # This algorithm does multiple expansion, so if vars['foo'] contains - # "${bar}", it will expand ${foo} to ${bar}, and then expand - # ${bar}... and so forth. This is fine as long as 'vars' comes from - # 'parse_makefile()', which takes care of such expansions eagerly, - # according to make's variable expansion semantics. - - while 1: - m = _findvar1_rx.search(s) or _findvar2_rx.search(s) - if m: - (beg, end) = m.span() - s = s[0:beg] + vars.get(m.group(1)) + s[end:] - else: - break - return s - - -_config_vars = None - -def _init_posix(): - """Initialize the module as appropriate for POSIX systems.""" - g = {} - # load the installed Makefile: - try: - filename = get_makefile_filename() - parse_makefile(filename, g) - except IOError, msg: - my_msg = "invalid Python installation: unable to open %s" % filename - if hasattr(msg, "strerror"): - my_msg = my_msg + " (%s)" % msg.strerror - - raise DistutilsPlatformError(my_msg) - - # load the installed pyconfig.h: - try: - filename = get_config_h_filename() - parse_config_h(file(filename), g) - except IOError, msg: - my_msg = "invalid Python installation: unable to open %s" % filename - if hasattr(msg, "strerror"): - my_msg = my_msg + " (%s)" % msg.strerror - - raise DistutilsPlatformError(my_msg) - - # On MacOSX we need to check the setting of the environment variable - # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so - # it needs to be compatible. - # If it isn't set we set it to the configure-time value - if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in g: - cfg_target = g['MACOSX_DEPLOYMENT_TARGET'] - cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '') - if cur_target == '': - cur_target = cfg_target - os.environ['MACOSX_DEPLOYMENT_TARGET'] = cfg_target - elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')): - my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure' - % (cur_target, cfg_target)) - raise DistutilsPlatformError(my_msg) - - # On AIX, there are wrong paths to the linker scripts in the Makefile - # -- these paths are relative to the Python source, but when installed - # the scripts are in another directory. - if python_build: - g['LDSHARED'] = g['BLDSHARED'] - - elif get_python_version() < '2.1': - # The following two branches are for 1.5.2 compatibility. - if sys.platform == 'aix4': # what about AIX 3.x ? - # Linker script is in the config directory, not in Modules as the - # Makefile says. - python_lib = get_python_lib(standard_lib=1) - ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix') - python_exp = os.path.join(python_lib, 'config', 'python.exp') - - g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp) - - elif sys.platform == 'beos': - # Linker script is in the config directory. In the Makefile it is - # relative to the srcdir, which after installation no longer makes - # sense. - python_lib = get_python_lib(standard_lib=1) - linkerscript_path = string.split(g['LDSHARED'])[0] - linkerscript_name = os.path.basename(linkerscript_path) - linkerscript = os.path.join(python_lib, 'config', - linkerscript_name) - - # XXX this isn't the right place to do this: adding the Python - # library to the link, if needed, should be in the "build_ext" - # command. (It's also needed for non-MS compilers on Windows, and - # it's taken care of for them by the 'build_ext.get_libraries()' - # method.) - g['LDSHARED'] = ("%s -L%s/lib -lpython%s" % - (linkerscript, PREFIX, get_python_version())) - - global _config_vars - _config_vars = g - - -def _init_nt(): - """Initialize the module as appropriate for NT""" - g = {} - # set basic install directories - g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) - g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) - - # XXX hmmm.. a normal install puts include files here - g['INCLUDEPY'] = get_python_inc(plat_specific=0) - - g['SO'] = '.pyd' - g['EXE'] = ".exe" - g['VERSION'] = get_python_version().replace(".", "") - g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable)) - - global _config_vars - _config_vars = g - - -def _init_os2(): - """Initialize the module as appropriate for OS/2""" - g = {} - # set basic install directories - g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) - g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) - - # XXX hmmm.. a normal install puts include files here - g['INCLUDEPY'] = get_python_inc(plat_specific=0) - - g['SO'] = '.pyd' - g['EXE'] = ".exe" - - global _config_vars - _config_vars = g - - -def get_config_vars(*args): - """With no arguments, return a dictionary of all configuration - variables relevant for the current platform. Generally this includes - everything needed to build extensions and install both pure modules and - extensions. On Unix, this means every variable defined in Python's - installed Makefile; on Windows and Mac OS it's a much smaller set. - - With arguments, return a list of values that result from looking up - each argument in the configuration variable dictionary. - """ - global _config_vars - if _config_vars is None: - func = globals().get("_init_" + os.name) - if func: - func() - else: - _config_vars = {} - - # Normalized versions of prefix and exec_prefix are handy to have; - # in fact, these are the standard versions used most places in the - # Distutils. - _config_vars['prefix'] = PREFIX - _config_vars['exec_prefix'] = EXEC_PREFIX - - if sys.platform == 'darwin': - kernel_version = os.uname()[2] # Kernel version (8.4.3) - major_version = int(kernel_version.split('.')[0]) - - if major_version < 8: - # On Mac OS X before 10.4, check if -arch and -isysroot - # are in CFLAGS or LDFLAGS and remove them if they are. - # This is needed when building extensions on a 10.3 system - # using a universal build of python. - for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - flags = _config_vars[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = re.sub('-isysroot [^ \t]*', ' ', flags) - _config_vars[key] = flags - - else: - - # Allow the user to override the architecture flags using - # an environment variable. - # NOTE: This name was introduced by Apple in OSX 10.5 and - # is used by several scripting languages distributed with - # that OS release. - - if 'ARCHFLAGS' in os.environ: - arch = os.environ['ARCHFLAGS'] - for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - - flags = _config_vars[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = flags + ' ' + arch - _config_vars[key] = flags - - # If we're on OSX 10.5 or later and the user tries to - # compiles an extension using an SDK that is not present - # on the current machine it is better to not use an SDK - # than to fail. - # - # The major usecase for this is users using a Python.org - # binary installer on OSX 10.6: that installer uses - # the 10.4u SDK, but that SDK is not installed by default - # when you install Xcode. - # - m = re.search('-isysroot\s+(\S+)', _config_vars['CFLAGS']) - if m is not None: - sdk = m.group(1) - if not os.path.exists(sdk): - for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - - flags = _config_vars[key] - flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags) - _config_vars[key] = flags - - if args: - vals = [] - for name in args: - vals.append(_config_vars.get(name)) - return vals - else: - return _config_vars - -def get_config_var(name): - """Return the value of a single variable using the dictionary - returned by 'get_config_vars()'. Equivalent to - get_config_vars().get(name) - """ - return get_config_vars().get(name) diff --git a/lib-python/modified-2.7/distutils/sysconfig_cpython.py b/lib-python/2.7/distutils/sysconfig_cpython.py rename from lib-python/modified-2.7/distutils/sysconfig_cpython.py rename to lib-python/2.7/distutils/sysconfig_cpython.py diff --git a/lib-python/modified-2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py rename from lib-python/modified-2.7/distutils/sysconfig_pypy.py rename to lib-python/2.7/distutils/sysconfig_pypy.py diff --git a/lib-python/2.7/distutils/tests/test_build_ext.py b/lib-python/2.7/distutils/tests/test_build_ext.py --- a/lib-python/2.7/distutils/tests/test_build_ext.py +++ b/lib-python/2.7/distutils/tests/test_build_ext.py @@ -293,7 +293,7 @@ finally: os.chdir(old_wd) self.assertTrue(os.path.exists(so_file)) - self.assertEqual(os.path.splitext(so_file)[-1], + self.assertEqual(so_file[so_file.index(os.path.extsep):], sysconfig.get_config_var('SO')) so_dir = os.path.dirname(so_file) self.assertEqual(so_dir, other_tmp_dir) @@ -302,7 +302,7 @@ cmd.run() so_file = cmd.get_outputs()[0] self.assertTrue(os.path.exists(so_file)) - self.assertEqual(os.path.splitext(so_file)[-1], + self.assertEqual(so_file[so_file.index(os.path.extsep):], sysconfig.get_config_var('SO')) so_dir = os.path.dirname(so_file) self.assertEqual(so_dir, cmd.build_lib) diff --git a/lib-python/2.7/distutils/tests/test_install.py b/lib-python/2.7/distutils/tests/test_install.py --- a/lib-python/2.7/distutils/tests/test_install.py +++ b/lib-python/2.7/distutils/tests/test_install.py @@ -2,6 +2,7 @@ import os import unittest +from test import test_support from test.test_support import run_unittest @@ -40,14 +41,15 @@ expected = os.path.normpath(expected) self.assertEqual(got, expected) - libdir = os.path.join(destination, "lib", "python") - check_path(cmd.install_lib, libdir) - check_path(cmd.install_platlib, libdir) - check_path(cmd.install_purelib, libdir) - check_path(cmd.install_headers, - os.path.join(destination, "include", "python", "foopkg")) - check_path(cmd.install_scripts, os.path.join(destination, "bin")) - check_path(cmd.install_data, destination) + if test_support.check_impl_detail(): + libdir = os.path.join(destination, "lib", "python") + check_path(cmd.install_lib, libdir) + check_path(cmd.install_platlib, libdir) + check_path(cmd.install_purelib, libdir) + check_path(cmd.install_headers, + os.path.join(destination, "include", "python", "foopkg")) + check_path(cmd.install_scripts, os.path.join(destination, "bin")) + check_path(cmd.install_data, destination) def test_suite(): diff --git a/lib-python/2.7/distutils/unixccompiler.py b/lib-python/2.7/distutils/unixccompiler.py --- a/lib-python/2.7/distutils/unixccompiler.py +++ b/lib-python/2.7/distutils/unixccompiler.py @@ -125,7 +125,22 @@ } if sys.platform[:6] == "darwin": + import platform + if platform.machine() == 'i386': + if platform.architecture()[0] == '32bit': + arch = 'i386' + else: + arch = 'x86_64' + else: + # just a guess + arch = platform.machine() executables['ranlib'] = ["ranlib"] + executables['linker_so'] += ['-undefined', 'dynamic_lookup'] + + for k, v in executables.iteritems(): + if v and v[0] == 'cc': + v += ['-arch', arch] + # Needed for the filename generation methods provided by the base # class, CCompiler. NB. whoever instantiates/uses a particular @@ -309,7 +324,7 @@ # On OSX users can specify an alternate SDK using # '-isysroot', calculate the SDK root if it is specified # (and use it further on) - cflags = sysconfig.get_config_var('CFLAGS') + cflags = sysconfig.get_config_var('CFLAGS') or '' m = re.search(r'-isysroot\s+(\S+)', cflags) if m is None: sysroot = '/' diff --git a/lib-python/2.7/heapq.py b/lib-python/2.7/heapq.py --- a/lib-python/2.7/heapq.py +++ b/lib-python/2.7/heapq.py @@ -193,6 +193,8 @@ Equivalent to: sorted(iterable, reverse=True)[:n] """ + if n < 0: # for consistency with the c impl + return [] it = iter(iterable) result = list(islice(it, n)) if not result: @@ -209,6 +211,8 @@ Equivalent to: sorted(iterable)[:n] """ + if n < 0: # for consistency with the c impl + return [] if hasattr(iterable, '__len__') and n * 10 <= len(iterable): # For smaller values of n, the bisect method is faster than a minheap. # It is also memory efficient, consuming only n elements of space. diff --git a/lib-python/2.7/httplib.py b/lib-python/2.7/httplib.py --- a/lib-python/2.7/httplib.py +++ b/lib-python/2.7/httplib.py @@ -1024,7 +1024,11 @@ kwds["buffering"] = True; response = self.response_class(*args, **kwds) - response.begin() + try: + response.begin() + except: + response.close() + raise assert response.will_close != _UNKNOWN self.__state = _CS_IDLE diff --git a/lib-python/2.7/idlelib/Delegator.py b/lib-python/2.7/idlelib/Delegator.py --- a/lib-python/2.7/idlelib/Delegator.py +++ b/lib-python/2.7/idlelib/Delegator.py @@ -12,6 +12,14 @@ self.__cache[name] = attr return attr + def __nonzero__(self): + # this is needed for PyPy: else, if self.delegate is None, the + # __getattr__ above picks NoneType.__nonzero__, which returns + # False. Thus, bool(Delegator()) is False as well, but it's not what + # we want. On CPython, bool(Delegator()) is True because NoneType + # does not have __nonzero__ + return True + def resetcache(self): for key in self.__cache.keys(): try: diff --git a/lib-python/2.7/inspect.py b/lib-python/2.7/inspect.py --- a/lib-python/2.7/inspect.py +++ b/lib-python/2.7/inspect.py @@ -746,8 +746,15 @@ 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" if not iscode(co): - raise TypeError('{!r} is not a code object'.format(co)) + if hasattr(len, 'func_code') and type(co) is type(len.func_code): + # PyPy extension: built-in function objects have a func_code too. + # There is no co_code on it, but co_argcount and co_varnames and + # co_flags are present. + pass + else: + raise TypeError('{!r} is not a code object'.format(co)) + code = getattr(co, 'co_code', '') nargs = co.co_argcount names = co.co_varnames args = list(names[:nargs]) @@ -757,12 +764,12 @@ for i in range(nargs): if args[i][:1] in ('', '.'): stack, remain, count = [], [], [] - while step < len(co.co_code): - op = ord(co.co_code[step]) + while step < len(code): + op = ord(code[step]) step = step + 1 if op >= dis.HAVE_ARGUMENT: opname = dis.opname[op] - value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256 + value = ord(code[step]) + ord(code[step+1])*256 step = step + 2 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): remain.append(value) @@ -809,7 +816,9 @@ if ismethod(func): func = func.im_func - if not isfunction(func): + if not (isfunction(func) or + isbuiltin(func) and hasattr(func, 'func_code')): + # PyPy extension: this works for built-in functions too raise TypeError('{!r} is not a Python function'.format(func)) args, varargs, varkw = getargs(func.func_code) return ArgSpec(args, varargs, varkw, func.func_defaults) @@ -949,7 +958,7 @@ raise TypeError('%s() takes exactly 0 arguments ' '(%d given)' % (f_name, num_total)) else: - raise TypeError('%s() takes no arguments (%d given)' % + raise TypeError('%s() takes no argument (%d given)' % (f_name, num_total)) for arg in args: if isinstance(arg, str) and arg in named: diff --git a/lib-python/2.7/json/encoder.py b/lib-python/2.7/json/encoder.py --- a/lib-python/2.7/json/encoder.py +++ b/lib-python/2.7/json/encoder.py @@ -2,14 +2,7 @@ """ import re -try: - from _json import encode_basestring_ascii as c_encode_basestring_ascii -except ImportError: - c_encode_basestring_ascii = None -try: - from _json import make_encoder as c_make_encoder -except ImportError: - c_make_encoder = None +from __pypy__.builders import StringBuilder, UnicodeBuilder ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]') ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') @@ -24,23 +17,22 @@ '\t': '\\t', } for i in range(0x20): - ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) - #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) + ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) # Assume this produces an infinity on all machines (probably not guaranteed) INFINITY = float('1e66666') FLOAT_REPR = repr -def encode_basestring(s): +def raw_encode_basestring(s): """Return a JSON representation of a Python string """ def replace(match): return ESCAPE_DCT[match.group(0)] - return '"' + ESCAPE.sub(replace, s) + '"' + return ESCAPE.sub(replace, s) +encode_basestring = lambda s: '"' + raw_encode_basestring(s) + '"' - -def py_encode_basestring_ascii(s): +def raw_encode_basestring_ascii(s): """Return an ASCII-only JSON representation of a Python string """ @@ -53,21 +45,19 @@ except KeyError: n = ord(s) if n < 0x10000: - return '\\u{0:04x}'.format(n) - #return '\\u%04x' % (n,) + return '\\u%04x' % (n,) else: # surrogate pair n -= 0x10000 s1 = 0xd800 | ((n >> 10) & 0x3ff) s2 = 0xdc00 | (n & 0x3ff) - return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) - #return '\\u%04x\\u%04x' % (s1, s2) - return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' + return '\\u%04x\\u%04x' % (s1, s2) + if ESCAPE_ASCII.search(s): + return str(ESCAPE_ASCII.sub(replace, s)) + return s +encode_basestring_ascii = lambda s: '"' + raw_encode_basestring_ascii(s) + '"' -encode_basestring_ascii = ( - c_encode_basestring_ascii or py_encode_basestring_ascii) - class JSONEncoder(object): """Extensible JSON encoder for Python data structures. @@ -147,6 +137,17 @@ self.skipkeys = skipkeys self.ensure_ascii = ensure_ascii + if ensure_ascii: + self.encoder = raw_encode_basestring_ascii + else: + self.encoder = raw_encode_basestring + if encoding != 'utf-8': + orig_encoder = self.encoder + def encoder(o): + if isinstance(o, str): + o = o.decode(encoding) + return orig_encoder(o) + self.encoder = encoder self.check_circular = check_circular self.allow_nan = allow_nan self.sort_keys = sort_keys @@ -184,24 +185,126 @@ '{"foo": ["bar", "baz"]}' """ - # This is for extremely simple cases and benchmarks. + if self.check_circular: + markers = {} + else: + markers = None + if self.ensure_ascii: + builder = StringBuilder() + else: + builder = UnicodeBuilder() + self._encode(o, markers, builder, 0) + return builder.build() + + def _emit_indent(self, builder, _current_indent_level): + if self.indent is not None: + _current_indent_level += 1 + newline_indent = '\n' + (' ' * (self.indent * + _current_indent_level)) + separator = self.item_separator + newline_indent + builder.append(newline_indent) + else: + separator = self.item_separator + return separator, _current_indent_level + + def _emit_unindent(self, builder, _current_indent_level): + if self.indent is not None: + builder.append('\n') + builder.append(' ' * (self.indent * (_current_indent_level - 1))) + + def _encode(self, o, markers, builder, _current_indent_level): if isinstance(o, basestring): - if isinstance(o, str): - _encoding = self.encoding - if (_encoding is not None - and not (_encoding == 'utf-8')): - o = o.decode(_encoding) - if self.ensure_ascii: - return encode_basestring_ascii(o) + builder.append('"') + builder.append(self.encoder(o)) + builder.append('"') + elif o is None: + builder.append('null') + elif o is True: + builder.append('true') + elif o is False: + builder.append('false') + elif isinstance(o, (int, long)): + builder.append(str(o)) + elif isinstance(o, float): + builder.append(self._floatstr(o)) + elif isinstance(o, (list, tuple)): + if not o: + builder.append('[]') + return + self._encode_list(o, markers, builder, _current_indent_level) + elif isinstance(o, dict): + if not o: + builder.append('{}') + return + self._encode_dict(o, markers, builder, _current_indent_level) + else: + self._mark_markers(markers, o) + res = self.default(o) + self._encode(res, markers, builder, _current_indent_level) + self._remove_markers(markers, o) + return res + + def _encode_list(self, l, markers, builder, _current_indent_level): + self._mark_markers(markers, l) + builder.append('[') + first = True + separator, _current_indent_level = self._emit_indent(builder, + _current_indent_level) + for elem in l: + if first: + first = False else: - return encode_basestring(o) - # This doesn't pass the iterator directly to ''.join() because the - # exceptions aren't as detailed. The list call should be roughly - # equivalent to the PySequence_Fast that ''.join() would do. - chunks = self.iterencode(o, _one_shot=True) - if not isinstance(chunks, (list, tuple)): - chunks = list(chunks) - return ''.join(chunks) + builder.append(separator) + self._encode(elem, markers, builder, _current_indent_level) + del elem # XXX grumble + self._emit_unindent(builder, _current_indent_level) + builder.append(']') + self._remove_markers(markers, l) + + def _encode_dict(self, d, markers, builder, _current_indent_level): + self._mark_markers(markers, d) + first = True + builder.append('{') + separator, _current_indent_level = self._emit_indent(builder, + _current_indent_level) + if self.sort_keys: + items = sorted(d.items(), key=lambda kv: kv[0]) + else: + items = d.iteritems() + + for key, v in items: + if first: + first = False + else: + builder.append(separator) + if isinstance(key, basestring): + pass + # JavaScript is weakly typed for these, so it makes sense to + # also allow them. Many encoders seem to do something like this. + elif isinstance(key, float): + key = self._floatstr(key) + elif key is True: + key = 'true' + elif key is False: + key = 'false' + elif key is None: + key = 'null' + elif isinstance(key, (int, long)): + key = str(key) + elif self.skipkeys: + continue + else: + raise TypeError("key " + repr(key) + " is not a string") + builder.append('"') + builder.append(self.encoder(key)) + builder.append('"') + builder.append(self.key_separator) + self._encode(v, markers, builder, _current_indent_level) + del key + del v # XXX grumble + self._emit_unindent(builder, _current_indent_level) + builder.append('}') + self._remove_markers(markers, d) def iterencode(self, o, _one_shot=False): """Encode the given object and yield each string @@ -217,86 +320,54 @@ markers = {} else: markers = None - if self.ensure_ascii: - _encoder = encode_basestring_ascii + return self._iterencode(o, markers, 0) + + def _floatstr(self, o): + # Check for specials. Note that this type of test is processor + # and/or platform-specific, so do tests which don't depend on the + # internals. + + if o != o: + text = 'NaN' + elif o == INFINITY: + text = 'Infinity' + elif o == -INFINITY: + text = '-Infinity' else: - _encoder = encode_basestring - if self.encoding != 'utf-8': - def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): - if isinstance(o, str): - o = o.decode(_encoding) - return _orig_encoder(o) + return FLOAT_REPR(o) - def floatstr(o, allow_nan=self.allow_nan, - _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY): - # Check for specials. Note that this type of test is processor - # and/or platform-specific, so do tests which don't depend on the - # internals. + if not self.allow_nan: + raise ValueError( + "Out of range float values are not JSON compliant: " + + repr(o)) - if o != o: - text = 'NaN' - elif o == _inf: - text = 'Infinity' - elif o == _neginf: - text = '-Infinity' - else: - return _repr(o) + return text - if not allow_nan: - raise ValueError( - "Out of range float values are not JSON compliant: " + - repr(o)) + def _mark_markers(self, markers, o): + if markers is not None: + if id(o) in markers: + raise ValueError("Circular reference detected") + markers[id(o)] = None - return text + def _remove_markers(self, markers, o): + if markers is not None: + del markers[id(o)] - - if (_one_shot and c_make_encoder is not None - and self.indent is None and not self.sort_keys): - _iterencode = c_make_encoder( - markers, self.default, _encoder, self.indent, - self.key_separator, self.item_separator, self.sort_keys, - self.skipkeys, self.allow_nan) - else: - _iterencode = _make_iterencode( - markers, self.default, _encoder, self.indent, floatstr, - self.key_separator, self.item_separator, self.sort_keys, - self.skipkeys, _one_shot) - return _iterencode(o, 0) - -def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, - _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot, - ## HACK: hand-optimized bytecode; turn globals into locals - ValueError=ValueError, - basestring=basestring, - dict=dict, - float=float, - id=id, - int=int, - isinstance=isinstance, - list=list, - long=long, - str=str, - tuple=tuple, - ): - - def _iterencode_list(lst, _current_indent_level): + def _iterencode_list(self, lst, markers, _current_indent_level): if not lst: yield '[]' return - if markers is not None: - markerid = id(lst) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = lst + self._mark_markers(markers, lst) buf = '[' - if _indent is not None: + if self.indent is not None: _current_indent_level += 1 - newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) - separator = _item_separator + newline_indent + newline_indent = '\n' + (' ' * (self.indent * + _current_indent_level)) + separator = self.item_separator + newline_indent buf += newline_indent else: newline_indent = None - separator = _item_separator + separator = self.item_separator first = True for value in lst: if first: @@ -304,7 +375,7 @@ else: buf = separator if isinstance(value, basestring): - yield buf + _encoder(value) + yield buf + '"' + self.encoder(value) + '"' elif value is None: yield buf + 'null' elif value is True: @@ -314,44 +385,43 @@ elif isinstance(value, (int, long)): yield buf + str(value) elif isinstance(value, float): - yield buf + _floatstr(value) + yield buf + self._floatstr(value) else: yield buf if isinstance(value, (list, tuple)): - chunks = _iterencode_list(value, _current_indent_level) + chunks = self._iterencode_list(value, markers, + _current_indent_level) elif isinstance(value, dict): - chunks = _iterencode_dict(value, _current_indent_level) + chunks = self._iterencode_dict(value, markers, + _current_indent_level) else: - chunks = _iterencode(value, _current_indent_level) + chunks = self._iterencode(value, markers, + _current_indent_level) for chunk in chunks: yield chunk if newline_indent is not None: _current_indent_level -= 1 - yield '\n' + (' ' * (_indent * _current_indent_level)) + yield '\n' + (' ' * (self.indent * _current_indent_level)) yield ']' - if markers is not None: - del markers[markerid] + self._remove_markers(markers, lst) - def _iterencode_dict(dct, _current_indent_level): + def _iterencode_dict(self, dct, markers, _current_indent_level): if not dct: yield '{}' return - if markers is not None: - markerid = id(dct) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = dct + self._mark_markers(markers, dct) yield '{' - if _indent is not None: + if self.indent is not None: _current_indent_level += 1 - newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) - item_separator = _item_separator + newline_indent + newline_indent = '\n' + (' ' * (self.indent * + _current_indent_level)) + item_separator = self.item_separator + newline_indent yield newline_indent else: newline_indent = None - item_separator = _item_separator + item_separator = self.item_separator first = True - if _sort_keys: + if self.sort_keys: items = sorted(dct.items(), key=lambda kv: kv[0]) else: items = dct.iteritems() @@ -361,7 +431,7 @@ # JavaScript is weakly typed for these, so it makes sense to # also allow them. Many encoders seem to do something like this. elif isinstance(key, float): - key = _floatstr(key) + key = self._floatstr(key) elif key is True: key = 'true' elif key is False: @@ -370,7 +440,7 @@ key = 'null' elif isinstance(key, (int, long)): key = str(key) - elif _skipkeys: + elif self.skipkeys: continue else: raise TypeError("key " + repr(key) + " is not a string") @@ -378,10 +448,10 @@ first = False else: yield item_separator - yield _encoder(key) - yield _key_separator + yield '"' + self.encoder(key) + '"' + yield self.key_separator if isinstance(value, basestring): - yield _encoder(value) + yield '"' + self.encoder(value) + '"' elif value is None: yield 'null' elif value is True: @@ -391,26 +461,28 @@ elif isinstance(value, (int, long)): yield str(value) elif isinstance(value, float): - yield _floatstr(value) + yield self._floatstr(value) else: if isinstance(value, (list, tuple)): - chunks = _iterencode_list(value, _current_indent_level) + chunks = self._iterencode_list(value, markers, + _current_indent_level) elif isinstance(value, dict): - chunks = _iterencode_dict(value, _current_indent_level) + chunks = self._iterencode_dict(value, markers, + _current_indent_level) else: - chunks = _iterencode(value, _current_indent_level) + chunks = self._iterencode(value, markers, + _current_indent_level) for chunk in chunks: yield chunk if newline_indent is not None: _current_indent_level -= 1 - yield '\n' + (' ' * (_indent * _current_indent_level)) + yield '\n' + (' ' * (self.indent * _current_indent_level)) yield '}' - if markers is not None: - del markers[markerid] + self._remove_markers(markers, dct) - def _iterencode(o, _current_indent_level): + def _iterencode(self, o, markers, _current_indent_level): if isinstance(o, basestring): - yield _encoder(o) + yield '"' + self.encoder(o) + '"' elif o is None: yield 'null' elif o is True: @@ -420,23 +492,19 @@ elif isinstance(o, (int, long)): yield str(o) elif isinstance(o, float): - yield _floatstr(o) + yield self._floatstr(o) elif isinstance(o, (list, tuple)): - for chunk in _iterencode_list(o, _current_indent_level): + for chunk in self._iterencode_list(o, markers, + _current_indent_level): yield chunk elif isinstance(o, dict): - for chunk in _iterencode_dict(o, _current_indent_level): + for chunk in self._iterencode_dict(o, markers, + _current_indent_level): yield chunk else: - if markers is not None: - markerid = id(o) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = o - o = _default(o) - for chunk in _iterencode(o, _current_indent_level): + self._mark_markers(markers, o) + obj = self.default(o) + for chunk in self._iterencode(obj, markers, + _current_indent_level): yield chunk - if markers is not None: - del markers[markerid] - - return _iterencode + self._remove_markers(markers, o) diff --git a/lib-python/2.7/json/tests/test_unicode.py b/lib-python/2.7/json/tests/test_unicode.py --- a/lib-python/2.7/json/tests/test_unicode.py +++ b/lib-python/2.7/json/tests/test_unicode.py @@ -80,6 +80,12 @@ # Issue 10038. self.assertEqual(type(self.loads('"foo"')), unicode) + def test_encode_not_utf_8(self): + self.assertEqual(self.dumps('\xb1\xe6', encoding='iso8859-2'), + '"\\u0105\\u0107"') + self.assertEqual(self.dumps(['\xb1\xe6'], encoding='iso8859-2'), + '["\\u0105\\u0107"]') + class TestPyUnicode(TestUnicode, PyTest): pass class TestCUnicode(TestUnicode, CTest): pass diff --git a/lib-python/2.7/multiprocessing/forking.py b/lib-python/2.7/multiprocessing/forking.py --- a/lib-python/2.7/multiprocessing/forking.py +++ b/lib-python/2.7/multiprocessing/forking.py @@ -73,15 +73,12 @@ return getattr, (m.im_self, m.im_func.func_name) ForkingPickler.register(type(ForkingPickler.save), _reduce_method) -def _reduce_method_descriptor(m): - return getattr, (m.__objclass__, m.__name__) -ForkingPickler.register(type(list.append), _reduce_method_descriptor) -ForkingPickler.register(type(int.__add__), _reduce_method_descriptor) - -#def _reduce_builtin_function_or_method(m): -# return getattr, (m.__self__, m.__name__) -#ForkingPickler.register(type(list().append), _reduce_builtin_function_or_method) -#ForkingPickler.register(type(int().__add__), _reduce_builtin_function_or_method) +if type(list.append) is not type(ForkingPickler.save): + # Some python implementations have unbound methods even for builtin types + def _reduce_method_descriptor(m): + return getattr, (m.__objclass__, m.__name__) + ForkingPickler.register(type(list.append), _reduce_method_descriptor) + ForkingPickler.register(type(int.__add__), _reduce_method_descriptor) try: from functools import partial diff --git a/lib-python/2.7/opcode.py b/lib-python/2.7/opcode.py --- a/lib-python/2.7/opcode.py +++ b/lib-python/2.7/opcode.py @@ -1,4 +1,3 @@ - """ opcode module - potentially shared between dis and other modules which operate on bytecodes (e.g. peephole optimizers). @@ -189,4 +188,10 @@ def_op('SET_ADD', 146) def_op('MAP_ADD', 147) +# pypy modification, experimental bytecode +def_op('LOOKUP_METHOD', 201) # Index in name list +hasname.append(201) +def_op('CALL_METHOD', 202) # #args not including 'self' +def_op('BUILD_LIST_FROM_ARG', 203) + del def_op, name_op, jrel_op, jabs_op diff --git a/lib-python/2.7/pickle.py b/lib-python/2.7/pickle.py --- a/lib-python/2.7/pickle.py +++ b/lib-python/2.7/pickle.py @@ -168,7 +168,7 @@ # Pickling machinery -class Pickler: +class Pickler(object): def __init__(self, file, protocol=None): """This takes a file-like object for writing a pickle data stream. @@ -638,6 +638,10 @@ # else tmp is empty, and we're done def save_dict(self, obj): + modict_saver = self._pickle_moduledict(obj) + if modict_saver is not None: + return self.save_reduce(*modict_saver) + write = self.write if self.bin: @@ -687,6 +691,29 @@ write(SETITEM) # else tmp is empty, and we're done + def _pickle_moduledict(self, obj): + # save module dictionary as "getattr(module, '__dict__')" + + # build index of module dictionaries + try: + modict = self.module_dict_ids + except AttributeError: + modict = {} + from sys import modules + for mod in modules.values(): + if isinstance(mod, ModuleType): + modict[id(mod.__dict__)] = mod + self.module_dict_ids = modict + + thisid = id(obj) + try: + themodule = modict[thisid] + except KeyError: + return None + from __builtin__ import getattr + return getattr, (themodule, '__dict__') + + def save_inst(self, obj): cls = obj.__class__ @@ -727,6 +754,29 @@ dispatch[InstanceType] = save_inst + def save_function(self, obj): + try: + return self.save_global(obj) + except PicklingError, e: + pass + # Check copy_reg.dispatch_table + reduce = dispatch_table.get(type(obj)) + if reduce: + rv = reduce(obj) + else: + # Check for a __reduce_ex__ method, fall back to __reduce__ + reduce = getattr(obj, "__reduce_ex__", None) + if reduce: + rv = reduce(self.proto) + else: + reduce = getattr(obj, "__reduce__", None) + if reduce: + rv = reduce() + else: + raise e + return self.save_reduce(obj=obj, *rv) + dispatch[FunctionType] = save_function + def save_global(self, obj, name=None, pack=struct.pack): write = self.write memo = self.memo @@ -768,7 +818,6 @@ self.memoize(obj) dispatch[ClassType] = save_global - dispatch[FunctionType] = save_global dispatch[BuiltinFunctionType] = save_global dispatch[TypeType] = save_global @@ -824,7 +873,7 @@ # Unpickling machinery -class Unpickler: +class Unpickler(object): def __init__(self, file): """This takes a file-like object for reading a pickle data stream. diff --git a/lib-python/2.7/pkgutil.py b/lib-python/2.7/pkgutil.py --- a/lib-python/2.7/pkgutil.py +++ b/lib-python/2.7/pkgutil.py @@ -244,7 +244,8 @@ return mod def get_data(self, pathname): - return open(pathname, "rb").read() + with open(pathname, "rb") as f: + return f.read() def _reopen(self): if self.file and self.file.closed: diff --git a/lib-python/2.7/pprint.py b/lib-python/2.7/pprint.py --- a/lib-python/2.7/pprint.py +++ b/lib-python/2.7/pprint.py @@ -144,7 +144,7 @@ return r = getattr(typ, "__repr__", None) - if issubclass(typ, dict) and r is dict.__repr__: + if issubclass(typ, dict) and r == dict.__repr__: write('{') if self._indent_per_level > 1: write((self._indent_per_level - 1) * ' ') @@ -173,10 +173,10 @@ write('}') return - if ((issubclass(typ, list) and r is list.__repr__) or - (issubclass(typ, tuple) and r is tuple.__repr__) or - (issubclass(typ, set) and r is set.__repr__) or - (issubclass(typ, frozenset) and r is frozenset.__repr__) + if ((issubclass(typ, list) and r == list.__repr__) or + (issubclass(typ, tuple) and r == tuple.__repr__) or + (issubclass(typ, set) and r == set.__repr__) or + (issubclass(typ, frozenset) and r == frozenset.__repr__) ): length = _len(object) if issubclass(typ, list): @@ -266,7 +266,7 @@ return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False r = getattr(typ, "__repr__", None) - if issubclass(typ, dict) and r is dict.__repr__: + if issubclass(typ, dict) and r == dict.__repr__: if not object: return "{}", True, False objid = _id(object) @@ -291,8 +291,8 @@ del context[objid] return "{%s}" % _commajoin(components), readable, recursive - if (issubclass(typ, list) and r is list.__repr__) or \ - (issubclass(typ, tuple) and r is tuple.__repr__): + if (issubclass(typ, list) and r == list.__repr__) or \ + (issubclass(typ, tuple) and r == tuple.__repr__): if issubclass(typ, list): if not object: return "[]", True, False diff --git a/lib-python/2.7/pydoc.py b/lib-python/2.7/pydoc.py --- a/lib-python/2.7/pydoc.py +++ b/lib-python/2.7/pydoc.py @@ -623,7 +623,9 @@ head, '#ffffff', '#7799ee', 'index
' + filelink + docloc) - modules = inspect.getmembers(object, inspect.ismodule) + def isnonbuiltinmodule(obj): + return inspect.ismodule(obj) and obj is not __builtin__ + modules = inspect.getmembers(object, isnonbuiltinmodule) classes, cdict = [], {} for key, value in inspect.getmembers(object, inspect.isclass): diff --git a/lib-python/2.7/random.py b/lib-python/2.7/random.py --- a/lib-python/2.7/random.py +++ b/lib-python/2.7/random.py @@ -41,7 +41,6 @@ from __future__ import division from warnings import warn as _warn -from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin from os import urandom as _urandom @@ -240,8 +239,7 @@ return self.randrange(a, b+1) - def _randbelow(self, n, _log=_log, int=int, _maxwidth=1L< n-1 > 2**(k-2) r = getrandbits(k) while r >= n: diff --git a/lib-python/2.7/site.py b/lib-python/2.7/site.py --- a/lib-python/2.7/site.py +++ b/lib-python/2.7/site.py @@ -75,7 +75,6 @@ USER_SITE = None USER_BASE = None - def makepath(*paths): dir = os.path.join(*paths) try: @@ -91,7 +90,10 @@ if hasattr(m, '__loader__'): continue # don't mess with a PEP 302-supplied __file__ try: - m.__file__ = os.path.abspath(m.__file__) + prev = m.__file__ + new = os.path.abspath(m.__file__) + if prev != new: + m.__file__ = new except (AttributeError, OSError): pass @@ -289,6 +291,7 @@ will find its `site-packages` subdirectory depending on the system environment, and will return a list of full paths. """ + is_pypy = '__pypy__' in sys.builtin_module_names sitepackages = [] seen = set() @@ -299,6 +302,10 @@ if sys.platform in ('os2emx', 'riscos'): sitepackages.append(os.path.join(prefix, "Lib", "site-packages")) + elif is_pypy: + from distutils.sysconfig import get_python_lib + sitedir = get_python_lib(standard_lib=False, prefix=prefix) + sitepackages.append(sitedir) elif os.sep == '/': sitepackages.append(os.path.join(prefix, "lib", "python" + sys.version[:3], @@ -435,22 +442,33 @@ if key == 'q': break +##def setcopyright(): +## """Set 'copyright' and 'credits' in __builtin__""" +## __builtin__.copyright = _Printer("copyright", sys.copyright) +## if sys.platform[:4] == 'java': +## __builtin__.credits = _Printer( +## "credits", +## "Jython is maintained by the Jython developers (www.jython.org).") +## else: +## __builtin__.credits = _Printer("credits", """\ +## Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands +## for supporting Python development. See www.python.org for more information.""") +## here = os.path.dirname(os.__file__) +## __builtin__.license = _Printer( +## "license", "See http://www.python.org/%.3s/license.html" % sys.version, +## ["LICENSE.txt", "LICENSE"], +## [os.path.join(here, os.pardir), here, os.curdir]) + def setcopyright(): - """Set 'copyright' and 'credits' in __builtin__""" + # XXX this is the PyPy-specific version. Should be unified with the above. __builtin__.copyright = _Printer("copyright", sys.copyright) - if sys.platform[:4] == 'java': - __builtin__.credits = _Printer( - "credits", - "Jython is maintained by the Jython developers (www.jython.org).") - else: - __builtin__.credits = _Printer("credits", """\ - Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands - for supporting Python development. See www.python.org for more information.""") - here = os.path.dirname(os.__file__) + __builtin__.credits = _Printer( + "credits", + "PyPy is maintained by the PyPy developers: http://pypy.org/") __builtin__.license = _Printer( - "license", "See http://www.python.org/%.3s/license.html" % sys.version, - ["LICENSE.txt", "LICENSE"], - [os.path.join(here, os.pardir), here, os.curdir]) + "license", + "See https://bitbucket.org/pypy/pypy/src/default/LICENSE") + class _Helper(object): @@ -476,7 +494,7 @@ if sys.platform == 'win32': import locale, codecs enc = locale.getdefaultlocale()[1] - if enc.startswith('cp'): # "cp***" ? + if enc is not None and enc.startswith('cp'): # "cp***" ? try: codecs.lookup(enc) except LookupError: @@ -532,9 +550,18 @@ "'import usercustomize' failed; use -v for traceback" +def import_builtin_stuff(): + """PyPy specific: pre-import a few built-in modules, because + some programs actually rely on them to be in sys.modules :-(""" + import exceptions + if 'zipimport' in sys.builtin_module_names: + import zipimport + + def main(): global ENABLE_USER_SITE + import_builtin_stuff() abs__file__() known_paths = removeduppaths() if (os.name == "posix" and sys.path and diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py --- a/lib-python/2.7/socket.py +++ b/lib-python/2.7/socket.py @@ -46,8 +46,6 @@ import _socket from _socket import * -from functools import partial -from types import MethodType try: import _ssl @@ -159,11 +157,6 @@ if sys.platform == "riscos": _socketmethods = _socketmethods + ('sleeptaskw',) -# All the method names that must be delegated to either the real socket -# object or the _closedsocket object. -_delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into", - "send", "sendto") - class _closedsocket(object): __slots__ = [] def _dummy(*args): @@ -180,22 +173,43 @@ __doc__ = _realsocket.__doc__ - __slots__ = ["_sock", "__weakref__"] + list(_delegate_methods) - def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None): if _sock is None: _sock = _realsocket(family, type, proto) self._sock = _sock - for method in _delegate_methods: - setattr(self, method, getattr(_sock, method)) + self._io_refs = 0 + self._closed = False - def close(self, _closedsocket=_closedsocket, - _delegate_methods=_delegate_methods, setattr=setattr): + def send(self, data, flags=0): + return self._sock.send(data, flags=flags) + send.__doc__ = _realsocket.send.__doc__ + + def recv(self, buffersize, flags=0): + return self._sock.recv(buffersize, flags=flags) + recv.__doc__ = _realsocket.recv.__doc__ + + def recv_into(self, buffer, nbytes=0, flags=0): + return self._sock.recv_into(buffer, nbytes=nbytes, flags=flags) + recv_into.__doc__ = _realsocket.recv_into.__doc__ + + def recvfrom(self, buffersize, flags=0): + return self._sock.recvfrom(buffersize, flags=flags) + recvfrom.__doc__ = _realsocket.recvfrom.__doc__ + + def recvfrom_into(self, buffer, nbytes=0, flags=0): + return self._sock.recvfrom_into(buffer, nbytes=nbytes, flags=flags) + recvfrom_into.__doc__ = _realsocket.recvfrom_into.__doc__ + + def sendto(self, data, param2, param3=None): + if param3 is None: + return self._sock.sendto(data, param2) + else: + return self._sock.sendto(data, param2, param3) + sendto.__doc__ = _realsocket.sendto.__doc__ + + def close(self): # This function should not reference any globals. See issue #808164. self._sock = _closedsocket() - dummy = self._sock._dummy - for method in _delegate_methods: - setattr(self, method, dummy) close.__doc__ = _realsocket.close.__doc__ def accept(self): @@ -214,21 +228,49 @@ Return a regular file object corresponding to the socket. The mode and bufsize arguments are as for the built-in open() function.""" - return _fileobject(self._sock, mode, bufsize) + self._io_refs += 1 + return _fileobject(self, mode, bufsize) + + def _decref_socketios(self): + if self._io_refs > 0: + self._io_refs -= 1 + if self._closed: + self.close() + + def _real_close(self): + # This function should not reference any globals. See issue #808164. + self._sock.close() + + def close(self): + # This function should not reference any globals. See issue #808164. + self._closed = True + if self._io_refs <= 0: + self._real_close() family = property(lambda self: self._sock.family, doc="the socket family") type = property(lambda self: self._sock.type, doc="the socket type") proto = property(lambda self: self._sock.proto, doc="the socket protocol") -def meth(name,self,*args): - return getattr(self._sock,name)(*args) + # Delegate many calls to the raw socket object. + _s = ("def %(name)s(self, %(args)s): return self._sock.%(name)s(%(args)s)\n\n" + "%(name)s.__doc__ = _realsocket.%(name)s.__doc__\n") + for _m in _socketmethods: + # yupi! we're on pypy, all code objects have this interface + argcount = getattr(_realsocket, _m).im_func.func_code.co_argcount - 1 + exec _s % {'name': _m, 'args': ', '.join('arg%d' % i for i in range(argcount))} + del _m, _s, argcount -for _m in _socketmethods: - p = partial(meth,_m) - p.__name__ = _m - p.__doc__ = getattr(_realsocket,_m).__doc__ - m = MethodType(p,None,_socketobject) - setattr(_socketobject,_m,m) + # Delegation methods with default arguments, that the code above + # cannot handle correctly + def sendall(self, data, flags=0): + self._sock.sendall(data, flags) + sendall.__doc__ = _realsocket.sendall.__doc__ + + def getsockopt(self, level, optname, buflen=None): + if buflen is None: + return self._sock.getsockopt(level, optname) + return self._sock.getsockopt(level, optname, buflen) + getsockopt.__doc__ = _realsocket.getsockopt.__doc__ socket = SocketType = _socketobject @@ -278,8 +320,11 @@ if self._sock: self.flush() finally: - if self._close: - self._sock.close() + if self._sock: + if self._close: + self._sock.close() + else: + self._sock._decref_socketios() self._sock = None def __del__(self): diff --git a/lib-python/2.7/sqlite3/test/dbapi.py b/lib-python/2.7/sqlite3/test/dbapi.py --- a/lib-python/2.7/sqlite3/test/dbapi.py +++ b/lib-python/2.7/sqlite3/test/dbapi.py @@ -1,4 +1,4 @@ -#-*- coding: ISO-8859-1 -*- +#-*- coding: iso-8859-1 -*- # pysqlite2/test/dbapi.py: tests for DB-API compliance # # Copyright (C) 2004-2010 Gerhard H�ring @@ -332,6 +332,9 @@ def __init__(self): self.value = 5 + def __iter__(self): + return self + def next(self): if self.value == 10: raise StopIteration @@ -826,7 +829,7 @@ con = sqlite.connect(":memory:") con.close() try: - con() + con("select 1") self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass diff --git a/lib-python/2.7/sqlite3/test/regression.py b/lib-python/2.7/sqlite3/test/regression.py --- a/lib-python/2.7/sqlite3/test/regression.py +++ b/lib-python/2.7/sqlite3/test/regression.py @@ -264,6 +264,28 @@ """ self.assertRaises(sqlite.Warning, self.con, 1) + def CheckUpdateDescriptionNone(self): + """ + Call Cursor.update with an UPDATE query and check that it sets the + cursor's description to be None. + """ + cur = self.con.cursor() + cur.execute("CREATE TABLE foo (id INTEGER)") + cur.execute("UPDATE foo SET id = 3 WHERE id = 1") + self.assertEqual(cur.description, None) + + def CheckStatementCache(self): + cur = self.con.cursor() + cur.execute("CREATE TABLE foo (id INTEGER)") + values = [(i,) for i in xrange(5)] + cur.executemany("INSERT INTO foo (id) VALUES (?)", values) + + cur.execute("SELECT id FROM foo") + self.assertEqual(list(cur), values) + self.con.commit() + cur.execute("SELECT id FROM foo") + self.assertEqual(list(cur), values) + def suite(): regression_suite = unittest.makeSuite(RegressionTests, "Check") return unittest.TestSuite((regression_suite,)) diff --git a/lib-python/2.7/sqlite3/test/userfunctions.py b/lib-python/2.7/sqlite3/test/userfunctions.py --- a/lib-python/2.7/sqlite3/test/userfunctions.py +++ b/lib-python/2.7/sqlite3/test/userfunctions.py @@ -275,12 +275,14 @@ pass def CheckAggrNoStep(self): + # XXX it's better to raise OperationalError in order to stop + # the query earlier. cur = self.con.cursor() try: cur.execute("select nostep(t) from test") - self.fail("should have raised an AttributeError") - except AttributeError, e: - self.assertEqual(e.args[0], "AggrNoStep instance has no attribute 'step'") + self.fail("should have raised an OperationalError") + except sqlite.OperationalError, e: + self.assertEqual(e.args[0], "user-defined aggregate's 'step' method raised error") def CheckAggrNoFinalize(self): cur = self.con.cursor() diff --git a/lib-python/2.7/ssl.py b/lib-python/2.7/ssl.py --- a/lib-python/2.7/ssl.py +++ b/lib-python/2.7/ssl.py @@ -86,7 +86,7 @@ else: _PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2" -from socket import socket, _fileobject, _delegate_methods, error as socket_error +from socket import socket, _fileobject, error as socket_error from socket import getnameinfo as _getnameinfo import base64 # for DER-to-PEM translation import errno @@ -103,14 +103,6 @@ do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None): socket.__init__(self, _sock=sock._sock) - # The initializer for socket overrides the methods send(), recv(), etc. - # in the instancce, which we don't need -- but we want to provide the - # methods defined in SSLSocket. - for attr in _delegate_methods: - try: - delattr(self, attr) - except AttributeError: - pass if certfile and not keyfile: keyfile = certfile diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py --- a/lib-python/2.7/subprocess.py +++ b/lib-python/2.7/subprocess.py @@ -803,7 +803,7 @@ elif stderr == PIPE: errread, errwrite = _subprocess.CreatePipe(None, 0) elif stderr == STDOUT: - errwrite = c2pwrite + errwrite = c2pwrite.handle # pass id to not close it elif isinstance(stderr, int): errwrite = msvcrt.get_osfhandle(stderr) else: @@ -818,9 +818,13 @@ def _make_inheritable(self, handle): """Return a duplicate of handle, which is inheritable""" - return _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(), + dupl = _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(), handle, _subprocess.GetCurrentProcess(), 0, 1, _subprocess.DUPLICATE_SAME_ACCESS) + # If the initial handle was obtained with CreatePipe, close it. + if not isinstance(handle, int): + handle.Close() + return dupl def _find_w9xpopen(self): diff --git a/lib-python/2.7/sysconfig.py b/lib-python/2.7/sysconfig.py --- a/lib-python/2.7/sysconfig.py +++ b/lib-python/2.7/sysconfig.py @@ -26,6 +26,16 @@ 'scripts': '{base}/bin', 'data' : '{base}', }, + 'pypy': { + 'stdlib': '{base}/lib-python', + 'platstdlib': '{base}/lib-python', + 'purelib': '{base}/lib-python', + 'platlib': '{base}/lib-python', + 'include': '{base}/include', + 'platinclude': '{base}/include', + 'scripts': '{base}/bin', + 'data' : '{base}', + }, 'nt': { 'stdlib': '{base}/Lib', 'platstdlib': '{base}/Lib', @@ -158,7 +168,9 @@ return res def _get_default_scheme(): - if os.name == 'posix': + if '__pypy__' in sys.builtin_module_names: + return 'pypy' + elif os.name == 'posix': # the default scheme for posix is posix_prefix return 'posix_prefix' return os.name @@ -182,126 +194,9 @@ return env_base if env_base else joinuser("~", ".local") -def _parse_makefile(filename, vars=None): - """Parse a Makefile-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - import re - # Regexes needed for parsing Makefile (and similar syntaxes, - # like old-style Setup files). - _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") - _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") - _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") - - if vars is None: - vars = {} - done = {} - notdone = {} - - with open(filename) as f: - lines = f.readlines() - - for line in lines: - if line.startswith('#') or line.strip() == '': - continue - m = _variable_rx.match(line) - if m: - n, v = m.group(1, 2) - v = v.strip() - # `$$' is a literal `$' in make - tmpv = v.replace('$$', '') - - if "$" in tmpv: - notdone[n] = v - else: - try: - v = int(v) - except ValueError: - # insert literal `$' - done[n] = v.replace('$$', '$') - else: - done[n] = v - - # do variable interpolation here - while notdone: - for name in notdone.keys(): - value = notdone[name] - m = _findvar1_rx.search(value) or _findvar2_rx.search(value) - if m: - n = m.group(1) - found = True - if n in done: - item = str(done[n]) - elif n in notdone: - # get it on a subsequent round - found = False - elif n in os.environ: - # do it like make: fall back to environment - item = os.environ[n] - else: - done[n] = item = "" - if found: - after = value[m.end():] - value = value[:m.start()] + item + after - if "$" in after: - notdone[name] = value - else: - try: value = int(value) - except ValueError: - done[name] = value.strip() - else: - done[name] = value - del notdone[name] - else: - # bogus variable reference; just drop it since we can't deal - del notdone[name] - # strip spurious spaces - for k, v in done.items(): - if isinstance(v, str): - done[k] = v.strip() - - # save the results in the global dictionary - vars.update(done) - return vars - - -def _get_makefile_filename(): - if _PYTHON_BUILD: - return os.path.join(_PROJECT_BASE, "Makefile") - return os.path.join(get_path('platstdlib'), "config", "Makefile") - - def _init_posix(vars): """Initialize the module as appropriate for POSIX systems.""" - # load the installed Makefile: - makefile = _get_makefile_filename() - try: - _parse_makefile(makefile, vars) - except IOError, e: - msg = "invalid Python installation: unable to open %s" % makefile - if hasattr(e, "strerror"): - msg = msg + " (%s)" % e.strerror - raise IOError(msg) - - # load the installed pyconfig.h: - config_h = get_config_h_filename() - try: - with open(config_h) as f: - parse_config_h(f, vars) - except IOError, e: - msg = "invalid Python installation: unable to open %s" % config_h - if hasattr(e, "strerror"): - msg = msg + " (%s)" % e.strerror - raise IOError(msg) - - # On AIX, there are wrong paths to the linker scripts in the Makefile - # -- these paths are relative to the Python source, but when installed - # the scripts are in another directory. - if _PYTHON_BUILD: - vars['LDSHARED'] = vars['BLDSHARED'] + return def _init_non_posix(vars): """Initialize the module as appropriate for NT""" @@ -474,10 +369,11 @@ # patched up as well. 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - flags = _CONFIG_VARS[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = flags + ' ' + arch - _CONFIG_VARS[key] = flags + if key in _CONFIG_VARS: + flags = _CONFIG_VARS[key] + flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = flags + ' ' + arch + _CONFIG_VARS[key] = flags # If we're on OSX 10.5 or later and the user tries to # compiles an extension using an SDK that is not present diff --git a/lib-python/2.7/tarfile.py b/lib-python/2.7/tarfile.py --- a/lib-python/2.7/tarfile.py +++ b/lib-python/2.7/tarfile.py @@ -1716,9 +1716,6 @@ except (ImportError, AttributeError): raise CompressionError("gzip module is not available") - if fileobj is None: - fileobj = bltn_open(name, mode + "b") - try: t = cls.taropen(name, mode, gzip.GzipFile(name, mode, compresslevel, fileobj), diff --git a/lib-python/2.7/test/list_tests.py b/lib-python/2.7/test/list_tests.py --- a/lib-python/2.7/test/list_tests.py +++ b/lib-python/2.7/test/list_tests.py @@ -45,8 +45,12 @@ self.assertEqual(str(a2), "[0, 1, 2, [...], 3]") self.assertEqual(repr(a2), "[0, 1, 2, [...], 3]") + if test_support.check_impl_detail(): + depth = sys.getrecursionlimit() + 100 + else: + depth = 1000 * 1000 # should be enough to exhaust the stack l0 = [] - for i in xrange(sys.getrecursionlimit() + 100): + for i in xrange(depth): l0 = [l0] self.assertRaises(RuntimeError, repr, l0) @@ -472,7 +476,11 @@ u += "eggs" self.assertEqual(u, self.type2test("spameggs")) - self.assertRaises(TypeError, u.__iadd__, None) + def f_iadd(u, x): + u += x + return u + + self.assertRaises(TypeError, f_iadd, u, None) def test_imul(self): u = self.type2test([0, 1]) diff --git a/lib-python/2.7/test/mapping_tests.py b/lib-python/2.7/test/mapping_tests.py --- a/lib-python/2.7/test/mapping_tests.py +++ b/lib-python/2.7/test/mapping_tests.py @@ -531,7 +531,10 @@ self.assertEqual(va, int(ka)) kb, vb = tb = b.popitem() self.assertEqual(vb, int(kb)) - self.assertTrue(not(copymode < 0 and ta != tb)) + if copymode < 0 and test_support.check_impl_detail(): + # popitem() is not guaranteed to be deterministic on + # all implementations + self.assertEqual(ta, tb) self.assertTrue(not a) self.assertTrue(not b) diff --git a/lib-python/2.7/test/pickletester.py b/lib-python/2.7/test/pickletester.py --- a/lib-python/2.7/test/pickletester.py +++ b/lib-python/2.7/test/pickletester.py @@ -6,7 +6,7 @@ import pickletools import copy_reg -from test.test_support import TestFailed, have_unicode, TESTFN +from test.test_support import TestFailed, have_unicode, TESTFN, impl_detail # Tests that try a number of pickle protocols should have a # for proto in protocols: @@ -949,6 +949,7 @@ "Failed protocol %d: %r != %r" % (proto, obj, loaded)) + @impl_detail("pypy does not store attribute names", pypy=False) def test_attribute_name_interning(self): # Test that attribute names of pickled objects are interned when # unpickling. @@ -1091,6 +1092,7 @@ s = StringIO.StringIO("X''.") self.assertRaises(EOFError, self.module.load, s) + @impl_detail("no full restricted mode in pypy", pypy=False) def test_restricted(self): # issue7128: cPickle failed in restricted mode builtins = {self.module.__name__: self.module, diff --git a/lib-python/2.7/test/regrtest.py b/lib-python/2.7/test/regrtest.py --- a/lib-python/2.7/test/regrtest.py +++ b/lib-python/2.7/test/regrtest.py @@ -1388,7 +1388,26 @@ test_zipimport test_zlib """, - 'openbsd3': + 'openbsd4': + """ + test_ascii_formatd + test_bsddb + test_bsddb3 + test_ctypes + test_dl + test_epoll + test_gdbm + test_locale + test_normalization + test_ossaudiodev + test_pep277 + test_tcl + test_tk + test_ttk_guionly + test_ttk_textonly + test_multiprocessing + """, + 'openbsd5': """ test_ascii_formatd test_bsddb @@ -1503,13 +1522,7 @@ return self.expected if __name__ == '__main__': - # findtestdir() gets the dirname out of __file__, so we have to make it - # absolute before changing the working directory. - # For example __file__ may be relative when running trace or profile. - # See issue #9323. - __file__ = os.path.abspath(__file__) - - # sanity check + # Simplification for findtestdir(). assert __file__ == os.path.abspath(sys.argv[0]) # When tests are run from the Python build directory, it is best practice diff --git a/lib-python/2.7/test/seq_tests.py b/lib-python/2.7/test/seq_tests.py --- a/lib-python/2.7/test/seq_tests.py +++ b/lib-python/2.7/test/seq_tests.py @@ -307,12 +307,18 @@ def test_bigrepeat(self): import sys - if sys.maxint <= 2147483647: - x = self.type2test([0]) - x *= 2**16 - self.assertRaises(MemoryError, x.__mul__, 2**16) - if hasattr(x, '__imul__'): - self.assertRaises(MemoryError, x.__imul__, 2**16) + # we chose an N such as 2**16 * N does not fit into a cpu word + if sys.maxint == 2147483647: + # 32 bit system + N = 2**16 + else: + # 64 bit system + N = 2**48 + x = self.type2test([0]) + x *= 2**16 + self.assertRaises(MemoryError, x.__mul__, N) + if hasattr(x, '__imul__'): + self.assertRaises(MemoryError, x.__imul__, N) def test_subscript(self): a = self.type2test([10, 11]) diff --git a/lib-python/2.7/test/string_tests.py b/lib-python/2.7/test/string_tests.py --- a/lib-python/2.7/test/string_tests.py +++ b/lib-python/2.7/test/string_tests.py @@ -1024,7 +1024,10 @@ self.checkequal('abc', 'abc', '__mul__', 1) self.checkequal('abcabcabc', 'abc', '__mul__', 3) self.checkraises(TypeError, 'abc', '__mul__') - self.checkraises(TypeError, 'abc', '__mul__', '') + class Mul(object): + def mul(self, a, b): + return a * b + self.checkraises(TypeError, Mul(), 'mul', 'abc', '') # XXX: on a 64-bit system, this doesn't raise an overflow error, # but either raises a MemoryError, or succeeds (if you have 54TiB) #self.checkraises(OverflowError, 10000*'abc', '__mul__', 2000000000) diff --git a/lib-python/2.7/test/test_abstract_numbers.py b/lib-python/2.7/test/test_abstract_numbers.py --- a/lib-python/2.7/test/test_abstract_numbers.py +++ b/lib-python/2.7/test/test_abstract_numbers.py @@ -40,7 +40,8 @@ c1, c2 = complex(3, 2), complex(4,1) # XXX: This is not ideal, but see the comment in math_trunc(). - self.assertRaises(AttributeError, math.trunc, c1) + # Modified to suit PyPy, which gives TypeError in all cases + self.assertRaises((AttributeError, TypeError), math.trunc, c1) self.assertRaises(TypeError, float, c1) self.assertRaises(TypeError, int, c1) diff --git a/lib-python/2.7/test/test_aifc.py b/lib-python/2.7/test/test_aifc.py --- a/lib-python/2.7/test/test_aifc.py +++ b/lib-python/2.7/test/test_aifc.py @@ -1,4 +1,4 @@ -from test.test_support import findfile, run_unittest, TESTFN +from test.test_support import findfile, run_unittest, TESTFN, impl_detail import unittest import os @@ -68,6 +68,7 @@ self.assertEqual(f.getparams(), fout.getparams()) self.assertEqual(f.readframes(5), fout.readframes(5)) + @impl_detail("PyPy has no audioop module yet", pypy=False) def test_compress(self): f = self.f = aifc.open(self.sndfilepath) fout = self.fout = aifc.open(TESTFN, 'wb') diff --git a/lib-python/2.7/test/test_array.py b/lib-python/2.7/test/test_array.py --- a/lib-python/2.7/test/test_array.py +++ b/lib-python/2.7/test/test_array.py @@ -295,9 +295,10 @@ ) b = array.array(self.badtypecode()) - self.assertRaises(TypeError, a.__add__, b) - - self.assertRaises(TypeError, a.__add__, "bad") + with self.assertRaises(TypeError): + a + b + with self.assertRaises(TypeError): + a + 'bad' def test_iadd(self): a = array.array(self.typecode, self.example[::-1]) @@ -316,9 +317,10 @@ ) b = array.array(self.badtypecode()) - self.assertRaises(TypeError, a.__add__, b) - - self.assertRaises(TypeError, a.__iadd__, "bad") + with self.assertRaises(TypeError): + a += b + with self.assertRaises(TypeError): + a += 'bad' def test_mul(self): a = 5*array.array(self.typecode, self.example) @@ -345,7 +347,8 @@ array.array(self.typecode) ) - self.assertRaises(TypeError, a.__mul__, "bad") + with self.assertRaises(TypeError): + a * 'bad' def test_imul(self): a = array.array(self.typecode, self.example) @@ -374,7 +377,8 @@ a *= -1 self.assertEqual(a, array.array(self.typecode)) - self.assertRaises(TypeError, a.__imul__, "bad") + with self.assertRaises(TypeError): + a *= 'bad' def test_getitem(self): a = array.array(self.typecode, self.example) @@ -769,6 +773,7 @@ p = proxy(s) self.assertEqual(p.tostring(), s.tostring()) s = None + test_support.gc_collect() self.assertRaises(ReferenceError, len, p) def test_bug_782369(self): diff --git a/lib-python/2.7/test/test_ascii_formatd.py b/lib-python/2.7/test/test_ascii_formatd.py --- a/lib-python/2.7/test/test_ascii_formatd.py +++ b/lib-python/2.7/test/test_ascii_formatd.py @@ -4,6 +4,10 @@ import unittest from test.test_support import check_warnings, run_unittest, import_module +from test.test_support import check_impl_detail + +if not check_impl_detail(cpython=True): + raise unittest.SkipTest("this test is only for CPython") # Skip tests if _ctypes module does not exist import_module('_ctypes') diff --git a/lib-python/2.7/test/test_ast.py b/lib-python/2.7/test/test_ast.py --- a/lib-python/2.7/test/test_ast.py +++ b/lib-python/2.7/test/test_ast.py @@ -20,10 +20,24 @@ # These tests are compiled through "exec" # There should be atleast one test per statement exec_tests = [ + # None + "None", # FunctionDef "def f(): pass", + # FunctionDef with arg + "def f(a): pass", + # FunctionDef with arg and default value + "def f(a=0): pass", + # FunctionDef with varargs + "def f(*args): pass", + # FunctionDef with kwargs + "def f(**kwargs): pass", + # FunctionDef with all kind of args + "def f(a, b=1, c=None, d=[], e={}, *args, **kwargs): pass", # ClassDef "class C:pass", + # ClassDef, new style class + "class C(object): pass", # Return "def f():return 1", # Delete @@ -68,6 +82,27 @@ "for a,b in c: pass", "[(a,b) for a,b in c]", "((a,b) for a,b in c)", + "((a,b) for (a,b) in c)", + # Multiline generator expression + """( + ( + Aa + , + Bb + ) + for + Aa + , + Bb in Cc + )""", + # dictcomp + "{a : b for w in x for m in p if g}", + # dictcomp with naked tuple + "{a : b for v,w in x}", + # setcomp + "{r for l in x if g}", + # setcomp with naked tuple + "{r for l,m in x}", ] # These are compiled through "single" @@ -80,6 +115,8 @@ # These are compiled through "eval" # It should test all expressions eval_tests = [ + # None + "None", # BoolOp "a and b", # BinOp @@ -90,6 +127,16 @@ "lambda:None", # Dict "{ 1:2 }", + # Empty dict + "{}", + # Set + "{None,}", + # Multiline dict + """{ + 1 + : + 2 + }""", # ListComp "[a for b in c if d]", # GeneratorExp @@ -114,8 +161,14 @@ "v", # List "[1,2,3]", + # Empty list + "[]", # Tuple "1,2,3", + # Tuple + "(1,2,3)", + # Empty tuple + "()", # Combination "a.b.c.d(a.b[1:2])", @@ -141,6 +194,35 @@ elif value is not None: self._assertTrueorder(value, parent_pos) + def test_AST_objects(self): + if test_support.check_impl_detail(): + # PyPy also provides a __dict__ to the ast.AST base class. + + x = ast.AST() + try: + x.foobar = 21 + except AttributeError, e: + self.assertEquals(e.args[0], + "'_ast.AST' object has no attribute 'foobar'") + else: + self.assert_(False) + + try: + ast.AST(lineno=2) + except AttributeError, e: + self.assertEquals(e.args[0], + "'_ast.AST' object has no attribute 'lineno'") + else: + self.assert_(False) + + try: + ast.AST(2) + except TypeError, e: + self.assertEquals(e.args[0], + "_ast.AST constructor takes 0 positional arguments") + else: + self.assert_(False) + def test_snippets(self): for input, output, kind in ((exec_tests, exec_results, "exec"), (single_tests, single_results, "single"), @@ -169,6 +251,114 @@ self.assertTrue(issubclass(ast.comprehension, ast.AST)) self.assertTrue(issubclass(ast.Gt, ast.AST)) + def test_field_attr_existence(self): + for name, item in ast.__dict__.iteritems(): + if isinstance(item, type) and name != 'AST' and name[0].isupper(): # XXX: pypy does not allow abstract ast class instanciation + x = item() + if isinstance(x, ast.AST): + self.assertEquals(type(x._fields), tuple) + + def test_arguments(self): + x = ast.arguments() + self.assertEquals(x._fields, ('args', 'vararg', 'kwarg', 'defaults')) + try: + x.vararg + except AttributeError, e: + self.assertEquals(e.args[0], + "'arguments' object has no attribute 'vararg'") + else: + self.assert_(False) + x = ast.arguments(1, 2, 3, 4) + self.assertEquals(x.vararg, 2) + + def test_field_attr_writable(self): + x = ast.Num() + # We can assign to _fields + x._fields = 666 + self.assertEquals(x._fields, 666) + + def test_classattrs(self): + x = ast.Num() + self.assertEquals(x._fields, ('n',)) + try: + x.n + except AttributeError, e: + self.assertEquals(e.args[0], + "'Num' object has no attribute 'n'") + else: + self.assert_(False) + + x = ast.Num(42) + self.assertEquals(x.n, 42) + try: + x.lineno + except AttributeError, e: + self.assertEquals(e.args[0], + "'Num' object has no attribute 'lineno'") + else: + self.assert_(False) + + y = ast.Num() + x.lineno = y + self.assertEquals(x.lineno, y) + + try: + x.foobar + except AttributeError, e: + self.assertEquals(e.args[0], + "'Num' object has no attribute 'foobar'") + else: + self.assert_(False) + + x = ast.Num(lineno=2) + self.assertEquals(x.lineno, 2) + + x = ast.Num(42, lineno=0) + self.assertEquals(x.lineno, 0) + self.assertEquals(x._fields, ('n',)) + self.assertEquals(x.n, 42) + + self.assertRaises(TypeError, ast.Num, 1, 2) + self.assertRaises(TypeError, ast.Num, 1, 2, lineno=0) + + def test_module(self): + body = [ast.Num(42)] + x = ast.Module(body) + self.assertEquals(x.body, body) + + def test_nodeclass(self): + x = ast.BinOp() + self.assertEquals(x._fields, ('left', 'op', 'right')) + + # Zero arguments constructor explicitely allowed + x = ast.BinOp() + # Random attribute allowed too + x.foobarbaz = 5 + self.assertEquals(x.foobarbaz, 5) + + n1 = ast.Num(1) + n3 = ast.Num(3) + addop = ast.Add() + x = ast.BinOp(n1, addop, n3) + self.assertEquals(x.left, n1) + self.assertEquals(x.op, addop) + self.assertEquals(x.right, n3) + + x = ast.BinOp(1, 2, 3) + self.assertEquals(x.left, 1) + self.assertEquals(x.op, 2) + self.assertEquals(x.right, 3) + + x = ast.BinOp(1, 2, 3, lineno=0) + self.assertEquals(x.lineno, 0) + + def test_nodeclasses(self): + x = ast.BinOp(1, 2, 3, lineno=0) + self.assertEquals(x.left, 1) + self.assertEquals(x.op, 2) + self.assertEquals(x.right, 3) + self.assertEquals(x.lineno, 0) + def test_nodeclasses(self): x = ast.BinOp(1, 2, 3, lineno=0) self.assertEqual(x.left, 1) @@ -178,6 +368,12 @@ # node raises exception when not given enough arguments self.assertRaises(TypeError, ast.BinOp, 1, 2) + # node raises exception when given too many arguments + self.assertRaises(TypeError, ast.BinOp, 1, 2, 3, 4) + # node raises exception when not given enough arguments + self.assertRaises(TypeError, ast.BinOp, 1, 2, lineno=0) + # node raises exception when given too many arguments + self.assertRaises(TypeError, ast.BinOp, 1, 2, 3, 4, lineno=0) # can set attributes through kwargs too x = ast.BinOp(left=1, op=2, right=3, lineno=0) @@ -186,8 +382,14 @@ self.assertEqual(x.right, 3) self.assertEqual(x.lineno, 0) + # Random kwargs also allowed + x = ast.BinOp(1, 2, 3, foobarbaz=42) + self.assertEquals(x.foobarbaz, 42) + + def test_no_fields(self): # this used to fail because Sub._fields was None x = ast.Sub() + self.assertEquals(x._fields, ()) def test_pickling(self): import pickle @@ -330,8 +532,15 @@ #### EVERYTHING BELOW IS GENERATED ##### exec_results = [ +('Module', [('Expr', (1, 0), ('Name', (1, 0), 'None', ('Load',)))]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, []), [('Pass', (1, 9))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('Name', (1, 6), 'a', ('Param',))], None, None, []), [('Pass', (1, 10))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('Name', (1, 6), 'a', ('Param',))], None, None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], 'args', None, []), [('Pass', (1, 14))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, 'kwargs', []), [('Pass', (1, 17))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('Name', (1, 6), 'a', ('Param',)), ('Name', (1, 9), 'b', ('Param',)), ('Name', (1, 14), 'c', ('Param',)), ('Name', (1, 22), 'd', ('Param',)), ('Name', (1, 28), 'e', ('Param',))], 'args', 'kwargs', [('Num', (1, 11), 1), ('Name', (1, 16), 'None', ('Load',)), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Pass', (1, 52))], [])]), ('Module', [('ClassDef', (1, 0), 'C', [], [('Pass', (1, 8))], [])]), +('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [('Pass', (1, 17))], [])]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [])]), ('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]), ('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]), @@ -355,16 +564,26 @@ ('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [])]), ('Module', [('Expr', (1, 0), ('ListComp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [])]))]), ('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [])]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 12), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [])]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (2, 4), ('Tuple', (3, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [])]))]), +('Module', [('Expr', (1, 0), ('DictComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), []), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))])]))]), +('Module', [('Expr', (1, 0), ('DictComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [])]))]), +('Module', [('Expr', (1, 0), ('SetComp', (1, 1), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))])]))]), +('Module', [('Expr', (1, 0), ('SetComp', (1, 1), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [])]))]), ] single_results = [ ('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]), ] eval_results = [ +('Expression', ('Name', (1, 0), 'None', ('Load',))), ('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])), ('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))), ('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))), ('Expression', ('Lambda', (1, 0), ('arguments', [], None, None, []), ('Name', (1, 7), 'None', ('Load',)))), ('Expression', ('Dict', (1, 0), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])), +('Expression', ('Dict', (1, 0), [], [])), +('Expression', ('Set', (1, 0), [('Name', (1, 1), 'None', ('Load',))])), +('Expression', ('Dict', (1, 0), [('Num', (2, 6), 1)], [('Num', (4, 10), 2)])), ('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])), ('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])), ('Expression', ('Compare', (1, 0), ('Num', (1, 0), 1), [('Lt',), ('Lt',)], [('Num', (1, 4), 2), ('Num', (1, 8), 3)])), @@ -376,7 +595,10 @@ ('Expression', ('Subscript', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Slice', ('Name', (1, 2), 'b', ('Load',)), ('Name', (1, 4), 'c', ('Load',)), None), ('Load',))), ('Expression', ('Name', (1, 0), 'v', ('Load',))), ('Expression', ('List', (1, 0), [('Num', (1, 1), 1), ('Num', (1, 3), 2), ('Num', (1, 5), 3)], ('Load',))), +('Expression', ('List', (1, 0), [], ('Load',))), ('Expression', ('Tuple', (1, 0), [('Num', (1, 0), 1), ('Num', (1, 2), 2), ('Num', (1, 4), 3)], ('Load',))), +('Expression', ('Tuple', (1, 1), [('Num', (1, 1), 1), ('Num', (1, 3), 2), ('Num', (1, 5), 3)], ('Load',))), +('Expression', ('Tuple', (1, 0), [], ('Load',))), ('Expression', ('Call', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8), ('Attribute', (1, 8), ('Name', (1, 8), 'a', ('Load',)), 'b', ('Load',)), ('Slice', ('Num', (1, 12), 1), ('Num', (1, 14), 2), None), ('Load',))], [], None, None)), ] main() diff --git a/lib-python/2.7/test/test_builtin.py b/lib-python/2.7/test/test_builtin.py --- a/lib-python/2.7/test/test_builtin.py +++ b/lib-python/2.7/test/test_builtin.py @@ -3,7 +3,8 @@ import platform import unittest from test.test_support import fcmp, have_unicode, TESTFN, unlink, \ - run_unittest, check_py3k_warnings + run_unittest, check_py3k_warnings, \ + check_impl_detail import warnings from operator import neg @@ -247,12 +248,14 @@ self.assertRaises(TypeError, compile) self.assertRaises(ValueError, compile, 'print 42\n', '', 'badmode') self.assertRaises(ValueError, compile, 'print 42\n', '', 'single', 0xff) - self.assertRaises(TypeError, compile, chr(0), 'f', 'exec') + if check_impl_detail(cpython=True): + self.assertRaises(TypeError, compile, chr(0), 'f', 'exec') self.assertRaises(TypeError, compile, 'pass', '?', 'exec', mode='eval', source='0', filename='tmp') if have_unicode: compile(unicode('print u"\xc3\xa5"\n', 'utf8'), '', 'exec') - self.assertRaises(TypeError, compile, unichr(0), 'f', 'exec') + if check_impl_detail(cpython=True): + self.assertRaises(TypeError, compile, unichr(0), 'f', 'exec') self.assertRaises(ValueError, compile, unicode('a = 1'), 'f', 'bad') @@ -395,12 +398,16 @@ self.assertEqual(eval('dir()', g, m), list('xyz')) self.assertEqual(eval('globals()', g, m), g) self.assertEqual(eval('locals()', g, m), m) - self.assertRaises(TypeError, eval, 'a', m) + # on top of CPython, the first dictionary (the globals) has to + # be a real dict. This is not the case on top of PyPy. + if check_impl_detail(pypy=False): + self.assertRaises(TypeError, eval, 'a', m) + class A: "Non-mapping" pass m = A() - self.assertRaises(TypeError, eval, 'a', g, m) + self.assertRaises((TypeError, AttributeError), eval, 'a', g, m) # Verify that dict subclasses work as well class D(dict): @@ -491,9 +498,10 @@ execfile(TESTFN, globals, locals) self.assertEqual(locals['z'], 2) + self.assertRaises(TypeError, execfile, TESTFN, {}, ()) unlink(TESTFN) self.assertRaises(TypeError, execfile) - self.assertRaises(TypeError, execfile, TESTFN, {}, ()) + self.assertRaises((TypeError, IOError), execfile, TESTFN, {}, ()) import os self.assertRaises(IOError, execfile, os.curdir) self.assertRaises(IOError, execfile, "I_dont_exist") @@ -1108,7 +1116,8 @@ def __cmp__(self, other): raise RuntimeError __hash__ = None # Invalid cmp makes this unhashable - self.assertRaises(RuntimeError, range, a, a + 1, badzero(1)) + if check_impl_detail(cpython=True): + self.assertRaises(RuntimeError, range, a, a + 1, badzero(1)) # Reject floats. self.assertRaises(TypeError, range, 1., 1., 1.) diff --git a/lib-python/2.7/test/test_bytes.py b/lib-python/2.7/test/test_bytes.py --- a/lib-python/2.7/test/test_bytes.py +++ b/lib-python/2.7/test/test_bytes.py @@ -694,6 +694,7 @@ self.assertEqual(b, b1) self.assertTrue(b is b1) + @test.test_support.impl_detail("undocumented bytes.__alloc__()") def test_alloc(self): b = bytearray() alloc = b.__alloc__() @@ -821,6 +822,8 @@ self.assertEqual(b, b"") self.assertEqual(c, b"") + @test.test_support.impl_detail( + "resizing semantics of CPython rely on refcounting") def test_resize_forbidden(self): # #4509: can't resize a bytearray when there are buffer exports, even # if it wouldn't reallocate the underlying buffer. @@ -853,6 +856,26 @@ self.assertRaises(BufferError, delslice) self.assertEqual(b, orig) + @test.test_support.impl_detail("resizing semantics", cpython=False) + def test_resize_forbidden_non_cpython(self): + # on non-CPython implementations, we cannot prevent changes to + # bytearrays just because there are buffers around. Instead, + # we get (on PyPy) a buffer that follows the changes and resizes. + b = bytearray(range(10)) + for v in [memoryview(b), buffer(b)]: + b[5] = 99 + self.assertIn(v[5], (99, chr(99))) + b[5] = 100 + b += b + b += b + b += b + self.assertEquals(len(v), 80) + self.assertIn(v[5], (100, chr(100))) + self.assertIn(v[79], (9, chr(9))) + del b[10:] + self.assertRaises(IndexError, lambda: v[10]) + self.assertEquals(len(v), 10) + def test_empty_bytearray(self): # Issue #7561: operations on empty bytearrays could crash in many # situations, due to a fragile implementation of the diff --git a/lib-python/2.7/test/test_bz2.py b/lib-python/2.7/test/test_bz2.py --- a/lib-python/2.7/test/test_bz2.py +++ b/lib-python/2.7/test/test_bz2.py @@ -50,6 +50,7 @@ self.filename = TESTFN def tearDown(self): + test_support.gc_collect() if os.path.isfile(self.filename): os.unlink(self.filename) @@ -246,6 +247,8 @@ for i in xrange(10000): o = BZ2File(self.filename) del o + if i % 100 == 0: + test_support.gc_collect() def testOpenNonexistent(self): # "Test opening a nonexistent file" @@ -310,6 +313,7 @@ for t in threads: t.join() + @test_support.impl_detail() def testMixedIterationReads(self): # Issue #8397: mixed iteration and reads should be forbidden. with bz2.BZ2File(self.filename, 'wb') as f: diff --git a/lib-python/2.7/test/test_cmd_line_script.py b/lib-python/2.7/test/test_cmd_line_script.py --- a/lib-python/2.7/test/test_cmd_line_script.py +++ b/lib-python/2.7/test/test_cmd_line_script.py @@ -112,6 +112,8 @@ self._check_script(script_dir, script_name, script_dir, '') def test_directory_compiled(self): + if test.test_support.check_impl_detail(pypy=True): + raise unittest.SkipTest("pypy won't load lone .pyc files") with temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') compiled_name = compile_script(script_name) @@ -173,6 +175,8 @@ script_name, 'test_pkg') def test_package_compiled(self): + if test.test_support.check_impl_detail(pypy=True): + raise unittest.SkipTest("pypy won't load lone .pyc files") with temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') make_pkg(pkg_dir) diff --git a/lib-python/2.7/test/test_code.py b/lib-python/2.7/test/test_code.py --- a/lib-python/2.7/test/test_code.py +++ b/lib-python/2.7/test/test_code.py @@ -82,7 +82,7 @@ import unittest import weakref -import _testcapi +from test import test_support def consts(t): @@ -104,7 +104,9 @@ class CodeTest(unittest.TestCase): + @test_support.impl_detail("test for PyCode_NewEmpty") def test_newempty(self): + import _testcapi co = _testcapi.code_newempty("filename", "funcname", 15) self.assertEqual(co.co_filename, "filename") self.assertEqual(co.co_name, "funcname") @@ -132,6 +134,7 @@ coderef = weakref.ref(f.__code__, callback) self.assertTrue(bool(coderef())) del f + test_support.gc_collect() self.assertFalse(bool(coderef())) self.assertTrue(self.called) diff --git a/lib-python/2.7/test/test_codeop.py b/lib-python/2.7/test/test_codeop.py --- a/lib-python/2.7/test/test_codeop.py +++ b/lib-python/2.7/test/test_codeop.py @@ -3,7 +3,7 @@ Nick Mathewson """ import unittest -from test.test_support import run_unittest, is_jython +from test.test_support import run_unittest, is_jython, check_impl_detail from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT @@ -270,7 +270,9 @@ ai("a = 'a\\\n") ai("a = 1","eval") - ai("a = (","eval") + if check_impl_detail(): # on PyPy it asks for more data, which is not + ai("a = (","eval") # completely correct but hard to fix and + # really a detail (in my opinion ) ai("]","eval") ai("())","eval") ai("[}","eval") diff --git a/lib-python/2.7/test/test_coercion.py b/lib-python/2.7/test/test_coercion.py --- a/lib-python/2.7/test/test_coercion.py +++ b/lib-python/2.7/test/test_coercion.py @@ -1,6 +1,7 @@ import copy import unittest -from test.test_support import run_unittest, TestFailed, check_warnings +from test.test_support import ( + run_unittest, TestFailed, check_warnings, check_impl_detail) # Fake a number that implements numeric methods through __coerce__ @@ -306,12 +307,18 @@ self.assertNotEqual(cmp(u'fish', evil_coercer), 0) self.assertNotEqual(cmp(slice(1), evil_coercer), 0) # ...but that this still works - class WackyComparer(object): - def __cmp__(slf, other): - self.assertTrue(other == 42, 'expected evil_coercer, got %r' % other) - return 0 - __hash__ = None # Invalid cmp makes this unhashable - self.assertEqual(cmp(WackyComparer(), evil_coercer), 0) + if check_impl_detail(): + # NB. I (arigo) would consider the following as implementation- + # specific. For example, in CPython, if we replace 42 with 42.0 + # both below and in CoerceTo() above, then the test fails. This + # hints that the behavior is really dependent on some obscure + # internal details. + class WackyComparer(object): + def __cmp__(slf, other): + self.assertTrue(other == 42, 'expected evil_coercer, got %r' % other) + return 0 + __hash__ = None # Invalid cmp makes this unhashable + self.assertEqual(cmp(WackyComparer(), evil_coercer), 0) # ...and classic classes too, since that code path is a little different class ClassicWackyComparer: def __cmp__(slf, other): diff --git a/lib-python/2.7/test/test_compile.py b/lib-python/2.7/test/test_compile.py --- a/lib-python/2.7/test/test_compile.py +++ b/lib-python/2.7/test/test_compile.py @@ -3,6 +3,7 @@ import _ast from test import test_support import textwrap +from test.test_support import check_impl_detail class TestSpecifics(unittest.TestCase): @@ -90,12 +91,13 @@ self.assertEqual(m.results, ('z', g)) exec 'z = locals()' in g, m self.assertEqual(m.results, ('z', m)) - try: - exec 'z = b' in m - except TypeError: - pass - else: - self.fail('Did not validate globals as a real dict') + if check_impl_detail(): + try: + exec 'z = b' in m + except TypeError: + pass + else: + self.fail('Did not validate globals as a real dict') class A: "Non-mapping" diff --git a/lib-python/2.7/test/test_copy.py b/lib-python/2.7/test/test_copy.py --- a/lib-python/2.7/test/test_copy.py +++ b/lib-python/2.7/test/test_copy.py @@ -637,6 +637,7 @@ self.assertEqual(v[c], d) self.assertEqual(len(v), 2) del c, d + test_support.gc_collect() self.assertEqual(len(v), 1) x, y = C(), C() # The underlying containers are decoupled @@ -666,6 +667,7 @@ self.assertEqual(v[a].i, b.i) self.assertEqual(v[c].i, d.i) del c + test_support.gc_collect() self.assertEqual(len(v), 1) def test_deepcopy_weakvaluedict(self): @@ -689,6 +691,7 @@ self.assertTrue(t is d) del x, y, z, t del d + test_support.gc_collect() self.assertEqual(len(v), 1) def test_deepcopy_bound_method(self): diff --git a/lib-python/2.7/test/test_cpickle.py b/lib-python/2.7/test/test_cpickle.py --- a/lib-python/2.7/test/test_cpickle.py +++ b/lib-python/2.7/test/test_cpickle.py @@ -61,27 +61,27 @@ error = cPickle.BadPickleGet def test_recursive_list(self): - self.assertRaises(ValueError, + self.assertRaises((ValueError, RuntimeError), AbstractPickleTests.test_recursive_list, self) def test_recursive_tuple(self): - self.assertRaises(ValueError, + self.assertRaises((ValueError, RuntimeError), AbstractPickleTests.test_recursive_tuple, self) def test_recursive_inst(self): - self.assertRaises(ValueError, + self.assertRaises((ValueError, RuntimeError), AbstractPickleTests.test_recursive_inst, self) def test_recursive_dict(self): - self.assertRaises(ValueError, + self.assertRaises((ValueError, RuntimeError), AbstractPickleTests.test_recursive_dict, self) def test_recursive_multi(self): - self.assertRaises(ValueError, + self.assertRaises((ValueError, RuntimeError), AbstractPickleTests.test_recursive_multi, self) diff --git a/lib-python/2.7/test/test_csv.py b/lib-python/2.7/test/test_csv.py --- a/lib-python/2.7/test/test_csv.py +++ b/lib-python/2.7/test/test_csv.py @@ -54,8 +54,10 @@ self.assertEqual(obj.dialect.skipinitialspace, False) self.assertEqual(obj.dialect.strict, False) # Try deleting or changing attributes (they are read-only) - self.assertRaises(TypeError, delattr, obj.dialect, 'delimiter') - self.assertRaises(TypeError, setattr, obj.dialect, 'delimiter', ':') + self.assertRaises((TypeError, AttributeError), delattr, obj.dialect, + 'delimiter') + self.assertRaises((TypeError, AttributeError), setattr, obj.dialect, + 'delimiter', ':') self.assertRaises(AttributeError, delattr, obj.dialect, 'quoting') self.assertRaises(AttributeError, setattr, obj.dialect, 'quoting', None) diff --git a/lib-python/2.7/test/test_deque.py b/lib-python/2.7/test/test_deque.py --- a/lib-python/2.7/test/test_deque.py +++ b/lib-python/2.7/test/test_deque.py @@ -109,7 +109,7 @@ self.assertEqual(deque('abc', maxlen=4).maxlen, 4) self.assertEqual(deque('abc', maxlen=2).maxlen, 2) self.assertEqual(deque('abc', maxlen=0).maxlen, 0) - with self.assertRaises(AttributeError): + with self.assertRaises((AttributeError, TypeError)): d = deque('abc') d.maxlen = 10 @@ -352,7 +352,10 @@ for match in (True, False): d = deque(['ab']) d.extend([MutateCmp(d, match), 'c']) - self.assertRaises(IndexError, d.remove, 'c') + # On CPython we get IndexError: deque mutated during remove(). + # Why is it an IndexError during remove() only??? + # On PyPy it is a RuntimeError, as in the other operations. + self.assertRaises((IndexError, RuntimeError), d.remove, 'c') self.assertEqual(d, deque()) def test_repr(self): @@ -514,7 +517,7 @@ container = reversed(deque([obj, 1])) obj.x = iter(container) del obj, container - gc.collect() + test_support.gc_collect() self.assertTrue(ref() is None, "Cycle was not collected") class TestVariousIteratorArgs(unittest.TestCase): @@ -630,6 +633,7 @@ p = weakref.proxy(d) self.assertEqual(str(p), str(d)) d = None + test_support.gc_collect() self.assertRaises(ReferenceError, str, p) def test_strange_subclass(self): diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -2,6 +2,7 @@ import sys import types import unittest +import popen2 # trigger early the warning from popen2.py from copy import deepcopy from test import test_support @@ -1128,7 +1129,7 @@ # Test lookup leaks [SF bug 572567] import gc - if hasattr(gc, 'get_objects'): + if test_support.check_impl_detail(): class G(object): def __cmp__(self, other): return 0 @@ -1741,6 +1742,10 @@ raise MyException for name, runner, meth_impl, ok, env in specials: + if name == '__length_hint__' or name == '__sizeof__': + if not test_support.check_impl_detail(): + continue + class X(Checker): pass for attr, obj in env.iteritems(): @@ -1980,7 +1985,9 @@ except TypeError, msg: self.assertTrue(str(msg).find("weak reference") >= 0) else: - self.fail("weakref.ref(no) should be illegal") + if test_support.check_impl_detail(pypy=False): + self.fail("weakref.ref(no) should be illegal") + #else: pypy supports taking weakrefs to some more objects class Weak(object): __slots__ = ['foo', '__weakref__'] yes = Weak() @@ -3092,7 +3099,16 @@ class R(J): __slots__ = ["__dict__", "__weakref__"] - for cls, cls2 in ((G, H), (G, I), (I, H), (Q, R), (R, Q)): + if test_support.check_impl_detail(pypy=False): + lst = ((G, H), (G, I), (I, H), (Q, R), (R, Q)) + else: + # Not supported in pypy: changing the __class__ of an object + # to another __class__ that just happens to have the same slots. + # If needed, we can add the feature, but what we'll likely do + # then is to allow mostly any __class__ assignment, even if the + # classes have different __slots__, because we it's easier. + lst = ((Q, R), (R, Q)) + for cls, cls2 in lst: x = cls() x.a = 1 x.__class__ = cls2 @@ -3175,7 +3191,8 @@ except TypeError: pass else: - self.fail("%r's __dict__ can be modified" % cls) + if test_support.check_impl_detail(pypy=False): + self.fail("%r's __dict__ can be modified" % cls) # Modules also disallow __dict__ assignment class Module1(types.ModuleType, Base): @@ -4383,13 +4400,10 @@ self.assertTrue(l.__add__ != [5].__add__) self.assertTrue(l.__add__ != l.__mul__) self.assertTrue(l.__add__.__name__ == '__add__') - if hasattr(l.__add__, '__self__'): - # CPython - self.assertTrue(l.__add__.__self__ is l) + self.assertTrue(l.__add__.__self__ is l) + if hasattr(l.__add__, '__objclass__'): # CPython self.assertTrue(l.__add__.__objclass__ is list) - else: - # Python implementations where [].__add__ is a normal bound method - self.assertTrue(l.__add__.im_self is l) + else: # PyPy self.assertTrue(l.__add__.im_class is list) self.assertEqual(l.__add__.__doc__, list.__add__.__doc__) try: @@ -4578,8 +4592,12 @@ str.split(fake_str) # call a slot wrapper descriptor - with self.assertRaises(TypeError): - str.__add__(fake_str, "abc") + try: + r = str.__add__(fake_str, "abc") + except TypeError: + pass + else: + self.assertEqual(r, NotImplemented) class DictProxyTests(unittest.TestCase): diff --git a/lib-python/2.7/test/test_descrtut.py b/lib-python/2.7/test/test_descrtut.py --- a/lib-python/2.7/test/test_descrtut.py +++ b/lib-python/2.7/test/test_descrtut.py @@ -172,46 +172,12 @@ AttributeError: 'list' object has no attribute '__methods__' >>> -Instead, you can get the same information from the list type: +Instead, you can get the same information from the list type +(the following example filters out the numerous method names +starting with '_'): - >>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted - ['__add__', - '__class__', - '__contains__', - '__delattr__', - '__delitem__', - '__delslice__', - '__doc__', - '__eq__', - '__format__', - '__ge__', - '__getattribute__', - '__getitem__', - '__getslice__', - '__gt__', - '__hash__', - '__iadd__', - '__imul__', - '__init__', - '__iter__', - '__le__', - '__len__', - '__lt__', - '__mul__', - '__ne__', - '__new__', - '__reduce__', - '__reduce_ex__', - '__repr__', - '__reversed__', - '__rmul__', - '__setattr__', - '__setitem__', - '__setslice__', - '__sizeof__', - '__str__', - '__subclasshook__', - 'append', + >>> pprint.pprint([name for name in dir(list) if not name.startswith('_')]) + ['append', 'count', 'extend', 'index', diff --git a/lib-python/2.7/test/test_dict.py b/lib-python/2.7/test/test_dict.py --- a/lib-python/2.7/test/test_dict.py +++ b/lib-python/2.7/test/test_dict.py @@ -319,7 +319,8 @@ self.assertEqual(va, int(ka)) kb, vb = tb = b.popitem() self.assertEqual(vb, int(kb)) - self.assertFalse(copymode < 0 and ta != tb) + if test_support.check_impl_detail(): + self.assertFalse(copymode < 0 and ta != tb) self.assertFalse(a) self.assertFalse(b) diff --git a/lib-python/2.7/test/test_dis.py b/lib-python/2.7/test/test_dis.py --- a/lib-python/2.7/test/test_dis.py +++ b/lib-python/2.7/test/test_dis.py @@ -56,8 +56,8 @@ %-4d 0 LOAD_CONST 1 (0) 3 POP_JUMP_IF_TRUE 38 6 LOAD_GLOBAL 0 (AssertionError) - 9 BUILD_LIST 0 - 12 LOAD_FAST 0 (x) + 9 LOAD_FAST 0 (x) + 12 BUILD_LIST_FROM_ARG 0 15 GET_ITER >> 16 FOR_ITER 12 (to 31) 19 STORE_FAST 1 (s) diff --git a/lib-python/2.7/test/test_doctest.py b/lib-python/2.7/test/test_doctest.py --- a/lib-python/2.7/test/test_doctest.py +++ b/lib-python/2.7/test/test_doctest.py @@ -782,7 +782,7 @@ ... >>> x = 12 ... >>> print x//0 ... Traceback (most recent call last): - ... ZeroDivisionError: integer division or modulo by zero + ... ZeroDivisionError: integer division by zero ... ''' >>> test = doctest.DocTestFinder().find(f)[0] >>> doctest.DocTestRunner(verbose=False).run(test) @@ -799,7 +799,7 @@ ... >>> print 'pre-exception output', x//0 ... pre-exception output ... Traceback (most recent call last): - ... ZeroDivisionError: integer division or modulo by zero + ... ZeroDivisionError: integer division by zero ... ''' >>> test = doctest.DocTestFinder().find(f)[0] >>> doctest.DocTestRunner(verbose=False).run(test) @@ -810,7 +810,7 @@ print 'pre-exception output', x//0 Exception raised: ... - ZeroDivisionError: integer division or modulo by zero + ZeroDivisionError: integer division by zero TestResults(failed=1, attempted=2) Exception messages may contain newlines: @@ -978,7 +978,7 @@ Exception raised: Traceback (most recent call last): ... - ZeroDivisionError: integer division or modulo by zero + ZeroDivisionError: integer division by zero TestResults(failed=1, attempted=1) """ def displayhook(): r""" @@ -1924,7 +1924,7 @@ > (1)() -> calls_set_trace() (Pdb) print foo - *** NameError: name 'foo' is not defined + *** NameError: global name 'foo' is not defined (Pdb) continue TestResults(failed=0, attempted=2) """ @@ -2229,7 +2229,7 @@ favorite_color Exception raised: ... - NameError: name 'favorite_color' is not defined + NameError: global name 'favorite_color' is not defined @@ -2289,7 +2289,7 @@ favorite_color Exception raised: ... - NameError: name 'favorite_color' is not defined + NameError: global name 'favorite_color' is not defined ********************************************************************** 1 items had failures: 1 of 2 in test_doctest.txt @@ -2382,7 +2382,7 @@ favorite_color Exception raised: ... - NameError: name 'favorite_color' is not defined + NameError: global name 'favorite_color' is not defined TestResults(failed=1, attempted=2) >>> doctest.master = None # Reset master. diff --git a/lib-python/2.7/test/test_dumbdbm.py b/lib-python/2.7/test/test_dumbdbm.py --- a/lib-python/2.7/test/test_dumbdbm.py +++ b/lib-python/2.7/test/test_dumbdbm.py @@ -107,9 +107,11 @@ f.close() # Mangle the file by adding \r before each newline - data = open(_fname + '.dir').read() + with open(_fname + '.dir') as f: + data = f.read() data = data.replace('\n', '\r\n') - open(_fname + '.dir', 'wb').write(data) + with open(_fname + '.dir', 'wb') as f: + f.write(data) f = dumbdbm.open(_fname) self.assertEqual(f['1'], 'hello') diff --git a/lib-python/2.7/test/test_extcall.py b/lib-python/2.7/test/test_extcall.py --- a/lib-python/2.7/test/test_extcall.py +++ b/lib-python/2.7/test/test_extcall.py @@ -90,19 +90,19 @@ >>> class Nothing: pass ... - >>> g(*Nothing()) + >>> g(*Nothing()) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: g() argument after * must be a sequence, not instance + TypeError: ...argument after * must be a sequence, not instance >>> class Nothing: ... def __len__(self): return 5 ... - >>> g(*Nothing()) + >>> g(*Nothing()) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: g() argument after * must be a sequence, not instance + TypeError: ...argument after * must be a sequence, not instance >>> class Nothing(): ... def __len__(self): return 5 @@ -154,52 +154,50 @@ ... TypeError: g() got multiple values for keyword argument 'x' - >>> f(**{1:2}) + >>> f(**{1:2}) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: f() keywords must be strings + TypeError: ...keywords must be strings >>> h(**{'e': 2}) Traceback (most recent call last): ... TypeError: h() got an unexpected keyword argument 'e' - >>> h(*h) + >>> h(*h) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: h() argument after * must be a sequence, not function + TypeError: ...argument after * must be a sequence, not function - >>> dir(*h) + >>> dir(*h) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: dir() argument after * must be a sequence, not function + TypeError: ...argument after * must be a sequence, not function - >>> None(*h) + >>> None(*h) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: NoneType object argument after * must be a sequence, \ -not function + TypeError: ...argument after * must be a sequence, not function - >>> h(**h) + >>> h(**h) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: h() argument after ** must be a mapping, not function + TypeError: ...argument after ** must be a mapping, not function - >>> dir(**h) + >>> dir(**h) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: dir() argument after ** must be a mapping, not function + TypeError: ...argument after ** must be a mapping, not function - >>> None(**h) + >>> None(**h) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: NoneType object argument after ** must be a mapping, \ -not function + TypeError: ...argument after ** must be a mapping, not function - >>> dir(b=1, **{'b': 1}) + >>> dir(b=1, **{'b': 1}) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: dir() got multiple values for keyword argument 'b' + TypeError: ...got multiple values for keyword argument 'b' Another helper function @@ -247,10 +245,10 @@ ... False True - >>> id(1, **{'foo': 1}) + >>> id(1, **{'foo': 1}) #doctest: +ELLIPSIS Traceback (most recent call last): ... - TypeError: id() takes no keyword arguments + TypeError: id() ... keyword argument... A corner case of keyword dictionary items being deleted during the function call setup. See . diff --git a/lib-python/2.7/test/test_fcntl.py b/lib-python/2.7/test/test_fcntl.py --- a/lib-python/2.7/test/test_fcntl.py +++ b/lib-python/2.7/test/test_fcntl.py @@ -32,7 +32,7 @@ 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8', 'bsdos2', 'bsdos3', 'bsdos4', - 'openbsd', 'openbsd2', 'openbsd3', 'openbsd4'): + 'openbsd', 'openbsd2', 'openbsd3', 'openbsd4', 'openbsd5'): if struct.calcsize('l') == 8: off_t = 'l' pid_t = 'i' diff --git a/lib-python/2.7/test/test_file.py b/lib-python/2.7/test/test_file.py --- a/lib-python/2.7/test/test_file.py +++ b/lib-python/2.7/test/test_file.py @@ -12,7 +12,7 @@ import io import _pyio as pyio -from test.test_support import TESTFN, run_unittest +from test.test_support import TESTFN, run_unittest, gc_collect from UserList import UserList class AutoFileTests(unittest.TestCase): @@ -33,6 +33,7 @@ self.assertEqual(self.f.tell(), p.tell()) self.f.close() self.f = None + gc_collect() self.assertRaises(ReferenceError, getattr, p, 'tell') def testAttributes(self): @@ -157,7 +158,12 @@ def testStdin(self): # This causes the interpreter to exit on OSF1 v5.1. if sys.platform != 'osf1V5': - self.assertRaises((IOError, ValueError), sys.stdin.seek, -1) + if sys.stdin.isatty(): + self.assertRaises((IOError, ValueError), sys.stdin.seek, -1) + else: + print(( + ' Skipping sys.stdin.seek(-1): stdin is not a tty.' + ' Test manually.'), file=sys.__stdout__) else: print(( ' Skipping sys.stdin.seek(-1), it may crash the interpreter.' diff --git a/lib-python/2.7/test/test_file2k.py b/lib-python/2.7/test/test_file2k.py --- a/lib-python/2.7/test/test_file2k.py +++ b/lib-python/2.7/test/test_file2k.py @@ -11,7 +11,7 @@ threading = None from test import test_support -from test.test_support import TESTFN, run_unittest +from test.test_support import TESTFN, run_unittest, gc_collect from UserList import UserList class AutoFileTests(unittest.TestCase): @@ -32,6 +32,7 @@ self.assertEqual(self.f.tell(), p.tell()) self.f.close() self.f = None + gc_collect() self.assertRaises(ReferenceError, getattr, p, 'tell') def testAttributes(self): @@ -116,8 +117,12 @@ for methodname in methods: method = getattr(self.f, methodname) + args = {'readinto': (bytearray(''),), + 'seek': (0,), + 'write': ('',), + }.get(methodname, ()) # should raise on closed file - self.assertRaises(ValueError, method) + self.assertRaises(ValueError, method, *args) with test_support.check_py3k_warnings(): for methodname in deprecated_methods: method = getattr(self.f, methodname) @@ -216,7 +221,12 @@ def testStdin(self): # This causes the interpreter to exit on OSF1 v5.1. if sys.platform != 'osf1V5': - self.assertRaises(IOError, sys.stdin.seek, -1) + if sys.stdin.isatty(): + self.assertRaises(IOError, sys.stdin.seek, -1) + else: + print >>sys.__stdout__, ( + ' Skipping sys.stdin.seek(-1): stdin is not a tty.' + ' Test manualy.') else: print >>sys.__stdout__, ( ' Skipping sys.stdin.seek(-1), it may crash the interpreter.' @@ -336,8 +346,9 @@ except ValueError: pass else: - self.fail("%s%r after next() didn't raise ValueError" % - (methodname, args)) + if test_support.check_impl_detail(): + self.fail("%s%r after next() didn't raise ValueError" % + (methodname, args)) f.close() # Test to see if harmless (by accident) mixing of read* and @@ -388,6 +399,7 @@ if lines != testlines: self.fail("readlines() after next() with empty buffer " "failed. Got %r, expected %r" % (line, testline)) + f.close() # Reading after iteration hit EOF shouldn't hurt either f = open(TESTFN) try: @@ -438,6 +450,9 @@ self.close_count = 0 self.close_success_count = 0 self.use_buffering = False + # to prevent running out of file descriptors on PyPy, + # we only keep the 50 most recent files open + self.all_files = [None] * 50 def tearDown(self): if self.f: @@ -453,9 +468,14 @@ def _create_file(self): if self.use_buffering: - self.f = open(self.filename, "w+", buffering=1024*16) + f = open(self.filename, "w+", buffering=1024*16) else: - self.f = open(self.filename, "w+") + f = open(self.filename, "w+") + self.f = f + self.all_files.append(f) + oldf = self.all_files.pop(0) + if oldf is not None: + oldf.close() def _close_file(self): with self._count_lock: @@ -496,7 +516,6 @@ def _test_close_open_io(self, io_func, nb_workers=5): def worker(): - self._create_file() funcs = itertools.cycle(( lambda: io_func(), lambda: self._close_and_reopen_file(), @@ -508,7 +527,11 @@ f() except (IOError, ValueError): pass + self._create_file() self._run_workers(worker, nb_workers) + # make sure that all files can be closed now + del self.all_files + gc_collect() if test_support.verbose: # Useful verbose statistics when tuning this test to take # less time to run but still ensuring that its still useful. diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py --- a/lib-python/2.7/test/test_fileio.py +++ b/lib-python/2.7/test/test_fileio.py @@ -12,6 +12,7 @@ from test.test_support import TESTFN, check_warnings, run_unittest, make_bad_fd from test.test_support import py3k_bytes as bytes +from test.test_support import gc_collect from test.script_helper import run_python from _io import FileIO as _FileIO @@ -34,6 +35,7 @@ self.assertEqual(self.f.tell(), p.tell()) self.f.close() self.f = None + gc_collect() self.assertRaises(ReferenceError, getattr, p, 'tell') def testSeekTell(self): @@ -104,8 +106,8 @@ self.assertTrue(f.closed) def testMethods(self): - methods = ['fileno', 'isatty', 'read', 'readinto', - 'seek', 'tell', 'truncate', 'write', 'seekable', + methods = ['fileno', 'isatty', 'read', + 'tell', 'truncate', 'seekable', 'readable', 'writable'] if sys.platform.startswith('atheos'): methods.remove('truncate') @@ -117,6 +119,10 @@ method = getattr(self.f, methodname) # should raise on closed file self.assertRaises(ValueError, method) + # methods with one argument + self.assertRaises(ValueError, self.f.readinto, 0) + self.assertRaises(ValueError, self.f.write, 0) + self.assertRaises(ValueError, self.f.seek, 0) def testOpendir(self): # Issue 3703: opening a directory should fill the errno @@ -312,6 +318,7 @@ self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(OSError, _FileIO, make_bad_fd()) if sys.platform == 'win32': + raise unittest.SkipTest('Set _invalid_parameter_handler for low level io') import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/lib-python/2.7/test/test_format.py b/lib-python/2.7/test/test_format.py --- a/lib-python/2.7/test/test_format.py +++ b/lib-python/2.7/test/test_format.py @@ -242,7 +242,7 @@ try: testformat(formatstr, args) except exception, exc: - if str(exc) == excmsg: + if str(exc) == excmsg or not test_support.check_impl_detail(): if verbose: print "yes" else: @@ -272,13 +272,16 @@ test_exc(u'no format', u'1', TypeError, "not all arguments converted during string formatting") - class Foobar(long): - def __oct__(self): - # Returning a non-string should not blow up. - return self + 1 - - test_exc('%o', Foobar(), TypeError, - "expected string or Unicode object, long found") + if test_support.check_impl_detail(): + # __oct__() is called if Foobar inherits from 'long', but + # not, say, 'object' or 'int' or 'str'. This seems strange + # enough to consider it a complete implementation detail. + class Foobar(long): + def __oct__(self): + # Returning a non-string should not blow up. + return self + 1 + test_exc('%o', Foobar(), TypeError, + "expected string or Unicode object, long found") if maxsize == 2**31-1: # crashes 2.2.1 and earlier: diff --git a/lib-python/2.7/test/test_funcattrs.py b/lib-python/2.7/test/test_funcattrs.py --- a/lib-python/2.7/test/test_funcattrs.py +++ b/lib-python/2.7/test/test_funcattrs.py @@ -14,6 +14,8 @@ self.b = b def cannot_set_attr(self, obj, name, value, exceptions): + if not test_support.check_impl_detail(): + exceptions = (TypeError, AttributeError) # Helper method for other tests. try: setattr(obj, name, value) @@ -286,13 +288,13 @@ def test_delete_func_dict(self): try: del self.b.__dict__ - except TypeError: + except (AttributeError, TypeError): pass else: self.fail("deleting function dictionary should raise TypeError") try: del self.b.func_dict - except TypeError: + except (AttributeError, TypeError): pass else: self.fail("deleting function dictionary should raise TypeError") diff --git a/lib-python/2.7/test/test_functools.py b/lib-python/2.7/test/test_functools.py --- a/lib-python/2.7/test/test_functools.py +++ b/lib-python/2.7/test/test_functools.py @@ -45,6 +45,8 @@ # attributes should not be writable if not isinstance(self.thetype, type): return + if not test_support.check_impl_detail(): + return self.assertRaises(TypeError, setattr, p, 'func', map) self.assertRaises(TypeError, setattr, p, 'args', (1, 2)) self.assertRaises(TypeError, setattr, p, 'keywords', dict(a=1, b=2)) @@ -136,6 +138,7 @@ p = proxy(f) self.assertEqual(f.func, p.func) f = None + test_support.gc_collect() self.assertRaises(ReferenceError, getattr, p, 'func') def test_with_bound_and_unbound_methods(self): @@ -172,7 +175,7 @@ updated=functools.WRAPPER_UPDATES): # Check attributes were assigned for name in assigned: - self.assertTrue(getattr(wrapper, name) is getattr(wrapped, name)) + self.assertTrue(getattr(wrapper, name) == getattr(wrapped, name), name) # Check attributes were updated for name in updated: wrapper_attr = getattr(wrapper, name) diff --git a/lib-python/2.7/test/test_generators.py b/lib-python/2.7/test/test_generators.py --- a/lib-python/2.7/test/test_generators.py +++ b/lib-python/2.7/test/test_generators.py @@ -190,7 +190,7 @@ File "", line 1, in ? File "", line 2, in g File "", line 2, in f - ZeroDivisionError: integer division or modulo by zero + ZeroDivisionError: integer division by zero >>> k.next() # and the generator cannot be resumed Traceback (most recent call last): File "", line 1, in ? @@ -733,14 +733,16 @@ ... yield 1 Traceback (most recent call last): .. -SyntaxError: 'return' with argument inside generator (, line 3) + File "", line 3 +SyntaxError: 'return' with argument inside generator >>> def f(): ... yield 1 ... return 22 Traceback (most recent call last): .. -SyntaxError: 'return' with argument inside generator (, line 3) + File "", line 3 +SyntaxError: 'return' with argument inside generator "return None" is not the same as "return" in a generator: @@ -749,7 +751,8 @@ ... return None Traceback (most recent call last): .. -SyntaxError: 'return' with argument inside generator (, line 3) + File "", line 3 +SyntaxError: 'return' with argument inside generator These are fine: @@ -878,7 +881,9 @@ ... if 0: ... yield 2 # because it's a generator (line 10) Traceback (most recent call last): -SyntaxError: 'return' with argument inside generator (, line 10) + ... + File "", line 10 +SyntaxError: 'return' with argument inside generator This one caused a crash (see SF bug 567538): @@ -1496,6 +1501,10 @@ """ coroutine_tests = """\ +A helper function to call gc.collect() without printing +>>> import gc +>>> def gc_collect(): gc.collect() + Sending a value into a started generator: >>> def f(): @@ -1570,13 +1579,14 @@ >>> def f(): return lambda x=(yield): 1 Traceback (most recent call last): ... -SyntaxError: 'return' with argument inside generator (, line 1) + File "", line 1 +SyntaxError: 'return' with argument inside generator >>> def f(): x = yield = y Traceback (most recent call last): ... File "", line 1 -SyntaxError: assignment to yield expression not possible +SyntaxError: can't assign to yield expression >>> def f(): (yield bar) = y Traceback (most recent call last): @@ -1665,7 +1675,7 @@ >>> f().throw("abc") # throw on just-opened generator Traceback (most recent call last): ... -TypeError: exceptions must be classes, or instances, not str +TypeError: exceptions must be old-style classes or derived from BaseException, not str Now let's try closing a generator: @@ -1697,7 +1707,7 @@ >>> g = f() >>> g.next() ->>> del g +>>> del g; gc_collect() exiting >>> class context(object): @@ -1708,7 +1718,7 @@ ... yield >>> g = f() >>> g.next() ->>> del g +>>> del g; gc_collect() exiting @@ -1721,7 +1731,7 @@ >>> g = f() >>> g.next() ->>> del g +>>> del g; gc_collect() finally @@ -1747,6 +1757,7 @@ >>> g = f() >>> g.next() >>> del g +>>> gc_collect() >>> sys.stderr.getvalue().startswith( ... "Exception RuntimeError: 'generator ignored GeneratorExit' in " ... ) @@ -1812,6 +1823,9 @@ references. We add it to the standard suite so the routine refleak-tests would trigger if it starts being uncleanable again. +>>> import gc +>>> def gc_collect(): gc.collect() + >>> import itertools >>> def leak(): ... class gen: @@ -1863,9 +1877,10 @@ ... ... l = Leaker() ... del l +... gc_collect() ... err = sys.stderr.getvalue().strip() ... err.startswith( -... "Exception RuntimeError: RuntimeError() in <" +... "Exception RuntimeError: RuntimeError() in " ... ) ... err.endswith("> ignored") ... len(err.splitlines()) diff --git a/lib-python/2.7/test/test_genexps.py b/lib-python/2.7/test/test_genexps.py --- a/lib-python/2.7/test/test_genexps.py +++ b/lib-python/2.7/test/test_genexps.py @@ -128,8 +128,9 @@ Verify re-use of tuples (a side benefit of using genexps over listcomps) + >>> from test.test_support import check_impl_detail >>> tupleids = map(id, ((i,i) for i in xrange(10))) - >>> int(max(tupleids) - min(tupleids)) + >>> int(max(tupleids) - min(tupleids)) if check_impl_detail() else 0 0 Verify that syntax error's are raised for genexps used as lvalues @@ -198,13 +199,13 @@ >>> g = (10 // i for i in (5, 0, 2)) >>> g.next() 2 - >>> g.next() + >>> g.next() # doctest: +ELLIPSIS Traceback (most recent call last): File "", line 1, in -toplevel- g.next() File "", line 1, in g = (10 // i for i in (5, 0, 2)) - ZeroDivisionError: integer division or modulo by zero + ZeroDivisionError: integer division...by zero >>> g.next() Traceback (most recent call last): File "", line 1, in -toplevel- diff --git a/lib-python/2.7/test/test_heapq.py b/lib-python/2.7/test/test_heapq.py --- a/lib-python/2.7/test/test_heapq.py +++ b/lib-python/2.7/test/test_heapq.py @@ -215,6 +215,11 @@ class TestHeapPython(TestHeap): module = py_heapq + def test_islice_protection(self): + m = self.module + self.assertFalse(m.nsmallest(-1, [1])) + self.assertFalse(m.nlargest(-1, [1])) + @skipUnless(c_heapq, 'requires _heapq') class TestHeapC(TestHeap): diff --git a/lib-python/2.7/test/test_import.py b/lib-python/2.7/test/test_import.py --- a/lib-python/2.7/test/test_import.py +++ b/lib-python/2.7/test/test_import.py @@ -7,7 +7,8 @@ import sys import unittest from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree, - is_jython, check_warnings, EnvironmentVarGuard) + is_jython, check_warnings, EnvironmentVarGuard, + impl_detail, check_impl_detail) import textwrap from test import script_helper @@ -69,7 +70,8 @@ self.assertEqual(mod.b, b, "module loaded (%s) but contents invalid" % mod) finally: - unlink(source) + if check_impl_detail(pypy=False): + unlink(source) try: imp.reload(mod) @@ -149,13 +151,16 @@ # Compile & remove .py file, we only need .pyc (or .pyo). with open(filename, 'r') as f: py_compile.compile(filename) - unlink(filename) + if check_impl_detail(pypy=False): + # pypy refuses to import a .pyc if the .py does not exist + unlink(filename) # Need to be able to load from current dir. sys.path.append('') # This used to crash. exec 'import ' + module + reload(longlist) # Cleanup. del sys.path[-1] @@ -326,6 +331,7 @@ self.assertEqual(mod.code_filename, self.file_name) self.assertEqual(mod.func_filename, self.file_name) + @impl_detail("pypy refuses to import without a .py source", pypy=False) def test_module_without_source(self): target = "another_module.py" py_compile.compile(self.file_name, dfile=target) diff --git a/lib-python/2.7/test/test_inspect.py b/lib-python/2.7/test/test_inspect.py --- a/lib-python/2.7/test/test_inspect.py +++ b/lib-python/2.7/test/test_inspect.py @@ -4,11 +4,11 @@ import unittest import inspect import linecache -import datetime from UserList import UserList from UserDict import UserDict from test.test_support import run_unittest, check_py3k_warnings +from test.test_support import check_impl_detail with check_py3k_warnings( ("tuple parameter unpacking has been removed", SyntaxWarning), @@ -74,7 +74,8 @@ def test_excluding_predicates(self): self.istest(inspect.isbuiltin, 'sys.exit') - self.istest(inspect.isbuiltin, '[].append') + if check_impl_detail(): + self.istest(inspect.isbuiltin, '[].append') self.istest(inspect.iscode, 'mod.spam.func_code') self.istest(inspect.isframe, 'tb.tb_frame') self.istest(inspect.isfunction, 'mod.spam') @@ -92,9 +93,9 @@ else: self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals)) if hasattr(types, 'MemberDescriptorType'): - self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days') + self.istest(inspect.ismemberdescriptor, 'type(lambda: None).func_globals') else: - self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days)) + self.assertFalse(inspect.ismemberdescriptor(type(lambda: None).func_globals)) def test_isroutine(self): self.assertTrue(inspect.isroutine(mod.spam)) @@ -567,7 +568,8 @@ else: self.fail('Exception not raised') self.assertIs(type(ex1), type(ex2)) - self.assertEqual(str(ex1), str(ex2)) + if check_impl_detail(): + self.assertEqual(str(ex1), str(ex2)) def makeCallable(self, signature): """Create a function that returns its locals(), excluding the diff --git a/lib-python/2.7/test/test_int.py b/lib-python/2.7/test/test_int.py --- a/lib-python/2.7/test/test_int.py +++ b/lib-python/2.7/test/test_int.py @@ -1,7 +1,7 @@ import sys import unittest -from test.test_support import run_unittest, have_unicode +from test.test_support import run_unittest, have_unicode, check_impl_detail import math L = [ @@ -392,9 +392,10 @@ try: int(TruncReturnsNonIntegral()) except TypeError as e: - self.assertEqual(str(e), - "__trunc__ returned non-Integral" - " (type NonIntegral)") + if check_impl_detail(cpython=True): + self.assertEqual(str(e), + "__trunc__ returned non-Integral" + " (type NonIntegral)") else: self.fail("Failed to raise TypeError with %s" % ((base, trunc_result_base),)) diff --git a/lib-python/2.7/test/test_io.py b/lib-python/2.7/test/test_io.py --- a/lib-python/2.7/test/test_io.py +++ b/lib-python/2.7/test/test_io.py @@ -2561,6 +2561,31 @@ """Check that a partial write, when it gets interrupted, properly invokes the signal handler, and bubbles up the exception raised in the latter.""" + + # XXX This test has three flaws that appear when objects are + # XXX not reference counted. + + # - if wio.write() happens to trigger a garbage collection, + # the signal exception may be raised when some __del__ + # method is running; it will not reach the assertRaises() + # call. + + # - more subtle, if the wio object is not destroyed at once + # and survives this function, the next opened file is likely + # to have the same fileno (since the file descriptor was + # actively closed). When wio.__del__ is finally called, it + # will close the other's test file... To trigger this with + # CPython, try adding "global wio" in this function. + + # - This happens only for streams created by the _pyio module, + # because a wio.close() that fails still consider that the + # file needs to be closed again. You can try adding an + # "assert wio.closed" at the end of the function. + + # Fortunately, a little gc.gollect() seems to be enough to + # work around all these issues. + support.gc_collect() + read_results = [] def _read(): s = os.read(r, 1) diff --git a/lib-python/2.7/test/test_isinstance.py b/lib-python/2.7/test/test_isinstance.py --- a/lib-python/2.7/test/test_isinstance.py +++ b/lib-python/2.7/test/test_isinstance.py @@ -260,7 +260,18 @@ # Make sure that calling isinstance with a deeply nested tuple for its # argument will raise RuntimeError eventually. tuple_arg = (compare_to,) - for cnt in xrange(sys.getrecursionlimit()+5): + + + if test_support.check_impl_detail(cpython=True): + RECURSION_LIMIT = sys.getrecursionlimit() + else: + # on non-CPython implementations, the maximum + # actual recursion limit might be higher, but + # probably not higher than 99999 + # + RECURSION_LIMIT = 99999 + + for cnt in xrange(RECURSION_LIMIT+5): tuple_arg = (tuple_arg,) fxn(arg, tuple_arg) diff --git a/lib-python/2.7/test/test_itertools.py b/lib-python/2.7/test/test_itertools.py --- a/lib-python/2.7/test/test_itertools.py +++ b/lib-python/2.7/test/test_itertools.py @@ -137,6 +137,8 @@ self.assertEqual(result, list(combinations2(values, r))) # matches second pure python version self.assertEqual(result, list(combinations3(values, r))) # matches second pure python version + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_combinations_tuple_reuse(self): # Test implementation detail: tuple re-use self.assertEqual(len(set(map(id, combinations('abcde', 3)))), 1) self.assertNotEqual(len(set(map(id, list(combinations('abcde', 3))))), 1) @@ -207,7 +209,10 @@ self.assertEqual(result, list(cwr1(values, r))) # matches first pure python version self.assertEqual(result, list(cwr2(values, r))) # matches second pure python version + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_combinations_with_replacement_tuple_reuse(self): # Test implementation detail: tuple re-use + cwr = combinations_with_replacement self.assertEqual(len(set(map(id, cwr('abcde', 3)))), 1) self.assertNotEqual(len(set(map(id, list(cwr('abcde', 3))))), 1) @@ -271,6 +276,8 @@ self.assertEqual(result, list(permutations(values, None))) # test r as None self.assertEqual(result, list(permutations(values))) # test default r + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_permutations_tuple_reuse(self): # Test implementation detail: tuple re-use self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1) self.assertNotEqual(len(set(map(id, list(permutations('abcde', 3))))), 1) @@ -526,6 +533,9 @@ self.assertEqual(list(izip()), zip()) self.assertRaises(TypeError, izip, 3) self.assertRaises(TypeError, izip, range(3), 3) + + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_izip_tuple_reuse(self): # Check tuple re-use (implementation detail) self.assertEqual([tuple(list(pair)) for pair in izip('abc', 'def')], zip('abc', 'def')) @@ -575,6 +585,8 @@ else: self.fail('Did not raise Type in: ' + stmt) + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_iziplongest_tuple_reuse(self): # Check tuple re-use (implementation detail) self.assertEqual([tuple(list(pair)) for pair in izip_longest('abc', 'def')], zip('abc', 'def')) @@ -683,6 +695,8 @@ args = map(iter, args) self.assertEqual(len(list(product(*args))), expected_len) + @test_support.impl_detail("tuple reuse is specific to CPython") + def test_product_tuple_reuse(self): # Test implementation detail: tuple re-use self.assertEqual(len(set(map(id, product('abc', 'def')))), 1) self.assertNotEqual(len(set(map(id, list(product('abc', 'def'))))), 1) @@ -771,11 +785,11 @@ self.assertRaises(ValueError, islice, xrange(10), 1, -5, -1) self.assertRaises(ValueError, islice, xrange(10), 1, 10, -1) self.assertRaises(ValueError, islice, xrange(10), 1, 10, 0) - self.assertRaises(ValueError, islice, xrange(10), 'a') - self.assertRaises(ValueError, islice, xrange(10), 'a', 1) - self.assertRaises(ValueError, islice, xrange(10), 1, 'a') - self.assertRaises(ValueError, islice, xrange(10), 'a', 1, 1) - self.assertRaises(ValueError, islice, xrange(10), 1, 'a', 1) + self.assertRaises((ValueError, TypeError), islice, xrange(10), 'a') + self.assertRaises((ValueError, TypeError), islice, xrange(10), 'a', 1) + self.assertRaises((ValueError, TypeError), islice, xrange(10), 1, 'a') + self.assertRaises((ValueError, TypeError), islice, xrange(10), 'a', 1, 1) + self.assertRaises((ValueError, TypeError), islice, xrange(10), 1, 'a', 1) self.assertEqual(len(list(islice(count(), 1, 10, maxsize))), 1) # Issue #10323: Less islice in a predictable state @@ -855,9 +869,17 @@ self.assertRaises(TypeError, tee, [1,2], 3, 'x') # tee object should be instantiable - a, b = tee('abc') - c = type(a)('def') - self.assertEqual(list(c), list('def')) + if test_support.check_impl_detail(): + # XXX I (arigo) would argue that 'type(a)(iterable)' has + # ill-defined semantics: it always return a fresh tee object, + # but depending on whether 'iterable' is itself a tee object + # or not, it is ok or not to continue using 'iterable' after + # the call. I cannot imagine why 'type(a)(non_tee_object)' + # would be useful, as 'iter(non_tee_obect)' is equivalent + # as far as I can see. + a, b = tee('abc') + c = type(a)('def') + self.assertEqual(list(c), list('def')) # test long-lagged and multi-way split a, b, c = tee(xrange(2000), 3) @@ -895,6 +917,7 @@ p = proxy(a) self.assertEqual(getattr(p, '__class__'), type(b)) del a + test_support.gc_collect() self.assertRaises(ReferenceError, getattr, p, '__class__') def test_StopIteration(self): @@ -1317,6 +1340,7 @@ class LengthTransparency(unittest.TestCase): + @test_support.impl_detail("__length_hint__() API is undocumented") def test_repeat(self): from test.test_iterlen import len self.assertEqual(len(repeat(None, 50)), 50) diff --git a/lib-python/2.7/test/test_linecache.py b/lib-python/2.7/test/test_linecache.py --- a/lib-python/2.7/test/test_linecache.py +++ b/lib-python/2.7/test/test_linecache.py @@ -54,13 +54,13 @@ # Check whether lines correspond to those from file iteration for entry in TESTS: - filename = os.path.join(TEST_PATH, entry) + '.py' + filename = support.findfile( entry + '.py') for index, line in enumerate(open(filename)): self.assertEqual(line, getline(filename, index + 1)) # Check module loading for entry in MODULES: - filename = os.path.join(MODULE_PATH, entry) + '.py' + filename = support.findfile( entry + '.py') for index, line in enumerate(open(filename)): self.assertEqual(line, getline(filename, index + 1)) @@ -78,7 +78,7 @@ def test_clearcache(self): cached = [] for entry in TESTS: - filename = os.path.join(TEST_PATH, entry) + '.py' + filename = support.findfile( entry + '.py') cached.append(filename) linecache.getline(filename, 1) diff --git a/lib-python/2.7/test/test_list.py b/lib-python/2.7/test/test_list.py --- a/lib-python/2.7/test/test_list.py +++ b/lib-python/2.7/test/test_list.py @@ -15,6 +15,10 @@ self.assertEqual(list(''), []) self.assertEqual(list('spam'), ['s', 'p', 'a', 'm']) + # the following test also works with pypy, but eats all your address + # space's RAM before raising and takes too long. + @test_support.impl_detail("eats all your RAM before working", pypy=False) + def test_segfault_1(self): if sys.maxsize == 0x7fffffff: # This test can currently only work on 32-bit machines. # XXX If/when PySequence_Length() returns a ssize_t, it should be @@ -32,6 +36,7 @@ # http://sources.redhat.com/ml/newlib/2002/msg00369.html self.assertRaises(MemoryError, list, xrange(sys.maxint // 2)) + def test_segfault_2(self): # This code used to segfault in Py2.4a3 x = [] x.extend(-y for y in x) diff --git a/lib-python/2.7/test/test_long.py b/lib-python/2.7/test/test_long.py --- a/lib-python/2.7/test/test_long.py +++ b/lib-python/2.7/test/test_long.py @@ -530,9 +530,10 @@ try: long(TruncReturnsNonIntegral()) except TypeError as e: - self.assertEqual(str(e), - "__trunc__ returned non-Integral" - " (type NonIntegral)") + if test_support.check_impl_detail(cpython=True): + self.assertEqual(str(e), + "__trunc__ returned non-Integral" + " (type NonIntegral)") else: self.fail("Failed to raise TypeError with %s" % ((base, trunc_result_base),)) diff --git a/lib-python/2.7/test/test_marshal.py b/lib-python/2.7/test/test_marshal.py --- a/lib-python/2.7/test/test_marshal.py +++ b/lib-python/2.7/test/test_marshal.py @@ -7,20 +7,31 @@ import unittest import os -class IntTestCase(unittest.TestCase): +class HelperMixin: + def helper(self, sample, *extra, **kwargs): + expected = kwargs.get('expected', sample) + new = marshal.loads(marshal.dumps(sample, *extra)) + self.assertEqual(expected, new) + self.assertEqual(type(expected), type(new)) + try: + with open(test_support.TESTFN, "wb") as f: + marshal.dump(sample, f, *extra) + with open(test_support.TESTFN, "rb") as f: + new = marshal.load(f) + self.assertEqual(expected, new) + self.assertEqual(type(expected), type(new)) + finally: + test_support.unlink(test_support.TESTFN) + + +class IntTestCase(unittest.TestCase, HelperMixin): def test_ints(self): # Test the full range of Python ints. n = sys.maxint while n: for expected in (-n, n): - s = marshal.dumps(expected) - got = marshal.loads(s) - self.assertEqual(expected, got) - marshal.dump(expected, file(test_support.TESTFN, "wb")) - got = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(expected, got) + self.helper(expected) n = n >> 1 - os.unlink(test_support.TESTFN) def test_int64(self): # Simulate int marshaling on a 64-bit box. This is most interesting if @@ -48,28 +59,16 @@ def test_bool(self): for b in (True, False): - new = marshal.loads(marshal.dumps(b)) - self.assertEqual(b, new) - self.assertEqual(type(b), type(new)) - marshal.dump(b, file(test_support.TESTFN, "wb")) - new = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(b, new) - self.assertEqual(type(b), type(new)) + self.helper(b) -class FloatTestCase(unittest.TestCase): +class FloatTestCase(unittest.TestCase, HelperMixin): def test_floats(self): # Test a few floats small = 1e-25 n = sys.maxint * 3.7e250 while n > small: for expected in (-n, n): - f = float(expected) - s = marshal.dumps(f) - got = marshal.loads(s) - self.assertEqual(f, got) - marshal.dump(f, file(test_support.TESTFN, "wb")) - got = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(f, got) + self.helper(expected) n /= 123.4567 f = 0.0 @@ -85,59 +84,25 @@ while n < small: for expected in (-n, n): f = float(expected) + self.helper(f) + self.helper(f, 1) + n *= 123.4567 - s = marshal.dumps(f) - got = marshal.loads(s) - self.assertEqual(f, got) - - s = marshal.dumps(f, 1) - got = marshal.loads(s) - self.assertEqual(f, got) - - marshal.dump(f, file(test_support.TESTFN, "wb")) - got = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(f, got) - - marshal.dump(f, file(test_support.TESTFN, "wb"), 1) - got = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(f, got) - n *= 123.4567 - os.unlink(test_support.TESTFN) - -class StringTestCase(unittest.TestCase): +class StringTestCase(unittest.TestCase, HelperMixin): def test_unicode(self): for s in [u"", u"Andr� Previn", u"abc", u" "*10000]: - new = marshal.loads(marshal.dumps(s)) - self.assertEqual(s, new) - self.assertEqual(type(s), type(new)) - marshal.dump(s, file(test_support.TESTFN, "wb")) - new = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(s, new) - self.assertEqual(type(s), type(new)) - os.unlink(test_support.TESTFN) + self.helper(s) def test_string(self): for s in ["", "Andr� Previn", "abc", " "*10000]: - new = marshal.loads(marshal.dumps(s)) - self.assertEqual(s, new) - self.assertEqual(type(s), type(new)) - marshal.dump(s, file(test_support.TESTFN, "wb")) - new = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(s, new) - self.assertEqual(type(s), type(new)) - os.unlink(test_support.TESTFN) + self.helper(s) def test_buffer(self): for s in ["", "Andr� Previn", "abc", " "*10000]: with test_support.check_py3k_warnings(("buffer.. not supported", DeprecationWarning)): b = buffer(s) - new = marshal.loads(marshal.dumps(b)) - self.assertEqual(s, new) - marshal.dump(b, file(test_support.TESTFN, "wb")) - new = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(s, new) - os.unlink(test_support.TESTFN) + self.helper(b, expected=s) class ExceptionTestCase(unittest.TestCase): def test_exceptions(self): @@ -150,7 +115,7 @@ new = marshal.loads(marshal.dumps(co)) self.assertEqual(co, new) -class ContainerTestCase(unittest.TestCase): +class ContainerTestCase(unittest.TestCase, HelperMixin): d = {'astring': 'foo at bar.baz.spam', 'afloat': 7283.43, 'anint': 2**20, @@ -161,42 +126,20 @@ 'aunicode': u"Andr� Previn" } def test_dict(self): - new = marshal.loads(marshal.dumps(self.d)) - self.assertEqual(self.d, new) - marshal.dump(self.d, file(test_support.TESTFN, "wb")) - new = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(self.d, new) - os.unlink(test_support.TESTFN) + self.helper(self.d) def test_list(self): lst = self.d.items() - new = marshal.loads(marshal.dumps(lst)) - self.assertEqual(lst, new) - marshal.dump(lst, file(test_support.TESTFN, "wb")) - new = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(lst, new) - os.unlink(test_support.TESTFN) + self.helper(lst) def test_tuple(self): t = tuple(self.d.keys()) - new = marshal.loads(marshal.dumps(t)) - self.assertEqual(t, new) - marshal.dump(t, file(test_support.TESTFN, "wb")) - new = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(t, new) - os.unlink(test_support.TESTFN) + self.helper(t) def test_sets(self): for constructor in (set, frozenset): t = constructor(self.d.keys()) - new = marshal.loads(marshal.dumps(t)) - self.assertEqual(t, new) - self.assertTrue(isinstance(new, constructor)) - self.assertNotEqual(id(t), id(new)) - marshal.dump(t, file(test_support.TESTFN, "wb")) - new = marshal.load(file(test_support.TESTFN, "rb")) - self.assertEqual(t, new) - os.unlink(test_support.TESTFN) + self.helper(t) class BugsTestCase(unittest.TestCase): def test_bug_5888452(self): @@ -226,6 +169,7 @@ s = 'c' + ('X' * 4*4) + '{' * 2**20 self.assertRaises(ValueError, marshal.loads, s) + @test_support.impl_detail('specific recursion check') def test_recursion_limit(self): # Create a deeply nested structure. head = last = [] diff --git a/lib-python/2.7/test/test_memoryio.py b/lib-python/2.7/test/test_memoryio.py --- a/lib-python/2.7/test/test_memoryio.py +++ b/lib-python/2.7/test/test_memoryio.py @@ -617,7 +617,7 @@ state = memio.__getstate__() self.assertEqual(len(state), 3) bytearray(state[0]) # Check if state[0] supports the buffer interface. - self.assertIsInstance(state[1], int) + self.assertIsInstance(state[1], (int, long)) self.assertTrue(isinstance(state[2], dict) or state[2] is None) memio.close() self.assertRaises(ValueError, memio.__getstate__) diff --git a/lib-python/2.7/test/test_memoryview.py b/lib-python/2.7/test/test_memoryview.py --- a/lib-python/2.7/test/test_memoryview.py +++ b/lib-python/2.7/test/test_memoryview.py @@ -26,7 +26,8 @@ def check_getitem_with_type(self, tp): item = self.getitem_type b = tp(self._source) - oldrefcount = sys.getrefcount(b) + if hasattr(sys, 'getrefcount'): + oldrefcount = sys.getrefcount(b) m = self._view(b) self.assertEqual(m[0], item(b"a")) self.assertIsInstance(m[0], bytes) @@ -43,7 +44,8 @@ self.assertRaises(TypeError, lambda: m[0.0]) self.assertRaises(TypeError, lambda: m["a"]) m = None - self.assertEqual(sys.getrefcount(b), oldrefcount) + if hasattr(sys, 'getrefcount'): + self.assertEqual(sys.getrefcount(b), oldrefcount) def test_getitem(self): for tp in self._types: @@ -65,7 +67,8 @@ if not self.ro_type: return b = self.ro_type(self._source) - oldrefcount = sys.getrefcount(b) + if hasattr(sys, 'getrefcount'): + oldrefcount = sys.getrefcount(b) m = self._view(b) def setitem(value): m[0] = value @@ -73,14 +76,16 @@ self.assertRaises(TypeError, setitem, 65) self.assertRaises(TypeError, setitem, memoryview(b"a")) m = None - self.assertEqual(sys.getrefcount(b), oldrefcount) + if hasattr(sys, 'getrefcount'): + self.assertEqual(sys.getrefcount(b), oldrefcount) def test_setitem_writable(self): if not self.rw_type: return tp = self.rw_type b = self.rw_type(self._source) - oldrefcount = sys.getrefcount(b) + if hasattr(sys, 'getrefcount'): + oldrefcount = sys.getrefcount(b) m = self._view(b) m[0] = tp(b"0") self._check_contents(tp, b, b"0bcdef") @@ -110,13 +115,14 @@ self.assertRaises(TypeError, setitem, (0,), b"a") self.assertRaises(TypeError, setitem, "a", b"a") # Trying to resize the memory object - self.assertRaises(ValueError, setitem, 0, b"") - self.assertRaises(ValueError, setitem, 0, b"ab") + self.assertRaises((ValueError, TypeError), setitem, 0, b"") + self.assertRaises((ValueError, TypeError), setitem, 0, b"ab") self.assertRaises(ValueError, setitem, slice(1,1), b"a") self.assertRaises(ValueError, setitem, slice(0,2), b"a") m = None - self.assertEqual(sys.getrefcount(b), oldrefcount) + if hasattr(sys, 'getrefcount'): + self.assertEqual(sys.getrefcount(b), oldrefcount) def test_delitem(self): for tp in self._types: @@ -292,6 +298,7 @@ def _check_contents(self, tp, obj, contents): self.assertEqual(obj[1:7], tp(contents)) + @unittest.skipUnless(hasattr(sys, 'getrefcount'), "Reference counting") def test_refs(self): for tp in self._types: m = memoryview(tp(self._source)) diff --git a/lib-python/2.7/test/test_mmap.py b/lib-python/2.7/test/test_mmap.py --- a/lib-python/2.7/test/test_mmap.py +++ b/lib-python/2.7/test/test_mmap.py @@ -119,7 +119,8 @@ def test_access_parameter(self): # Test for "access" keyword parameter mapsize = 10 - open(TESTFN, "wb").write("a"*mapsize) + with open(TESTFN, "wb") as f: + f.write("a"*mapsize) f = open(TESTFN, "rb") m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ) self.assertEqual(m[:], 'a'*mapsize, "Readonly memory map data incorrect.") @@ -168,9 +169,11 @@ else: self.fail("Able to resize readonly memory map") f.close() + m.close() del m, f - self.assertEqual(open(TESTFN, "rb").read(), 'a'*mapsize, - "Readonly memory map data file was modified") + with open(TESTFN, "rb") as f: + self.assertEqual(f.read(), 'a'*mapsize, + "Readonly memory map data file was modified") # Opening mmap with size too big import sys @@ -220,11 +223,13 @@ self.assertEqual(m[:], 'd' * mapsize, "Copy-on-write memory map data not written correctly.") m.flush() - self.assertEqual(open(TESTFN, "rb").read(), 'c'*mapsize, - "Copy-on-write test data file should not be modified.") + f.close() + with open(TESTFN, "rb") as f: + self.assertEqual(f.read(), 'c'*mapsize, + "Copy-on-write test data file should not be modified.") # Ensuring copy-on-write maps cannot be resized self.assertRaises(TypeError, m.resize, 2*mapsize) - f.close() + m.close() del m, f # Ensuring invalid access parameter raises exception @@ -287,6 +292,7 @@ self.assertEqual(m.find('one', 1), 8) self.assertEqual(m.find('one', 1, -1), 8) self.assertEqual(m.find('one', 1, -2), -1) + m.close() def test_rfind(self): @@ -305,6 +311,7 @@ self.assertEqual(m.rfind('one', 0, -2), 0) self.assertEqual(m.rfind('one', 1, -1), 8) self.assertEqual(m.rfind('one', 1, -2), -1) + m.close() def test_double_close(self): @@ -533,7 +540,8 @@ if not hasattr(mmap, 'PROT_READ'): return mapsize = 10 - open(TESTFN, "wb").write("a"*mapsize) + with open(TESTFN, "wb") as f: + f.write("a"*mapsize) f = open(TESTFN, "rb") m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ) self.assertRaises(TypeError, m.write, "foo") @@ -545,7 +553,8 @@ def test_io_methods(self): data = "0123456789" - open(TESTFN, "wb").write("x"*len(data)) + with open(TESTFN, "wb") as f: + f.write("x"*len(data)) f = open(TESTFN, "r+b") m = mmap.mmap(f.fileno(), len(data)) f.close() @@ -574,6 +583,7 @@ self.assertEqual(m[:], "012bar6789") m.seek(8) self.assertRaises(ValueError, m.write, "bar") + m.close() if os.name == 'nt': def test_tagname(self): @@ -611,7 +621,8 @@ m.close() # Should not crash (Issue 5385) - open(TESTFN, "wb").write("x"*10) + with open(TESTFN, "wb") as f: + f.write("x"*10) f = open(TESTFN, "r+b") m = mmap.mmap(f.fileno(), 0) f.close() diff --git a/lib-python/2.7/test/test_module.py b/lib-python/2.7/test/test_module.py --- a/lib-python/2.7/test/test_module.py +++ b/lib-python/2.7/test/test_module.py @@ -1,6 +1,6 @@ # Test the module type import unittest -from test.test_support import run_unittest, gc_collect +from test.test_support import run_unittest, gc_collect, check_impl_detail import sys ModuleType = type(sys) @@ -10,8 +10,10 @@ # An uninitialized module has no __dict__ or __name__, # and __doc__ is None foo = ModuleType.__new__(ModuleType) - self.assertTrue(foo.__dict__ is None) - self.assertRaises(SystemError, dir, foo) + self.assertFalse(foo.__dict__) + if check_impl_detail(): + self.assertTrue(foo.__dict__ is None) + self.assertRaises(SystemError, dir, foo) try: s = foo.__name__ self.fail("__name__ = %s" % repr(s)) diff --git a/lib-python/2.7/test/test_multibytecodec.py b/lib-python/2.7/test/test_multibytecodec.py --- a/lib-python/2.7/test/test_multibytecodec.py +++ b/lib-python/2.7/test/test_multibytecodec.py @@ -42,7 +42,7 @@ dec = codecs.getdecoder('euc-kr') myreplace = lambda exc: (u'', sys.maxint+1) codecs.register_error('test.cjktest', myreplace) - self.assertRaises(IndexError, dec, + self.assertRaises((IndexError, OverflowError), dec, 'apple\x92ham\x93spam', 'test.cjktest') def test_codingspec(self): @@ -148,7 +148,8 @@ class Test_StreamReader(unittest.TestCase): def test_bug1728403(self): try: - open(TESTFN, 'w').write('\xa1') + with open(TESTFN, 'w') as f: + f.write('\xa1') f = codecs.open(TESTFN, encoding='cp949') self.assertRaises(UnicodeDecodeError, f.read, 2) finally: diff --git a/lib-python/2.7/test/test_multibytecodec_support.py b/lib-python/2.7/test/test_multibytecodec_support.py --- a/lib-python/2.7/test/test_multibytecodec_support.py +++ b/lib-python/2.7/test/test_multibytecodec_support.py @@ -110,8 +110,8 @@ def myreplace(exc): return (u'x', sys.maxint + 1) codecs.register_error("test.cjktest", myreplace) - self.assertRaises(IndexError, self.encode, self.unmappedunicode, - 'test.cjktest') + self.assertRaises((IndexError, OverflowError), self.encode, + self.unmappedunicode, 'test.cjktest') def test_callback_None_index(self): def myreplace(exc): @@ -330,7 +330,7 @@ repr(csetch), repr(unich), exc.reason)) def load_teststring(name): - dir = os.path.join(os.path.dirname(__file__), 'cjkencodings') + dir = test_support.findfile('cjkencodings') with open(os.path.join(dir, name + '.txt'), 'rb') as f: encoded = f.read() with open(os.path.join(dir, name + '-utf8.txt'), 'rb') as f: diff --git a/lib-python/2.7/test/test_multiprocessing.py b/lib-python/2.7/test/test_multiprocessing.py --- a/lib-python/2.7/test/test_multiprocessing.py +++ b/lib-python/2.7/test/test_multiprocessing.py @@ -1316,6 +1316,7 @@ queue = manager.get_queue() self.assertEqual(queue.get(), 'hello world') del queue + test_support.gc_collect() manager.shutdown() manager = QueueManager( address=addr, authkey=authkey, serializer=SERIALIZER) @@ -1605,6 +1606,10 @@ if len(blocks) > maxblocks: i = random.randrange(maxblocks) del blocks[i] + # XXX There should be a better way to release resources for a + # single block + if i % maxblocks == 0: + import gc; gc.collect() # get the heap object heap = multiprocessing.heap.BufferWrapper._heap @@ -1704,6 +1709,7 @@ a = Foo() util.Finalize(a, conn.send, args=('a',)) del a # triggers callback for a + test_support.gc_collect() b = Foo() close_b = util.Finalize(b, conn.send, args=('b',)) diff --git a/lib-python/2.7/test/test_mutants.py b/lib-python/2.7/test/test_mutants.py --- a/lib-python/2.7/test/test_mutants.py +++ b/lib-python/2.7/test/test_mutants.py @@ -1,4 +1,4 @@ -from test.test_support import verbose, TESTFN +from test.test_support import verbose, TESTFN, check_impl_detail import random import os @@ -137,10 +137,16 @@ while dict1 and len(dict1) == len(dict2): if verbose: print ".", - if random.random() < 0.5: - c = cmp(dict1, dict2) - else: - c = dict1 == dict2 + try: + if random.random() < 0.5: + c = cmp(dict1, dict2) + else: + c = dict1 == dict2 + except RuntimeError: + # CPython never raises RuntimeError here, but other implementations + # might, and it's fine. + if check_impl_detail(cpython=True): + raise if verbose: print diff --git a/lib-python/2.7/test/test_optparse.py b/lib-python/2.7/test/test_optparse.py --- a/lib-python/2.7/test/test_optparse.py +++ b/lib-python/2.7/test/test_optparse.py @@ -383,6 +383,7 @@ self.assertRaises(self.parser.remove_option, ('foo',), None, ValueError, "no such option 'foo'") + @test_support.impl_detail("sys.getrefcount") def test_refleak(self): # If an OptionParser is carrying around a reference to a large # object, various cycles can prevent it from being GC'd in diff --git a/lib-python/2.7/test/test_os.py b/lib-python/2.7/test/test_os.py --- a/lib-python/2.7/test/test_os.py +++ b/lib-python/2.7/test/test_os.py @@ -690,7 +690,8 @@ class PosixUidGidTests(unittest.TestCase): pass - at unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + at unittest.skipUnless(sys.platform == "win32" and hasattr(os,'kill'), + "Win32 specific tests") class Win32KillTests(unittest.TestCase): def _kill(self, sig): # Start sys.executable as a subprocess and communicate from the diff --git a/lib-python/2.7/test/test_peepholer.py b/lib-python/2.7/test/test_peepholer.py --- a/lib-python/2.7/test/test_peepholer.py +++ b/lib-python/2.7/test/test_peepholer.py @@ -41,7 +41,7 @@ def test_none_as_constant(self): # LOAD_GLOBAL None --> LOAD_CONST None def f(x): - None + y = None return x asm = disassemble(f) for elem in ('LOAD_GLOBAL',): @@ -67,10 +67,13 @@ self.assertIn(elem, asm) def test_pack_unpack(self): + # On PyPy, "a, b = ..." is even more optimized, by removing + # the ROT_TWO. But the ROT_TWO is not removed if assigning + # to more complex expressions, so check that. for line, elem in ( ('a, = a,', 'LOAD_CONST',), - ('a, b = a, b', 'ROT_TWO',), - ('a, b, c = a, b, c', 'ROT_THREE',), + ('a[1], b = a, b', 'ROT_TWO',), + ('a, b[2], c = a, b, c', 'ROT_THREE',), ): asm = dis_single(line) self.assertIn(elem, asm) @@ -78,6 +81,8 @@ self.assertNotIn('UNPACK_TUPLE', asm) def test_folding_of_tuples_of_constants(self): + # On CPython, "a,b,c=1,2,3" turns into "a,b,c=" + # but on PyPy, it turns into "a=1;b=2;c=3". for line, elem in ( ('a = 1,2,3', '((1, 2, 3))'), ('("a","b","c")', "(('a', 'b', 'c'))"), @@ -86,7 +91,8 @@ ('((1, 2), 3, 4)', '(((1, 2), 3, 4))'), ): asm = dis_single(line) - self.assertIn(elem, asm) + self.assert_(elem in asm or ( + line == 'a,b,c = 1,2,3' and 'UNPACK_TUPLE' not in asm)) self.assertNotIn('BUILD_TUPLE', asm) # Bug 1053819: Tuple of constants misidentified when presented with: @@ -139,12 +145,15 @@ def test_binary_subscr_on_unicode(self): # valid code get optimized - asm = dis_single('u"foo"[0]') - self.assertIn("(u'f')", asm) - self.assertNotIn('BINARY_SUBSCR', asm) - asm = dis_single('u"\u0061\uffff"[1]') - self.assertIn("(u'\\uffff')", asm) - self.assertNotIn('BINARY_SUBSCR', asm) + # XXX for now we always disable this optimization + # XXX see CPython's issue5057 + if 0: + asm = dis_single('u"foo"[0]') + self.assertIn("(u'f')", asm) + self.assertNotIn('BINARY_SUBSCR', asm) + asm = dis_single('u"\u0061\uffff"[1]') + self.assertIn("(u'\\uffff')", asm) + self.assertNotIn('BINARY_SUBSCR', asm) # invalid code doesn't get optimized # out of range diff --git a/lib-python/2.7/test/test_pprint.py b/lib-python/2.7/test/test_pprint.py --- a/lib-python/2.7/test/test_pprint.py +++ b/lib-python/2.7/test/test_pprint.py @@ -233,7 +233,16 @@ frozenset([0, 2]), frozenset([0, 1])])}""" cube = test.test_set.cube(3) - self.assertEqual(pprint.pformat(cube), cube_repr_tgt) + # XXX issues of dictionary order, and for the case below, + # order of items in the frozenset([...]) representation. + # Whether we get precisely cube_repr_tgt or not is open + # to implementation-dependent choices (this test probably + # fails horribly in CPython if we tweak the dict order too). + got = pprint.pformat(cube) + if test.test_support.check_impl_detail(cpython=True): + self.assertEqual(got, cube_repr_tgt) + else: + self.assertEqual(eval(got), cube) cubo_repr_tgt = """\ {frozenset([frozenset([0, 2]), frozenset([0])]): frozenset([frozenset([frozenset([0, 2]), @@ -393,7 +402,11 @@ 2])])])}""" cubo = test.test_set.linegraph(cube) - self.assertEqual(pprint.pformat(cubo), cubo_repr_tgt) + got = pprint.pformat(cubo) + if test.test_support.check_impl_detail(cpython=True): + self.assertEqual(got, cubo_repr_tgt) + else: + self.assertEqual(eval(got), cubo) def test_depth(self): nested_tuple = (1, (2, (3, (4, (5, 6))))) diff --git a/lib-python/2.7/test/test_pydoc.py b/lib-python/2.7/test/test_pydoc.py --- a/lib-python/2.7/test/test_pydoc.py +++ b/lib-python/2.7/test/test_pydoc.py @@ -267,8 +267,8 @@ testpairs = ( ('i_am_not_here', 'i_am_not_here'), ('test.i_am_not_here_either', 'i_am_not_here_either'), - ('test.i_am_not_here.neither_am_i', 'i_am_not_here.neither_am_i'), - ('i_am_not_here.{}'.format(modname), 'i_am_not_here.{}'.format(modname)), + ('test.i_am_not_here.neither_am_i', 'i_am_not_here'), + ('i_am_not_here.{}'.format(modname), 'i_am_not_here'), ('test.{}'.format(modname), modname), ) @@ -292,8 +292,8 @@ result = run_pydoc(modname) finally: forget(modname) - expected = badimport_pattern % (modname, expectedinmsg) - self.assertEqual(expected, result) + expected = badimport_pattern % (modname, '(.+\\.)?' + expectedinmsg + '(\\..+)?$') + self.assertTrue(re.match(expected, result)) def test_input_strip(self): missing_module = " test.i_am_not_here " diff --git a/lib-python/2.7/test/test_pyexpat.py b/lib-python/2.7/test/test_pyexpat.py --- a/lib-python/2.7/test/test_pyexpat.py +++ b/lib-python/2.7/test/test_pyexpat.py @@ -570,6 +570,9 @@ self.assertEqual(self.n, 4) class MalformedInputText(unittest.TestCase): + # CPython seems to ship its own version of expat, they fixed it on this commit : + # http://svn.python.org/view?revision=74429&view=revision + @unittest.skipIf(sys.platform == "darwin", "Expat is broken on Mac OS X 10.6.6") def test1(self): xml = "\0\r\n" parser = expat.ParserCreate() @@ -579,6 +582,7 @@ except expat.ExpatError as e: self.assertEqual(str(e), 'unclosed token: line 2, column 0') + @unittest.skipIf(sys.platform == "darwin", "Expat is broken on Mac OS X 10.6.6") def test2(self): xml = "\r\n" parser = expat.ParserCreate() diff --git a/lib-python/2.7/test/test_repr.py b/lib-python/2.7/test/test_repr.py --- a/lib-python/2.7/test/test_repr.py +++ b/lib-python/2.7/test/test_repr.py @@ -9,6 +9,7 @@ import unittest from test.test_support import run_unittest, check_py3k_warnings +from test.test_support import check_impl_detail from repr import repr as r # Don't shadow builtin repr from repr import Repr @@ -145,8 +146,11 @@ # Functions eq(repr(hash), '') # Methods - self.assertTrue(repr(''.split).startswith( - '") def test_xrange(self): eq = self.assertEqual @@ -185,7 +189,10 @@ def test_descriptors(self): eq = self.assertEqual # method descriptors - eq(repr(dict.items), "") + if check_impl_detail(cpython=True): + eq(repr(dict.items), "") + elif check_impl_detail(pypy=True): + eq(repr(dict.items), "") # XXX member descriptors # XXX attribute descriptors # XXX slot descriptors @@ -247,8 +254,14 @@ eq = self.assertEqual touch(os.path.join(self.subpkgname, self.pkgname + os.extsep + 'py')) from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation - eq(repr(areallylongpackageandmodulenametotestreprtruncation), - "" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__)) + # On PyPy, we use %r to format the file name; on CPython it is done + # with '%s'. It seems to me that %r is safer . + if '__pypy__' in sys.builtin_module_names: + eq(repr(areallylongpackageandmodulenametotestreprtruncation), + "" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__)) + else: + eq(repr(areallylongpackageandmodulenametotestreprtruncation), + "" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__)) eq(repr(sys), "") def test_type(self): diff --git a/lib-python/2.7/test/test_runpy.py b/lib-python/2.7/test/test_runpy.py --- a/lib-python/2.7/test/test_runpy.py +++ b/lib-python/2.7/test/test_runpy.py @@ -5,10 +5,15 @@ import sys import re import tempfile -from test.test_support import verbose, run_unittest, forget +from test.test_support import verbose, run_unittest, forget, check_impl_detail from test.script_helper import (temp_dir, make_script, compile_script, make_pkg, make_zip_script, make_zip_pkg) +if check_impl_detail(pypy=True): + no_lone_pyc_file = True +else: + no_lone_pyc_file = False + from runpy import _run_code, _run_module_code, run_module, run_path # Note: This module can't safely test _run_module_as_main as it @@ -168,13 +173,14 @@ self.assertIn("x", d1) self.assertTrue(d1["x"] == 1) del d1 # Ensure __loader__ entry doesn't keep file open - __import__(mod_name) - os.remove(mod_fname) - if verbose: print "Running from compiled:", mod_name - d2 = run_module(mod_name) # Read from bytecode - self.assertIn("x", d2) - self.assertTrue(d2["x"] == 1) - del d2 # Ensure __loader__ entry doesn't keep file open + if not no_lone_pyc_file: + __import__(mod_name) + os.remove(mod_fname) + if verbose: print "Running from compiled:", mod_name + d2 = run_module(mod_name) # Read from bytecode + self.assertIn("x", d2) + self.assertTrue(d2["x"] == 1) + del d2 # Ensure __loader__ entry doesn't keep file open finally: self._del_pkg(pkg_dir, depth, mod_name) if verbose: print "Module executed successfully" @@ -190,13 +196,14 @@ self.assertIn("x", d1) self.assertTrue(d1["x"] == 1) del d1 # Ensure __loader__ entry doesn't keep file open - __import__(mod_name) - os.remove(mod_fname) - if verbose: print "Running from compiled:", pkg_name - d2 = run_module(pkg_name) # Read from bytecode - self.assertIn("x", d2) - self.assertTrue(d2["x"] == 1) - del d2 # Ensure __loader__ entry doesn't keep file open + if not no_lone_pyc_file: + __import__(mod_name) + os.remove(mod_fname) + if verbose: print "Running from compiled:", pkg_name + d2 = run_module(pkg_name) # Read from bytecode + self.assertIn("x", d2) + self.assertTrue(d2["x"] == 1) + del d2 # Ensure __loader__ entry doesn't keep file open finally: self._del_pkg(pkg_dir, depth, pkg_name) if verbose: print "Package executed successfully" @@ -244,15 +251,17 @@ self.assertIn("sibling", d1) self.assertIn("nephew", d1) del d1 # Ensure __loader__ entry doesn't keep file open - __import__(mod_name) - os.remove(mod_fname) - if verbose: print "Running from compiled:", mod_name - d2 = run_module(mod_name, run_name=run_name) # Read from bytecode - self.assertIn("__package__", d2) - self.assertTrue(d2["__package__"] == pkg_name) - self.assertIn("sibling", d2) - self.assertIn("nephew", d2) - del d2 # Ensure __loader__ entry doesn't keep file open + if not no_lone_pyc_file: + __import__(mod_name) + os.remove(mod_fname) + if verbose: print "Running from compiled:", mod_name + # Read from bytecode + d2 = run_module(mod_name, run_name=run_name) + self.assertIn("__package__", d2) + self.assertTrue(d2["__package__"] == pkg_name) + self.assertIn("sibling", d2) + self.assertIn("nephew", d2) + del d2 # Ensure __loader__ entry doesn't keep file open finally: self._del_pkg(pkg_dir, depth, mod_name) if verbose: print "Module executed successfully" @@ -345,6 +354,8 @@ script_dir, '') def test_directory_compiled(self): + if no_lone_pyc_file: + return with temp_dir() as script_dir: mod_name = '__main__' script_name = self._make_test_script(script_dir, mod_name) diff --git a/lib-python/2.7/test/test_scope.py b/lib-python/2.7/test/test_scope.py --- a/lib-python/2.7/test/test_scope.py +++ b/lib-python/2.7/test/test_scope.py @@ -1,6 +1,6 @@ import unittest from test.test_support import check_syntax_error, check_py3k_warnings, \ - check_warnings, run_unittest + check_warnings, run_unittest, gc_collect class ScopeTests(unittest.TestCase): @@ -432,6 +432,7 @@ for i in range(100): f1() + gc_collect() self.assertEqual(Foo.count, 0) diff --git a/lib-python/2.7/test/test_set.py b/lib-python/2.7/test/test_set.py --- a/lib-python/2.7/test/test_set.py +++ b/lib-python/2.7/test/test_set.py @@ -309,6 +309,7 @@ fo.close() test_support.unlink(test_support.TESTFN) + @test_support.impl_detail(pypy=False) def test_do_not_rehash_dict_keys(self): n = 10 d = dict.fromkeys(map(HashCountingInt, xrange(n))) @@ -559,6 +560,7 @@ p = weakref.proxy(s) self.assertEqual(str(p), str(s)) s = None + test_support.gc_collect() self.assertRaises(ReferenceError, str, p) # C API test only available in a debug build @@ -590,6 +592,7 @@ s.__init__(self.otherword) self.assertEqual(s, set(self.word)) + @test_support.impl_detail() def test_singleton_empty_frozenset(self): f = frozenset() efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''), @@ -770,9 +773,10 @@ for v in self.set: self.assertIn(v, self.values) setiter = iter(self.set) - # note: __length_hint__ is an internal undocumented API, - # don't rely on it in your own programs - self.assertEqual(setiter.__length_hint__(), len(self.set)) + if test_support.check_impl_detail(): + # note: __length_hint__ is an internal undocumented API, + # don't rely on it in your own programs + self.assertEqual(setiter.__length_hint__(), len(self.set)) def test_pickling(self): p = pickle.dumps(self.set) @@ -1564,7 +1568,7 @@ for meth in (s.union, s.intersection, s.difference, s.symmetric_difference, s.isdisjoint): for g in (G, I, Ig, L, R): expected = meth(data) - actual = meth(G(data)) + actual = meth(g(data)) if isinstance(expected, bool): self.assertEqual(actual, expected) else: diff --git a/lib-python/2.7/test/test_sets.py b/lib-python/2.7/test/test_sets.py --- a/lib-python/2.7/test/test_sets.py +++ b/lib-python/2.7/test/test_sets.py @@ -686,7 +686,9 @@ set_list = sorted(self.set) self.assertEqual(len(dup_list), len(set_list)) for i, el in enumerate(dup_list): - self.assertIs(el, set_list[i]) + # Object identity is not guarnteed for immutable objects, so we + # can't use assertIs here. + self.assertEqual(el, set_list[i]) def test_deep_copy(self): dup = copy.deepcopy(self.set) diff --git a/lib-python/2.7/test/test_site.py b/lib-python/2.7/test/test_site.py --- a/lib-python/2.7/test/test_site.py +++ b/lib-python/2.7/test/test_site.py @@ -226,6 +226,10 @@ self.assertEqual(len(dirs), 1) wanted = os.path.join('xoxo', 'Lib', 'site-packages') self.assertEqual(dirs[0], wanted) + elif '__pypy__' in sys.builtin_module_names: + self.assertEquals(len(dirs), 1) + wanted = os.path.join('xoxo', 'site-packages') + self.assertEquals(dirs[0], wanted) elif os.sep == '/': self.assertEqual(len(dirs), 2) wanted = os.path.join('xoxo', 'lib', 'python' + sys.version[:3], diff --git a/lib-python/2.7/test/test_socket.py b/lib-python/2.7/test/test_socket.py --- a/lib-python/2.7/test/test_socket.py +++ b/lib-python/2.7/test/test_socket.py @@ -252,6 +252,7 @@ self.assertEqual(p.fileno(), s.fileno()) s.close() s = None + test_support.gc_collect() try: p.fileno() except ReferenceError: @@ -285,32 +286,34 @@ s.sendto(u'\u2620', sockname) with self.assertRaises(TypeError) as cm: s.sendto(5j, sockname) - self.assertIn('not complex', str(cm.exception)) + self.assertIn('complex', str(cm.exception)) with self.assertRaises(TypeError) as cm: s.sendto('foo', None) - self.assertIn('not NoneType', str(cm.exception)) + self.assertIn('NoneType', str(cm.exception)) # 3 args with self.assertRaises(UnicodeEncodeError): s.sendto(u'\u2620', 0, sockname) with self.assertRaises(TypeError) as cm: s.sendto(5j, 0, sockname) - self.assertIn('not complex', str(cm.exception)) + self.assertIn('complex', str(cm.exception)) with self.assertRaises(TypeError) as cm: s.sendto('foo', 0, None) - self.assertIn('not NoneType', str(cm.exception)) + if test_support.check_impl_detail(): + self.assertIn('not NoneType', str(cm.exception)) with self.assertRaises(TypeError) as cm: s.sendto('foo', 'bar', sockname) - self.assertIn('an integer is required', str(cm.exception)) + self.assertIn('integer', str(cm.exception)) with self.assertRaises(TypeError) as cm: s.sendto('foo', None, None) - self.assertIn('an integer is required', str(cm.exception)) + if test_support.check_impl_detail(): + self.assertIn('an integer is required', str(cm.exception)) # wrong number of args with self.assertRaises(TypeError) as cm: s.sendto('foo') - self.assertIn('(1 given)', str(cm.exception)) + self.assertIn(' given)', str(cm.exception)) with self.assertRaises(TypeError) as cm: s.sendto('foo', 0, sockname, 4) - self.assertIn('(4 given)', str(cm.exception)) + self.assertIn(' given)', str(cm.exception)) def testCrucialConstants(self): @@ -385,10 +388,10 @@ socket.htonl(k) socket.htons(k) for k in bad_values: - self.assertRaises(OverflowError, socket.ntohl, k) - self.assertRaises(OverflowError, socket.ntohs, k) - self.assertRaises(OverflowError, socket.htonl, k) - self.assertRaises(OverflowError, socket.htons, k) + self.assertRaises((OverflowError, ValueError), socket.ntohl, k) + self.assertRaises((OverflowError, ValueError), socket.ntohs, k) + self.assertRaises((OverflowError, ValueError), socket.htonl, k) + self.assertRaises((OverflowError, ValueError), socket.htons, k) def testGetServBy(self): eq = self.assertEqual @@ -428,8 +431,8 @@ if udpport is not None: eq(socket.getservbyport(udpport, 'udp'), service) # Make sure getservbyport does not accept out of range ports. - self.assertRaises(OverflowError, socket.getservbyport, -1) - self.assertRaises(OverflowError, socket.getservbyport, 65536) + self.assertRaises((OverflowError, ValueError), socket.getservbyport, -1) + self.assertRaises((OverflowError, ValueError), socket.getservbyport, 65536) def testDefaultTimeout(self): # Testing default timeout @@ -608,8 +611,8 @@ neg_port = port - 65536 sock = socket.socket() try: - self.assertRaises(OverflowError, sock.bind, (host, big_port)) - self.assertRaises(OverflowError, sock.bind, (host, neg_port)) + self.assertRaises((OverflowError, ValueError), sock.bind, (host, big_port)) + self.assertRaises((OverflowError, ValueError), sock.bind, (host, neg_port)) sock.bind((host, port)) finally: sock.close() @@ -1309,6 +1312,7 @@ closed = False def flush(self): pass def close(self): self.closed = True + def _decref_socketios(self): pass # must not close unless we request it: the original use of _fileobject # by module socket requires that the underlying socket not be closed until diff --git a/lib-python/2.7/test/test_sort.py b/lib-python/2.7/test/test_sort.py --- a/lib-python/2.7/test/test_sort.py +++ b/lib-python/2.7/test/test_sort.py @@ -140,7 +140,10 @@ return random.random() < 0.5 L = [C() for i in range(50)] - self.assertRaises(ValueError, L.sort) + try: + L.sort() + except ValueError: + pass def test_cmpNone(self): # Testing None as a comparison function. @@ -150,8 +153,10 @@ L.sort(None) self.assertEqual(L, range(50)) + @test_support.impl_detail(pypy=False) def test_undetected_mutation(self): # Python 2.4a1 did not always detect mutation + # So does pypy... memorywaster = [] for i in range(20): def mutating_cmp(x, y): @@ -226,7 +231,10 @@ def __del__(self): del data[:] data[:] = range(20) - self.assertRaises(ValueError, data.sort, key=SortKiller) + try: + data.sort(key=SortKiller) + except ValueError: + pass def test_key_with_mutating_del_and_exception(self): data = range(10) diff --git a/lib-python/2.7/test/test_ssl.py b/lib-python/2.7/test/test_ssl.py --- a/lib-python/2.7/test/test_ssl.py +++ b/lib-python/2.7/test/test_ssl.py @@ -881,6 +881,8 @@ c = socket.socket() c.connect((HOST, port)) listener_gone.wait() + # XXX why is it necessary? + test_support.gc_collect() try: ssl_sock = ssl.wrap_socket(c) except IOError: @@ -1330,10 +1332,8 @@ def test_main(verbose=False): global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT - CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, - "keycert.pem") - SVN_PYTHON_ORG_ROOT_CERT = os.path.join( - os.path.dirname(__file__) or os.curdir, + CERTFILE = test_support.findfile("keycert.pem") + SVN_PYTHON_ORG_ROOT_CERT = test_support.findfile( "https_svn_python_org_root.pem") if (not os.path.exists(CERTFILE) or diff --git a/lib-python/2.7/test/test_str.py b/lib-python/2.7/test/test_str.py --- a/lib-python/2.7/test/test_str.py +++ b/lib-python/2.7/test/test_str.py @@ -422,10 +422,11 @@ for meth in ('foo'.startswith, 'foo'.endswith): with self.assertRaises(TypeError) as cm: meth(['f']) - exc = str(cm.exception) - self.assertIn('unicode', exc) - self.assertIn('str', exc) - self.assertIn('tuple', exc) + if test_support.check_impl_detail(): + exc = str(cm.exception) + self.assertIn('unicode', exc) + self.assertIn('str', exc) + self.assertIn('tuple', exc) def test_main(): test_support.run_unittest(StrTest) diff --git a/lib-python/2.7/test/test_struct.py b/lib-python/2.7/test/test_struct.py --- a/lib-python/2.7/test/test_struct.py +++ b/lib-python/2.7/test/test_struct.py @@ -535,7 +535,8 @@ @unittest.skipUnless(IS32BIT, "Specific to 32bit machines") def test_crasher(self): - self.assertRaises(MemoryError, struct.pack, "357913941c", "a") + self.assertRaises((MemoryError, struct.error), struct.pack, + "357913941c", "a") def test_count_overflow(self): hugecount = '{}b'.format(sys.maxsize+1) diff --git a/lib-python/2.7/test/test_subprocess.py b/lib-python/2.7/test/test_subprocess.py --- a/lib-python/2.7/test/test_subprocess.py +++ b/lib-python/2.7/test/test_subprocess.py @@ -16,11 +16,11 @@ # Depends on the following external programs: Python # -if mswindows: - SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), ' - 'os.O_BINARY);') -else: - SETBINARY = '' +#if mswindows: +# SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), ' +# 'os.O_BINARY);') +#else: +# SETBINARY = '' try: @@ -420,8 +420,9 @@ self.assertStderrEqual(stderr, "") def test_universal_newlines(self): - p = subprocess.Popen([sys.executable, "-c", - 'import sys,os;' + SETBINARY + + # NB. replaced SETBINARY with the -u flag + p = subprocess.Popen([sys.executable, "-u", "-c", + 'import sys,os;' + #SETBINARY + 'sys.stdout.write("line1\\n");' 'sys.stdout.flush();' 'sys.stdout.write("line2\\r");' @@ -448,8 +449,9 @@ def test_universal_newlines_communicate(self): # universal newlines through communicate() - p = subprocess.Popen([sys.executable, "-c", - 'import sys,os;' + SETBINARY + + # NB. replaced SETBINARY with the -u flag + p = subprocess.Popen([sys.executable, "-u", "-c", + 'import sys,os;' + #SETBINARY + 'sys.stdout.write("line1\\n");' 'sys.stdout.flush();' 'sys.stdout.write("line2\\r");' diff --git a/lib-python/2.7/test/test_support.py b/lib-python/2.7/test/test_support.py --- a/lib-python/2.7/test/test_support.py +++ b/lib-python/2.7/test/test_support.py @@ -431,16 +431,20 @@ rmtree(name) -def findfile(file, here=__file__, subdir=None): +def findfile(file, here=None, subdir=None): """Try to find a file on sys.path and the working directory. If it is not found the argument passed to the function is returned (this does not necessarily signal failure; could still be the legitimate path).""" + import test if os.path.isabs(file): return file if subdir is not None: file = os.path.join(subdir, file) path = sys.path - path = [os.path.dirname(here)] + path + if here is None: + path = test.__path__ + path + else: + path = [os.path.dirname(here)] + path for dn in path: fn = os.path.join(dn, file) if os.path.exists(fn): return fn @@ -1050,15 +1054,33 @@ guards, default = _parse_guards(guards) return guards.get(platform.python_implementation().lower(), default) +# ---------------------------------- +# PyPy extension: you can run:: +# python ..../test_foo.py --pdb +# to get a pdb prompt in case of exceptions +ResultClass = unittest.TextTestRunner.resultclass + +class TestResultWithPdb(ResultClass): + + def addError(self, testcase, exc_info): + ResultClass.addError(self, testcase, exc_info) + if '--pdb' in sys.argv: + import pdb, traceback + traceback.print_tb(exc_info[2]) + pdb.post_mortem(exc_info[2]) + +# ---------------------------------- def _run_suite(suite): """Run tests from a unittest.TestSuite-derived class.""" if verbose: - runner = unittest.TextTestRunner(sys.stdout, verbosity=2) + runner = unittest.TextTestRunner(sys.stdout, verbosity=2, + resultclass=TestResultWithPdb) else: runner = BasicTestRunner() + result = runner.run(suite) if not result.wasSuccessful(): if len(result.errors) == 1 and not result.failures: @@ -1071,6 +1093,34 @@ err += "; run in verbose mode for details" raise TestFailed(err) +# ---------------------------------- +# PyPy extension: you can run:: +# python ..../test_foo.py --filter bar +# to run only the test cases whose name contains bar + +def filter_maybe(suite): + try: + i = sys.argv.index('--filter') + filter = sys.argv[i+1] + except (ValueError, IndexError): + return suite + tests = [] + for test in linearize_suite(suite): + if filter in test._testMethodName: + tests.append(test) + return unittest.TestSuite(tests) + +def linearize_suite(suite_or_test): + try: + it = iter(suite_or_test) + except TypeError: + yield suite_or_test + return + for subsuite in it: + for item in linearize_suite(subsuite): + yield item + +# ---------------------------------- def run_unittest(*classes): """Run tests from unittest.TestCase-derived classes.""" @@ -1086,6 +1136,7 @@ suite.addTest(cls) else: suite.addTest(unittest.makeSuite(cls)) + suite = filter_maybe(suite) _run_suite(suite) diff --git a/lib-python/2.7/test/test_syntax.py b/lib-python/2.7/test/test_syntax.py --- a/lib-python/2.7/test/test_syntax.py +++ b/lib-python/2.7/test/test_syntax.py @@ -5,7 +5,8 @@ >>> def f(x): ... global x Traceback (most recent call last): -SyntaxError: name 'x' is local and global (, line 1) + File "", line 1 +SyntaxError: name 'x' is local and global The tests are all raise SyntaxErrors. They were created by checking each C call that raises SyntaxError. There are several modules that @@ -375,7 +376,7 @@ In 2.5 there was a missing exception and an assert was triggered in a debug build. The number of blocks must be greater than CO_MAXBLOCKS. SF #1565514 - >>> while 1: + >>> while 1: # doctest:+SKIP ... while 2: ... while 3: ... while 4: diff --git a/lib-python/2.7/test/test_sys.py b/lib-python/2.7/test/test_sys.py --- a/lib-python/2.7/test/test_sys.py +++ b/lib-python/2.7/test/test_sys.py @@ -264,6 +264,7 @@ self.assertEqual(sys.getdlopenflags(), oldflags+1) sys.setdlopenflags(oldflags) + @test.test_support.impl_detail("reference counting") def test_refcount(self): # n here must be a global in order for this test to pass while # tracing with a python function. Tracing calls PyFrame_FastToLocals @@ -287,7 +288,7 @@ is sys._getframe().f_code ) - # sys._current_frames() is a CPython-only gimmick. + @test.test_support.impl_detail("current_frames") def test_current_frames(self): have_threads = True try: @@ -383,7 +384,10 @@ self.assertEqual(len(sys.float_info), 11) self.assertEqual(sys.float_info.radix, 2) self.assertEqual(len(sys.long_info), 2) - self.assertTrue(sys.long_info.bits_per_digit % 5 == 0) + if test.test_support.check_impl_detail(cpython=True): + self.assertTrue(sys.long_info.bits_per_digit % 5 == 0) + else: + self.assertTrue(sys.long_info.bits_per_digit >= 1) self.assertTrue(sys.long_info.sizeof_digit >= 1) self.assertEqual(type(sys.long_info.bits_per_digit), int) self.assertEqual(type(sys.long_info.sizeof_digit), int) @@ -432,6 +436,7 @@ self.assertEqual(type(getattr(sys.flags, attr)), int, attr) self.assertTrue(repr(sys.flags)) + @test.test_support.impl_detail("sys._clear_type_cache") def test_clear_type_cache(self): sys._clear_type_cache() @@ -473,6 +478,7 @@ p.wait() self.assertIn(executable, ["''", repr(sys.executable)]) + at unittest.skipUnless(test.test_support.check_impl_detail(), "sys.getsizeof()") class SizeofTest(unittest.TestCase): TPFLAGS_HAVE_GC = 1<<14 diff --git a/lib-python/2.7/test/test_sys_settrace.py b/lib-python/2.7/test/test_sys_settrace.py --- a/lib-python/2.7/test/test_sys_settrace.py +++ b/lib-python/2.7/test/test_sys_settrace.py @@ -213,12 +213,16 @@ "finally" def generator_example(): # any() will leave the generator before its end - x = any(generator_function()) + x = any(generator_function()); gc.collect() # the following lines were not traced for x in range(10): y = x +# On CPython, when the generator is decref'ed to zero, we see the trace +# for the "finally:" portion. On PyPy, we don't see it before the next +# garbage collection. That's why we put gc.collect() on the same line above. + generator_example.events = ([(0, 'call'), (2, 'line'), (-6, 'call'), @@ -282,11 +286,11 @@ self.compare_events(func.func_code.co_firstlineno, tracer.events, func.events) - def set_and_retrieve_none(self): + def test_set_and_retrieve_none(self): sys.settrace(None) assert sys.gettrace() is None - def set_and_retrieve_func(self): + def test_set_and_retrieve_func(self): def fn(*args): pass @@ -323,17 +327,24 @@ self.run_test(tighterloop_example) def test_13_genexp(self): - self.run_test(generator_example) - # issue1265: if the trace function contains a generator, - # and if the traced function contains another generator - # that is not completely exhausted, the trace stopped. - # Worse: the 'finally' clause was not invoked. - tracer = Tracer() - sys.settrace(tracer.traceWithGenexp) - generator_example() - sys.settrace(None) - self.compare_events(generator_example.__code__.co_firstlineno, - tracer.events, generator_example.events) + if self.using_gc: + test_support.gc_collect() + gc.enable() + try: + self.run_test(generator_example) + # issue1265: if the trace function contains a generator, + # and if the traced function contains another generator + # that is not completely exhausted, the trace stopped. + # Worse: the 'finally' clause was not invoked. + tracer = Tracer() + sys.settrace(tracer.traceWithGenexp) + generator_example() + sys.settrace(None) + self.compare_events(generator_example.__code__.co_firstlineno, + tracer.events, generator_example.events) + finally: + if self.using_gc: + gc.disable() def test_14_onliner_if(self): def onliners(): diff --git a/lib-python/2.7/test/test_sysconfig.py b/lib-python/2.7/test/test_sysconfig.py --- a/lib-python/2.7/test/test_sysconfig.py +++ b/lib-python/2.7/test/test_sysconfig.py @@ -209,13 +209,22 @@ self.assertEqual(get_platform(), 'macosx-10.4-fat64') - for arch in ('ppc', 'i386', 'x86_64', 'ppc64'): + for arch in ('ppc', 'i386', 'ppc64', 'x86_64'): get_config_vars()['CFLAGS'] = ('-arch %s -isysroot ' '/Developer/SDKs/MacOSX10.4u.sdk ' '-fno-strict-aliasing -fno-common ' '-dynamic -DNDEBUG -g -O3'%(arch,)) self.assertEqual(get_platform(), 'macosx-10.4-%s'%(arch,)) + + # macosx with ARCHFLAGS set and empty _CONFIG_VARS + os.environ['ARCHFLAGS'] = '-arch i386' + sysconfig._CONFIG_VARS = None + + # this will attempt to recreate the _CONFIG_VARS based on environment + # variables; used to check a problem with the PyPy's _init_posix + # implementation; see: issue 705 + get_config_vars() # linux debian sarge os.name = 'posix' @@ -235,7 +244,7 @@ def test_get_scheme_names(self): wanted = ('nt', 'nt_user', 'os2', 'os2_home', 'osx_framework_user', - 'posix_home', 'posix_prefix', 'posix_user') + 'posix_home', 'posix_prefix', 'posix_user', 'pypy') self.assertEqual(get_scheme_names(), wanted) def test_symlink(self): diff --git a/lib-python/2.7/test/test_tarfile.py b/lib-python/2.7/test/test_tarfile.py --- a/lib-python/2.7/test/test_tarfile.py +++ b/lib-python/2.7/test/test_tarfile.py @@ -169,6 +169,7 @@ except tarfile.ReadError: self.fail("tarfile.open() failed on empty archive") self.assertListEqual(tar.getmembers(), []) + tar.close() def test_null_tarfile(self): # Test for issue6123: Allow opening empty archives. @@ -207,16 +208,21 @@ fobj = open(self.tarname, "rb") tar = tarfile.open(fileobj=fobj, mode=self.mode) self.assertEqual(tar.name, os.path.abspath(fobj.name)) + tar.close() def test_no_name_attribute(self): - data = open(self.tarname, "rb").read() + f = open(self.tarname, "rb") + data = f.read() + f.close() fobj = StringIO.StringIO(data) self.assertRaises(AttributeError, getattr, fobj, "name") tar = tarfile.open(fileobj=fobj, mode=self.mode) self.assertEqual(tar.name, None) def test_empty_name_attribute(self): - data = open(self.tarname, "rb").read() + f = open(self.tarname, "rb") + data = f.read() + f.close() fobj = StringIO.StringIO(data) fobj.name = "" tar = tarfile.open(fileobj=fobj, mode=self.mode) @@ -515,6 +521,7 @@ self.tar = tarfile.open(self.tarname, mode=self.mode, encoding="iso8859-1") tarinfo = self.tar.getmember("pax/umlauts-�������") self._test_member(tarinfo, size=7011, chksum=md5_regtype) + self.tar.close() class LongnameTest(ReadTest): @@ -675,6 +682,7 @@ tar = tarfile.open(tmpname, self.mode) tarinfo = tar.gettarinfo(path) self.assertEqual(tarinfo.size, 0) + tar.close() finally: os.rmdir(path) @@ -692,6 +700,7 @@ tar.gettarinfo(target) tarinfo = tar.gettarinfo(link) self.assertEqual(tarinfo.size, 0) + tar.close() finally: os.remove(target) os.remove(link) @@ -704,6 +713,7 @@ tar = tarfile.open(tmpname, self.mode) tarinfo = tar.gettarinfo(path) self.assertEqual(tarinfo.size, 0) + tar.close() finally: os.remove(path) @@ -722,6 +732,7 @@ tar.add(dstname) os.chdir(cwd) self.assertTrue(tar.getnames() == [], "added the archive to itself") + tar.close() def test_exclude(self): tempdir = os.path.join(TEMPDIR, "exclude") @@ -742,6 +753,7 @@ tar = tarfile.open(tmpname, "r") self.assertEqual(len(tar.getmembers()), 1) self.assertEqual(tar.getnames()[0], "empty_dir") + tar.close() finally: shutil.rmtree(tempdir) @@ -947,7 +959,9 @@ fobj.close() elif self.mode.endswith("bz2"): dec = bz2.BZ2Decompressor() - data = open(tmpname, "rb").read() + f = open(tmpname, "rb") + data = f.read() + f.close() data = dec.decompress(data) self.assertTrue(len(dec.unused_data) == 0, "found trailing data") @@ -1026,6 +1040,7 @@ "unable to read longname member") self.assertEqual(tarinfo.linkname, member.linkname, "unable to read longname member") + tar.close() def test_longname_1023(self): self._test(("longnam/" * 127) + "longnam") @@ -1118,6 +1133,7 @@ else: n = tar.getmembers()[0].name self.assertTrue(name == n, "PAX longname creation failed") + tar.close() def test_pax_global_header(self): pax_headers = { @@ -1146,6 +1162,7 @@ tarfile.PAX_NUMBER_FIELDS[key](val) except (TypeError, ValueError): self.fail("unable to convert pax header field") + tar.close() def test_pax_extended_header(self): # The fields from the pax header have priority over the @@ -1165,6 +1182,7 @@ self.assertEqual(t.pax_headers, pax_headers) self.assertEqual(t.name, "foo") self.assertEqual(t.uid, 123) + tar.close() class UstarUnicodeTest(unittest.TestCase): @@ -1208,6 +1226,7 @@ tarinfo.name = "foo" tarinfo.uname = u"���" self.assertRaises(UnicodeError, tar.addfile, tarinfo) + tar.close() def test_unicode_argument(self): tar = tarfile.open(tarname, "r", encoding="iso8859-1", errors="strict") @@ -1262,6 +1281,7 @@ tar = tarfile.open(tmpname, format=self.format, encoding="ascii", errors=handler) self.assertEqual(tar.getnames()[0], name) + tar.close() self.assertRaises(UnicodeError, tarfile.open, tmpname, encoding="ascii", errors="strict") @@ -1274,6 +1294,7 @@ tar = tarfile.open(tmpname, format=self.format, encoding="iso8859-1", errors="utf-8") self.assertEqual(tar.getnames()[0], "���/" + u"�".encode("utf8")) + tar.close() class AppendTest(unittest.TestCase): @@ -1301,6 +1322,7 @@ def _test(self, names=["bar"], fileobj=None): tar = tarfile.open(self.tarname, fileobj=fileobj) self.assertEqual(tar.getnames(), names) + tar.close() def test_non_existing(self): self._add_testfile() @@ -1319,7 +1341,9 @@ def test_fileobj(self): self._create_testtar() - data = open(self.tarname).read() + f = open(self.tarname) + data = f.read() + f.close() fobj = StringIO.StringIO(data) self._add_testfile(fobj) fobj.seek(0) @@ -1345,7 +1369,9 @@ # Append mode is supposed to fail if the tarfile to append to # does not end with a zero block. def _test_error(self, data): - open(self.tarname, "wb").write(data) + f = open(self.tarname, "wb") + f.write(data) + f.close() self.assertRaises(tarfile.ReadError, self._add_testfile) def test_null(self): diff --git a/lib-python/2.7/test/test_tempfile.py b/lib-python/2.7/test/test_tempfile.py --- a/lib-python/2.7/test/test_tempfile.py +++ b/lib-python/2.7/test/test_tempfile.py @@ -23,8 +23,8 @@ # TEST_FILES may need to be tweaked for systems depending on the maximum # number of files that can be opened at one time (see ulimit -n) -if sys.platform in ('openbsd3', 'openbsd4'): - TEST_FILES = 48 +if sys.platform.startswith("openbsd"): + TEST_FILES = 64 # ulimit -n defaults to 128 for normal users else: TEST_FILES = 100 @@ -244,6 +244,7 @@ dir = tempfile.mkdtemp() From noreply at buildbot.pypy.org Tue Jun 5 09:59:53 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:59:53 +0200 (CEST) Subject: [pypy-commit] pypy stm-thread: hg merge default Message-ID: <20120605075953.547311C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-thread Changeset: r55400:413edddebcae Date: 2012-06-04 22:41 +0200 http://bitbucket.org/pypy/pypy/changeset/413edddebcae/ Log: hg merge default diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py --- a/lib_pypy/_ctypes/basics.py +++ b/lib_pypy/_ctypes/basics.py @@ -47,10 +47,6 @@ else: return self.from_param(as_parameter) - def get_ffi_param(self, value): - cdata = self.from_param(value) - return cdata, cdata._to_ffi_param() - def get_ffi_argtype(self): if self._ffiargtype: return self._ffiargtype diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -444,10 +444,6 @@ @classmethod def _conv_param(cls, argtype, arg): - if isinstance(argtype, _CDataMeta): - cobj, ffiparam = argtype.get_ffi_param(arg) - return cobj, ffiparam, argtype - if argtype is not None: arg = argtype.from_param(arg) if hasattr(arg, '_as_parameter_'): diff --git a/lib_pypy/ctypes_support.py b/lib_pypy/ctypes_support.py --- a/lib_pypy/ctypes_support.py +++ b/lib_pypy/ctypes_support.py @@ -12,6 +12,8 @@ if sys.platform == 'win32': import _ffi standard_c_lib = ctypes.CDLL('msvcrt', handle=_ffi.get_libc()) +elif sys.platform == 'cygwin': + standard_c_lib = ctypes.CDLL(ctypes.util.find_library('cygwin')) else: standard_c_lib = ctypes.CDLL(ctypes.util.find_library('c')) diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py --- a/pypy/annotation/bookkeeper.py +++ b/pypy/annotation/bookkeeper.py @@ -531,8 +531,11 @@ try: assert pyobj._freeze_() except AttributeError: - raise Exception("unexpected prebuilt constant: %r" % ( - pyobj,)) + if hasattr(pyobj, '__call__'): + msg = "object with a __call__ is not RPython" + else: + msg = "unexpected prebuilt constant" + raise Exception("%s: %r" % (msg, pyobj)) result = self.getfrozen(pyobj) self.descs[pyobj] = result return result diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py --- a/pypy/annotation/test/test_annrpython.py +++ b/pypy/annotation/test/test_annrpython.py @@ -3769,6 +3769,17 @@ assert isinstance(s, annmodel.SomeString) assert not s.can_be_None + def test_no___call__(self): + class X(object): + def __call__(self): + xxx + x = X() + def f(): + return x + a = self.RPythonAnnotator() + e = py.test.raises(Exception, a.build_types, f, []) + assert 'object with a __call__ is not RPython' in str(e.value) + def g(n): return [0,1,2,n] diff --git a/pypy/bin/rpython b/pypy/bin/rpython old mode 100644 new mode 100755 diff --git a/pypy/doc/test/test_whatsnew.py b/pypy/doc/test/test_whatsnew.py --- a/pypy/doc/test/test_whatsnew.py +++ b/pypy/doc/test/test_whatsnew.py @@ -16,6 +16,7 @@ startrev = parseline(line) elif line.startswith('.. branch:'): branches.add(parseline(line)) + branches.discard('default') return startrev, branches def get_merged_branches(path, startrev, endrev): @@ -51,6 +52,10 @@ .. branch: hello qqq www ttt + +.. branch: default + +"default" should be ignored and not put in the set of documented branches """ startrev, branches = parse_doc(s) assert startrev == '12345' diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst --- a/pypy/doc/whatsnew-1.9.rst +++ b/pypy/doc/whatsnew-1.9.rst @@ -5,8 +5,12 @@ .. this is the revision just after the creation of the release-1.8.x branch .. startrev: a4261375b359 +.. branch: default +* Working hash function for numpy types. + .. branch: array_equal .. branch: better-jit-hooks-2 +Improved jit hooks .. branch: faster-heapcache .. branch: faster-str-decode-escape .. branch: float-bytes @@ -16,9 +20,14 @@ .. branch: jit-frame-counter Put more debug info into resops. .. branch: kill-geninterp +Kill "geninterp", an old attempt to statically turn some fixed +app-level code to interp-level. .. branch: kqueue Finished select.kqueue. .. branch: kwargsdict-strategy +Special dictionary strategy for dealing with \*\*kwds. Now having a simple +proxy ``def f(*args, **kwds): return x(*args, **kwds`` should not make +any allocations at all. .. branch: matrixmath-dot numpypy can now handle matrix multiplication. .. branch: merge-2.7.2 @@ -29,13 +38,19 @@ cpyext: Better support for PyEval_SaveThread and other PyTreadState_* functions. .. branch: numppy-flatitter +flatitier for numpy .. branch: numpy-back-to-applevel +reuse more of original numpy .. branch: numpy-concatenate +concatenation support for numpy .. branch: numpy-indexing-by-arrays-bool +indexing by bool arrays .. branch: numpy-record-dtypes +record dtypes on numpy has been started .. branch: numpy-single-jitdriver .. branch: numpy-ufuncs2 .. branch: numpy-ufuncs3 +various refactorings regarding numpy .. branch: numpypy-issue1137 .. branch: numpypy-out The "out" argument was added to most of the numypypy functions. @@ -43,8 +58,13 @@ .. branch: numpypy-ufuncs .. branch: pytest .. branch: safe-getargs-freelist +CPyext improvements. For example PyOpenSSL should now work .. branch: set-strategies +Sets now have strategies just like dictionaries. This means a set +containing only ints will be more compact (and faster) .. branch: speedup-list-comprehension +The simplest case of list comprehension is preallocating the correct size +of the list. This speeds up select benchmarks quite significantly. .. branch: stdlib-unification The directory "lib-python/modified-2.7" has been removed, and its content merged into "lib-python/2.7". @@ -66,6 +86,7 @@ Add os.kill to windows even if translating python does not have os.kill .. branch: win64-stage1 .. branch: zlib-mem-pressure +Memory "leaks" associated with zlib are fixed. .. branch: ffistruct The ``ffistruct`` branch adds a very low level way to express C structures diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py --- a/pypy/jit/backend/llsupport/gc.py +++ b/pypy/jit/backend/llsupport/gc.py @@ -577,7 +577,6 @@ def __init__(self, gc_ll_descr): self.llop1 = gc_ll_descr.llop1 self.WB_FUNCPTR = gc_ll_descr.WB_FUNCPTR - self.WB_ARRAY_FUNCPTR = gc_ll_descr.WB_ARRAY_FUNCPTR self.fielddescr_tid = gc_ll_descr.fielddescr_tid # GCClass = gc_ll_descr.GCClass @@ -592,6 +591,11 @@ self.jit_wb_card_page_shift = GCClass.JIT_WB_CARD_PAGE_SHIFT self.jit_wb_cards_set_byteofs, self.jit_wb_cards_set_singlebyte = ( self.extract_flag_byte(self.jit_wb_cards_set)) + # + # the x86 backend uses the following "accidental" facts to + # avoid one instruction: + assert self.jit_wb_cards_set_byteofs == self.jit_wb_if_flag_byteofs + assert self.jit_wb_cards_set_singlebyte == -0x80 else: self.jit_wb_cards_set = 0 @@ -615,7 +619,7 @@ # returns a function with arguments [array, index, newvalue] llop1 = self.llop1 funcptr = llop1.get_write_barrier_from_array_failing_case( - self.WB_ARRAY_FUNCPTR) + self.WB_FUNCPTR) funcaddr = llmemory.cast_ptr_to_adr(funcptr) return cpu.cast_adr_to_int(funcaddr) # this may return 0 @@ -699,9 +703,7 @@ def _setup_write_barrier(self): self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( - [llmemory.Address, llmemory.Address], lltype.Void)) - self.WB_ARRAY_FUNCPTR = lltype.Ptr(lltype.FuncType( - [llmemory.Address, lltype.Signed, llmemory.Address], lltype.Void)) + [llmemory.Address], lltype.Void)) self.write_barrier_descr = WriteBarrierDescr(self) def _make_functions(self, really_not_translated): @@ -859,8 +861,7 @@ # the GC, and call it immediately llop1 = self.llop1 funcptr = llop1.get_write_barrier_failing_case(self.WB_FUNCPTR) - funcptr(llmemory.cast_ptr_to_adr(gcref_struct), - llmemory.cast_ptr_to_adr(gcref_newptr)) + funcptr(llmemory.cast_ptr_to_adr(gcref_struct)) def can_use_nursery_malloc(self, size): return size < self.max_size_of_young_obj diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py --- a/pypy/jit/backend/llsupport/test/test_gc.py +++ b/pypy/jit/backend/llsupport/test/test_gc.py @@ -276,8 +276,8 @@ repr(offset_to_length), p)) return p - def _write_barrier_failing_case(self, adr_struct, adr_newptr): - self.record.append(('barrier', adr_struct, adr_newptr)) + def _write_barrier_failing_case(self, adr_struct): + self.record.append(('barrier', adr_struct)) def get_write_barrier_failing_case(self, FPTRTYPE): return llhelper(FPTRTYPE, self._write_barrier_failing_case) @@ -402,7 +402,7 @@ # s_hdr.tid |= gc_ll_descr.GCClass.JIT_WB_IF_FLAG gc_ll_descr.do_write_barrier(s_gcref, r_gcref) - assert self.llop1.record == [('barrier', s_adr, r_adr)] + assert self.llop1.record == [('barrier', s_adr)] def test_gen_write_barrier(self): gc_ll_descr = self.gc_ll_descr diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py --- a/pypy/jit/backend/test/runner_test.py +++ b/pypy/jit/backend/test/runner_test.py @@ -1835,12 +1835,12 @@ assert not excvalue def test_cond_call_gc_wb(self): - def func_void(a, b): - record.append((a, b)) + def func_void(a): + record.append(a) record = [] # S = lltype.GcStruct('S', ('tid', lltype.Signed)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Ptr(S)], lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): @@ -1866,26 +1866,25 @@ [BoxPtr(sgcref), ConstPtr(tgcref)], 'void', descr=WriteBarrierDescr()) if cond: - assert record == [(s, t)] + assert record == [s] else: assert record == [] def test_cond_call_gc_wb_array(self): - def func_void(a, b, c): - record.append((a, b, c)) + def func_void(a): + record.append(a) record = [] # S = lltype.GcStruct('S', ('tid', lltype.Signed)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)], - lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): jit_wb_if_flag = 4096 jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10') jit_wb_if_flag_singlebyte = 0x10 - jit_wb_cards_set = 0 - def get_write_barrier_from_array_fn(self, cpu): + jit_wb_cards_set = 0 # <= without card marking + def get_write_barrier_fn(self, cpu): return funcbox.getint() # for cond in [False, True]: @@ -1902,13 +1901,15 @@ [BoxPtr(sgcref), ConstInt(123), BoxPtr(sgcref)], 'void', descr=WriteBarrierDescr()) if cond: - assert record == [(s, 123, s)] + assert record == [s] else: assert record == [] def test_cond_call_gc_wb_array_card_marking_fast_path(self): - def func_void(a, b, c): - record.append((a, b, c)) + def func_void(a): + record.append(a) + if cond == 1: # the write barrier sets the flag + s.data.tid |= 32768 record = [] # S = lltype.Struct('S', ('tid', lltype.Signed)) @@ -1922,34 +1923,40 @@ ('card6', lltype.Char), ('card7', lltype.Char), ('data', S)) - FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)], - lltype.Void) + FUNC = self.FuncType([lltype.Ptr(S)], lltype.Void) func_ptr = llhelper(lltype.Ptr(FUNC), func_void) funcbox = self.get_funcbox(self.cpu, func_ptr) class WriteBarrierDescr(AbstractDescr): jit_wb_if_flag = 4096 jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10') jit_wb_if_flag_singlebyte = 0x10 - jit_wb_cards_set = 8192 - jit_wb_cards_set_byteofs = struct.pack("i", 8192).index('\x20') - jit_wb_cards_set_singlebyte = 0x20 + jit_wb_cards_set = 32768 + jit_wb_cards_set_byteofs = struct.pack("i", 32768).index('\x80') + jit_wb_cards_set_singlebyte = -0x80 jit_wb_card_page_shift = 7 def get_write_barrier_from_array_fn(self, cpu): return funcbox.getint() # - for BoxIndexCls in [BoxInt, ConstInt]: - for cond in [False, True]: + for BoxIndexCls in [BoxInt, ConstInt]*3: + for cond in [-1, 0, 1, 2]: + # cond=-1:GCFLAG_TRACK_YOUNG_PTRS, GCFLAG_CARDS_SET are not set + # cond=0: GCFLAG_CARDS_SET is never set + # cond=1: GCFLAG_CARDS_SET is not set, but the wb sets it + # cond=2: GCFLAG_CARDS_SET is already set print print '_'*79 print 'BoxIndexCls =', BoxIndexCls - print 'JIT_WB_CARDS_SET =', cond + print 'testing cond =', cond print value = random.randrange(-sys.maxint, sys.maxint) - value |= 4096 - if cond: - value |= 8192 + if cond >= 0: + value |= 4096 else: - value &= ~8192 + value &= ~4096 + if cond == 2: + value |= 32768 + else: + value &= ~32768 s = lltype.malloc(S_WITH_CARDS, immortal=True, zero=True) s.data.tid = value sgcref = rffi.cast(llmemory.GCREF, s.data) @@ -1958,11 +1965,13 @@ self.execute_operation(rop.COND_CALL_GC_WB_ARRAY, [BoxPtr(sgcref), box_index, BoxPtr(sgcref)], 'void', descr=WriteBarrierDescr()) - if cond: + if cond in [0, 1]: + assert record == [s.data] + else: assert record == [] + if cond in [1, 2]: assert s.card6 == '\x02' else: - assert record == [(s.data, (9<<7) + 17, s.data)] assert s.card6 == '\x00' assert s.card0 == '\x00' assert s.card1 == '\x00' @@ -1971,6 +1980,9 @@ assert s.card4 == '\x00' assert s.card5 == '\x00' assert s.card7 == '\x00' + if cond == 1: + value |= 32768 + assert s.data.tid == value def test_force_operations_returning_void(self): values = [] diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py --- a/pypy/jit/backend/x86/assembler.py +++ b/pypy/jit/backend/x86/assembler.py @@ -10,7 +10,7 @@ from pypy.rlib.jit import AsmInfo from pypy.jit.backend.model import CompiledLoopToken from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale, - gpr_reg_mgr_cls, _valid_addressing_size) + gpr_reg_mgr_cls, xmm_reg_mgr_cls, _valid_addressing_size) from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD, IS_X86_32, IS_X86_64) @@ -83,6 +83,7 @@ self.float_const_abs_addr = 0 self.malloc_slowpath1 = 0 self.malloc_slowpath2 = 0 + self.wb_slowpath = [0, 0, 0, 0] self.memcpy_addr = 0 self.setup_failure_recovery() self._debug = False @@ -109,9 +110,13 @@ self.memcpy_addr = self.cpu.cast_ptr_to_int(support.memcpy_fn) self._build_failure_recovery(False) self._build_failure_recovery(True) + self._build_wb_slowpath(False) + self._build_wb_slowpath(True) if self.cpu.supports_floats: self._build_failure_recovery(False, withfloats=True) self._build_failure_recovery(True, withfloats=True) + self._build_wb_slowpath(False, withfloats=True) + self._build_wb_slowpath(True, withfloats=True) support.ensure_sse2_floats() self._build_float_constants() self._build_propagate_exception_path() @@ -344,6 +349,82 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.stack_check_slowpath = rawstart + def _build_wb_slowpath(self, withcards, withfloats=False): + descr = self.cpu.gc_ll_descr.write_barrier_descr + if descr is None: + return + if not withcards: + func = descr.get_write_barrier_fn(self.cpu) + else: + if descr.jit_wb_cards_set == 0: + return + func = descr.get_write_barrier_from_array_fn(self.cpu) + if func == 0: + return + # + # This builds a helper function called from the slow path of + # write barriers. It must save all registers, and optionally + # all XMM registers. It takes a single argument just pushed + # on the stack even on X86_64. It must restore stack alignment + # accordingly. + mc = codebuf.MachineCodeBlockWrapper() + # + frame_size = (1 + # my argument, considered part of my frame + 1 + # my return address + len(gpr_reg_mgr_cls.save_around_call_regs)) + if withfloats: + frame_size += 16 # X86_32: 16 words for 8 registers; + # X86_64: just 16 registers + if IS_X86_32: + frame_size += 1 # argument to pass to the call + # + # align to a multiple of 16 bytes + frame_size = (frame_size + (CALL_ALIGN-1)) & ~(CALL_ALIGN-1) + # + correct_esp_by = (frame_size - 2) * WORD + mc.SUB_ri(esp.value, correct_esp_by) + # + ofs = correct_esp_by + if withfloats: + for reg in xmm_reg_mgr_cls.save_around_call_regs: + ofs -= 8 + mc.MOVSD_sx(ofs, reg.value) + for reg in gpr_reg_mgr_cls.save_around_call_regs: + ofs -= WORD + mc.MOV_sr(ofs, reg.value) + # + if IS_X86_32: + mc.MOV_rs(eax.value, (frame_size - 1) * WORD) + mc.MOV_sr(0, eax.value) + elif IS_X86_64: + mc.MOV_rs(edi.value, (frame_size - 1) * WORD) + mc.CALL(imm(func)) + # + if withcards: + # A final TEST8 before the RET, for the caller. Careful to + # not follow this instruction with another one that changes + # the status of the CPU flags! + mc.MOV_rs(eax.value, (frame_size - 1) * WORD) + mc.TEST8(addr_add_const(eax, descr.jit_wb_if_flag_byteofs), + imm(-0x80)) + # + ofs = correct_esp_by + if withfloats: + for reg in xmm_reg_mgr_cls.save_around_call_regs: + ofs -= 8 + mc.MOVSD_xs(reg.value, ofs) + for reg in gpr_reg_mgr_cls.save_around_call_regs: + ofs -= WORD + mc.MOV_rs(reg.value, ofs) + # + # ADD esp, correct_esp_by --- but cannot use ADD, because + # of its effects on the CPU flags + mc.LEA_rs(esp.value, correct_esp_by) + mc.RET16_i(WORD) + # + rawstart = mc.materialize(self.cpu.asmmemmgr, []) + self.wb_slowpath[withcards + 2 * withfloats] = rawstart + @staticmethod @rgc.no_collect def _release_gil_asmgcc(css): @@ -2324,102 +2405,83 @@ def genop_discard_cond_call_gc_wb(self, op, arglocs): # Write code equivalent to write_barrier() in the GC: it checks - # a flag in the object at arglocs[0], and if set, it calls the - # function remember_young_pointer() from the GC. The arguments - # to the call are in arglocs[:N]. The rest, arglocs[N:], contains - # registers that need to be saved and restored across the call. - # N is either 2 (regular write barrier) or 3 (array write barrier). + # a flag in the object at arglocs[0], and if set, it calls a + # helper piece of assembler. The latter saves registers as needed + # and call the function jit_remember_young_pointer() from the GC. descr = op.getdescr() if we_are_translated(): cls = self.cpu.gc_ll_descr.has_write_barrier_class() assert cls is not None and isinstance(descr, cls) # opnum = op.getopnum() - if opnum == rop.COND_CALL_GC_WB: - N = 2 - func = descr.get_write_barrier_fn(self.cpu) - card_marking = False - elif opnum == rop.COND_CALL_GC_WB_ARRAY: - N = 3 - func = descr.get_write_barrier_from_array_fn(self.cpu) - assert func != 0 - card_marking = descr.jit_wb_cards_set != 0 - else: - raise AssertionError(opnum) + card_marking = False + mask = descr.jit_wb_if_flag_singlebyte + if opnum == rop.COND_CALL_GC_WB_ARRAY and descr.jit_wb_cards_set != 0: + # assumptions the rest of the function depends on: + assert (descr.jit_wb_cards_set_byteofs == + descr.jit_wb_if_flag_byteofs) + assert descr.jit_wb_cards_set_singlebyte == -0x80 + card_marking = True + mask = descr.jit_wb_if_flag_singlebyte | -0x80 # loc_base = arglocs[0] self.mc.TEST8(addr_add_const(loc_base, descr.jit_wb_if_flag_byteofs), - imm(descr.jit_wb_if_flag_singlebyte)) + imm(mask)) self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later jz_location = self.mc.get_relative_pos() # for cond_call_gc_wb_array, also add another fast path: # if GCFLAG_CARDS_SET, then we can just set one bit and be done if card_marking: - self.mc.TEST8(addr_add_const(loc_base, - descr.jit_wb_cards_set_byteofs), - imm(descr.jit_wb_cards_set_singlebyte)) - self.mc.J_il8(rx86.Conditions['NZ'], 0) # patched later - jnz_location = self.mc.get_relative_pos() + # GCFLAG_CARDS_SET is in this byte at 0x80, so this fact can + # been checked by the status flags of the previous TEST8 + self.mc.J_il8(rx86.Conditions['S'], 0) # patched later + js_location = self.mc.get_relative_pos() else: - jnz_location = 0 + js_location = 0 - # the following is supposed to be the slow path, so whenever possible - # we choose the most compact encoding over the most efficient one. - if IS_X86_32: - limit = -1 # push all arglocs on the stack - elif IS_X86_64: - limit = N - 1 # push only arglocs[N:] on the stack - for i in range(len(arglocs)-1, limit, -1): - loc = arglocs[i] - if isinstance(loc, RegLoc): - self.mc.PUSH_r(loc.value) - else: - assert not IS_X86_64 # there should only be regs in arglocs[N:] - self.mc.PUSH_i32(loc.getint()) - if IS_X86_64: - # We clobber these registers to pass the arguments, but that's - # okay, because consider_cond_call_gc_wb makes sure that any - # caller-save registers with values in them are present in - # arglocs[N:] too, so they are saved on the stack above and - # restored below. - if N == 2: - callargs = [edi, esi] - else: - callargs = [edi, esi, edx] - remap_frame_layout(self, arglocs[:N], callargs, - X86_64_SCRATCH_REG) + # Write only a CALL to the helper prepared in advance, passing it as + # argument the address of the structure we are writing into + # (the first argument to COND_CALL_GC_WB). + helper_num = card_marking + if self._regalloc.xrm.reg_bindings: + helper_num += 2 + if self.wb_slowpath[helper_num] == 0: # tests only + assert not we_are_translated() + self.cpu.gc_ll_descr.write_barrier_descr = descr + self._build_wb_slowpath(card_marking, + bool(self._regalloc.xrm.reg_bindings)) + assert self.wb_slowpath[helper_num] != 0 # - # misaligned stack in the call, but it's ok because the write barrier - # is not going to call anything more. Also, this assumes that the - # write barrier does not touch the xmm registers. (Slightly delicate - # assumption, given that the write barrier can end up calling the - # platform's malloc() from AddressStack.append(). XXX may need to - # be done properly) - self.mc.CALL(imm(func)) - if IS_X86_32: - self.mc.ADD_ri(esp.value, N*WORD) - for i in range(N, len(arglocs)): - loc = arglocs[i] - assert isinstance(loc, RegLoc) - self.mc.POP_r(loc.value) + self.mc.PUSH(loc_base) + self.mc.CALL(imm(self.wb_slowpath[helper_num])) - # if GCFLAG_CARDS_SET, then we can do the whole thing that would - # be done in the CALL above with just four instructions, so here - # is an inline copy of them if card_marking: - self.mc.JMP_l8(0) # jump to the exit, patched later - jmp_location = self.mc.get_relative_pos() - # patch the JNZ above - offset = self.mc.get_relative_pos() - jnz_location + # The helper ends again with a check of the flag in the object. + # So here, we can simply write again a 'JNS', which will be + # taken if GCFLAG_CARDS_SET is still not set. + self.mc.J_il8(rx86.Conditions['NS'], 0) # patched later + jns_location = self.mc.get_relative_pos() + # + # patch the JS above + offset = self.mc.get_relative_pos() - js_location assert 0 < offset <= 127 - self.mc.overwrite(jnz_location-1, chr(offset)) + self.mc.overwrite(js_location-1, chr(offset)) # + # case GCFLAG_CARDS_SET: emit a few instructions to do + # directly the card flag setting loc_index = arglocs[1] if isinstance(loc_index, RegLoc): - # choose a scratch register - tmp1 = loc_index - self.mc.PUSH_r(tmp1.value) + if IS_X86_64 and isinstance(loc_base, RegLoc): + # copy loc_index into r11 + tmp1 = X86_64_SCRATCH_REG + self.mc.MOV_rr(tmp1.value, loc_index.value) + final_pop = False + else: + # must save the register loc_index before it is mutated + self.mc.PUSH_r(loc_index.value) + tmp1 = loc_index + final_pop = True # SHR tmp, card_page_shift self.mc.SHR_ri(tmp1.value, descr.jit_wb_card_page_shift) # XOR tmp, -8 @@ -2427,7 +2489,9 @@ # BTS [loc_base], tmp self.mc.BTS(addr_add_const(loc_base, 0), tmp1) # done - self.mc.POP_r(tmp1.value) + if final_pop: + self.mc.POP_r(loc_index.value) + # elif isinstance(loc_index, ImmedLoc): byte_index = loc_index.value >> descr.jit_wb_card_page_shift byte_ofs = ~(byte_index >> 3) @@ -2435,11 +2499,12 @@ self.mc.OR8(addr_add_const(loc_base, byte_ofs), imm(byte_val)) else: raise AssertionError("index is neither RegLoc nor ImmedLoc") - # patch the JMP above - offset = self.mc.get_relative_pos() - jmp_location + # + # patch the JNS above + offset = self.mc.get_relative_pos() - jns_location assert 0 < offset <= 127 - self.mc.overwrite(jmp_location-1, chr(offset)) - # + self.mc.overwrite(jns_location-1, chr(offset)) + # patch the JZ above offset = self.mc.get_relative_pos() - jz_location assert 0 < offset <= 127 diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py --- a/pypy/jit/backend/x86/regalloc.py +++ b/pypy/jit/backend/x86/regalloc.py @@ -980,16 +980,6 @@ # or setarrayitem_gc. It avoids loading it twice from the memory. arglocs = [self.rm.make_sure_var_in_reg(op.getarg(i), args) for i in range(N)] - # add eax, ecx and edx as extra "arguments" to ensure they are - # saved and restored. Fish in self.rm to know which of these - # registers really need to be saved (a bit of a hack). Moreover, - # we don't save and restore any SSE register because the called - # function, a GC write barrier, is known not to touch them. - # See remember_young_pointer() in rpython/memory/gc/generation.py. - for v, reg in self.rm.reg_bindings.items(): - if (reg in self.rm.save_around_call_regs - and self.rm.stays_alive(v)): - arglocs.append(reg) self.PerformDiscard(op, arglocs) self.rm.possibly_free_vars_for_op(op) diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py --- a/pypy/jit/backend/x86/rx86.py +++ b/pypy/jit/backend/x86/rx86.py @@ -316,6 +316,13 @@ assert rexbyte == 0 return 0 +# REX prefixes: 'rex_w' generates a REX_W, forcing the instruction +# to operate on 64-bit. 'rex_nw' doesn't, so the instruction operates +# on 32-bit or less; the complete REX prefix is omitted if unnecessary. +# 'rex_fw' is a special case which doesn't generate a REX_W but forces +# the REX prefix in all cases. It is only useful on instructions which +# have an 8-bit register argument, to force access to the "sil" or "dil" +# registers (as opposed to "ah-dh"). rex_w = encode_rex, 0, (0x40 | REX_W), None # a REX.W prefix rex_nw = encode_rex, 0, 0, None # an optional REX prefix rex_fw = encode_rex, 0, 0x40, None # a forced REX prefix @@ -496,9 +503,9 @@ AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0') OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0') - OR8_mi = insn(rex_fw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), + OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), immediate(2, 'b')) - OR8_ji = insn(rex_fw, '\x80', orbyte(1<<3), abs_, immediate(1), + OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1), immediate(2, 'b')) NEG_r = insn(rex_w, '\xF7', register(1), '\xD8') @@ -531,7 +538,13 @@ PUSH_r = insn(rex_nw, register(1), '\x50') PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1)) + PUSH_i8 = insn('\x6A', immediate(1, 'b')) PUSH_i32 = insn('\x68', immediate(1, 'i')) + def PUSH_i(mc, immed): + if single_byte(immed): + mc.PUSH_i8(immed) + else: + mc.PUSH_i32(immed) POP_r = insn(rex_nw, register(1), '\x58') POP_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1)) diff --git a/pypy/jit/backend/x86/test/test_rx86.py b/pypy/jit/backend/x86/test/test_rx86.py --- a/pypy/jit/backend/x86/test/test_rx86.py +++ b/pypy/jit/backend/x86/test/test_rx86.py @@ -183,7 +183,8 @@ def test_push32(): cb = CodeBuilder32 - assert_encodes_as(cb, 'PUSH_i32', (9,), '\x68\x09\x00\x00\x00') + assert_encodes_as(cb, 'PUSH_i', (0x10009,), '\x68\x09\x00\x01\x00') + assert_encodes_as(cb, 'PUSH_i', (9,), '\x6A\x09') def test_sub_ji8(): cb = CodeBuilder32 diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py --- a/pypy/module/_minimal_curses/fficurses.py +++ b/pypy/module/_minimal_curses/fficurses.py @@ -8,11 +8,20 @@ from pypy.rpython.extfunc import register_external from pypy.module._minimal_curses import interp_curses from pypy.translator.tool.cbuild import ExternalCompilationInfo +from sys import platform -eci = ExternalCompilationInfo( - includes = ['curses.h', 'term.h'], - libraries = ['curses'], -) +_CYGWIN = platform == 'cygwin' + +if _CYGWIN: + eci = ExternalCompilationInfo( + includes = ['ncurses/curses.h', 'ncurses/term.h'], + libraries = ['curses'], + ) +else: + eci = ExternalCompilationInfo( + includes = ['curses.h', 'term.h'], + libraries = ['curses'], + ) rffi_platform.verify_eci(eci) diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py --- a/pypy/module/_socket/test/test_sock_app.py +++ b/pypy/module/_socket/test/test_sock_app.py @@ -611,14 +611,19 @@ buf = t.recv(1) assert buf == '?' # test send() timeout + count = 0 try: while 1: - cli.send('foobar' * 70) + count += cli.send('foobar' * 70) except timeout: pass - # test sendall() timeout, be sure to send data larger than the - # socket buffer - raises(timeout, cli.sendall, 'foobar' * 7000) + t.recv(count) + # test sendall() timeout + try: + while 1: + cli.sendall('foobar' * 70) + except timeout: + pass # done cli.close() t.close() diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -12,15 +12,18 @@ MIXIN_32 = (int_typedef,) if LONG_BIT == 32 else () MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else () + def new_dtype_getter(name): def _get_dtype(space): from pypy.module.micronumpy.interp_dtype import get_dtype_cache return getattr(get_dtype_cache(space), "w_%sdtype" % name) + def new(space, w_subtype, w_value): dtype = _get_dtype(space) return dtype.itemtype.coerce_subtype(space, w_subtype, w_value) return func_with_new_name(new, name + "_box_new"), staticmethod(_get_dtype) + class PrimitiveBox(object): _mixin_ = True @@ -30,6 +33,7 @@ def convert_to(self, dtype): return dtype.box(self.value) + class W_GenericBox(Wrappable): _attrs_ = () @@ -71,7 +75,7 @@ def _binop_right_impl(ufunc_name): def impl(self, space, w_other, w_out=None): from pypy.module.micronumpy import interp_ufuncs - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self, w_out]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name) @@ -132,6 +136,9 @@ w_remainder = self.descr_rmod(space, w_other) return space.newtuple([w_quotient, w_remainder]) + def descr_hash(self, space): + return space.hash(self.item(space)) + def item(self, space): return self.get_dtype(space).itemtype.to_builtin_type(space, self) @@ -315,6 +322,8 @@ __abs__ = interp2app(W_GenericBox.descr_abs), __invert__ = interp2app(W_GenericBox.descr_invert), + __hash__ = interp2app(W_GenericBox.descr_hash), + tolist = interp2app(W_GenericBox.item), ) @@ -440,4 +449,4 @@ __module__ = "numpypy", __new__ = interp2app(W_UnicodeBox.descr__new__unicode_box.im_func), ) - + diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -690,11 +690,17 @@ return self.getitem(offset).convert_to(longdtype).item( space) + @jit.unroll_safe def descr_item(self, space, w_arg=None): if space.is_w(w_arg, space.w_None): - if not isinstance(self, Scalar): - raise OperationError(space.w_ValueError, space.wrap("index out of bounds")) - return self.value.item(space) + if isinstance(self, Scalar): + return self.value.item(space) + if support.product(self.shape) == 1: + return self.descr_getitem(space, + space.newtuple([space.wrap(0) for i + in range(len(self.shape))])) + raise OperationError(space.w_ValueError, + space.wrap("index out of bounds")) if space.isinstance_w(w_arg, space.w_int): if isinstance(self, Scalar): raise OperationError(space.w_ValueError, space.wrap("index out of bounds")) @@ -841,7 +847,6 @@ out_arg=None): VirtualArray.__init__(self, name, shape, res_dtype, out_arg) self.values = values - self.size = values.size self.ufunc = ufunc self.calc_dtype = calc_dtype diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py --- a/pypy/module/micronumpy/signature.py +++ b/pypy/module/micronumpy/signature.py @@ -441,7 +441,11 @@ ofs = frame.iterators[0].offset arr.left.setitem(ofs, self.right.eval(frame, arr.right).convert_to( self.calc_dtype)) - + + def _invent_numbering(self, cache, allnumbers): + self.left._invent_numbering(new_cache(), allnumbers) + self.right._invent_numbering(cache, allnumbers) + def debug_repr(self): return 'SliceLoop(%s, %s, %s)' % (self.name, self.left.debug_repr(), self.right.debug_repr()) diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -211,9 +211,23 @@ a = array(range(10), dtype=int64) b = array([0] * 10, dtype=int64) - for idx in b: a[idx] += 1 + for idx in b: + a[idx] += 1 -class AppTestTypes(BaseNumpyAppTest): + def test_hash(self): + import _numpypy as numpy + for tp, value in [ + (numpy.int8, 4), + (numpy.int16, 5), + (numpy.uint32, 7), + (numpy.int64, 3), + (numpy.float32, 2.0), + (numpy.float64, 4.32), + ]: + assert hash(tp(value)) == hash(value) + + +class AppTestTypes(BaseNumpyAppTest): def test_abstract_types(self): import _numpypy as numpy raises(TypeError, numpy.generic, 0) @@ -437,7 +451,7 @@ def test_various_types(self): import _numpypy as numpy import sys - + assert numpy.int16 is numpy.short assert numpy.int8 is numpy.byte assert numpy.bool_ is numpy.bool8 @@ -448,7 +462,7 @@ def test_mro(self): import _numpypy as numpy - + assert numpy.int16.__mro__ == (numpy.int16, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object) @@ -504,7 +518,7 @@ class AppTestStrUnicodeDtypes(BaseNumpyAppTest): def test_str_unicode(self): from _numpypy import str_, unicode_, character, flexible, generic - + assert str_.mro() == [str_, str, basestring, character, flexible, generic, object] assert unicode_.mro() == [unicode_, unicode, basestring, character, flexible, generic, object] @@ -564,7 +578,7 @@ from _numpypy import dtype d = dtype({'names': ['a', 'b', 'c'], }) - + class AppTestNotDirect(BaseNumpyAppTest): def setup_class(cls): BaseNumpyAppTest.setup_class.im_func(cls) diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -281,11 +281,13 @@ assert zeros(()).shape == () def test_size(self): - from _numpypy import array + from _numpypy import array,arange,cos assert array(3).size == 1 a = array([1, 2, 3]) assert a.size == 3 assert (a + a).size == 3 + ten = cos(1 + arange(10)).size + assert ten == 10 def test_empty(self): """ @@ -1246,6 +1248,7 @@ a = arange(3*2*6).reshape((3,2,6)) b = arange(3*2*6)[::-1].reshape((2,6,3)) assert dot(a, b)[2,0,1,2] == 1140 + assert (dot([[1,2],[3,4]],[5,6]) == [17, 39]).all() def test_dot_constant(self): from _numpypy import array, dot @@ -1530,6 +1533,12 @@ # test virtual assert ((x + x).swapaxes(0,1) == array([[[ 2, 4, 6], [14, 16, 18]], [[ 8, 10, 12], [20, 22, 24]]])).all() + + def test_filter_bug(self): + from numpypy import array + a = array([1.0,-1.0]) + a[a<0] = -a[a<0] + assert (a == [1, 1]).all() class AppTestMultiDim(BaseNumpyAppTest): def test_init(self): @@ -1991,6 +2000,7 @@ assert a[::2].item(1) == 3 assert (a + a).item(1) == 4 raises(ValueError, "array(5).item(1)") + assert array([1]).item() == 1 class AppTestSupport(BaseNumpyAppTest): def setup_class(cls): diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -13,11 +13,13 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.rlib import jit + VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True}) degToRad = math.pi / 180.0 log2 = math.log(2) -log2e = 1./log2 +log2e = 1. / log2 + def simple_unary_op(func): specialize.argtype(1)(func) @@ -66,7 +68,7 @@ class BaseType(object): _attrs_ = () - + def _unimplemented_ufunc(self, *args): raise NotImplementedError @@ -133,7 +135,7 @@ width, storage, i, offset, value) else: libffi.array_setitem_T(self.T, width, storage, i, offset, value) - + def store(self, arr, width, i, offset, box): self._write(arr.storage, width, i, offset, self.unbox(box)) @@ -242,7 +244,7 @@ class NonNativePrimitive(Primitive): _mixin_ = True - + def _read(self, storage, width, i, offset): if we_are_translated(): res = libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T), @@ -528,7 +530,7 @@ T = rffi.LONGLONG BoxType = interp_boxes.W_Int64Box - format_code = "q" + format_code = "q" _coerce = func_with_new_name(_int64_coerce, '_coerce') @@ -900,7 +902,7 @@ T = rffi.FLOAT BoxType = interp_boxes.W_Float32Box - format_code = "f" + format_code = "f" class Float64(BaseType, Float): _attrs_ = () @@ -918,7 +920,7 @@ class BaseStringType(object): _mixin_ = True - + def __init__(self, size=0): self.size = size @@ -949,14 +951,14 @@ def get_element_size(self): return self.size - + def read(self, arr, width, i, offset, dtype=None): if dtype is None: dtype = arr.dtype return interp_boxes.W_VoidBox(arr, i + offset, dtype) @jit.unroll_safe - def coerce(self, space, dtype, w_item): + def coerce(self, space, dtype, w_item): from pypy.module.micronumpy.interp_numarray import W_NDimArray if isinstance(w_item, interp_boxes.W_VoidBox): diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -7,7 +7,6 @@ from pypy.interpreter.error import operationerrfmt from pypy.rpython.module.ll_os import RegisterOs from pypy.rpython.module import ll_os_stat -from pypy.rlib import rwin32 from pypy.rpython.lltypesystem import rffi, lltype from pypy.rpython.tool import rffi_platform from pypy.translator.tool.cbuild import ExternalCompilationInfo @@ -624,7 +623,7 @@ def kill(space, pid, sig): "Kill a process with a signal." try: - rwin32.os_kill(pid, sig) + rposix.os_kill(pid, sig) except OSError, e: raise wrap_oserror(space, e) @@ -640,7 +639,7 @@ """Abort the interpreter immediately. This 'dumps core' or otherwise fails in the hardest way possible on the hosting operating system.""" import signal - rwin32.os_kill(os.getpid(), signal.SIGABRT) + rposix.os_kill(os.getpid(), signal.SIGABRT) @unwrap_spec(src='str0', dst='str0') def link(space, src, dst): diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -486,12 +486,11 @@ if hasattr(__import__(os.name), "spawnve"): def test_spawnve(self): os = self.posix - import sys - print self.python + env = {'PATH':os.environ['PATH'], 'FOOBAR': '42'} ret = os.spawnve(os.P_WAIT, self.python, ['python', '-c', "raise(SystemExit(int(__import__('os').environ['FOOBAR'])))"], - {'FOOBAR': '42'}) + env) assert ret == 42 def test_popen(self): @@ -946,6 +945,20 @@ import os assert hasattr(os, 'kill') + def test_pipe_flush(self): + os = self.posix + ffd, gfd = os.pipe() + f = os.fdopen(ffd, 'r') + g = os.fdopen(gfd, 'w') + g.write('he') + g.flush() + x = f.read(1) + assert x == 'h' + f.flush() + x = f.read(1) + assert x == 'e' + + class AppTestEnvironment(object): def setup_class(cls): cls.space = space diff --git a/pypy/module/rctime/interp_time.py b/pypy/module/rctime/interp_time.py --- a/pypy/module/rctime/interp_time.py +++ b/pypy/module/rctime/interp_time.py @@ -12,6 +12,15 @@ _POSIX = os.name == "posix" _WIN = os.name == "nt" +_CYGWIN = sys.platform == "cygwin" + +_time_zones = [] +if _CYGWIN: + _time_zones = ["GMT-12", "GMT-11", "GMT-10", "GMT-9", "GMT-8", "GMT-7", + "GMT-6", "GMT-5", "GMT-4", "GMT-3", "GMT-2", "GMT-1", + "GMT", "GMT+1", "GMT+2", "GMT+3", "GMT+4", "GMT+5", + "GMT+6", "GMT+7", "GMT+8", "GMT+9", "GMT+10", "GMT+11", + "GMT+12", "GMT+13", "GMT+14"] if _WIN: # Interruptible sleeps on Windows: @@ -107,11 +116,17 @@ CConfig.timeval = platform.Struct("struct timeval", [("tv_sec", rffi.INT), ("tv_usec", rffi.INT)]) - CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), - ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), - ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), - ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT), ("tm_gmtoff", rffi.LONG), - ("tm_zone", rffi.CCHARP)]) + if _CYGWIN: + CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), + ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), + ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), + ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT)]) + else: + CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), + ("tm_min", rffi.INT), ("tm_hour", rffi.INT), ("tm_mday", rffi.INT), + ("tm_mon", rffi.INT), ("tm_year", rffi.INT), ("tm_wday", rffi.INT), + ("tm_yday", rffi.INT), ("tm_isdst", rffi.INT), ("tm_gmtoff", rffi.LONG), + ("tm_zone", rffi.CCHARP)]) elif _WIN: calling_conv = 'win' CConfig.tm = platform.Struct("struct tm", [("tm_sec", rffi.INT), @@ -202,35 +217,81 @@ tzname = rffi.charp2str(tzname_ptr[0]), rffi.charp2str(tzname_ptr[1]) if _POSIX: - YEAR = (365 * 24 + 6) * 3600 + if _CYGWIN: + YEAR = (365 * 24 + 6) * 3600 - t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR) - # we cannot have reference to stack variable, put it on the heap - t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') - t_ref[0] = rffi.cast(rffi.TIME_T, t) - p = c_localtime(t_ref) - janzone = -p.c_tm_gmtoff - tm_zone = rffi.charp2str(p.c_tm_zone) - janname = [" ", tm_zone][bool(tm_zone)] - tt = t + YEAR / 2 - t_ref[0] = rffi.cast(rffi.TIME_T, tt) - p = c_localtime(t_ref) - lltype.free(t_ref, flavor='raw') - tm_zone = rffi.charp2str(p.c_tm_zone) - julyzone = -p.c_tm_gmtoff - julyname = [" ", tm_zone][bool(tm_zone)] + # about January 11th + t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR + 10 * 24 * 3600) + # we cannot have reference to stack variable, put it on the heap + t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') + t_ref[0] = rffi.cast(rffi.TIME_T, t) + p = c_localtime(t_ref) + q = c_gmtime(t_ref) + janzone = (p.c_tm_hour + 24 * p.c_tm_mday) - (q.c_tm_hour + 24 * q.c_tm_mday) + if janzone < -12: + janname = " " + elif janzone > 14: + janname = " " + else: + janname = _time_zones[janzone - 12] + janzone = janzone * 3600 + # about July 11th + tt = t + YEAR / 2 + t_ref[0] = rffi.cast(rffi.TIME_T, tt) + p = c_localtime(t_ref) + q = c_gmtime(t_ref) + julyzone = (p.c_tm_hour + 24 * p.c_tm_mday) - (q.c_tm_hour + 24 * q.c_tm_mday) + if julyzone < -12: + julyname = " " + elif julyzone > 14: + julyname = " " + else: + julyname = _time_zones[julyzone - 12] + julyzone = julyzone * 3600 + lltype.free(t_ref, flavor='raw') - if janzone < julyzone: - # DST is reversed in the southern hemisphere - timezone = julyzone - altzone = janzone - daylight = int(janzone != julyzone) - tzname = [julyname, janname] + if janzone < julyzone: + # DST is reversed in the southern hemisphere + timezone = julyzone + altzone = janzone + daylight = int(janzone != julyzone) + tzname = [julyname, janname] + else: + timezone = janzone + altzone = julyzone + daylight = int(janzone != julyzone) + tzname = [janname, julyname] + else: - timezone = janzone - altzone = julyzone - daylight = int(janzone != julyzone) - tzname = [janname, julyname] + YEAR = (365 * 24 + 6) * 3600 + + t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR) + # we cannot have reference to stack variable, put it on the heap + t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw') + t_ref[0] = rffi.cast(rffi.TIME_T, t) + p = c_localtime(t_ref) + janzone = -p.c_tm_gmtoff + tm_zone = rffi.charp2str(p.c_tm_zone) + janname = [" ", tm_zone][bool(tm_zone)] + tt = t + YEAR / 2 + t_ref[0] = rffi.cast(rffi.TIME_T, tt) + p = c_localtime(t_ref) + lltype.free(t_ref, flavor='raw') + tm_zone = rffi.charp2str(p.c_tm_zone) + julyzone = -p.c_tm_gmtoff + julyname = [" ", tm_zone][bool(tm_zone)] + + if janzone < julyzone: + # DST is reversed in the southern hemisphere + timezone = julyzone + altzone = janzone + daylight = int(janzone != julyzone) + tzname = [julyname, janname] + else: + timezone = janzone + altzone = julyzone + daylight = int(janzone != julyzone) + tzname = [janname, julyname] _set_module_object(space, "timezone", space.wrap(timezone)) _set_module_object(space, 'daylight', space.wrap(daylight)) @@ -361,9 +422,12 @@ rffi.setintfield(glob_buf, 'c_tm_yday', tm_yday) rffi.setintfield(glob_buf, 'c_tm_isdst', space.int_w(tup_w[8])) if _POSIX: - # actually never happens, but makes annotator happy - glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) - rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) + if _CYGWIN: + pass + else: + # actually never happens, but makes annotator happy + glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) + rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) w_accept2dyear = _get_module_object(space, "accept2dyear") accept2dyear = space.int_w(w_accept2dyear) diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py @@ -484,6 +484,20 @@ assert tf_b(-126) == -42 assert tf_b._ptr is ptr + def test_custom_from_param(self): + class A(c_byte): + @classmethod + def from_param(cls, obj): + seen.append(obj) + return -126 + tf_b = dll.tf_b + tf_b.restype = c_byte + tf_b.argtypes = (c_byte,) + tf_b.argtypes = [A] + seen = [] + assert tf_b("yadda") == -42 + assert seen == ["yadda"] + def test_warnings(self): import warnings warnings.simplefilter("always") diff --git a/pypy/module/unicodedata/generate_unicodedb.py b/pypy/module/unicodedata/generate_unicodedb.py --- a/pypy/module/unicodedata/generate_unicodedb.py +++ b/pypy/module/unicodedata/generate_unicodedb.py @@ -399,9 +399,19 @@ print >> outfile, 'version = %r' % version print >> outfile - cjk_end = 0x9FA5 - if version >= "4.1": - cjk_end = 0x9FBB + if version < "4.1": + cjk_interval = ("(0x3400 <= code <= 0x4DB5 or" + " 0x4E00 <= code <= 0x9FA5 or" + " 0x20000 <= code <= 0x2A6D6)") + elif version < "5": # don't know the exact limit + cjk_interval = ("(0x3400 <= code <= 0x4DB5 or" + " 0x4E00 <= code <= 0x9FBB or" + " 0x20000 <= code <= 0x2A6D6)") + else: + cjk_interval = ("(0x3400 <= code <= 0x4DB5 or" + " 0x4E00 <= code <= 0x9FCB or" + " 0x20000 <= code <= 0x2A6D6 or" + " 0x2A700 <= code <= 0x2B734)") write_character_names(outfile, table, base_mod) @@ -457,9 +467,7 @@ if not ('0' <= c <= '9' or 'A' <= c <= 'F'): raise KeyError code = int(cjk_code, 16) - if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x%X or - 0x20000 <= code <= 0x2A6D6): + if %s: return code raise KeyError @@ -481,9 +489,7 @@ raise def name(code): - if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x%X or - 0x20000 <= code <= 0x2A6D6): + if %s: return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) @@ -505,7 +511,7 @@ return base_mod.lookup_charcode(code) else: raise -''' % (cjk_end, cjk_end) +''' % (cjk_interval, cjk_interval) # Categories writeDbRecord(outfile, table) diff --git a/pypy/module/unicodedata/test/test_unicodedata.py b/pypy/module/unicodedata/test/test_unicodedata.py --- a/pypy/module/unicodedata/test/test_unicodedata.py +++ b/pypy/module/unicodedata/test/test_unicodedata.py @@ -53,7 +53,12 @@ import unicodedata cases = ((0x3400, 0x4DB5), (0x4E00, 0x9FA5)) - if unicodedata.unidata_version >= "4.1": + if unicodedata.unidata_version >= "5": # don't know the exact limit + cases = ((0x3400, 0x4DB5), + (0x4E00, 0x9FCB), + (0x20000, 0x2A6D6), + (0x2A700, 0x2B734)) + elif unicodedata.unidata_version >= "4.1": cases = ((0x3400, 0x4DB5), (0x4E00, 0x9FBB), (0x20000, 0x2A6D6)) diff --git a/pypy/module/unicodedata/unicodedb_5_2_0.py b/pypy/module/unicodedata/unicodedb_5_2_0.py --- a/pypy/module/unicodedata/unicodedb_5_2_0.py +++ b/pypy/module/unicodedata/unicodedb_5_2_0.py @@ -134464,9 +134464,7 @@ if not ('0' <= c <= '9' or 'A' <= c <= 'F'): raise KeyError code = int(cjk_code, 16) - if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x9FBB or - 0x20000 <= code <= 0x2A6D6): + if (0x3400 <= code <= 0x4DB5 or 0x4E00 <= code <= 0x9FCB or 0x20000 <= code <= 0x2A6D6 or 0x2A700 <= code <= 0x2B734): return code raise KeyError @@ -134488,9 +134486,7 @@ raise def name(code): - if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x9FBB or - 0x20000 <= code <= 0x2A6D6): + if (0x3400 <= code <= 0x4DB5 or 0x4E00 <= code <= 0x9FCB or 0x20000 <= code <= 0x2A6D6 or 0x2A700 <= code <= 0x2B734): return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) @@ -134501,7 +134497,7 @@ v_code = vl_code % len(_hangul_V) return ("HANGUL SYLLABLE " + _hangul_L[l_code] + _hangul_V[v_code] + _hangul_T[t_code]) - + if not base_mod: return lookup_charcode(code) else: diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -285,19 +285,6 @@ def str__Bytearray(space, w_bytearray): return space.wrap(''.join(w_bytearray.data)) -def str_count__Bytearray_Int_ANY_ANY(space, w_bytearray, w_char, w_start, w_stop): - char = w_char.intval - bytearray = w_bytearray.data - length = len(bytearray) - start, stop = slicetype.unwrap_start_stop( - space, length, w_start, w_stop, False) - count = 0 - for i in range(start, min(stop, length)): - c = w_bytearray.data[i] - if ord(c) == char: - count += 1 - return space.wrap(count) - def str_count__Bytearray_ANY_ANY_ANY(space, w_bytearray, w_char, w_start, w_stop): w_char = space.wrap(space.bufferstr_new_w(w_char)) w_str = str__Bytearray(space, w_bytearray) diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py --- a/pypy/objspace/std/longtype.py +++ b/pypy/objspace/std/longtype.py @@ -52,7 +52,10 @@ base = space.int_w(w_base) if space.isinstance_w(w_value, space.w_unicode): - from pypy.objspace.std.unicodeobject import unicode_to_decimal_w + if space.config.objspace.std.withropeunicode: + from pypy.objspace.std.ropeunicodeobject import unicode_to_decimal_w + else: + from pypy.objspace.std.unicodeobject import unicode_to_decimal_w s = unicode_to_decimal_w(space, w_value) else: try: diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py --- a/pypy/objspace/std/test/test_bytearrayobject.py +++ b/pypy/objspace/std/test/test_bytearrayobject.py @@ -168,7 +168,6 @@ assert bytearray('hello').count('l') == 2 assert bytearray('hello').count(bytearray('l')) == 2 assert bytearray('hello').count(memoryview('l')) == 2 - assert bytearray('hello').count(ord('l')) == 2 assert bytearray('hello').index('e') == 1 assert bytearray('hello').rindex('l') == 3 diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py --- a/pypy/objspace/std/test/test_stringobject.py +++ b/pypy/objspace/std/test/test_stringobject.py @@ -413,6 +413,9 @@ assert 'abcdefghiabc'.find('def', 4) == -1 assert 'abcdef'.find('', 13) == -1 assert 'abcdefg'.find('def', 5, None) == -1 + assert 'abcdef'.find('d', 6, 0) == -1 + assert 'abcdef'.find('d', 3, 3) == -1 + raises(TypeError, 'abcdef'.find, 'd', 1.0) def test_index(self): from sys import maxint diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -304,6 +304,7 @@ def test_long_from_unicode(self): assert long(u'12345678901234567890') == 12345678901234567890 assert int(u'12345678901234567890') == 12345678901234567890 + assert long(u'123', 7) == 66 def test_int_from_unicode(self): assert int(u'12345') == 12345 diff --git a/pypy/rlib/_rsocket_rffi.py b/pypy/rlib/_rsocket_rffi.py --- a/pypy/rlib/_rsocket_rffi.py +++ b/pypy/rlib/_rsocket_rffi.py @@ -58,12 +58,12 @@ header_lines = [ '#include ', '#include ', - '#include ', # winsock2 defines AF_UNIX, but not sockaddr_un '#undef AF_UNIX', ] if _MSVC: header_lines.extend([ + '#include ', # these types do not exist on microsoft compilers 'typedef int ssize_t;', 'typedef unsigned __int16 uint16_t;', @@ -71,7 +71,6 @@ ]) else: # MINGW includes = ('stdint.h',) - """ header_lines.extend([ '''\ #ifndef _WIN32_WINNT @@ -89,7 +88,6 @@ u_long keepaliveinterval; };''' ]) - """ HEADER = '\n'.join(header_lines) COND_HEADER = '' constants = {} diff --git a/pypy/rlib/rope.py b/pypy/rlib/rope.py --- a/pypy/rlib/rope.py +++ b/pypy/rlib/rope.py @@ -769,11 +769,11 @@ len2 = subnode.length() if stop > len1 or stop == -1: stop = len1 + if stop - start < 0: + return -1 if len2 == 1: return find_int(node, subnode.getint(0), start, stop) if len2 == 0: - if (stop - start) < 0: - return -1 return start if len2 > stop - start: return -1 diff --git a/pypy/rlib/rposix.py b/pypy/rlib/rposix.py --- a/pypy/rlib/rposix.py +++ b/pypy/rlib/rposix.py @@ -246,3 +246,10 @@ return nt._getfullpathname(path) else: return nt._getfullpathname(path.as_bytes()) + +if os.name == 'nt': + from pypy.rlib import rwin32 + os_kill = rwin32.os_kill +else: + os_kill = os.kill + diff --git a/pypy/rlib/rsdl/RIMG.py b/pypy/rlib/rsdl/RIMG.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RIMG.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_image.h'], - frameworks = ['SDL_image'], - include_dirs = ['/Library/Frameworks/SDL_image.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_image.h'], - libraries=['SDL_image'], - ) - -eci = eci.merge(RSDL.eci) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -Load = external('IMG_Load', [rffi.CCHARP], RSDL.SurfacePtr) diff --git a/pypy/rlib/rsdl/RMix.py b/pypy/rlib/rsdl/RMix.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix.py +++ /dev/null @@ -1,68 +0,0 @@ -import sys -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rlib.rsdl import RSDL - - -if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL_mixer.h'], - frameworks = ['SDL_mixer'], - include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Headers'] - ) -else: - eci = ExternalCompilationInfo( - includes=['SDL_mixer.h'], - libraries=['SDL_mixer'], - ) - -eci = eci.merge(RSDL.eci) -eci = eci.merge(eci) -eci = eci.merge(eci) - -ChunkPtr = lltype.Ptr(lltype.ForwardReference()) - -class CConfig: - _compilation_info_ = eci - - Chunk = platform.Struct('Mix_Chunk', [('allocated', rffi.INT), - ('abuf', RSDL.Uint8P), - ('alen', RSDL.Uint32), - ('volume', RSDL.Uint8)]) - -globals().update(platform.configure(CConfig)) - -ChunkPtr.TO.become(Chunk) - - -Buffer = rffi.CArray(RSDL.Uint8) - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -OpenAudio = external('Mix_OpenAudio', - [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], - rffi.INT) - -CloseAudio = external('Mix_CloseAudio', [], lltype.Void) - -LoadWAV_RW = external('Mix_LoadWAV_RW', - [RSDL.RWopsPtr, rffi.INT], - ChunkPtr) - -def LoadWAV(filename_ccharp): - with rffi.scoped_str2charp('rb') as mode: - return LoadWAV_RW(RSDL.RWFromFile(filename_ccharp, mode), 1) - - -PlayChannelTimed = external('Mix_PlayChannelTimed', - [rffi.INT, ChunkPtr, rffi.INT, rffi.INT], - rffi.INT) - -def PlayChannel(channel,chunk,loops): - return PlayChannelTimed(channel, chunk, loops, -1) - -"""Returns zero if the channel is not playing. -Otherwise if you passed in -1, the number of channels playing is returned""" -ChannelPlaying = external('Mix_Playing', [rffi.INT], rffi.INT) diff --git a/pypy/rlib/rsdl/RMix_helper.py b/pypy/rlib/rsdl/RMix_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RMix_helper.py +++ /dev/null @@ -1,24 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RMix, RSDL -from pypy.rpython.tool import rffi_platform as platform - - -def malloc_buffer_chunk(has_own_allocated_buffer, length_bytes, volume): - buffer_pointer = lltype.malloc(RMix.Buffer, length_bytes, flavor='raw') - return malloc_chunk(has_own_allocated_buffer, length_bytes, volume) - -def malloc_chunk(has_own_allocated_buffer, buffer_pointer, length_bytes, volume): - """ - Creates a new Mix_Chunk. - has_own_allocated_buffer: if 1 struct has its own allocated buffer, - if 0 abuf should not be freed - buffer_pointer: pointer to audio data - length_bytes: length of audio data in bytes - volume: Per-sample volume, 0-128 (normally - MIX_MAX_VOLUME after loading)""" - p = lltype.malloc(RMix.Chunk, flavor='raw') - rffi.setintfield(p, 'c_allocated', has_own_allocated_buffer) - rffi.setintfield(p, 'c_abuf', buffer_pointer) - rffi.setintfield(p, 'c_alen', length_bytes) - rffi.setintfield(p, 'c_volume', volume) - return p \ No newline at end of file diff --git a/pypy/rlib/rsdl/RSDL.py b/pypy/rlib/rsdl/RSDL.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL.py +++ /dev/null @@ -1,249 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.tool import rffi_platform as platform -from pypy.rlib.rsdl.constants import _constants -from pypy.rlib.rsdl.eci import get_rsdl_compilation_info -from pypy.rlib.objectmodel import we_are_translated -import py -import sys - -# ------------------------------------------------------------------------------ - -eci = get_rsdl_compilation_info() - -def external(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci) - -# ------------------------------------------------------------------------------ - -RectPtr = lltype.Ptr(lltype.ForwardReference()) -SurfacePtr = lltype.Ptr(lltype.ForwardReference()) -PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) -EventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) -MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyPtr = lltype.Ptr(lltype.ForwardReference()) -RWopsPtr = lltype.Ptr(lltype.ForwardReference()) - -# ------------------------------------------------------------------------------ - -class CConfig: - _compilation_info_ = eci - - Uint8 = platform.SimpleType('Uint8', rffi.INT) - Uint16 = platform.SimpleType('Uint16', rffi.INT) - Sint16 = platform.SimpleType('Sint16', rffi.INT) - Uint32 = platform.SimpleType('Uint32', rffi.INT) - - Rect = platform.Struct('SDL_Rect', - [('x', rffi.INT), - ('y', rffi.INT), - ('w', rffi.INT), - ('h', rffi.INT)]) - - Surface = platform.Struct('SDL_Surface', - [('w', rffi.INT), - ('h', rffi.INT), - ('format', PixelFormatPtr), - ('pitch', rffi.INT), - ('pixels', rffi.UCHARP)]) - - PixelFormat = platform.Struct('SDL_PixelFormat', - [('BitsPerPixel', rffi.INT), - ('BytesPerPixel', rffi.INT), - ('Rmask', rffi.INT), - ('Gmask', rffi.INT), - ('Bmask', rffi.INT), - ('Amask', rffi.INT)]) - - Event = platform.Struct('SDL_Event', - [('type', rffi.INT)]) - - keysym = platform.Struct('SDL_keysym', - [('scancode', rffi.INT), - ('sym', rffi.INT), - ('mod', rffi.INT), - ('unicode', rffi.INT)]) - - KeyboardEvent = platform.Struct('SDL_KeyboardEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('keysym', keysym)]) - - MouseButtonEvent = platform.Struct('SDL_MouseButtonEvent', - [('type', rffi.INT), - ('button', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT)]) - - MouseMotionEvent = platform.Struct('SDL_MouseMotionEvent', - [('type', rffi.INT), - ('state', rffi.INT), - ('x', rffi.INT), - ('y', rffi.INT), - ('xrel', rffi.INT), - ('yrel', rffi.INT)]) - - QuitEvent = platform.Struct('SDL_QuitEvent', - [('type', rffi.INT)]) - - RWops = platform.Struct('SDL_RWops', []) - -# ------------------------------------------------------------------------------ - -for _prefix, _list in _constants.items(): - for _name in _list: - setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) - -# ------------------------------------------------------------------------------ - -globals().update(platform.configure(CConfig)) - -# ------------------------------------------------------------------------------ - -RectPtr.TO.become(Rect) -SurfacePtr.TO.become(Surface) -PixelFormatPtr.TO.become(PixelFormat) -EventPtr.TO.become(Event) -KeyboardEventPtr.TO.become(KeyboardEvent) -MouseButtonEventPtr.TO.become(MouseButtonEvent) -MouseMotionEventPtr.TO.become(MouseMotionEvent) -RWopsPtr.TO.become(RWops) - -# ------------------------------------------------------------------------------ - -Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) -Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) -# need to add signed hint here -Sint16P = lltype.Ptr(lltype.Array(Sint16, hints={'nolength': True})) -Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) - - -# ------------------------------------------------------------------------------ - -_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Mac_Init = external('SDL_Init', - [Uint32], - rffi.INT) - -Quit = external('SDL_Quit', [], - lltype.Void) - -SetVideoMode = external('SDL_SetVideoMode', - [rffi.INT, rffi.INT, rffi.INT, Uint32], - SurfacePtr) - -WM_SetCaption = external('SDL_WM_SetCaption', - [rffi.CCHARP, rffi.CCHARP], - lltype.Void) - -EnableUNICODE = external('SDL_EnableUNICODE', - [rffi.INT], - rffi.INT) - -WaitEvent = external('SDL_WaitEvent', - [EventPtr], - rffi.INT) - -PollEvent = external('SDL_PollEvent', - [EventPtr], - rffi.INT) - -Flip = external('SDL_Flip', - [SurfacePtr], - rffi.INT) - -CreateRGBSurface = external('SDL_CreateRGBSurface', - [Uint32, rffi.INT, rffi.INT, rffi.INT, - Uint32, Uint32, Uint32, Uint32], - SurfacePtr) - -LockSurface = external('SDL_LockSurface', - [SurfacePtr], - rffi.INT) - -UnlockSurface = external('SDL_UnlockSurface', - [SurfacePtr], - lltype.Void) - -FreeSurface = external('SDL_FreeSurface', - [SurfacePtr], - lltype.Void) - -MapRGB = external('SDL_MapRGB', - [PixelFormatPtr, Uint8, Uint8, Uint8], - Uint32) - -GetRGB = external('SDL_GetRGB', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], - lltype.Void) - -GetRGBA = external('SDL_GetRGBA', - [Uint32, PixelFormatPtr, Uint8P, Uint8P, - Uint8P, Uint8P], - lltype.Void) - -FillRect = external('SDL_FillRect', - [SurfacePtr, RectPtr, Uint32], - rffi.INT) - -BlitSurface = external('SDL_UpperBlit', - [SurfacePtr, RectPtr, SurfacePtr, RectPtr], - rffi.INT) - -SetAlpha = external('SDL_SetAlpha', - [SurfacePtr, Uint32, Uint8], - rffi.INT) - -SetColorKey = external('SDL_SetColorKey', - [SurfacePtr, Uint32, Uint32], - rffi.INT) - -ShowCursor = external('SDL_ShowCursor', - [rffi.INT], - rffi.INT) - -GetTicks = external('SDL_GetTicks', - [], - Uint32) - -Delay = external('SDL_Delay', - [Uint32], - lltype.Void) - -UpdateRect = external('SDL_UpdateRect', - [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], - lltype.Void) - -GetKeyName = external('SDL_GetKeyName', - [rffi.INT], - rffi.CCHARP) - -GetError = external('SDL_GetError', - [], - rffi.CCHARP) - -RWFromFile = external('SDL_RWFromFile', - [rffi.CCHARP, rffi.CCHARP], - RWopsPtr) - -# ------------------------------------------------------------------------------ - - -if sys.platform == 'darwin': - def Init(flags): - if not we_are_translated(): - from AppKit import NSApplication - NSApplication.sharedApplication() - #CustomApplicationMain(0, " ") - return _Init(flags) - #Mac_Init() -else: - Init = _Init - - - diff --git a/pypy/rlib/rsdl/RSDL_helper.py b/pypy/rlib/rsdl/RSDL_helper.py deleted file mode 100644 --- a/pypy/rlib/rsdl/RSDL_helper.py +++ /dev/null @@ -1,108 +0,0 @@ -from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rlib.rsdl import RSDL - -def get_rgb(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - RSDL.GetRGB(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result = r, g, b - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_rgba(color, format): - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 4, flavor='raw') - try: - RSDL.GetRGBA(color, - format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2), - rffi.ptradd(rgb, 3)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - a = rffi.cast(lltype.Signed, rgb[3]) - result = r, g, b, a - finally: - lltype.free(rgb, flavor='raw') - - return result - -def get_pixel(image, x, y): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - return rffi.cast(RSDL.Uint32, p[0]) - elif bpp == 3: - p0 = rffi.cast(lltype.Signed, p[0]) - p1 = rffi.cast(lltype.Signed, p[1]) - p2 = rffi.cast(lltype.Signed, p[2]) - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - result = p0 << 16 | p1 << 8 | p2 - else: - result = p0 | p1 << 8 | p2 << 16 - return rffi.cast(RSDL.Uint32, result) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - return p[0] - else: - raise ValueError("bad BytesPerPixel") - -def set_pixel(image, x, y, pixel): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - p[0] = rffi.cast(rffi.UCHAR,pixel) - elif bpp == 2: - p = rffi.cast(RSDL.Uint16P, p) - p[0] = rffi.cast(RSDL.Uint16,pixel) - elif bpp == 3: - if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - p[0] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - else: - p[0] = rffi.cast(rffi.UCHAR,pixel & 0xFF) - p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) - p[2] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) - elif bpp == 4: - p = rffi.cast(RSDL.Uint32P, p) - p[0] = rffi.cast(RSDL.Uint32, pixel) - else: - raise ValueError("bad BytesPerPixel") - -def mallocrect(x, y, w, h): - p = lltype.malloc(RSDL.Rect, flavor='raw') - rffi.setintfield(p, 'c_x', x) - rffi.setintfield(p, 'c_y', y) - rffi.setintfield(p, 'c_w', w) - rffi.setintfield(p, 'c_h', h) - return p - -def blit_complete_surface(src, dst, x, y): - dstrect = mallocrect(x, y, rffi.getintfield(src, 'c_w'), rffi.getintfield(src, 'c_w')) - RSDL.BlitSurface(src, lltype.nullptr(RSDL.Rect), dst, dstrect) - lltype.free(dstrect, flavor='raw') - diff --git a/pypy/rlib/rsdl/__init__.py b/pypy/rlib/rsdl/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/constants.py b/pypy/rlib/rsdl/constants.py deleted file mode 100644 --- a/pypy/rlib/rsdl/constants.py +++ /dev/null @@ -1,261 +0,0 @@ - -_constants = { - 'SDL_': [ # constants with the 'SDL_' prefix in C - "YV12_OVERLAY", - "IYUV_OVERLAY", - "YUY2_OVERLAY", - "UYVY_OVERLAY", - "YVYU_OVERLAY", - - "SWSURFACE", - "HWSURFACE", - "RESIZABLE", - "ASYNCBLIT", - "OPENGL", - "OPENGLBLIT", - "ANYFORMAT", - "HWPALETTE", - "DOUBLEBUF", - "FULLSCREEN", - "HWACCEL", - "SRCCOLORKEY", - "RLEACCELOK", - "RLEACCEL", - "SRCALPHA", - "PREALLOC", - "NOFRAME", - - "GL_RED_SIZE", - "GL_GREEN_SIZE", - "GL_BLUE_SIZE", - "GL_ALPHA_SIZE", - "GL_BUFFER_SIZE", - "GL_DOUBLEBUFFER", - "GL_DEPTH_SIZE", - "GL_STENCIL_SIZE", - "GL_ACCUM_RED_SIZE", - "GL_ACCUM_GREEN_SIZE", - "GL_ACCUM_BLUE_SIZE", - "GL_ACCUM_ALPHA_SIZE", - "GL_STEREO", #if SDL_VERSION_ATLEAST(1, 2, 5) - "GL_MULTISAMPLEBUFFERS", #if SDL_VERSION_ATLEAST(1, 2, 6) - "GL_MULTISAMPLESAMPLES", #if SDL_VERSION_ATLEAST(1, 2, 6) - - "NOEVENT", - "ACTIVEEVENT", - "KEYDOWN", - "KEYUP", - "MOUSEMOTION", - "MOUSEBUTTONDOWN", - "MOUSEBUTTONUP", - "BUTTON_LEFT", - "BUTTON_MIDDLE", - "BUTTON_RIGHT", - "BUTTON_WHEELUP", - "BUTTON_WHEELDOWN", - "JOYAXISMOTION", - "JOYBALLMOTION", - "JOYHATMOTION", - "JOYBUTTONDOWN", - "JOYBUTTONUP", - "VIDEORESIZE", - "VIDEOEXPOSE", - "QUIT", - "SYSWMEVENT", - "USEREVENT", - "NUMEVENTS", - - "HAT_CENTERED", - "HAT_UP", - "HAT_RIGHTUP", - "HAT_RIGHT", - "HAT_RIGHTDOWN", - "HAT_DOWN", - "HAT_LEFTDOWN", - "HAT_LEFT", - "HAT_LEFTUP", - - "DISABLE", - "ENABLE", - - # the following ones are not exposed in Pygame - "INIT_VIDEO", - "BYTEORDER", - "BIG_ENDIAN", - "LIL_ENDIAN", - ], - - '': [ # constants with no prefix in C - "TIMER_RESOLUTION", - "AUDIO_U8", - "AUDIO_S8", - "AUDIO_U16LSB", - "AUDIO_S16LSB", - "AUDIO_U16MSB", - "AUDIO_S16MSB", - "AUDIO_U16", - "AUDIO_S16", - "AUDIO_U16SYS", - "AUDIO_S16SYS", - - "KMOD_NONE", - "KMOD_LSHIFT", - "KMOD_RSHIFT", - "KMOD_LCTRL", - "KMOD_RCTRL", - "KMOD_LALT", - "KMOD_RALT", - "KMOD_LMETA", - "KMOD_RMETA", - "KMOD_NUM", - "KMOD_CAPS", - "KMOD_MODE", - - "KMOD_CTRL", - "KMOD_SHIFT", - "KMOD_ALT", - "KMOD_META", - ], - - 'SDL': [ # constants with the 'SDL' prefix in C - "K_UNKNOWN", - "K_FIRST", - "K_BACKSPACE", - "K_TAB", - "K_CLEAR", - "K_RETURN", - "K_PAUSE", - "K_ESCAPE", - "K_SPACE", - "K_EXCLAIM", - "K_QUOTEDBL", - "K_HASH", - "K_DOLLAR", - "K_AMPERSAND", - "K_QUOTE", - "K_LEFTPAREN", - "K_RIGHTPAREN", - "K_ASTERISK", - "K_PLUS", - "K_COMMA", - "K_MINUS", - "K_PERIOD", - "K_SLASH", - "K_0", - "K_1", - "K_2", - "K_3", - "K_4", - "K_5", - "K_6", - "K_7", - "K_8", - "K_9", - "K_COLON", - "K_SEMICOLON", - "K_LESS", - "K_EQUALS", - "K_GREATER", - "K_QUESTION", - "K_AT", - "K_LEFTBRACKET", - "K_BACKSLASH", - "K_RIGHTBRACKET", - "K_CARET", - "K_UNDERSCORE", - "K_BACKQUOTE", - "K_a", - "K_b", - "K_c", - "K_d", - "K_e", - "K_f", - "K_g", - "K_h", - "K_i", - "K_j", - "K_k", - "K_l", - "K_m", - "K_n", - "K_o", - "K_p", - "K_q", - "K_r", - "K_s", - "K_t", - "K_u", - "K_v", - "K_w", - "K_x", - "K_y", - "K_z", - "K_DELETE", - - "K_KP0", - "K_KP1", - "K_KP2", - "K_KP3", - "K_KP4", - "K_KP5", - "K_KP6", - "K_KP7", - "K_KP8", - "K_KP9", - "K_KP_PERIOD", - "K_KP_DIVIDE", - "K_KP_MULTIPLY", - "K_KP_MINUS", - "K_KP_PLUS", - "K_KP_ENTER", - "K_KP_EQUALS", - "K_UP", - "K_DOWN", - "K_RIGHT", - "K_LEFT", - "K_INSERT", - "K_HOME", - "K_END", - "K_PAGEUP", - "K_PAGEDOWN", - "K_F1", - "K_F2", - "K_F3", - "K_F4", - "K_F5", - "K_F6", - "K_F7", - "K_F8", - "K_F9", - "K_F10", - "K_F11", - "K_F12", - "K_F13", - "K_F14", - "K_F15", - - "K_NUMLOCK", - "K_CAPSLOCK", - "K_SCROLLOCK", - "K_RSHIFT", - "K_LSHIFT", - "K_RCTRL", - "K_LCTRL", - "K_RALT", - "K_LALT", - "K_RMETA", - "K_LMETA", - "K_LSUPER", - "K_RSUPER", - "K_MODE", - - "K_HELP", - "K_PRINT", - "K_SYSREQ", - "K_BREAK", - "K_MENU", - "K_POWER", - "K_EURO", - "K_LAST", - ], - } diff --git a/pypy/rlib/rsdl/eci.py b/pypy/rlib/rsdl/eci.py deleted file mode 100644 --- a/pypy/rlib/rsdl/eci.py +++ /dev/null @@ -1,27 +0,0 @@ -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.translator.platform import CompilationError -import py -import sys - -def get_rsdl_compilation_info(): - if sys.platform == 'darwin': - eci = ExternalCompilationInfo( - includes = ['SDL.h'], - include_dirs = ['/Library/Frameworks/SDL.framework/Headers'], - link_files = [ - str(py.path.local(__file__).dirpath().join('macosx-sdl-main/SDLMain.m')), - ], - frameworks = ['SDL', 'Cocoa'] - ) - else: - eci = ExternalCompilationInfo( - includes=['SDL.h'], - ) - eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) - return eci - -def check_sdl_installation(): - from pypy.rpython.tool import rffi_platform as platform - platform.verify_eci(get_rsdl_compilation_info()) - -SDLNotInstalled = (ImportError, CompilationError) diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import - - at interface SDLMain : NSObject - at end diff --git a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m b/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m deleted file mode 100644 --- a/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m +++ /dev/null @@ -1,384 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import "SDL.h" -#import "SDLMain.h" -#import /* for MAXPATHLEN */ -#import - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ - at interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; - at end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ - at interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; - at end -#endif - - at interface SDLApplication : NSApplication - at end - - at implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} - at end - -/* The main class of the application, the application's delegate */ - at implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { - assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } - -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} - at end - - - at implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - - at end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/pypy/rlib/rsdl/test/__init__.py b/pypy/rlib/rsdl/test/__init__.py deleted file mode 100644 diff --git a/pypy/rlib/rsdl/test/applause.wav b/pypy/rlib/rsdl/test/applause.wav deleted file mode 100644 Binary file pypy/rlib/rsdl/test/applause.wav has changed diff --git a/pypy/rlib/rsdl/test/autopath.py b/pypy/rlib/rsdl/test/autopath.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/autopath.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -self cloning, automatic path configuration - -copy this into any subdirectory of pypy from which scripts need -to be run, typically all of the test subdirs. -The idea is that any such script simply issues - - import autopath - -and this will make sure that the parent directory containing "pypy" -is in sys.path. - -If you modify the master "autopath.py" version (in pypy/tool/autopath.py) -you can directly run it which will copy itself on all autopath.py files -it finds under the pypy root directory. - -This module always provides these attributes: - - pypydir pypy root directory path - this_dir directory where this autopath.py resides - -""" - -def __dirinfo(part): - """ return (partdir, this_dir) and insert parent of partdir - into sys.path. If the parent directories don't have the part - an EnvironmentError is raised.""" - - import sys, os - try: - head = this_dir = os.path.realpath(os.path.dirname(__file__)) - except NameError: - head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) - - error = None - while head: - partdir = head - head, tail = os.path.split(head) - if tail == part: - checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py') - if not os.path.exists(checkfile): - error = "Cannot find %r" % (os.path.normpath(checkfile),) - break - else: - error = "Cannot find the parent directory %r of the path %r" % ( - partdir, this_dir) - if not error: - # check for bogus end-of-line style (e.g. files checked out on - # Windows and moved to Unix) - f = open(__file__.replace('.pyc', '.py'), 'r') - data = f.read() - f.close() - if data.endswith('\r\n') or data.endswith('\r'): - error = ("Bad end-of-line style in the .py files. Typically " - "caused by a zip file or a checkout done on Windows and " - "moved to Unix or vice-versa.") - if error: - raise EnvironmentError("Invalid source tree - bogus checkout! " + - error) - - pypy_root = os.path.join(head, '') - try: - sys.path.remove(head) - except ValueError: - pass - sys.path.insert(0, head) - - munged = {} - for name, mod in sys.modules.items(): - if '.' in name: - continue - fn = getattr(mod, '__file__', None) - if not isinstance(fn, str): - continue - newname = os.path.splitext(os.path.basename(fn))[0] - if not newname.startswith(part + '.'): - continue - path = os.path.join(os.path.dirname(os.path.realpath(fn)), '') - if path.startswith(pypy_root) and newname != part: - modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep) - if newname != '__init__': - modpaths.append(newname) - modpath = '.'.join(modpaths) - if modpath not in sys.modules: - munged[modpath] = mod - - for name, mod in munged.iteritems(): - if name not in sys.modules: - sys.modules[name] = mod - if '.' in name: - prename = name[:name.rfind('.')] - postname = name[len(prename)+1:] - if prename not in sys.modules: - __import__(prename) - if not hasattr(sys.modules[prename], postname): - setattr(sys.modules[prename], postname, mod) - - return partdir, this_dir - -def __clone(): - """ clone master version of autopath.py into all subdirs """ - from os.path import join, walk - if not this_dir.endswith(join('pypy','tool')): - raise EnvironmentError("can only clone master version " - "'%s'" % join(pypydir, 'tool',_myname)) - - - def sync_walker(arg, dirname, fnames): - if _myname in fnames: - fn = join(dirname, _myname) - f = open(fn, 'rwb+') - try: - if f.read() == arg: - print "checkok", fn - else: - print "syncing", fn - f = open(fn, 'w') - f.write(arg) - finally: - f.close() - s = open(join(pypydir, 'tool', _myname), 'rb').read() - walk(pypydir, sync_walker, s) - -_myname = 'autopath.py' - -# set guaranteed attributes - -pypydir, this_dir = __dirinfo('pypy') - -if __name__ == '__main__': - __clone() diff --git a/pypy/rlib/rsdl/test/conftest.py b/pypy/rlib/rsdl/test/conftest.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -from pypy.rlib.rsdl.eci import check_sdl_installation, SDLNotInstalled -import py - -def pytest_ignore_collect(path): - try: - check_sdl_installation() - except SDLNotInstalled, e: - return True - else: - return False diff --git a/pypy/rlib/rsdl/test/demo.jpg b/pypy/rlib/rsdl/test/demo.jpg deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.jpg has changed diff --git a/pypy/rlib/rsdl/test/demo.png b/pypy/rlib/rsdl/test/demo.png deleted file mode 100644 Binary file pypy/rlib/rsdl/test/demo.png has changed diff --git a/pypy/rlib/rsdl/test/test_basic.py b/pypy/rlib/rsdl/test/test_basic.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_basic.py +++ /dev/null @@ -1,37 +0,0 @@ -import py -from pypy.rlib.rsdl import RSDL -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import rffi - - -def test_sdl_init(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Quit() - -def test_surface_basic(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - assert surface - assert rffi.getintfield(surface, 'c_w') == 150 - assert rffi.getintfield(surface, 'c_h') == 50 - RSDL.FreeSurface(surface) - RSDL.Quit() - - -def test_get_keyname(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - assert RSDL.GetKeyName(RSDL.K_PLUS)[0] == '+' - assert RSDL.GetKeyName(RSDL.K_RIGHTPAREN)[0] == ')' - assert RSDL.GetKeyName(RSDL.K_z)[0] == 'z' - -def test_delay_getticks(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - RSDL.Delay(10) - i = RSDL.GetTicks() - assert i >= 10 - RSDL.Quit() - \ No newline at end of file diff --git a/pypy/rlib/rsdl/test/test_sdl_image.py b/pypy/rlib/rsdl/test/test_sdl_image.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_image.py +++ /dev/null @@ -1,50 +0,0 @@ -import py, os -import autopath -from pypy.rlib.rsdl import RSDL, RIMG, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - - -def test_load_image(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image, 'c_w') == 17 - assert rffi.getintfield(image, 'c_h') == 23 - RSDL.FreeSurface(image) - -def test_image_pixels(): - for filename in ["demo.jpg", "demo.png"]: - image = RIMG.Load(os.path.join(autopath.this_dir, filename)) - assert image - assert rffi.getintfield(image.c_format, 'c_BytesPerPixel') in (3, 4) - RSDL.LockSurface(image) - result = {} - try: - rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') - try: - for y in range(23): - for x in range(y % 13, 17, 13): - color = RSDL_helper.get_pixel(image, x, y) - RSDL.GetRGB(color, - image.c_format, - rffi.ptradd(rgb, 0), - rffi.ptradd(rgb, 1), - rffi.ptradd(rgb, 2)) - r = rffi.cast(lltype.Signed, rgb[0]) - g = rffi.cast(lltype.Signed, rgb[1]) - b = rffi.cast(lltype.Signed, rgb[2]) - result[x, y] = r, g, b - finally: - lltype.free(rgb, flavor='raw') - finally: - RSDL.UnlockSurface(image) - RSDL.FreeSurface(image) - for x, y in result: - f = (x*17 + y*23) / float(17*17+23*23) - expected_r = int(255.0 * (1.0-f)) - expected_g = 0 - expected_b = int(255.0 * f) - r, g, b = result[x, y] - assert abs(r-expected_r) < 10 - assert abs(g-expected_g) < 10 - assert abs(b-expected_b) < 10 diff --git a/pypy/rlib/rsdl/test/test_sdl_mixer.py b/pypy/rlib/rsdl/test/test_sdl_mixer.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_sdl_mixer.py +++ /dev/null @@ -1,33 +0,0 @@ -import py -import os -import time -import autopath -from pypy.rlib.rsdl import RSDL, RMix, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi - -def test_open_mixer(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - RMix.CloseAudio() - -def test_load_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.CloseAudio() - -def test_play_wav(): - if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: - error = rffi.charp2str(RSDL.GetError()) - raise Exception(error) - filename = rffi.str2charp('applause.wav') - applause = RMix.LoadWAV(filename) - rffi.free_charp(filename) - RMix.PlayChannel(-1, applause, -1) - time.sleep(1) - RMix.CloseAudio() - diff --git a/pypy/rlib/rsdl/test/test_surface.py b/pypy/rlib/rsdl/test/test_surface.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_surface.py +++ /dev/null @@ -1,75 +0,0 @@ -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi - -class TestSurface: - - def setup_method(self, meth): - self.dst_surf = RSDL.CreateRGBSurface(0, 300, 300, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - self.src_surf = RSDL.CreateRGBSurface(0, 50, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0x00000000)) - fmt = self.src_surf.c_format - self.black = RSDL.MapRGB(fmt, 0, 0, 0) - self.red = RSDL.MapRGB(fmt, 255, 0, 0) - self.blue = RSDL.MapRGB(fmt, 0, 0, 255) - RSDL.FillRect(self.src_surf, lltype.nullptr(RSDL.Rect), self.red) - - def test_simple(self): - pass # only checks that creating the surfaces works - - def test_set_alpha(self): - # prepare - assert RSDL.SetAlpha(self.src_surf, RSDL.SRCALPHA, 128) == 0 - - # draw - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 10, 10) - RSDL_helper.blit_complete_surface( - self.src_surf, - self.dst_surf, - 20, 20) - - # check - for position, color in ( - (( 0, 0), ( 0,0,0)), # no rect - ((10,10), (127,0,0)), # one rect - ((20,20), (191,0,0)) # two overlapping rects - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert RSDL_helper.get_rgb(fetched_color, self.dst_surf.c_format) == color - - def test_set_color_key(self): - # prepare - fillrect = RSDL_helper.mallocrect(10, 10, 30, 30) - RSDL.FillRect(self.src_surf, fillrect, self.blue) - lltype.free(fillrect, flavor='raw') - assert RSDL.SetColorKey(self.src_surf, RSDL.SRCCOLORKEY, self.blue) == 0 - - # draw - RSDL_helper.blit_complete_surface(self.src_surf, self.dst_surf, 0, 0) - - # check - for position, color in ( - (( 0, 0), self.red), - ((10,10), self.black), - ((20,20), self.black), - ((40,40), self.red) - ): - fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) - assert fetched_color == color - - def teardown_method(self, meth): - RSDL.FreeSurface(self.src_surf) - RSDL.FreeSurface(self.dst_surf) - RSDL.Quit() - diff --git a/pypy/rlib/rsdl/test/test_video.py b/pypy/rlib/rsdl/test/test_video.py deleted file mode 100644 --- a/pypy/rlib/rsdl/test/test_video.py +++ /dev/null @@ -1,241 +0,0 @@ - -import py, sys -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rlib.rarithmetic import r_uint -from pypy.rpython.lltypesystem import lltype, rffi -from pypy import conftest - -# -# This test file is skipped unless run with "py.test --view". -# If it is run as "py.test --view -s", then it interactively asks -# for confirmation that the window looks as expected. -# - - -class TestVideo: - - def setup_method(self, meth): - if not conftest.option.view: - py.test.skip("'--view' not specified, " - "skipping tests that open a window") - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - self.screen = RSDL.SetVideoMode(640, 480, 32, 0) - assert self.screen - self.is_interactive = sys.stdout.isatty() - - def check(self, msg): - if self.is_interactive: - print - answer = raw_input('Interactive test: %s - ok? [Y] ' % msg) - if answer and not answer.upper().startswith('Y'): - py.test.fail(msg) - else: - print msg - - def test_simple(self): - pass # only checks that opening and closing the window works - - def test_fillrect_full(self): - fmt = self.screen.c_format - for colorname, r, g, b in [('dark red', 128, 0, 0), - ('yellow', 255, 255, 0), - ('blue', 0, 0, 255)]: - color = RSDL.MapRGB(fmt, r, g, b) - RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) - RSDL.Flip(self.screen) - self.check("Screen filled with %s" % colorname) - - def test_caption(self): - RSDL.WM_SetCaption("Hello World!", "Hello World!") - self.check('The window caption is "Hello World!"') - - def test_keypresses(self): - if not self.is_interactive: - py.test.skip("interactive test only") - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window should be printed below." - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - char = rffi.getintfield(p.c_keysym, 'c_unicode') - if char != 0: - print 'Key:', unichr(char).encode('utf-8') - else: - print 'Some special key' - else: - print '(event of type %d)' % c_type - finally: - lltype.free(event, flavor='raw') - - def test_poll(self): - if not self.is_interactive: - py.test.skip("interactive test only") - import time, sys - RSDL.EnableUNICODE(1) - print - print "Keys pressed in the Pygame window give a dot." - print " Wait 3 seconds to quit." - timeout = time.time() + 3 - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - while True: - # busy polling - ok = RSDL.PollEvent(event) - ok = rffi.cast(lltype.Signed, ok) - assert ok >= 0 - if ok > 0: - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - sys.stderr.write('.') - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - timeout = time.time() + 3 - else: - if time.time() > timeout: - break - time.sleep(0.05) - finally: - lltype.free(event, flavor='raw') - - def test_mousemove(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Move the Mouse up and down:" - print " Use Escape to quit." - event = lltype.malloc(RSDL.Event, flavor="raw") - directions = [False]*4 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, "c_type") - if c_type == RSDL.MOUSEMOTION: - m = rffi.cast(RSDL.MouseMotionEventPtr, event) - assert rffi.getintfield(m, "c_x") >= 0 - assert rffi.getintfield(m, "c_y") >= 0 - print rffi.getintfield(m, "c_xrel") - directions[0] |= rffi.getintfield(m, "c_xrel")>0 - directions[1] |= rffi.getintfield(m, "c_xrel")<0 - directions[2] |= rffi.getintfield(m, "c_yrel")>0 - directions[3] |= rffi.getintfield(m, "c_yrel")<0 - if False not in directions: - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print " test manually aborted" - py.test.fail(" mousemovement test aborted") - break - finally: - lltype.free(event, flavor='raw') - - - def test_mousebutton_wheel(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Press the given MouseButtons:" - print " Use Escape to pass tests." - - event_tests = [("left button", RSDL.BUTTON_LEFT), - ("middle button", RSDL.BUTTON_MIDDLE), - ("right button", RSDL.BUTTON_RIGHT), - ("scroll up", RSDL.BUTTON_WHEELUP), - ("scroll down", RSDL.BUTTON_WHEELDOWN)] - test_success = [] - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - for button_test in event_tests: - print " press %s:" % button_test[0] - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.MOUSEBUTTONDOWN: - pass - elif c_type == RSDL.MOUSEBUTTONUP: - b = rffi.cast(RSDL.MouseButtonEventPtr, event) - if rffi.getintfield(b, 'c_button') == button_test[1]: - test_success.append(True) - break - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - test_success.append(False) - print " manually aborted" - break - #break - if False in test_success: - py.test.fail("") - finally: - lltype.free(event, flavor='raw') - - - def test_show_hide_cursor(self): - RSDL.ShowCursor(RSDL.DISABLE) - self.check("Is the cursor hidden? ") - RSDL.ShowCursor(RSDL.ENABLE) - self.check("Is the cursor shown? ") - - def test_bit_pattern(self): - HEIGHT = WIDTH = 10 - fmt = self.screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(self.screen) - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = white - else: - c = black - RSDL_helper.set_pixel(self.screen, i, j, c) - RSDL.UnlockSurface(self.screen) - RSDL.Flip(self.screen) - self.check("Upper left corner 10x10 field with vertical black/white stripes") - - def test_blit_rect(self): - surface = RSDL.CreateRGBSurface(0, 150, 50, 32, - r_uint(0x000000FF), - r_uint(0x0000FF00), - r_uint(0x00FF0000), - r_uint(0xFF000000)) - fmt = surface.c_format - color = RSDL.MapRGB(fmt, 255, 0, 0) - RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) - - paintrect = RSDL_helper.mallocrect(75, 0, 150, 50) - dstrect = lltype.malloc(RSDL.Rect, flavor='raw') - try: - color = RSDL.MapRGB(fmt, 255, 128, 0) - RSDL.FillRect(surface, paintrect, color) - - rffi.setintfield(dstrect, 'c_x', 10) - rffi.setintfield(dstrect, 'c_y', 10) - rffi.setintfield(dstrect, 'c_w', 150) - rffi.setintfield(dstrect, 'c_h', 50) - RSDL.BlitSurface(surface, lltype.nullptr(RSDL.Rect), self.screen, dstrect) - RSDL.Flip(self.screen) - finally: - lltype.free(dstrect, flavor='raw') - lltype.free(paintrect, flavor='raw') - RSDL.FreeSurface(surface) - self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border") - - def teardown_method(self, meth): - RSDL.Quit() - diff --git a/pypy/rlib/rwin32.py b/pypy/rlib/rwin32.py --- a/pypy/rlib/rwin32.py +++ b/pypy/rlib/rwin32.py @@ -8,7 +8,6 @@ from pypy.translator.platform import CompilationError from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.rarithmetic import intmask -from pypy.rlib.rposix import validate_fd from pypy.rlib import jit import os, sys, errno @@ -76,7 +75,7 @@ DEFAULT_LANGUAGE = rffi_platform.ConstantInteger( "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)") - for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM + defines = """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM MAX_PATH WAIT_OBJECT_0 WAIT_TIMEOUT INFINITE ERROR_INVALID_HANDLE @@ -84,13 +83,17 @@ WRITE_OWNER PROCESS_ALL_ACCESS PROCESS_CREATE_PROCESS PROCESS_CREATE_THREAD PROCESS_DUP_HANDLE PROCESS_QUERY_INFORMATION - PROCESS_QUERY_LIMITED_INFORMATION PROCESS_SET_QUOTA PROCESS_SUSPEND_RESUME PROCESS_TERMINATE PROCESS_VM_OPERATION PROCESS_VM_READ PROCESS_VM_WRITE CTRL_C_EVENT CTRL_BREAK_EVENT - """.split(): + """ + from pypy.translator.platform import host_factory + static_platform = host_factory() + if static_platform.name == 'msvc': + defines += ' PROCESS_QUERY_LIMITED_INFORMATION' + for name in defines.split(): locals()[name] = rffi_platform.ConstantInteger(name) for k, v in rffi_platform.configure(CConfig).items(): @@ -139,6 +142,7 @@ _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE) def get_osfhandle(fd): + from pypy.rlib.rposix import validate_fd validate_fd(fd) handle = _get_osfhandle(fd) if handle == INVALID_HANDLE_VALUE: @@ -367,18 +371,12 @@ if sig == CTRL_C_EVENT or sig == CTRL_BREAK_EVENT: if GenerateConsoleCtrlEvent(sig, pid) == 0: raise lastWindowsError('os_kill failed generating event') + return handle = OpenProcess(PROCESS_ALL_ACCESS, False, pid) if handle == NULL_HANDLE: raise lastWindowsError('os_kill failed opening process') - t = TerminateProcess(handle, sig) - if t == 0: - err = lastWindowsError('os_kill failed to terminate process') + try: + if TerminateProcess(handle, sig) == 0: + raise lastWindowsError('os_kill failed to terminate process') + finally: CloseHandle(handle) - raise err - t = CloseHandle(handle) - if t == 0: - raise lastWindowsError('os_kill after terminating process,' - ' while closing handle') -else: - #not win32 - os_kill = os.kill diff --git a/pypy/rlib/streamio.py b/pypy/rlib/streamio.py --- a/pypy/rlib/streamio.py +++ b/pypy/rlib/streamio.py @@ -500,7 +500,7 @@ if self.buf: try: self.do_seek(self.tell(), 0) - except MyNotImplementedError: + except (MyNotImplementedError, OSError): pass else: self.buf = "" @@ -713,7 +713,7 @@ if self.buf is not None: try: self.do_seek(self.bufstart-len(self.buf), 1) - except MyNotImplementedError: + except (MyNotImplementedError, OSError): pass else: self.buf = None @@ -968,7 +968,10 @@ def flush_buffers(self): if self.lfbuffer: - self.base.seek(-len(self.lfbuffer), 1) + try: + self.base.seek(-len(self.lfbuffer), 1) + except (MyNotImplementedError, OSError): + return self.lfbuffer = "" self.do_flush() @@ -1102,7 +1105,7 @@ if self.buf: try: self.base.seek(-len(self.buf), 1) - except MyNotImplementedError: + except (MyNotImplementedError, OSError): pass else: self.buf = "" diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py --- a/pypy/rpython/memory/gc/minimark.py +++ b/pypy/rpython/memory/gc/minimark.py @@ -111,10 +111,13 @@ # The following flag is set on externally raw_malloc'ed arrays of pointers. # They are allocated with some extra space in front of them for a bitfield, # one bit per 'card_page_indices' indices. -GCFLAG_HAS_CARDS = first_gcflag << 5 -GCFLAG_CARDS_SET = first_gcflag << 6 # <- at least one card bit is set +GCFLAG_HAS_CARDS = first_gcflag << 6 +GCFLAG_CARDS_SET = first_gcflag << 7 # <- at least one card bit is set +# note that GCFLAG_CARDS_SET is the most significant bit of a byte: +# this is required for the JIT (x86) -TID_MASK = (first_gcflag << 7) - 1 +#GCFLAG_UNUSED = first_gcflag << 5 # this flag is free +TID_MASK = (first_gcflag << 8) - 1 FORWARDSTUB = lltype.GcStruct('forwarding_stub', @@ -995,12 +998,9 @@ def _init_writebarrier_logic(self): DEBUG = self.DEBUG # The purpose of attaching remember_young_pointer to the instance - # instead of keeping it as a regular method is to help the JIT call it. - # Additionally, it makes the code in write_barrier() marginally smaller + # instead of keeping it as a regular method is to + # make the code in write_barrier() marginally smaller # (which is important because it is inlined *everywhere*). - # For x86, there is also an extra requirement: when the JIT calls - # remember_young_pointer(), it assumes that it will not touch the SSE - # registers, so it does not save and restore them (that's a *hack*!). def remember_young_pointer(addr_struct, newvalue): # 'addr_struct' is the address of the object in which we write. # 'newvalue' is the address that we are going to write in there. @@ -1034,6 +1034,17 @@ remember_young_pointer._dont_inline_ = True self.remember_young_pointer = remember_young_pointer # + def jit_remember_young_pointer(addr_struct): + # minimal version of the above, with just one argument, + # called by the JIT when GCFLAG_TRACK_YOUNG_PTRS is set + self.old_objects_pointing_to_young.append(addr_struct) + objhdr = self.header(addr_struct) + objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS + if objhdr.tid & GCFLAG_NO_HEAP_PTRS: + objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS + self.prebuilt_root_objects.append(addr_struct) + self.jit_remember_young_pointer = jit_remember_young_pointer + # if self.card_page_indices > 0: self._init_writebarrier_with_card_marker() @@ -1088,60 +1099,21 @@ self.remember_young_pointer_from_array2 = ( remember_young_pointer_from_array2) - # xxx trying it out for the JIT: a 3-arguments version of the above - def remember_young_pointer_from_array3(addr_array, index, newvalue): + def jit_remember_young_pointer_from_array(addr_array): + # minimal version of the above, with just one argument, + # called by the JIT when GCFLAG_TRACK_YOUNG_PTRS is set + # but GCFLAG_CARDS_SET is cleared. This tries to set + # GCFLAG_CARDS_SET if possible; otherwise, it falls back + # to jit_remember_young_pointer(). objhdr = self.header(addr_array) - # - # a single check for the common case of neither GCFLAG_HAS_CARDS - # nor GCFLAG_NO_HEAP_PTRS - if objhdr.tid & (GCFLAG_HAS_CARDS | GCFLAG_NO_HEAP_PTRS) == 0: - # common case: fast path, jump to the end of the function - pass - elif objhdr.tid & GCFLAG_HAS_CARDS == 0: - # no cards, but GCFLAG_NO_HEAP_PTRS is set. - objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.prebuilt_root_objects.append(addr_array) - # jump to the end of the function + if objhdr.tid & GCFLAG_HAS_CARDS: + self.old_objects_with_cards_set.append(addr_array) + objhdr.tid |= GCFLAG_CARDS_SET else: - # case with cards. - # - # If the newly written address does not actually point to a - # young object, leave now. - if not self.appears_to_be_young(newvalue): - return - # - # 'addr_array' is a raw_malloc'ed array with card markers - # in front. Compute the index of the bit to set: - bitindex = index >> self.card_page_shift - byteindex = bitindex >> 3 - bitmask = 1 << (bitindex & 7) - # - # If the bit is already set, leave now. - addr_byte = self.get_card(addr_array, byteindex) - byte = ord(addr_byte.char[0]) - if byte & bitmask: - return - addr_byte.char[0] = chr(byte | bitmask) - # - if objhdr.tid & GCFLAG_CARDS_SET == 0: - self.old_objects_with_cards_set.append(addr_array) - objhdr.tid |= GCFLAG_CARDS_SET - return - # - # Logic for the no-cards case, put here to minimize the number - # of checks done at the start of the function - if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this - ll_assert(self.debug_is_old_object(addr_array), - "young array with no card but GCFLAG_TRACK_YOUNG_PTRS") - # - if self.appears_to_be_young(newvalue): - self.old_objects_pointing_to_young.append(addr_array) - objhdr.tid &= ~GCFLAG_TRACK_YOUNG_PTRS + self.jit_remember_young_pointer(addr_array) - remember_young_pointer_from_array3._dont_inline_ = True - assert self.card_page_indices > 0 - self.remember_young_pointer_from_array3 = ( - remember_young_pointer_from_array3) + self.jit_remember_young_pointer_from_array = ( + jit_remember_young_pointer_from_array) def get_card(self, obj, byteindex): size_gc_header = self.gcheaderbuilder.size_gc_header diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py --- a/pypy/rpython/memory/gctransform/framework.py +++ b/pypy/rpython/memory/gctransform/framework.py @@ -495,13 +495,12 @@ annmodel.SomeAddress()], annmodel.s_None, inline=True) - func = getattr(gcdata.gc, 'remember_young_pointer', None) + func = getattr(gcdata.gc, 'jit_remember_young_pointer', None) if func is not None: # func should not be a bound method, but a real function assert isinstance(func, types.FunctionType) self.write_barrier_failing_case_ptr = getfn(func, - [annmodel.SomeAddress(), - annmodel.SomeAddress()], + [annmodel.SomeAddress()], annmodel.s_None) func = getattr(GCClass, 'write_barrier_from_array', None) if func is not None: @@ -512,16 +511,15 @@ annmodel.SomeInteger()], annmodel.s_None, inline=True) - func = getattr(gcdata.gc, 'remember_young_pointer_from_array3', + func = getattr(gcdata.gc, + 'jit_remember_young_pointer_from_array', None) if func is not None: # func should not be a bound method, but a real function assert isinstance(func, types.FunctionType) self.write_barrier_from_array_failing_case_ptr = \ getfn(func, - [annmodel.SomeAddress(), - annmodel.SomeInteger(), - annmodel.SomeAddress()], + [annmodel.SomeAddress()], annmodel.s_None) self.statistics_ptr = getfn(GCClass.statistics.im_func, [s_gc, annmodel.SomeInteger()], diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py --- a/pypy/rpython/module/ll_os.py +++ b/pypy/rpython/module/ll_os.py @@ -148,6 +148,7 @@ else: includes += ['sys/utime.h'] +_CYGWIN = sys.platform == 'cygwin' class CConfig: """ @@ -1329,9 +1330,14 @@ return result else: # Posix - os_waitpid = self.llexternal('waitpid', - [rffi.PID_T, rffi.INTP, rffi.INT], - rffi.PID_T) + if _CYGWIN: + os_waitpid = self.llexternal('cygwin_waitpid', + [rffi.PID_T, rffi.INTP, rffi.INT], + rffi.PID_T) + else: + os_waitpid = self.llexternal('waitpid', + [rffi.PID_T, rffi.INTP, rffi.INT], + rffi.PID_T) def os_waitpid_llimpl(pid, options): status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -54,7 +54,15 @@ pypy_c = py.path.local(override_pypy_c) if not pypy_c.check(): print pypy_c - raise PyPyCNotFound('Please compile pypy first, using translate.py') + if os.path.isdir(os.path.dirname(str(pypy_c))): + raise PyPyCNotFound( + 'Please compile pypy first, using translate.py,' + ' or check that you gave the correct path' + ' (see docstring for more info)') + else: + raise PyPyCNotFound( + 'Bogus path: %r does not exist (see docstring for more info)' + % (os.path.dirname(str(pypy_c)),)) if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'): rename_pypy_c += '.exe' binaries = [(pypy_c, rename_pypy_c)] @@ -137,6 +145,8 @@ archive = str(builddir.join(name + '.tar.bz2')) if sys.platform == 'darwin' or sys.platform.startswith('freebsd'): e = os.system('tar --numeric-owner -cvjf ' + archive + " " + name) + elif sys.platform == 'cygwin': + e = os.system('tar --owner=Administrator --group=Administrators --numeric-owner -cvjf ' + archive + " " + name) else: e = os.system('tar --owner=root --group=root --numeric-owner -cvjf ' + archive + " " + name) if e: diff --git a/pypy/translator/c/gc.py b/pypy/translator/c/gc.py --- a/pypy/translator/c/gc.py +++ b/pypy/translator/c/gc.py @@ -313,6 +313,8 @@ class FrameworkGcPolicy(BasicGcPolicy): def gettransformer(self): + if hasattr(self, 'transformerclass'): # for rpython/memory tests + return self.transformerclass(self.db.translator) from pypy.rpython.memory.gctransform import framework return framework.FrameworkGCTransformer(self.db.translator) diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py --- a/pypy/translator/c/genc.py +++ b/pypy/translator/c/genc.py @@ -15,6 +15,8 @@ from pypy.rlib import exports from pypy.tool.nullpath import NullPyPathLocal +_CYGWIN = sys.platform == 'cygwin' + def import_module_from_directory(dir, modname): file, pathname, description = imp.find_module(modname, [str(dir)]) try: @@ -993,6 +995,8 @@ srcdir / 'profiling.c', srcdir / 'debug_print.c', ] + if _CYGWIN: + files.append(srcdir / 'cygwin_wait.c') return eci.merge(ExternalCompilationInfo(separate_module_files=files)) diff --git a/pypy/translator/c/src/cygwin_wait.c b/pypy/translator/c/src/cygwin_wait.c new file mode 100644 --- /dev/null +++ b/pypy/translator/c/src/cygwin_wait.c @@ -0,0 +1,47 @@ +/* + Work around compile error: + [translation:ERROR] implement_4.c: In function 'pypy_g_ccall_waitpid__Signed_arrayPtr_Signed': + [translation:ERROR] implement_4.c:150095:2: error: incompatible type for argument 2 of 'waitpid' + [translation:ERROR] /usr/include/sys/wait.h:43:7: note: expected '__wait_status_ptr_t' but argument is of type 'long int *' +*/ + +#ifdef __CYGWIN__ + +#include "wait.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* +typedef int *__wait_status_ptr_t; + */ + + /* +pid_t wait (__wait_status_ptr_t __status); +pid_t waitpid (pid_t __pid, __wait_status_ptr_t __status, int __options); +pid_t wait3 (__wait_status_ptr_t __status, int __options, struct rusage *__rusage); +pid_t wait4 (pid_t __pid, __wait_status_ptr_t __status, int __options, struct rusage *__rusage); + */ + + pid_t cygwin_wait (int * __status){ + return wait ((__wait_status_ptr_t) __status); + } + + pid_t cygwin_waitpid (pid_t __pid, int * __status, int __options){ + return waitpid (__pid, (__wait_status_ptr_t) __status, __options); + } + + pid_t cygwin_wait3 (int * __status, int __options, struct rusage *__rusage){ + return wait3 ((__wait_status_ptr_t) __status, __options, __rusage); + } + + pid_t cygwin_wait4 (pid_t __pid, int * __status, int __options, struct rusage *__rusage){ + return wait4 (__pid, (__wait_status_ptr_t) __status, __options, __rusage); + } + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pypy/translator/c/src/cygwin_wait.h b/pypy/translator/c/src/cygwin_wait.h new file mode 100644 --- /dev/null +++ b/pypy/translator/c/src/cygwin_wait.h @@ -0,0 +1,43 @@ +/* + Work around compile error: + [translation:ERROR] implement_4.c: In function 'pypy_g_ccall_waitpid__Signed_arrayPtr_Signed': + [translation:ERROR] implement_4.c:150095:2: error: incompatible type for argument 2 of 'waitpid' + [translation:ERROR] /usr/include/sys/wait.h:43:7: note: expected '__wait_status_ptr_t' but argument is of type 'long int *' +*/ + +#ifdef __CYGWIN__ + +#ifndef _PYPY_WAIT_H +#define _PYPY_WAIT_H + +#ifndef _SYS_WAIT_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /* +typedef int *__wait_status_ptr_t; + */ + + /* +pid_t wait (__wait_status_ptr_t __status); +pid_t waitpid (pid_t __pid, __wait_status_ptr_t __status, int __options); +pid_t wait3 (__wait_status_ptr_t __status, int __options, struct rusage *__rusage); +pid_t wait4 (pid_t __pid, __wait_status_ptr_t __status, int __options, struct rusage *__rusage); + */ + + pid_t cygwin_wait (int * __status); + pid_t cygwin_waitpid (pid_t __pid, int * __status, int __options); + pid_t cygwin_wait3 (int * __status, int __options, struct rusage *__rusage); + pid_t cygwin_wait4 (pid_t __pid, int * __status, int __options, struct rusage *__rusage); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/pypy/translator/c/src/g_include.h b/pypy/translator/c/src/g_include.h --- a/pypy/translator/c/src/g_include.h +++ b/pypy/translator/c/src/g_include.h @@ -63,3 +63,8 @@ # pragma warning(disable: 4033 4102 4101 4716) # endif #endif + +/* work around waitpid expecting different pointer type */ +#ifdef __CYGWIN__ +#include "src/cygwin_wait.h" +#endif diff --git a/pypy/translator/goal/targetsimplevideo.py b/pypy/translator/goal/targetsimplevideo.py deleted file mode 100644 --- a/pypy/translator/goal/targetsimplevideo.py +++ /dev/null @@ -1,98 +0,0 @@ -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rpython.lltypesystem import rffi, lltype -import py - -WIDTH = 1000 -HEIGHT = 1000 - -def entry_point(argv=None): - RSDL.Init(RSDL.INIT_VIDEO) >= 0 - screen = RSDL.SetVideoMode(WIDTH, HEIGHT, 32, 0) - event = lltype.malloc(RSDL.Event, flavor='raw') - paintpattern = 0 - try: - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - paintpattern += 1 - update_screen(screen, paintpattern) - finally: - lltype.free(event, flavor='raw') - - return 0 - -# ----------------------------------------------------------------------------- - -def chess(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - if (i+j) % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def white(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, colb) - -def black(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - RSDL_helper.set_pixel(screen, i, j, cola) - -def stripes_v(screen, cola, colb): - for i in xrange(WIDTH): - for j in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - -def stripes_m(screen, cola, colb): - for j in xrange(WIDTH): - for i in xrange(HEIGHT): - k = j*WIDTH + i - if k % 2: - c = cola - else: - c = colb - RSDL_helper.set_pixel(screen, i, j, c) - - -# ----------------------------------------------------------------------------- - -pattern = [chess, white, black, stripes_v, stripes_m] -pl = len(pattern) -def update_screen(screen, paintpattern): - fmt = screen.c_format - white = RSDL.MapRGB(fmt, 255, 255, 255) - black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(screen) - pattern[paintpattern % pl](screen, black, white) - RSDL.UnlockSurface(screen) - RSDL.Flip(screen) - RSDL.Delay(10 ) - - -# ----------------------------------------------------------------------------- - -def target(*args): - return entry_point, None - -def test_target(): - entry_point() - -if __name__ == '__main__': - entry_point() - - diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py --- a/pypy/translator/platform/__init__.py +++ b/pypy/translator/platform/__init__.py @@ -278,6 +278,13 @@ host_factory = Windows else: host_factory = Windows_x64 +elif sys.platform == 'cygwin': + from pypy.translator.platform.cygwin import Cygwin, Cygwin64 + import platform + if platform.architecture()[0] == '32bit': + host_factory = Cygwin + else: + host_factory = Cygwin64 else: # pray from pypy.translator.platform.distutils_platform import DistutilsPlatform diff --git a/pypy/translator/platform/cygwin.py b/pypy/translator/platform/cygwin.py new file mode 100644 --- /dev/null +++ b/pypy/translator/platform/cygwin.py @@ -0,0 +1,56 @@ +"""Support for Cygwin.""" + +import os +import sys +from pypy.translator.platform.posix import BasePosix + +class BaseCygwin(BasePosix): + name = "cygwin" + +# link_flags = tuple( +# ['-pthread',] +# + os.environ.get('LDFLAGS', '').split()) + link_flags = tuple( + [] + + os.environ.get('LDFLAGS', '').split()) + extra_libs = ('-lrt',) +# cflags = tuple( +# ['-O3', '-pthread', '-fomit-frame-pointer', +# '-Wall', '-Wno-unused'] +# + os.environ.get('CFLAGS', '').split()) + cflags = tuple( + ['-O3', '-fomit-frame-pointer', + '-Wall', '-Wno-unused'] + + os.environ.get('CFLAGS', '').split()) + standalone_only = () + shared_only = ('-fPIC',) + so_ext = 'dll' + exe_ext = 'exe' + so_prefixes = ('lib', '') + + def _args_for_shared(self, args): + return ['-shared'] + args + + def _include_dirs_for_libffi(self): + return self._pkg_config("libffi", "--cflags-only-I", + ['/usr/include/libffi']) + + def _library_dirs_for_libffi(self): + return self._pkg_config("libffi", "--libs-only-L", + ['/usr/lib/libffi']) + + def library_dirs_for_libffi_a(self): + # places where we need to look for libffi.a + # XXX obscuuure! only look for libffi.a if run with translate.py + if 'translate' in sys.modules: + return self.library_dirs_for_libffi() + ['/usr/lib'] + else: + return [] + + +class Cygwin(BaseCygwin): + shared_only = () # it seems that on 32-bit linux, compiling with -fPIC + # gives assembler that asmgcc is not happy about. + +class Cygwin64(BaseCygwin): + pass diff --git a/pypy/translator/platform/posix.py b/pypy/translator/platform/posix.py --- a/pypy/translator/platform/posix.py +++ b/pypy/translator/platform/posix.py @@ -1,6 +1,6 @@ """Base support for POSIX-like platforms.""" -import py, os +import py, os, sys from pypy.tool import autopath from pypy.translator.platform import Platform, log, _run_subprocess @@ -55,7 +55,8 @@ if relto: response_file = relto.bestrelpath(response_file) - if self.cc == 'mingw32' or (self.cc== 'gcc' and os.name=='nt'): + if (self.cc == 'mingw32' or (self.cc== 'gcc' and os.name=='nt') + or sys.platform == 'cygwin'): return ["-Wl,--export-all-symbols,--version-script=%s" % \ (response_file,)] return ["-Wl,--export-dynamic,--version-script=%s" % (response_file,)] From noreply at buildbot.pypy.org Tue Jun 5 09:59:54 2012 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 5 Jun 2012 09:59:54 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix for issue1077: [nan] <= [5] should be False. Message-ID: <20120605075954.759FE1C003C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r55401:c85db2c2730e Date: 2012-06-04 23:08 +0200 http://bitbucket.org/pypy/pypy/changeset/c85db2c2730e/ Log: Fix for issue1077: [nan] <= [5] should be False. diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -1221,41 +1221,29 @@ i += 1 return space.w_True -def lessthan_unwrappeditems(space, w_list1, w_list2): - # needs to be safe against eq_w() mutating the w_lists behind our back - # Search for the first index where items are different - i = 0 - # XXX in theory, this can be implemented more efficiently as well. let's - # not care for now - while i < w_list1.length() and i < w_list2.length(): - w_item1 = w_list1.getitem(i) - w_item2 = w_list2.getitem(i) - if not space.eq_w(w_item1, w_item2): - return space.lt(w_item1, w_item2) - i += 1 - # No more items to compare -- compare sizes - return space.newbool(w_list1.length() < w_list2.length()) +def _make_list_comparison(name): + import operator + op = getattr(operator, name) + def compare_unwrappeditems(space, w_list1, w_list2): + # needs to be safe against eq_w() mutating the w_lists behind our back + # Search for the first index where items are different + i = 0 + # XXX in theory, this can be implemented more efficiently as well. + # let's not care for now + while i < w_list1.length() and i < w_list2.length(): + w_item1 = w_list1.getitem(i) + w_item2 = w_list2.getitem(i) + if not space.eq_w(w_item1, w_item2): + return getattr(space, name)(w_item1, w_item2) + i += 1 + # No more items to compare -- compare sizes + return space.newbool(op(w_list1.length(), w_list2.length())) + return func_with_new_name(compare_unwrappeditems, name + '__List_List') -def greaterthan_unwrappeditems(space, w_list1, w_list2): - # needs to be safe against eq_w() mutating the w_lists behind our back - # Search for the first index where items are different - i = 0 - # XXX in theory, this can be implemented more efficiently as well. let's - # not care for now - while i < w_list1.length() and i < w_list2.length(): - w_item1 = w_list1.getitem(i) - w_item2 = w_list2.getitem(i) - if not space.eq_w(w_item1, w_item2): - return space.gt(w_item1, w_item2) - i += 1 - # No more items to compare -- compare sizes - return space.newbool(w_list1.length() > w_list2.length()) - -def lt__List_List(space, w_list1, w_list2): - return lessthan_unwrappeditems(space, w_list1, w_list2) - -def gt__List_List(space, w_list1, w_list2): - return greaterthan_unwrappeditems(space, w_list1, w_list2) +lt__List_List = _make_list_comparison('lt') +le__List_List = _make_list_comparison('le') +gt__List_List = _make_list_comparison('gt') +ge__List_List = _make_list_comparison('ge') def delitem__List_ANY(space, w_list, w_idx): idx = get_list_index(space, w_idx) diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -1204,6 +1204,57 @@ s.update(Sub2(arg)) assert s == set(base(arg)) + def test_comparison(self): + assert ([] < []) is False + assert ([] <= []) is True + assert ([] == []) is True + assert ([] != []) is False + assert ([] > []) is False + assert ([] >= []) is True + assert ([5] < []) is False + assert ([5] <= []) is False + assert ([5] == []) is False + assert ([5] != []) is True + assert ([5] > []) is True + assert ([5] >= []) is True + assert ([] < [5]) is True + assert ([] <= [5]) is True + assert ([] == [5]) is False + assert ([] != [5]) is True + assert ([] > [5]) is False + assert ([] >= [5]) is False + assert ([4] < [5]) is True + assert ([4] <= [5]) is True + assert ([4] == [5]) is False + assert ([4] != [5]) is True + assert ([4] > [5]) is False + assert ([4] >= [5]) is False + assert ([5] < [5]) is False + assert ([5] <= [5]) is True + assert ([5] == [5]) is True + assert ([5] != [5]) is False + assert ([5] > [5]) is False + assert ([5] >= [5]) is True + assert ([6] < [5]) is False + assert ([6] <= [5]) is False + assert ([6] == [5]) is False + assert ([6] != [5]) is True + assert ([6] > [5]) is True + assert ([6] >= [5]) is True + N = float('nan') + assert ([N] < [5]) is False + assert ([N] <= [5]) is False + assert ([N] == [5]) is False + assert ([N] != [5]) is True + assert ([N] > [5]) is False + assert ([N] >= [5]) is False + assert ([5] < [N]) is False + assert ([5] <= [N]) is False + assert ([5] == [N]) is False + assert ([5] != [N]) is True + assert ([5] > [N]) is False + assert ([5] >= [N]) is False + class AppTestForRangeLists(AppTestW_ListObject): def setup_class(cls): diff --git a/pypy/objspace/std/test/test_tupleobject.py b/pypy/objspace/std/test/test_tupleobject.py --- a/pypy/objspace/std/test/test_tupleobject.py +++ b/pypy/objspace/std/test/test_tupleobject.py @@ -348,3 +348,54 @@ assert (4, 2, 3, 4).index(4, 1) == 3 assert (4, 4, 4).index(4, 1, 2) == 1 raises(ValueError, (1, 2, 3, 4).index, 4, 0, 2) + + def test_comparison(self): + assert (() < ()) is False + assert (() <= ()) is True + assert (() == ()) is True + assert (() != ()) is False + assert (() > ()) is False + assert (() >= ()) is True + assert ((5,) < ()) is False + assert ((5,) <= ()) is False + assert ((5,) == ()) is False + assert ((5,) != ()) is True + assert ((5,) > ()) is True + assert ((5,) >= ()) is True + assert (() < (5,)) is True + assert (() <= (5,)) is True + assert (() == (5,)) is False + assert (() != (5,)) is True + assert (() > (5,)) is False + assert (() >= (5,)) is False + assert ((4,) < (5,)) is True + assert ((4,) <= (5,)) is True + assert ((4,) == (5,)) is False + assert ((4,) != (5,)) is True + assert ((4,) > (5,)) is False + assert ((4,) >= (5,)) is False + assert ((5,) < (5,)) is False + assert ((5,) <= (5,)) is True + assert ((5,) == (5,)) is True + assert ((5,) != (5,)) is False + assert ((5,) > (5,)) is False + assert ((5,) >= (5,)) is True + assert ((6,) < (5,)) is False + assert ((6,) <= (5,)) is False + assert ((6,) == (5,)) is False + assert ((6,) != (5,)) is True + assert ((6,) > (5,)) is True + assert ((6,) >= (5,)) is True + N = float('nan') + assert ((N,) < (5,)) is False + assert ((N,) <= (5,)) is False + assert ((N,) == (5,)) is False + assert ((N,) != (5,)) is True + assert ((N,) > (5,)) is False + assert ((N,) >= (5,)) is False + assert ((5,) < (N,)) is False + assert ((5,) <= (N,)) is False + assert ((5,) == (N,)) is False + assert ((5,) != (N,)) is True + assert ((5,) > (N,)) is False + assert ((5,) >= (N,)) is False diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py --- a/pypy/objspace/std/tupleobject.py +++ b/pypy/objspace/std/tupleobject.py @@ -8,6 +8,7 @@ from pypy.objspace.std import slicetype from pypy.rlib.debug import make_sure_not_resized from pypy.rlib import jit +from pypy.tool.sourcetools import func_with_new_name # Tuples of known length up to UNROLL_TUPLE_LIMIT have unrolled certain methods UNROLL_TUPLE_LIMIT = 10 @@ -138,29 +139,27 @@ return space.w_False return space.w_True - at jit.look_inside_iff(tuple_unroll_condition) -def lt__Tuple_Tuple(space, w_tuple1, w_tuple2): - items1 = w_tuple1.wrappeditems - items2 = w_tuple2.wrappeditems - ncmp = min(len(items1), len(items2)) - # Search for the first index where items are different - for p in range(ncmp): - if not space.eq_w(items1[p], items2[p]): - return space.lt(items1[p], items2[p]) - # No more items to compare -- compare sizes - return space.newbool(len(items1) < len(items2)) +def _make_tuple_comparison(name): + import operator + op = getattr(operator, name) + # + @jit.look_inside_iff(tuple_unroll_condition) + def compare_tuples(space, w_tuple1, w_tuple2): + items1 = w_tuple1.wrappeditems + items2 = w_tuple2.wrappeditems + ncmp = min(len(items1), len(items2)) + # Search for the first index where items are different + for p in range(ncmp): + if not space.eq_w(items1[p], items2[p]): + return getattr(space, name)(items1[p], items2[p]) + # No more items to compare -- compare sizes + return space.newbool(op(len(items1), len(items2))) + return func_with_new_name(compare_tuples, name + '__Tuple_Tuple') - at jit.look_inside_iff(tuple_unroll_condition) -def gt__Tuple_Tuple(space, w_tuple1, w_tuple2): - items1 = w_tuple1.wrappeditems - items2 = w_tuple2.wrappeditems - ncmp = min(len(items1), len(items2)) - # Search for the first index where items are different - for p in range(ncmp): - if not space.eq_w(items1[p], items2[p]): - return space.gt(items1[p], items2[p]) - # No more items to compare -- compare sizes - return space.newbool(len(items1) > len(items2)) +lt__Tuple_Tuple = _make_tuple_comparison('lt') +le__Tuple_Tuple = _make_tuple_comparison('le') +gt__Tuple_Tuple = _make_tuple_comparison('gt') +ge__Tuple_Tuple = _make_tuple_comparison('ge') def repr__Tuple(space, w_tuple): items = w_tuple.wrappeditems From noreply at buildbot.pypy.org Tue Jun 5 10:00:12 2012 From: noreply at buildbot.pypy.org (wlav) Date: Tue, 5 Jun 2012 10:00:12 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: merge default into branch Message-ID: <20120605080012.6ADB51C003C@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r55402:401fe4cc4532 Date: 2012-06-01 13:04 -0700 http://bitbucket.org/pypy/pypy/changeset/401fe4cc4532/ Log: merge default into branch diff too long, truncating to 10000 out of 565790 lines diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py --- a/lib-python/2.7/test/test_fileio.py +++ b/lib-python/2.7/test/test_fileio.py @@ -318,6 +318,7 @@ self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(OSError, _FileIO, make_bad_fd()) if sys.platform == 'win32': + raise unittest.SkipTest('Set _invalid_parameter_handler for low level io') import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/lib-python/2.7/test/test_os.py b/lib-python/2.7/test/test_os.py --- a/lib-python/2.7/test/test_os.py +++ b/lib-python/2.7/test/test_os.py @@ -690,7 +690,8 @@ class PosixUidGidTests(unittest.TestCase): pass - at unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + at unittest.skipUnless(sys.platform == "win32" and hasattr(os,'kill'), + "Win32 specific tests") class Win32KillTests(unittest.TestCase): def _kill(self, sig): # Start sys.executable as a subprocess and communicate from the diff --git a/lib-python/3.2/__future__.py b/lib-python/3.2/__future__.py deleted file mode 100644 --- a/lib-python/3.2/__future__.py +++ /dev/null @@ -1,134 +0,0 @@ -"""Record of phased-in incompatible language changes. - -Each line is of the form: - - FeatureName = "_Feature(" OptionalRelease "," MandatoryRelease "," - CompilerFlag ")" - -where, normally, OptionalRelease < MandatoryRelease, and both are 5-tuples -of the same form as sys.version_info: - - (PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int - PY_MINOR_VERSION, # the 1; an int - PY_MICRO_VERSION, # the 0; an int - PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string - PY_RELEASE_SERIAL # the 3; an int - ) - -OptionalRelease records the first release in which - - from __future__ import FeatureName - -was accepted. - -In the case of MandatoryReleases that have not yet occurred, -MandatoryRelease predicts the release in which the feature will become part -of the language. - -Else MandatoryRelease records when the feature became part of the language; -in releases at or after that, modules no longer need - - from __future__ import FeatureName - -to use the feature in question, but may continue to use such imports. - -MandatoryRelease may also be None, meaning that a planned feature got -dropped. - -Instances of class _Feature have two corresponding methods, -.getOptionalRelease() and .getMandatoryRelease(). - -CompilerFlag is the (bitfield) flag that should be passed in the fourth -argument to the builtin function compile() to enable the feature in -dynamically compiled code. This flag is stored in the .compiler_flag -attribute on _Future instances. These values must match the appropriate -#defines of CO_xxx flags in Include/compile.h. - -No feature line is ever to be deleted from this file. -""" - -all_feature_names = [ - "nested_scopes", - "generators", - "division", - "absolute_import", - "with_statement", - "print_function", - "unicode_literals", - "barry_as_FLUFL", -] - -__all__ = ["all_feature_names"] + all_feature_names - -# The CO_xxx symbols are defined here under the same names used by -# compile.h, so that an editor search will find them here. However, -# they're not exported in __all__, because they don't really belong to -# this module. -CO_NESTED = 0x0010 # nested_scopes -CO_GENERATOR_ALLOWED = 0 # generators (obsolete, was 0x1000) -CO_FUTURE_DIVISION = 0x2000 # division -CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 # perform absolute imports by default -CO_FUTURE_WITH_STATEMENT = 0x8000 # with statement -CO_FUTURE_PRINT_FUNCTION = 0x10000 # print function -CO_FUTURE_UNICODE_LITERALS = 0x20000 # unicode string literals -CO_FUTURE_BARRY_AS_BDFL = 0x40000 - -class _Feature: - def __init__(self, optionalRelease, mandatoryRelease, compiler_flag): - self.optional = optionalRelease - self.mandatory = mandatoryRelease - self.compiler_flag = compiler_flag - - def getOptionalRelease(self): - """Return first release in which this feature was recognized. - - This is a 5-tuple, of the same form as sys.version_info. - """ - - return self.optional - - def getMandatoryRelease(self): - """Return release in which this feature will become mandatory. - - This is a 5-tuple, of the same form as sys.version_info, or, if - the feature was dropped, is None. - """ - - return self.mandatory - - def __repr__(self): - return "_Feature" + repr((self.optional, - self.mandatory, - self.compiler_flag)) - -nested_scopes = _Feature((2, 1, 0, "beta", 1), - (2, 2, 0, "alpha", 0), - CO_NESTED) - -generators = _Feature((2, 2, 0, "alpha", 1), - (2, 3, 0, "final", 0), - CO_GENERATOR_ALLOWED) - -division = _Feature((2, 2, 0, "alpha", 2), - (3, 0, 0, "alpha", 0), - CO_FUTURE_DIVISION) - -absolute_import = _Feature((2, 5, 0, "alpha", 1), - (2, 7, 0, "alpha", 0), - CO_FUTURE_ABSOLUTE_IMPORT) - -with_statement = _Feature((2, 5, 0, "alpha", 1), - (2, 6, 0, "alpha", 0), - CO_FUTURE_WITH_STATEMENT) - -print_function = _Feature((2, 6, 0, "alpha", 2), - (3, 0, 0, "alpha", 0), - CO_FUTURE_PRINT_FUNCTION) - -unicode_literals = _Feature((2, 6, 0, "alpha", 2), - (3, 0, 0, "alpha", 0), - CO_FUTURE_UNICODE_LITERALS) - -barry_as_FLUFL = _Feature((3, 1, 0, "alpha", 2), - (3, 9, 0, "alpha", 0), - CO_FUTURE_BARRY_AS_BDFL) diff --git a/lib-python/3.2/__phello__.foo.py b/lib-python/3.2/__phello__.foo.py deleted file mode 100644 --- a/lib-python/3.2/__phello__.foo.py +++ /dev/null @@ -1,1 +0,0 @@ -# This file exists as a helper for the test.test_frozen module. diff --git a/lib-python/3.2/_abcoll.py b/lib-python/3.2/_abcoll.py deleted file mode 100644 --- a/lib-python/3.2/_abcoll.py +++ /dev/null @@ -1,623 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Abstract Base Classes (ABCs) for collections, according to PEP 3119. - -DON'T USE THIS MODULE DIRECTLY! The classes here should be imported -via collections; they are defined here only to alleviate certain -bootstrapping issues. Unit tests are in test_collections. -""" - -from abc import ABCMeta, abstractmethod -import sys - -__all__ = ["Hashable", "Iterable", "Iterator", - "Sized", "Container", "Callable", - "Set", "MutableSet", - "Mapping", "MutableMapping", - "MappingView", "KeysView", "ItemsView", "ValuesView", - "Sequence", "MutableSequence", - "ByteString", - ] - - -### collection related types which are not exposed through builtin ### -## iterators ## -bytes_iterator = type(iter(b'')) -bytearray_iterator = type(iter(bytearray())) -#callable_iterator = ??? -dict_keyiterator = type(iter({}.keys())) -dict_valueiterator = type(iter({}.values())) -dict_itemiterator = type(iter({}.items())) -list_iterator = type(iter([])) -list_reverseiterator = type(iter(reversed([]))) -range_iterator = type(iter(range(0))) -set_iterator = type(iter(set())) -str_iterator = type(iter("")) -tuple_iterator = type(iter(())) -zip_iterator = type(iter(zip())) -## views ## -dict_keys = type({}.keys()) -dict_values = type({}.values()) -dict_items = type({}.items()) -## misc ## -dict_proxy = type(type.__dict__) - - -### ONE-TRICK PONIES ### - -class Hashable(metaclass=ABCMeta): - - @abstractmethod - def __hash__(self): - return 0 - - @classmethod - def __subclasshook__(cls, C): - if cls is Hashable: - for B in C.__mro__: - if "__hash__" in B.__dict__: - if B.__dict__["__hash__"]: - return True - break - return NotImplemented - - -class Iterable(metaclass=ABCMeta): - - @abstractmethod - def __iter__(self): - while False: - yield None - - @classmethod - def __subclasshook__(cls, C): - if cls is Iterable: - if any("__iter__" in B.__dict__ for B in C.__mro__): - return True - return NotImplemented - - -class Iterator(Iterable): - - @abstractmethod - def __next__(self): - raise StopIteration - - def __iter__(self): - return self - - @classmethod - def __subclasshook__(cls, C): - if cls is Iterator: - if (any("__next__" in B.__dict__ for B in C.__mro__) and - any("__iter__" in B.__dict__ for B in C.__mro__)): - return True - return NotImplemented - -Iterator.register(bytes_iterator) -Iterator.register(bytearray_iterator) -#Iterator.register(callable_iterator) -Iterator.register(dict_keyiterator) -Iterator.register(dict_valueiterator) -Iterator.register(dict_itemiterator) -Iterator.register(list_iterator) -Iterator.register(list_reverseiterator) -Iterator.register(range_iterator) -Iterator.register(set_iterator) -Iterator.register(str_iterator) -Iterator.register(tuple_iterator) -Iterator.register(zip_iterator) - -class Sized(metaclass=ABCMeta): - - @abstractmethod - def __len__(self): - return 0 - - @classmethod - def __subclasshook__(cls, C): - if cls is Sized: - if any("__len__" in B.__dict__ for B in C.__mro__): - return True - return NotImplemented - - -class Container(metaclass=ABCMeta): - - @abstractmethod - def __contains__(self, x): - return False - - @classmethod - def __subclasshook__(cls, C): - if cls is Container: - if any("__contains__" in B.__dict__ for B in C.__mro__): - return True - return NotImplemented - - -class Callable(metaclass=ABCMeta): - - @abstractmethod - def __call__(self, *args, **kwds): - return False - - @classmethod - def __subclasshook__(cls, C): - if cls is Callable: - if any("__call__" in B.__dict__ for B in C.__mro__): - return True - return NotImplemented - - -### SETS ### - - -class Set(Sized, Iterable, Container): - - """A set is a finite, iterable container. - - This class provides concrete generic implementations of all - methods except for __contains__, __iter__ and __len__. - - To override the comparisons (presumably for speed, as the - semantics are fixed), all you have to do is redefine __le__ and - then the other operations will automatically follow suit. - """ - - def __le__(self, other): - if not isinstance(other, Set): - return NotImplemented - if len(self) > len(other): - return False - for elem in self: - if elem not in other: - return False - return True - - def __lt__(self, other): - if not isinstance(other, Set): - return NotImplemented - return len(self) < len(other) and self.__le__(other) - - def __gt__(self, other): - if not isinstance(other, Set): - return NotImplemented - return other < self - - def __ge__(self, other): - if not isinstance(other, Set): - return NotImplemented - return other <= self - - def __eq__(self, other): - if not isinstance(other, Set): - return NotImplemented - return len(self) == len(other) and self.__le__(other) - - def __ne__(self, other): - return not (self == other) - - @classmethod - def _from_iterable(cls, it): - '''Construct an instance of the class from any iterable input. - - Must override this method if the class constructor signature - does not accept an iterable for an input. - ''' - return cls(it) - - def __and__(self, other): - if not isinstance(other, Iterable): - return NotImplemented - return self._from_iterable(value for value in other if value in self) - - def isdisjoint(self, other): - for value in other: - if value in self: - return False - return True - - def __or__(self, other): - if not isinstance(other, Iterable): - return NotImplemented - chain = (e for s in (self, other) for e in s) - return self._from_iterable(chain) - - def __sub__(self, other): - if not isinstance(other, Set): - if not isinstance(other, Iterable): - return NotImplemented - other = self._from_iterable(other) - return self._from_iterable(value for value in self - if value not in other) - - def __xor__(self, other): - if not isinstance(other, Set): - if not isinstance(other, Iterable): - return NotImplemented - other = self._from_iterable(other) - return (self - other) | (other - self) - - def _hash(self): - """Compute the hash value of a set. - - Note that we don't define __hash__: not all sets are hashable. - But if you define a hashable set type, its __hash__ should - call this function. - - This must be compatible __eq__. - - All sets ought to compare equal if they contain the same - elements, regardless of how they are implemented, and - regardless of the order of the elements; so there's not much - freedom for __eq__ or __hash__. We match the algorithm used - by the built-in frozenset type. - """ - MAX = sys.maxsize - MASK = 2 * MAX + 1 - n = len(self) - h = 1927868237 * (n + 1) - h &= MASK - for x in self: - hx = hash(x) - h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167 - h &= MASK - h = h * 69069 + 907133923 - h &= MASK - if h > MAX: - h -= MASK + 1 - if h == -1: - h = 590923713 - return h - -Set.register(frozenset) - - -class MutableSet(Set): - - @abstractmethod - def add(self, value): - """Add an element.""" - raise NotImplementedError - - @abstractmethod - def discard(self, value): - """Remove an element. Do not raise an exception if absent.""" - raise NotImplementedError - - def remove(self, value): - """Remove an element. If not a member, raise a KeyError.""" - if value not in self: - raise KeyError(value) - self.discard(value) - - def pop(self): - """Return the popped value. Raise KeyError if empty.""" - it = iter(self) - try: - value = next(it) - except StopIteration: - raise KeyError - self.discard(value) - return value - - def clear(self): - """This is slow (creates N new iterators!) but effective.""" - try: - while True: - self.pop() - except KeyError: - pass - - def __ior__(self, it): - for value in it: - self.add(value) - return self - - def __iand__(self, it): - for value in (self - it): - self.discard(value) - return self - - def __ixor__(self, it): - if it is self: - self.clear() - else: - if not isinstance(it, Set): - it = self._from_iterable(it) - for value in it: - if value in self: - self.discard(value) - else: - self.add(value) - return self - - def __isub__(self, it): - if it is self: - self.clear() - else: - for value in it: - self.discard(value) - return self - -MutableSet.register(set) - - -### MAPPINGS ### - - -class Mapping(Sized, Iterable, Container): - - @abstractmethod - def __getitem__(self, key): - raise KeyError - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default - - def __contains__(self, key): - try: - self[key] - except KeyError: - return False - else: - return True - - def keys(self): - return KeysView(self) - - def items(self): - return ItemsView(self) - - def values(self): - return ValuesView(self) - - def __eq__(self, other): - if not isinstance(other, Mapping): - return NotImplemented - return dict(self.items()) == dict(other.items()) - - def __ne__(self, other): - return not (self == other) - - -class MappingView(Sized): - - def __init__(self, mapping): - self._mapping = mapping - - def __len__(self): - return len(self._mapping) - - def __repr__(self): - return '{0.__class__.__name__}({0._mapping!r})'.format(self) - - -class KeysView(MappingView, Set): - - @classmethod - def _from_iterable(self, it): - return set(it) - - def __contains__(self, key): - return key in self._mapping - - def __iter__(self): - for key in self._mapping: - yield key - -KeysView.register(dict_keys) - - -class ItemsView(MappingView, Set): - - @classmethod - def _from_iterable(self, it): - return set(it) - - def __contains__(self, item): - key, value = item - try: - v = self._mapping[key] - except KeyError: - return False - else: - return v == value - - def __iter__(self): - for key in self._mapping: - yield (key, self._mapping[key]) - -ItemsView.register(dict_items) - - -class ValuesView(MappingView): - - def __contains__(self, value): - for key in self._mapping: - if value == self._mapping[key]: - return True - return False - - def __iter__(self): - for key in self._mapping: - yield self._mapping[key] - -ValuesView.register(dict_values) - - -class MutableMapping(Mapping): - - @abstractmethod - def __setitem__(self, key, value): - raise KeyError - - @abstractmethod - def __delitem__(self, key): - raise KeyError - - __marker = object() - - def pop(self, key, default=__marker): - try: - value = self[key] - except KeyError: - if default is self.__marker: - raise - return default - else: - del self[key] - return value - - def popitem(self): - try: - key = next(iter(self)) - except StopIteration: - raise KeyError - value = self[key] - del self[key] - return key, value - - def clear(self): - try: - while True: - self.popitem() - except KeyError: - pass - - def update(*args, **kwds): - if len(args) > 2: - raise TypeError("update() takes at most 2 positional " - "arguments ({} given)".format(len(args))) - elif not args: - raise TypeError("update() takes at least 1 argument (0 given)") - self = args[0] - other = args[1] if len(args) >= 2 else () - - if isinstance(other, Mapping): - for key in other: - self[key] = other[key] - elif hasattr(other, "keys"): - for key in other.keys(): - self[key] = other[key] - else: - for key, value in other: - self[key] = value - for key, value in kwds.items(): - self[key] = value - - def setdefault(self, key, default=None): - try: - return self[key] - except KeyError: - self[key] = default - return default - -MutableMapping.register(dict) - - -### SEQUENCES ### - - -class Sequence(Sized, Iterable, Container): - - """All the operations on a read-only sequence. - - Concrete subclasses must override __new__ or __init__, - __getitem__, and __len__. - """ - - @abstractmethod - def __getitem__(self, index): - raise IndexError - - def __iter__(self): - i = 0 - try: - while True: - v = self[i] - yield v - i += 1 - except IndexError: - return - - def __contains__(self, value): - for v in self: - if v == value: - return True - return False - - def __reversed__(self): - for i in reversed(range(len(self))): - yield self[i] - - def index(self, value): - for i, v in enumerate(self): - if v == value: - return i - raise ValueError - - def count(self, value): - return sum(1 for v in self if v == value) - -Sequence.register(tuple) -Sequence.register(str) -Sequence.register(range) - - -class ByteString(Sequence): - - """This unifies bytes and bytearray. - - XXX Should add all their methods. - """ - -ByteString.register(bytes) -ByteString.register(bytearray) - - -class MutableSequence(Sequence): - - @abstractmethod - def __setitem__(self, index, value): - raise IndexError - - @abstractmethod - def __delitem__(self, index): - raise IndexError - - @abstractmethod - def insert(self, index, value): - raise IndexError - - def append(self, value): - self.insert(len(self), value) - - def reverse(self): - n = len(self) - for i in range(n//2): - self[i], self[n-i-1] = self[n-i-1], self[i] - - def extend(self, values): - for v in values: - self.append(v) - - def pop(self, index=-1): - v = self[index] - del self[index] - return v - - def remove(self, value): - del self[self.index(value)] - - def __iadd__(self, values): - self.extend(values) - return self - -MutableSequence.register(list) -MutableSequence.register(bytearray) # Multiply inheriting, see ByteString diff --git a/lib-python/3.2/_compat_pickle.py b/lib-python/3.2/_compat_pickle.py deleted file mode 100644 --- a/lib-python/3.2/_compat_pickle.py +++ /dev/null @@ -1,81 +0,0 @@ -# This module is used to map the old Python 2 names to the new names used in -# Python 3 for the pickle module. This needed to make pickle streams -# generated with Python 2 loadable by Python 3. - -# This is a copy of lib2to3.fixes.fix_imports.MAPPING. We cannot import -# lib2to3 and use the mapping defined there, because lib2to3 uses pickle. -# Thus, this could cause the module to be imported recursively. -IMPORT_MAPPING = { - 'StringIO': 'io', - 'cStringIO': 'io', - 'cPickle': 'pickle', - '__builtin__' : 'builtins', - 'copy_reg': 'copyreg', - 'Queue': 'queue', - 'SocketServer': 'socketserver', - 'ConfigParser': 'configparser', - 'repr': 'reprlib', - 'FileDialog': 'tkinter.filedialog', - 'tkFileDialog': 'tkinter.filedialog', - 'SimpleDialog': 'tkinter.simpledialog', - 'tkSimpleDialog': 'tkinter.simpledialog', - 'tkColorChooser': 'tkinter.colorchooser', - 'tkCommonDialog': 'tkinter.commondialog', - 'Dialog': 'tkinter.dialog', - 'Tkdnd': 'tkinter.dnd', - 'tkFont': 'tkinter.font', - 'tkMessageBox': 'tkinter.messagebox', - 'ScrolledText': 'tkinter.scrolledtext', - 'Tkconstants': 'tkinter.constants', - 'Tix': 'tkinter.tix', - 'ttk': 'tkinter.ttk', - 'Tkinter': 'tkinter', - 'markupbase': '_markupbase', - '_winreg': 'winreg', - 'thread': '_thread', - 'dummy_thread': '_dummy_thread', - 'dbhash': 'dbm.bsd', - 'dumbdbm': 'dbm.dumb', - 'dbm': 'dbm.ndbm', - 'gdbm': 'dbm.gnu', - 'xmlrpclib': 'xmlrpc.client', - 'DocXMLRPCServer': 'xmlrpc.server', - 'SimpleXMLRPCServer': 'xmlrpc.server', - 'httplib': 'http.client', - 'htmlentitydefs' : 'html.entities', - 'HTMLParser' : 'html.parser', - 'Cookie': 'http.cookies', - 'cookielib': 'http.cookiejar', - 'BaseHTTPServer': 'http.server', - 'SimpleHTTPServer': 'http.server', - 'CGIHTTPServer': 'http.server', - 'test.test_support': 'test.support', - 'commands': 'subprocess', - 'UserString' : 'collections', - 'UserList' : 'collections', - 'urlparse' : 'urllib.parse', - 'robotparser' : 'urllib.robotparser', - 'whichdb': 'dbm', - 'anydbm': 'dbm' -} - - -# This contains rename rules that are easy to handle. We ignore the more -# complex stuff (e.g. mapping the names in the urllib and types modules). -# These rules should be run before import names are fixed. -NAME_MAPPING = { - ('__builtin__', 'xrange'): ('builtins', 'range'), - ('__builtin__', 'reduce'): ('functools', 'reduce'), - ('__builtin__', 'intern'): ('sys', 'intern'), - ('__builtin__', 'unichr'): ('builtins', 'chr'), - ('__builtin__', 'basestring'): ('builtins', 'str'), - ('__builtin__', 'long'): ('builtins', 'int'), - ('itertools', 'izip'): ('builtins', 'zip'), - ('itertools', 'imap'): ('builtins', 'map'), - ('itertools', 'ifilter'): ('builtins', 'filter'), - ('itertools', 'ifilterfalse'): ('itertools', 'filterfalse'), -} - -# Same, but for 3.x to 2.x -REVERSE_IMPORT_MAPPING = dict((v, k) for (k, v) in IMPORT_MAPPING.items()) -REVERSE_NAME_MAPPING = dict((v, k) for (k, v) in NAME_MAPPING.items()) diff --git a/lib-python/3.2/_dummy_thread.py b/lib-python/3.2/_dummy_thread.py deleted file mode 100644 --- a/lib-python/3.2/_dummy_thread.py +++ /dev/null @@ -1,155 +0,0 @@ -"""Drop-in replacement for the thread module. - -Meant to be used as a brain-dead substitute so that threaded code does -not need to be rewritten for when the thread module is not present. - -Suggested usage is:: - - try: - import _thread - except ImportError: - import _dummy_thread as _thread - -""" -# Exports only things specified by thread documentation; -# skipping obsolete synonyms allocate(), start_new(), exit_thread(). -__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock', - 'interrupt_main', 'LockType'] - -# A dummy value -TIMEOUT_MAX = 2**31 - -# NOTE: this module can be imported early in the extension building process, -# and so top level imports of other modules should be avoided. Instead, all -# imports are done when needed on a function-by-function basis. Since threads -# are disabled, the import lock should not be an issue anyway (??). - -class error(Exception): - """Dummy implementation of _thread.error.""" - - def __init__(self, *args): - self.args = args - -def start_new_thread(function, args, kwargs={}): - """Dummy implementation of _thread.start_new_thread(). - - Compatibility is maintained by making sure that ``args`` is a - tuple and ``kwargs`` is a dictionary. If an exception is raised - and it is SystemExit (which can be done by _thread.exit()) it is - caught and nothing is done; all other exceptions are printed out - by using traceback.print_exc(). - - If the executed function calls interrupt_main the KeyboardInterrupt will be - raised when the function returns. - - """ - if type(args) != type(tuple()): - raise TypeError("2nd arg must be a tuple") - if type(kwargs) != type(dict()): - raise TypeError("3rd arg must be a dict") - global _main - _main = False - try: - function(*args, **kwargs) - except SystemExit: - pass - except: - import traceback - traceback.print_exc() - _main = True - global _interrupt - if _interrupt: - _interrupt = False - raise KeyboardInterrupt - -def exit(): - """Dummy implementation of _thread.exit().""" - raise SystemExit - -def get_ident(): - """Dummy implementation of _thread.get_ident(). - - Since this module should only be used when _threadmodule is not - available, it is safe to assume that the current process is the - only thread. Thus a constant can be safely returned. - """ - return -1 - -def allocate_lock(): - """Dummy implementation of _thread.allocate_lock().""" - return LockType() - -def stack_size(size=None): - """Dummy implementation of _thread.stack_size().""" - if size is not None: - raise error("setting thread stack size not supported") - return 0 - -class LockType(object): - """Class implementing dummy implementation of _thread.LockType. - - Compatibility is maintained by maintaining self.locked_status - which is a boolean that stores the state of the lock. Pickling of - the lock, though, should not be done since if the _thread module is - then used with an unpickled ``lock()`` from here problems could - occur from this class not having atomic methods. - - """ - - def __init__(self): - self.locked_status = False - - def acquire(self, waitflag=None, timeout=-1): - """Dummy implementation of acquire(). - - For blocking calls, self.locked_status is automatically set to - True and returned appropriately based on value of - ``waitflag``. If it is non-blocking, then the value is - actually checked and not set if it is already acquired. This - is all done so that threading.Condition's assert statements - aren't triggered and throw a little fit. - - """ - if waitflag is None or waitflag: - self.locked_status = True - return True - else: - if not self.locked_status: - self.locked_status = True - return True - else: - if timeout > 0: - import time - time.sleep(timeout) - return False - - __enter__ = acquire - - def __exit__(self, typ, val, tb): - self.release() - - def release(self): - """Release the dummy lock.""" - # XXX Perhaps shouldn't actually bother to test? Could lead - # to problems for complex, threaded code. - if not self.locked_status: - raise error - self.locked_status = False - return True - - def locked(self): - return self.locked_status - -# Used to signal that interrupt_main was called in a "thread" -_interrupt = False -# True when not executing in a "thread" -_main = True - -def interrupt_main(): - """Set _interrupt flag to True to have start_new_thread raise - KeyboardInterrupt upon exiting.""" - if _main: - raise KeyboardInterrupt - else: - global _interrupt - _interrupt = True diff --git a/lib-python/3.2/_markupbase.py b/lib-python/3.2/_markupbase.py deleted file mode 100644 --- a/lib-python/3.2/_markupbase.py +++ /dev/null @@ -1,395 +0,0 @@ -"""Shared support for scanning document type declarations in HTML and XHTML. - -This module is used as a foundation for the html.parser module. It has no -documented public API and should not be used directly. - -""" - -import re - -_declname_match = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9]*\s*').match -_declstringlit_match = re.compile(r'(\'[^\']*\'|"[^"]*")\s*').match -_commentclose = re.compile(r'--\s*>') -_markedsectionclose = re.compile(r']\s*]\s*>') - -# An analysis of the MS-Word extensions is available at -# http://www.planetpublish.com/xmlarena/xap/Thursday/WordtoXML.pdf - -_msmarkedsectionclose = re.compile(r']\s*>') - -del re - - -class ParserBase: - """Parser base class which provides some common support methods used - by the SGML/HTML and XHTML parsers.""" - - def __init__(self): - if self.__class__ is ParserBase: - raise RuntimeError( - "_markupbase.ParserBase must be subclassed") - - def error(self, message): - raise NotImplementedError( - "subclasses of ParserBase must override error()") - - def reset(self): - self.lineno = 1 - self.offset = 0 - - def getpos(self): - """Return current line number and offset.""" - return self.lineno, self.offset - - # Internal -- update line number and offset. This should be - # called for each piece of data exactly once, in order -- in other - # words the concatenation of all the input strings to this - # function should be exactly the entire input. - def updatepos(self, i, j): - if i >= j: - return j - rawdata = self.rawdata - nlines = rawdata.count("\n", i, j) - if nlines: - self.lineno = self.lineno + nlines - pos = rawdata.rindex("\n", i, j) # Should not fail - self.offset = j-(pos+1) - else: - self.offset = self.offset + j-i - return j - - _decl_otherchars = '' - - # Internal -- parse declaration (for use by subclasses). - def parse_declaration(self, i): - # This is some sort of declaration; in "HTML as - # deployed," this should only be the document type - # declaration (""). - # ISO 8879:1986, however, has more complex - # declaration syntax for elements in , including: - # --comment-- - # [marked section] - # name in the following list: ENTITY, DOCTYPE, ELEMENT, - # ATTLIST, NOTATION, SHORTREF, USEMAP, - # LINKTYPE, LINK, IDLINK, USELINK, SYSTEM - rawdata = self.rawdata - j = i + 2 - assert rawdata[i:j] == "": - # the empty comment - return j + 1 - if rawdata[j:j+1] in ("-", ""): - # Start of comment followed by buffer boundary, - # or just a buffer boundary. - return -1 - # A simple, practical version could look like: ((name|stringlit) S*) + '>' - n = len(rawdata) - if rawdata[j:j+2] == '--': #comment - # Locate --.*-- as the body of the comment - return self.parse_comment(i) - elif rawdata[j] == '[': #marked section - # Locate [statusWord [...arbitrary SGML...]] as the body of the marked section - # Where statusWord is one of TEMP, CDATA, IGNORE, INCLUDE, RCDATA - # Note that this is extended by Microsoft Office "Save as Web" function - # to include [if...] and [endif]. - return self.parse_marked_section(i) - else: #all other declaration elements - decltype, j = self._scan_name(j, i) - if j < 0: - return j - if decltype == "doctype": - self._decl_otherchars = '' - while j < n: - c = rawdata[j] - if c == ">": - # end of declaration syntax - data = rawdata[i+2:j] - if decltype == "doctype": - self.handle_decl(data) - else: - # According to the HTML5 specs sections "8.2.4.44 Bogus - # comment state" and "8.2.4.45 Markup declaration open - # state", a comment token should be emitted. - # Calling unknown_decl provides more flexibility though. - self.unknown_decl(data) - return j + 1 - if c in "\"'": - m = _declstringlit_match(rawdata, j) - if not m: - return -1 # incomplete - j = m.end() - elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ": - name, j = self._scan_name(j, i) - elif c in self._decl_otherchars: - j = j + 1 - elif c == "[": - # this could be handled in a separate doctype parser - if decltype == "doctype": - j = self._parse_doctype_subset(j + 1, i) - elif decltype in {"attlist", "linktype", "link", "element"}: - # must tolerate []'d groups in a content model in an element declaration - # also in data attribute specifications of attlist declaration - # also link type declaration subsets in linktype declarations - # also link attribute specification lists in link declarations - self.error("unsupported '[' char in %s declaration" % decltype) - else: - self.error("unexpected '[' char in declaration") - else: - self.error( - "unexpected %r char in declaration" % rawdata[j]) - if j < 0: - return j - return -1 # incomplete - - # Internal -- parse a marked section - # Override this to handle MS-word extension syntax content - def parse_marked_section(self, i, report=1): - rawdata= self.rawdata - assert rawdata[i:i+3] == ' ending - match= _markedsectionclose.search(rawdata, i+3) - elif sectName in {"if", "else", "endif"}: - # look for MS Office ]> ending - match= _msmarkedsectionclose.search(rawdata, i+3) - else: - self.error('unknown status keyword %r in marked section' % rawdata[i+3:j]) - if not match: - return -1 - if report: - j = match.start(0) - self.unknown_decl(rawdata[i+3: j]) - return match.end(0) - - # Internal -- parse comment, return length or -1 if not terminated - def parse_comment(self, i, report=1): - rawdata = self.rawdata - if rawdata[i:i+4] != ' + """, [ ("data", "\n"), @@ -142,24 +142,6 @@ ("data", " foo"), ]) - def test_doctype_decl(self): - inside = """\ -DOCTYPE html [ - - - - - - - %paramEntity; - -]""" - self._run_check("" % inside, [ - ("decl", inside), - ]) - def test_bad_nesting(self): # Strangely, this *is* supposed to test that overlapping # elements are allowed. HTMLParser is more geared toward @@ -181,62 +163,9 @@ ("data", "this < text > contains < bare>pointy< brackets"), ]) - def test_attr_syntax(self): - output = [ - ("starttag", "a", [("b", "v"), ("c", "v"), ("d", "v"), ("e", None)]) - ] - self._run_check("""""", output) - self._run_check("""""", output) - self._run_check("""""", output) - self._run_check("""""", output) - - def test_attr_values(self): - self._run_check("""""", - [("starttag", "a", [("b", "xxx\n\txxx"), - ("c", "yyy\t\nyyy"), - ("d", "\txyz\n")]) - ]) - self._run_check("""""", [ - ("starttag", "a", [("b", ""), ("c", "")]), - ]) - # Regression test for SF patch #669683. - self._run_check("", [ - ("starttag", "e", [("a", "rgb(1,2,3)")]), - ]) - # Regression test for SF bug #921657. - self._run_check("", [ - ("starttag", "a", [("href", "mailto:xyz at example.com")]), - ]) - - def test_attr_nonascii(self): - # see issue 7311 - self._run_check(u"\u4e2d\u6587", [ - ("starttag", "img", [("src", "/foo/bar.png"), - ("alt", u"\u4e2d\u6587")]), - ]) - self._run_check(u"", [ - ("starttag", "a", [("title", u"\u30c6\u30b9\u30c8"), - ("href", u"\u30c6\u30b9\u30c8.html")]), - ]) - self._run_check(u'', [ - ("starttag", "a", [("title", u"\u30c6\u30b9\u30c8"), - ("href", u"\u30c6\u30b9\u30c8.html")]), - ]) - - def test_attr_entity_replacement(self): - self._run_check("""""", [ - ("starttag", "a", [("b", "&><\"'")]), - ]) - - def test_attr_funky_names(self): - self._run_check("""""", [ - ("starttag", "a", [("a.b", "v"), ("c:d", "v"), ("e-f", "v")]), - ]) - def test_illegal_declarations(self): - self._parse_error('') + self._run_check('', + [('comment', 'spacer type="block" height="25"')]) def test_starttag_end_boundary(self): self._run_check("""""", [("starttag", "a", [("b", "<")])]) @@ -273,23 +202,67 @@ self._run_check(["", ""], output) def test_starttag_junk_chars(self): - self._parse_error("") - self._parse_error("") - self._parse_error("") - self._parse_error("") - self._parse_error("") - self._parse_error("'") - self._parse_error("", [('data', '", [('endtag', 'a'", [('data', "" % dtd, + [('decl', 'DOCTYPE ' + dtd)]) + + def test_slashes_in_starttag(self): + self._run_check('', [('startendtag', 'a', [('foo', 'var')])]) + html = ('') + expected = [( + 'startendtag', 'img', + [('width', '902'), ('height', '250px'), + ('src', '/sites/default/files/images/homepage/foo.jpg'), + ('*what', None), ('am', None), ('i', None), + ('doing', None), ('here*', None)] + )] + self._run_check(html, expected) + html = ('' + '') + expected = [ + ('startendtag', 'a', [('foo', None), ('=', None), ('bar', None)]), + ('starttag', 'a', [('foo', None), ('=', None), ('bar', None)]) + ] + self._run_check(html, expected) def test_declaration_junk_chars(self): - self._parse_error("") + self._run_check("", [('decl', 'DOCTYPE foo $ ')]) def test_startendtag(self): self._run_check("

", [ @@ -305,6 +278,44 @@ ("endtag", "p"), ]) + def test_invalid_end_tags(self): + # A collection of broken end tags.
is used as separator. + # see http://www.w3.org/TR/html5/tokenization.html#end-tag-open-state + # and #13993 + html = ('



' + '


') + expected = [('starttag', 'br', []), + # < is part of the name, / is discarded, p is an attribute + ('endtag', 'label<'), + ('starttag', 'br', []), + # text and attributes are discarded + ('endtag', 'div'), + ('starttag', 'br', []), + # comment because the first char after is ignored + ('starttag', 'br', [])] + self._run_check(html, expected) + + def test_broken_invalid_end_tag(self): + # This is technically wrong (the "> shouldn't be included in the 'data') + # but is probably not worth fixing it (in addition to all the cases of + # the previous test, it would require a full attribute parsing). + # see #13993 + html = 'This confuses the parser' + expected = [('starttag', 'b', []), + ('data', 'This'), + ('endtag', 'b'), + ('data', '"> confuses the parser')] + self._run_check(html, expected) + def test_get_starttag_text(self): s = """""" self._run_check_extra(s, [ @@ -312,23 +323,56 @@ ("starttag_text", s)]) def test_cdata_content(self): - s = """""" - self._run_check(s, [ - ("starttag", "script", []), - ("data", " ¬-an-entity-ref; "), - ("endtag", "script"), - ]) - s = """""" - self._run_check(s, [ - ("starttag", "script", []), - ("data", " "), - ("endtag", "script"), - ]) + contents = [ + ' ¬-an-entity-ref;', + "", + '

', + 'foo = "";', + 'foo = "";', + 'foo = <\n/script> ', + '', + ('\n//<\\/s\'+\'cript>\');\n//]]>'), + '\n\n', + 'foo = "";', + u'', + # these two should be invalid according to the HTML 5 spec, + # section 8.1.2.2 + #'foo = ', + #'foo = ', + ] + elements = ['script', 'style', 'SCRIPT', 'STYLE', 'Script', 'Style'] + for content in contents: + for element in elements: + element_lower = element.lower() + s = u'<{element}>{content}'.format(element=element, + content=content) + self._run_check(s, [("starttag", element_lower, []), + ("data", content), + ("endtag", element_lower)]) - def test_entityrefs_in_attributes(self): - self._run_check("", [ - ("starttag", "html", [("foo", u"\u20AC&aa&unsupported;")]) - ]) + def test_cdata_with_closing_tags(self): + # see issue #13358 + # make sure that HTMLParser calls handle_data only once for each CDATA. + # The normal event collector normalizes the events in get_events, + # so we override it to return the original list of events. + class Collector(EventCollector): + def get_events(self): + return self.events + + content = """ ¬-an-entity-ref; +

& + '' !""" + for element in [' script', 'script ', ' script ', + '\nscript', 'script\n', '\nscript\n']: + s = u'""" - self._run_check(s, [ - ("starttag", "script", []), - ("data", " ¬-an-entity-ref; "), - ("endtag", "script"), - ]) - s = """""" - self._run_check(s, [ - ("starttag", "script", []), - ("data", " "), - ("endtag", "script"), - ]) + contents = [ + ' ¬-an-entity-ref;', + "", + '

', + 'foo = "";', + 'foo = "";', + 'foo = <\n/script> ', + '', + ('\n//<\\/s\'+\'cript>\');\n//]]>'), + '\n\n', + 'foo = "";', + u'', + # these two should be invalid according to the HTML 5 spec, + # section 8.1.2.2 + #'foo = ', + #'foo = ', + ] + elements = ['script', 'style', 'SCRIPT', 'STYLE', 'Script', 'Style'] + for content in contents: + for element in elements: + element_lower = element.lower() + s = u'<{element}>{content}'.format(element=element, + content=content) + self._run_check(s, [("starttag", element_lower, []), + ("data", content), + ("endtag", element_lower)]) - def test_entityrefs_in_attributes(self): - self._run_check("", [ - ("starttag", "html", [("foo", u"\u20AC&aa&unsupported;")]) - ]) + def test_cdata_with_closing_tags(self): + # see issue #13358 + # make sure that HTMLParser calls handle_data only once for each CDATA. + # The normal event collector normalizes the events in get_events, + # so we override it to return the original list of events. + class Collector(EventCollector): + def get_events(self): + return self.events + + content = """ ¬-an-entity-ref; +

& + '' !""" + for element in [' script', 'script ', ' script ', + '\nscript', 'script\n', '\nscript\n']: + s = u'