[pypy-commit] pypy numpy-pickle: Merge default
rguillebert
noreply at buildbot.pypy.org
Wed May 15 17:08:34 CEST 2013
Author: Romain Guillebert <romain.py at gmail.com>
Branch: numpy-pickle
Changeset: r64170:3cc58301a108
Date: 2013-05-15 16:11 +0200
http://bitbucket.org/pypy/pypy/changeset/3cc58301a108/
Log: Merge default
diff too long, truncating to 2000 out of 6616 lines
diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py
--- a/lib-python/2.7/distutils/sysconfig_pypy.py
+++ b/lib-python/2.7/distutils/sysconfig_pypy.py
@@ -119,13 +119,13 @@
optional C speedup components.
"""
if compiler.compiler_type == "unix":
- compiler.compiler_so.extend(['-fPIC', '-Wimplicit'])
+ compiler.compiler_so.extend(['-O2', '-fPIC', '-Wimplicit'])
compiler.shared_lib_extension = get_config_var('SO')
if "CFLAGS" in os.environ:
- cflags = os.environ["CFLAGS"]
- compiler.compiler.append(cflags)
- compiler.compiler_so.append(cflags)
- compiler.linker_so.append(cflags)
+ cflags = os.environ["CFLAGS"].split()
+ compiler.compiler.extend(cflags)
+ compiler.compiler_so.extend(cflags)
+ compiler.linker_so.extend(cflags)
from sysconfig_cpython import (
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -32,10 +32,11 @@
"rctime" , "select", "zipimport", "_lsprof",
"crypt", "signal", "_rawffi", "termios", "zlib", "bz2",
"struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO",
- "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
+ "thread", "itertools", "pyexpat", "_ssl", "array",
"binascii", "_multiprocessing", '_warnings',
"_collections", "_multibytecodec", "micronumpy", "_ffi",
- "_continuation", "_cffi_backend", "_csv", "cppyy"]
+ "_continuation", "_cffi_backend", "_csv"] # "cpyext", "cppyy"]
+# disabled until problems are fixed
))
translation_modules = default_modules.copy()
@@ -91,7 +92,7 @@
# itself needs the interp-level struct module
# because 'P' is missing from the app-level one
"_rawffi": [("objspace.usemodules.struct", True)],
- "cpyext": [("translation.secondaryentrypoints", "cpyext"),
+ "cpyext": [("translation.secondaryentrypoints", "cpyext,main"),
("translation.shared", sys.platform == "win32")],
}
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -47,7 +47,7 @@
# The short X.Y version.
version = '2.0'
# The full version, including alpha/beta/rc tags.
-release = '2.0-beta1'
+release = '2.0.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -105,7 +105,7 @@
$ ./pypy-c
Python 2.7.3 (7e4f0faa3d51, Nov 22 2012, 10:35:18)
- [PyPy 2.0.0-beta1 with GCC 4.7.1] on linux2
+ [PyPy 2.0.0 with GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``RPython magically makes you rich
and famous (says so on the tin)''
@@ -235,7 +235,7 @@
the ``bin/pypy`` executable.
To install PyPy system wide on unix-like systems, it is recommended to put the
-whole hierarchy alone (e.g. in ``/opt/pypy2.0-beta1``) and put a symlink to the
+whole hierarchy alone (e.g. in ``/opt/pypy2.0``) and put a symlink to the
``pypy`` executable into ``/usr/bin`` or ``/usr/local/bin``
If the executable fails to find suitable libraries, it will report
diff --git a/pypy/doc/getting-started.rst b/pypy/doc/getting-started.rst
--- a/pypy/doc/getting-started.rst
+++ b/pypy/doc/getting-started.rst
@@ -53,10 +53,10 @@
PyPy is ready to be executed as soon as you unpack the tarball or the zip
file, with no need to install it in any specific location::
- $ tar xf pypy-2.0-beta1-linux.tar.bz2
- $ ./pypy-2.0-beta1/bin/pypy
+ $ tar xf pypy-2.0.tar.bz2
+ $ ./pypy-2.0/bin/pypy
Python 2.7.3 (7e4f0faa3d51, Nov 22 2012, 10:35:18)
- [PyPy 2.0.0-beta1 with GCC 4.7.1] on linux2
+ [PyPy 2.0.0 with GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``PyPy is an exciting technology
that lets you to write fast, portable, multi-platform interpreters with less
@@ -75,14 +75,14 @@
$ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
- $ ./pypy-2.0-beta1/bin/pypy distribute_setup.py
+ $ ./pypy-2.0/bin/pypy distribute_setup.py
- $ ./pypy-2.0-beta1/bin/pypy get-pip.py
+ $ ./pypy-2.0/bin/pypy get-pip.py
- $ ./pypy-2.0-beta1/bin/pip install pygments # for example
+ $ ./pypy-2.0/bin/pip install pygments # for example
-3rd party libraries will be installed in ``pypy-2.0-beta1/site-packages``, and
-the scripts in ``pypy-2.0-beta1/bin``.
+3rd party libraries will be installed in ``pypy-2.0/site-packages``, and
+the scripts in ``pypy-2.0/bin``.
Installing using virtualenv
---------------------------
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -40,7 +40,7 @@
* `FAQ`_: some frequently asked questions.
-* `Release 2.0 beta 2`_: the latest official release
+* `Release 2.0`_: the latest official release
* `PyPy Blog`_: news and status info about PyPy
@@ -110,7 +110,7 @@
.. _`Getting Started`: getting-started.html
.. _`Papers`: extradoc.html
.. _`Videos`: video-index.html
-.. _`Release 2.0 beta 2`: http://pypy.org/download.html
+.. _`Release 2.0`: http://pypy.org/download.html
.. _`speed.pypy.org`: http://speed.pypy.org
.. _`RPython toolchain`: translation.html
.. _`potential project ideas`: project-ideas.html
diff --git a/pypy/doc/release-2.0.0.rst b/pypy/doc/release-2.0.0.rst
--- a/pypy/doc/release-2.0.0.rst
+++ b/pypy/doc/release-2.0.0.rst
@@ -4,6 +4,8 @@
We're pleased to announce PyPy 2.0. This is a stable release that brings
a swath of bugfixes, small performance improvements and compatibility fixes.
+PyPy 2.0 is a big step for us and we hope in the future we'll be able to
+provide stable releases more often.
You can download the PyPy 2.0 release here:
@@ -19,6 +21,10 @@
.. _`cffi`: http://cffi.readthedocs.org
+If you're using PyPy for anything, it would help us immensely if you fill out
+the following survey: http://bit.ly/pypysurvey This is for the developers
+eyes and we will not make any information public without your agreement.
+
What is PyPy?
=============
@@ -28,8 +34,8 @@
This release supports x86 machines running Linux 32/64, Mac OS X 64 or
Windows 32. Windows 64 work is still stalling, we would welcome a volunteer
-to handle that. ARM support is on the way and we're expecting to release
-an alpha ARM version shortly.
+to handle that. ARM support is on the way, as you can see from the recently
+released alpha for ARM.
.. _`pypy 2.0 and cpython 2.7.3`: http://speed.pypy.org
@@ -54,6 +60,10 @@
* A lot of stability issues fixed.
+* Refactoring much of the numpypy array classes, which resulted in removal of
+ lazy expression evaluation. On the other hand, we now have more complete
+ dtype support and support more array attributes.
+
.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore/
.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -7,3 +7,6 @@
.. branch: numpy-pickle
Pickling of numpy arrays and dtypes (including record dtypes)
+
+.. branch: numpy-subarrays
+It is now possible to create arrays and dtypes that use subarrays
diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py
--- a/pypy/goal/getnightly.py
+++ b/pypy/goal/getnightly.py
@@ -8,7 +8,9 @@
arch = 'linux'
cmd = 'wget "%s"'
tar = "tar -x -v --wildcards --strip-components=2 -f %s '*/bin/pypy'"
-if sys.platform.startswith('darwin'):
+ if os.uname()[-1].startswith('arm'):
+ arch += '-armhf-raspbian'
+elif sys.platform.startswith('darwin'):
arch = 'osx'
cmd = 'curl -O "%s"'
tar = "tar -x -v --strip-components=2 -f %s '*/bin/pypy'"
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -2,6 +2,7 @@
import os, sys
+import pypy
from pypy.interpreter import gateway
from pypy.interpreter.error import OperationError
from pypy.tool.ann_override import PyPyAnnotatorPolicy
@@ -22,20 +23,22 @@
# __________ Entry point __________
+
def create_entry_point(space, w_dict):
- w_entry_point = space.getitem(w_dict, space.wrap('entry_point'))
- w_run_toplevel = space.getitem(w_dict, space.wrap('run_toplevel'))
- w_call_finish_gateway = space.wrap(gateway.interp2app(call_finish))
- w_call_startup_gateway = space.wrap(gateway.interp2app(call_startup))
- withjit = space.config.objspace.usemodules.pypyjit
+ if w_dict is not None: # for tests
+ w_entry_point = space.getitem(w_dict, space.wrap('entry_point'))
+ w_run_toplevel = space.getitem(w_dict, space.wrap('run_toplevel'))
+ w_call_finish_gateway = space.wrap(gateway.interp2app(call_finish))
+ w_call_startup_gateway = space.wrap(gateway.interp2app(call_startup))
+ withjit = space.config.objspace.usemodules.pypyjit
def entry_point(argv):
if withjit:
from rpython.jit.backend.hlinfo import highleveljitinfo
highleveljitinfo.sys_executable = argv[0]
- #debug("entry point starting")
- #for arg in argv:
+ #debug("entry point starting")
+ #for arg in argv:
# debug(" argv -> " + arg)
if len(argv) > 2 and argv[1] == '--heapsize':
# Undocumented option, handled at interp-level.
@@ -71,7 +74,70 @@
debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
return 1
return exitcode
- return entry_point
+
+ # register the minimal equivalent of running a small piece of code. This
+ # should be used as sparsely as possible, just to register callbacks
+
+ from rpython.rlib.entrypoint import entrypoint
+ from rpython.rtyper.lltypesystem import rffi, lltype
+
+ w_pathsetter = space.appexec([], """():
+ def f(path):
+ import sys
+ sys.path[:] = path
+ return f
+ """)
+
+ @entrypoint('main', [rffi.CCHARP, lltype.Signed], c_name='pypy_setup_home')
+ def pypy_setup_home(ll_home, verbose):
+ from pypy.module.sys.initpath import pypy_find_stdlib
+ if ll_home:
+ home = rffi.charp2str(ll_home)
+ else:
+ home = pypydir
+ w_path = pypy_find_stdlib(space, home)
+ if space.is_none(w_path):
+ if verbose:
+ debug("Failed to find library based on pypy_find_stdlib")
+ return 1
+ space.startup()
+ space.call_function(w_pathsetter, w_path)
+ # import site
+ try:
+ import_ = space.getattr(space.getbuiltinmodule('__builtin__'),
+ space.wrap('__import__'))
+ space.call_function(import_, space.wrap('site'))
+ return 0
+ except OperationError, e:
+ if verbose:
+ debug("OperationError:")
+ debug(" operror-type: " + e.w_type.getname(space))
+ debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
+ return 1
+
+ @entrypoint('main', [rffi.CCHARP], c_name='pypy_execute_source')
+ def pypy_execute_source(ll_source):
+ source = rffi.charp2str(ll_source)
+ return _pypy_execute_source(source)
+
+ w_globals = space.newdict()
+ space.setitem(w_globals, space.wrap('__builtins__'),
+ space.builtin_modules['__builtin__'])
+
+ def _pypy_execute_source(source):
+ try:
+ compiler = space.createcompiler()
+ stmt = compiler.compile(source, 'c callback', 'exec', 0)
+ stmt.exec_code(space, w_globals, w_globals)
+ except OperationError, e:
+ debug("OperationError:")
+ debug(" operror-type: " + e.w_type.getname(space))
+ debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
+ return 1
+ return 0
+
+ return entry_point, {'pypy_execute_source': pypy_execute_source,
+ 'pypy_setup_home': pypy_setup_home}
def call_finish(space):
space.finish()
@@ -219,7 +285,7 @@
def jitpolicy(self, driver):
from pypy.module.pypyjit.policy import PyPyJitPolicy, pypy_hooks
return PyPyJitPolicy(pypy_hooks)
-
+
def get_entry_point(self, config):
from pypy.tool.lib_pypy import import_from_lib_pypy
rebuild = import_from_lib_pypy('ctypes_config_cache/rebuild')
@@ -232,7 +298,7 @@
app = gateway.applevel(open(filename).read(), 'app_main.py', 'app_main')
app.hidden_applevel = False
w_dict = app.getwdict(space)
- entry_point = create_entry_point(space, w_dict)
+ entry_point, _ = create_entry_point(space, w_dict)
return entry_point, None, PyPyAnnotatorPolicy(single_space = space)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -666,7 +666,8 @@
def id(self, w_obj):
w_result = w_obj.immutable_unique_id(self)
if w_result is None:
- w_result = self.wrap(compute_unique_id(w_obj))
+ # in the common case, returns an unsigned value
+ w_result = self.wrap(r_uint(compute_unique_id(w_obj)))
return w_result
def hash_w(self, w_obj):
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -803,7 +803,6 @@
args = inspect.getargs(func.func_code)
if args.varargs or args.keywords:
raise TypeError("Varargs and keywords not supported in unwrap_spec")
- assert not func.func_defaults
argspec = ', '.join([arg for arg in args.args[1:]])
func_code = py.code.Source("""
def f(w_obj, %(args)s):
@@ -812,11 +811,13 @@
d = {}
exec func_code.compile() in d
f = d['f']
+ f.func_defaults = unbound_meth.func_defaults
+ f.func_doc = unbound_meth.func_doc
f.__module__ = func.__module__
# necessary for unique identifiers for pickling
f.func_name = func.func_name
if unwrap_spec is None:
- unwrap_spec = {}
+ unwrap_spec = getattr(unbound_meth, 'unwrap_spec', {})
else:
assert isinstance(unwrap_spec, dict)
unwrap_spec = unwrap_spec.copy()
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -27,7 +27,7 @@
new_inst = mod.get('generator_new')
w = space.wrap
if self.frame:
- w_frame = w(self.frame)
+ w_frame = self.frame._reduce_state(space)
else:
w_frame = space.w_None
@@ -36,7 +36,20 @@
w(self.running),
]
- return space.newtuple([new_inst, space.newtuple(tup)])
+ return space.newtuple([new_inst, space.newtuple([]),
+ space.newtuple(tup)])
+
+ def descr__setstate__(self, space, w_args):
+ from rpython.rlib.objectmodel import instantiate
+ args_w = space.unpackiterable(w_args)
+ w_framestate, w_running = args_w
+ if space.is_w(w_framestate, space.w_None):
+ self.frame = None
+ else:
+ frame = instantiate(space.FrameClass) # XXX fish
+ frame.descr__setstate__(space, w_framestate)
+ GeneratorIterator.__init__(self, frame)
+ self.running = self.space.is_true(w_running)
def descr__iter__(self):
"""x.__iter__() <==> iter(x)"""
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -16,10 +16,9 @@
from rpython.tool.stdlib_opcode import host_bytecode_spec
# Define some opcodes used
-g = globals()
for op in '''DUP_TOP POP_TOP SETUP_LOOP SETUP_EXCEPT SETUP_FINALLY
POP_BLOCK END_FINALLY'''.split():
- g[op] = stdlib_opcode.opmap[op]
+ globals()[op] = stdlib_opcode.opmap[op]
HAVE_ARGUMENT = stdlib_opcode.HAVE_ARGUMENT
class PyFrame(eval.Frame):
@@ -304,11 +303,17 @@
@jit.dont_look_inside
def descr__reduce__(self, space):
from pypy.interpreter.mixedmodule import MixedModule
- from pypy.module._pickle_support import maker # helper fns
w_mod = space.getbuiltinmodule('_pickle_support')
mod = space.interp_w(MixedModule, w_mod)
new_inst = mod.get('frame_new')
- w = space.wrap
+ w_tup_state = self._reduce_state(space)
+ nt = space.newtuple
+ return nt([new_inst, nt([]), w_tup_state])
+
+ @jit.dont_look_inside
+ def _reduce_state(self, space):
+ from pypy.module._pickle_support import maker # helper fns
+ w = space.wrap
nt = space.newtuple
cells = self._getcells()
@@ -359,8 +364,7 @@
w(self.instr_prev_plus_one),
w_cells,
]
-
- return nt([new_inst, nt([]), nt(tup_state)])
+ return nt(tup_state)
@jit.dont_look_inside
def descr__setstate__(self, space, w_args):
diff --git a/pypy/interpreter/test2/mymodule.py b/pypy/interpreter/test/mymodule.py
rename from pypy/interpreter/test2/mymodule.py
rename to pypy/interpreter/test/mymodule.py
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/test_app_main.py
@@ -0,0 +1,966 @@
+"""
+Tests for the entry point of pypy-c, app_main.py.
+"""
+from __future__ import with_statement
+import py
+import sys, os, re, runpy, subprocess
+from rpython.tool.udir import udir
+from contextlib import contextmanager
+from pypy.conftest import pypydir
+
+banner = sys.version.splitlines()[0]
+
+app_main = os.path.join(os.path.realpath(os.path.dirname(__file__)), os.pardir, 'app_main.py')
+app_main = os.path.abspath(app_main)
+
+_counter = 0
+def _get_next_path(ext='.py'):
+ global _counter
+ p = udir.join('demo_test_app_main_%d%s' % (_counter, ext))
+ _counter += 1
+ return p
+
+def getscript(source):
+ p = _get_next_path()
+ p.write(str(py.code.Source(source)))
+ return str(p)
+
+def getscript_pyc(space, source):
+ p = _get_next_path()
+ p.write(str(py.code.Source(source)))
+ w_dir = space.wrap(str(p.dirpath()))
+ w_modname = space.wrap(p.purebasename)
+ space.appexec([w_dir, w_modname], """(dir, modname):
+ import sys
+ d = sys.modules.copy()
+ sys.path.insert(0, dir)
+ __import__(modname)
+ sys.path.pop(0)
+ for key in sys.modules.keys():
+ if key not in d:
+ del sys.modules[key]
+ """)
+ p = str(p) + 'c'
+ assert os.path.isfile(p) # the .pyc file should have been created above
+ return p
+
+def getscript_in_dir(source):
+ pdir = _get_next_path(ext='')
+ p = pdir.ensure(dir=1).join('__main__.py')
+ p.write(str(py.code.Source(source)))
+ # return relative path for testing purposes
+ return py.path.local().bestrelpath(pdir)
+
+demo_script = getscript("""
+ print 'hello'
+ print 'Name:', __name__
+ print 'File:', __file__
+ import sys
+ print 'Exec:', sys.executable
+ print 'Argv:', sys.argv
+ print 'goodbye'
+ myvalue = 6*7
+ """)
+
+crashing_demo_script = getscript("""
+ print 'Hello2'
+ myvalue2 = 11
+ ooups
+ myvalue2 = 22
+ print 'Goodbye2' # should not be reached
+ """)
+
+
+class TestParseCommandLine:
+ def check_options(self, options, sys_argv, **expected):
+ assert sys.argv == sys_argv
+ for key, value in expected.items():
+ assert options[key] == value
+ for key, value in options.items():
+ if key not in expected:
+ assert not value, (
+ "option %r has unexpectedly the value %r" % (key, value))
+
+ def check(self, argv, env, **expected):
+ import StringIO
+ from pypy.interpreter import app_main
+ saved_env = os.environ.copy()
+ saved_sys_argv = sys.argv[:]
+ saved_sys_stdout = sys.stdout
+ saved_sys_stderr = sys.stdout
+ app_main.os = os
+ try:
+ os.environ.update(env)
+ sys.stdout = sys.stderr = StringIO.StringIO()
+ try:
+ options = app_main.parse_command_line(argv)
+ except SystemExit:
+ output = expected['output_contains']
+ assert output in sys.stdout.getvalue()
+ else:
+ self.check_options(options, **expected)
+ finally:
+ os.environ.clear()
+ os.environ.update(saved_env)
+ sys.argv[:] = saved_sys_argv
+ sys.stdout = saved_sys_stdout
+ sys.stderr = saved_sys_stderr
+
+ def test_all_combinations_I_can_think_of(self):
+ self.check([], {}, sys_argv=[''], run_stdin=True)
+ self.check(['-'], {}, sys_argv=['-'], run_stdin=True)
+ self.check(['-S'], {}, sys_argv=[''], run_stdin=True, no_site=1)
+ self.check(['-OO'], {}, sys_argv=[''], run_stdin=True, optimize=2)
+ self.check(['-O', '-O'], {}, sys_argv=[''], run_stdin=True, optimize=2)
+ self.check(['-Qnew'], {}, sys_argv=[''], run_stdin=True, division_new=1)
+ self.check(['-Qold'], {}, sys_argv=[''], run_stdin=True, division_new=0)
+ self.check(['-Qwarn'], {}, sys_argv=[''], run_stdin=True, division_warning=1)
+ self.check(['-Qwarnall'], {}, sys_argv=[''], run_stdin=True,
+ division_warning=2)
+ self.check(['-Q', 'new'], {}, sys_argv=[''], run_stdin=True, division_new=1)
+ self.check(['-SOQnew'], {}, sys_argv=[''], run_stdin=True,
+ no_site=1, optimize=1, division_new=1)
+ self.check(['-SOQ', 'new'], {}, sys_argv=[''], run_stdin=True,
+ no_site=1, optimize=1, division_new=1)
+ self.check(['-i'], {}, sys_argv=[''], run_stdin=True,
+ interactive=1, inspect=1)
+ self.check(['-?'], {}, output_contains='usage:')
+ self.check(['-h'], {}, output_contains='usage:')
+ self.check(['-S', '-tO', '-h'], {}, output_contains='usage:')
+ self.check(['-S', '-thO'], {}, output_contains='usage:')
+ self.check(['-S', '-tO', '--help'], {}, output_contains='usage:')
+ self.check(['-S', '-tO', '--info'], {}, output_contains='translation')
+ self.check(['-S', '-tO', '--version'], {}, output_contains='Python')
+ self.check(['-S', '-tOV'], {}, output_contains='Python')
+ self.check(['--jit', 'foobar', '-S'], {}, sys_argv=[''],
+ run_stdin=True, no_site=1)
+ self.check(['-c', 'pass'], {}, sys_argv=['-c'], run_command='pass')
+ self.check(['-cpass'], {}, sys_argv=['-c'], run_command='pass')
+ self.check(['-cpass','x'], {}, sys_argv=['-c','x'], run_command='pass')
+ self.check(['-Sc', 'pass'], {}, sys_argv=['-c'], run_command='pass',
+ no_site=1)
+ self.check(['-Scpass'], {}, sys_argv=['-c'], run_command='pass', no_site=1)
+ self.check(['-c', '', ''], {}, sys_argv=['-c', ''], run_command='')
+ self.check(['-mfoo', 'bar', 'baz'], {}, sys_argv=['foo', 'bar', 'baz'],
+ run_module=True)
+ self.check(['-m', 'foo', 'bar', 'baz'], {}, sys_argv=['foo', 'bar', 'baz'],
+ run_module=True)
+ self.check(['-Smfoo', 'bar', 'baz'], {}, sys_argv=['foo', 'bar', 'baz'],
+ run_module=True, no_site=1)
+ self.check(['-Sm', 'foo', 'bar', 'baz'], {}, sys_argv=['foo', 'bar', 'baz'],
+ run_module=True, no_site=1)
+ self.check(['-', 'foo', 'bar'], {}, sys_argv=['-', 'foo', 'bar'],
+ run_stdin=True)
+ self.check(['foo', 'bar'], {}, sys_argv=['foo', 'bar'])
+ self.check(['foo', '-i'], {}, sys_argv=['foo', '-i'])
+ self.check(['-i', 'foo'], {}, sys_argv=['foo'], interactive=1, inspect=1)
+ self.check(['--', 'foo'], {}, sys_argv=['foo'])
+ self.check(['--', '-i', 'foo'], {}, sys_argv=['-i', 'foo'])
+ self.check(['--', '-', 'foo'], {}, sys_argv=['-', 'foo'], run_stdin=True)
+ self.check(['-Wbog'], {}, sys_argv=[''], warnoptions=['bog'], run_stdin=True)
+ self.check(['-W', 'ab', '-SWc'], {}, sys_argv=[''], warnoptions=['ab', 'c'],
+ run_stdin=True, no_site=1)
+
+ self.check([], {'PYTHONDEBUG': '1'}, sys_argv=[''], run_stdin=True, debug=1)
+ self.check([], {'PYTHONDONTWRITEBYTECODE': '1'}, sys_argv=[''], run_stdin=True, dont_write_bytecode=1)
+ self.check([], {'PYTHONNOUSERSITE': '1'}, sys_argv=[''], run_stdin=True, no_user_site=1)
+ self.check([], {'PYTHONUNBUFFERED': '1'}, sys_argv=[''], run_stdin=True, unbuffered=1)
+ self.check([], {'PYTHONVERBOSE': '1'}, sys_argv=[''], run_stdin=True, verbose=1)
+
+ def test_sysflags(self):
+ flags = (
+ ("debug", "-d", "1"),
+ ("py3k_warning", "-3", "1"),
+ ("division_warning", "-Qwarn", "1"),
+ ("division_warning", "-Qwarnall", "2"),
+ ("division_new", "-Qnew", "1"),
+ (["inspect", "interactive"], "-i", "1"),
+ ("optimize", "-O", "1"),
+ ("optimize", "-OO", "2"),
+ ("dont_write_bytecode", "-B", "1"),
+ ("no_user_site", "-s", "1"),
+ ("no_site", "-S", "1"),
+ ("ignore_environment", "-E", "1"),
+ ("tabcheck", "-t", "1"),
+ ("tabcheck", "-tt", "2"),
+ ("verbose", "-v", "1"),
+ ("unicode", "-U", "1"),
+ ("bytes_warning", "-b", "1"),
+ )
+ for flag, opt, value in flags:
+ if isinstance(flag, list): # this is for inspect&interactive
+ expected = {}
+ for flag1 in flag:
+ expected[flag1] = int(value)
+ else:
+ expected = {flag: int(value)}
+ self.check([opt, '-c', 'pass'], {}, sys_argv=['-c'],
+ run_command='pass', **expected)
+
+ def test_sysflags_envvar(self, monkeypatch):
+ monkeypatch.setenv('PYTHONNOUSERSITE', '1')
+ expected = {"no_user_site": True}
+ self.check(['-c', 'pass'], {}, sys_argv=['-c'], run_command='pass', **expected)
+
+
+class TestInteraction:
+ """
+ These tests require pexpect (UNIX-only).
+ http://pexpect.sourceforge.net/
+ """
+ def _spawn(self, *args, **kwds):
+ try:
+ import pexpect
+ except ImportError, e:
+ py.test.skip(str(e))
+ else:
+ # Version is of the style "0.999" or "2.1". Older versions of
+ # pexpect try to get the fileno of stdin, which generally won't
+ # work with py.test (due to sys.stdin being a DontReadFromInput
+ # instance).
+ version = map(int, pexpect.__version__.split('.'))
+
+ # I only tested 0.999 and 2.1. The former does not work, the
+ # latter does. Feel free to refine this measurement.
+ # -exarkun, 17/12/2007
+ if version < [2, 1]:
+ py.test.skip(
+ "pexpect version too old, requires 2.1 or newer: %r" % (
+ pexpect.__version__,))
+
+ kwds.setdefault('timeout', 10)
+ print 'SPAWN:', ' '.join([args[0]] + args[1]), kwds
+ child = pexpect.spawn(*args, **kwds)
+ child.logfile = sys.stdout
+ return child
+
+ def spawn(self, argv):
+ return self._spawn(sys.executable, [app_main] + argv)
+
+ def test_interactive(self):
+ child = self.spawn([])
+ child.expect('Python ') # banner
+ child.expect('>>> ') # prompt
+ child.sendline('[6*7]')
+ child.expect(re.escape('[42]'))
+ child.sendline('def f(x):')
+ child.expect(re.escape('... '))
+ child.sendline(' return x + 100')
+ child.expect(re.escape('... '))
+ child.sendline('')
+ child.expect('>>> ')
+ child.sendline('f(98)')
+ child.expect('198')
+ child.expect('>>> ')
+ child.sendline('__name__')
+ child.expect("'__main__'")
+ child.expect('>>> ')
+ child.sendline('import sys')
+ child.expect('>>> ')
+ child.sendline("'' in sys.path")
+ child.expect("True")
+
+ def test_help(self):
+ # test that -h prints the usage, including the name of the executable
+ # which should be /full/path/to/app_main.py in this case
+ child = self.spawn(['-h'])
+ child.expect(r'usage: .*app_main.py \[option\]')
+ child.expect('PyPy options and arguments:')
+
+ def test_run_script(self):
+ child = self.spawn([demo_script])
+ idx = child.expect(['hello', 'Python ', '>>> '])
+ assert idx == 0 # no banner or prompt
+ child.expect(re.escape("Name: __main__"))
+ child.expect(re.escape('File: ' + demo_script))
+ child.expect(re.escape('Exec: ' + app_main))
+ child.expect(re.escape('Argv: ' + repr([demo_script])))
+ child.expect('goodbye')
+
+ def test_run_script_with_args(self):
+ argv = [demo_script, 'hello', 'world']
+ child = self.spawn(argv)
+ child.expect(re.escape('Argv: ' + repr(argv)))
+ child.expect('goodbye')
+
+ def test_no_such_script(self):
+ import errno
+ msg = os.strerror(errno.ENOENT) # 'No such file or directory'
+ child = self.spawn(['xxx-no-such-file-xxx'])
+ child.expect(re.escape(msg))
+
+ def test_option_i(self):
+ argv = [demo_script, 'foo', 'bar']
+ child = self.spawn(['-i'] + argv)
+ idx = child.expect(['hello', re.escape(banner)])
+ assert idx == 0 # no banner
+ child.expect(re.escape('File: ' + demo_script))
+ child.expect(re.escape('Argv: ' + repr(argv)))
+ child.expect('goodbye')
+ idx = child.expect(['>>> ', re.escape(banner)])
+ assert idx == 0 # prompt, but still no banner
+ child.sendline('myvalue * 102')
+ child.expect('4284')
+ child.sendline('__name__')
+ child.expect('__main__')
+
+ def test_option_i_crashing(self):
+ argv = [crashing_demo_script, 'foo', 'bar']
+ child = self.spawn(['-i'] + argv)
+ idx = child.expect(['Hello2', re.escape(banner)])
+ assert idx == 0 # no banner
+ child.expect('NameError')
+ child.sendline('myvalue2 * 1001')
+ child.expect('11011')
+ child.sendline('import sys; sys.argv')
+ child.expect(re.escape(repr(argv)))
+ child.sendline('sys.last_type.__name__')
+ child.expect(re.escape(repr('NameError')))
+
+ def test_options_i_c(self):
+ child = self.spawn(['-i', '-c', 'x=555'])
+ idx = child.expect(['>>> ', re.escape(banner)])
+ assert idx == 0 # prompt, but no banner
+ child.sendline('x')
+ child.expect('555')
+ child.sendline('__name__')
+ child.expect('__main__')
+ child.sendline('import sys; sys.argv')
+ child.expect(re.escape("['-c']"))
+
+ def test_options_i_c_crashing(self, monkeypatch):
+ monkeypatch.setenv('PYTHONPATH', None)
+ child = self.spawn(['-i', '-c', 'x=666;foobar'])
+ child.expect('NameError')
+ idx = child.expect(['>>> ', re.escape(banner)])
+ assert idx == 0 # prompt, but no banner
+ child.sendline('x')
+ child.expect('666')
+ child.sendline('__name__')
+ child.expect('__main__')
+ child.sendline('import sys; sys.argv')
+ child.expect(re.escape("['-c']"))
+ child.sendline('sys.last_type.__name__')
+ child.expect(re.escape(repr('NameError')))
+
+ def test_atexit(self):
+ child = self.spawn([])
+ child.expect('>>> ')
+ child.sendline('def f(): print "foobye"')
+ child.sendline('')
+ child.sendline('import atexit; atexit.register(f)')
+ child.sendline('6*7')
+ child.expect('42')
+ # pexpect's sendeof() is confused by py.test capturing, though
+ # I think that it is a bug of sendeof()
+ old = sys.stdin
+ try:
+ sys.stdin = child
+ child.sendeof()
+ finally:
+ sys.stdin = old
+ child.expect('foobye')
+
+ def test_pythonstartup(self, monkeypatch):
+ monkeypatch.setenv('PYTHONPATH', None)
+ monkeypatch.setenv('PYTHONSTARTUP', crashing_demo_script)
+ child = self.spawn([])
+ child.expect(re.escape(banner))
+ child.expect('Traceback')
+ child.expect('NameError')
+ child.expect('>>> ')
+ child.sendline('[myvalue2]')
+ child.expect(re.escape('[11]'))
+ child.expect('>>> ')
+
+ child = self.spawn(['-i', demo_script])
+ for line in ['hello', 'goodbye', '>>> ']:
+ idx = child.expect([line, 'Hello2'])
+ assert idx == 0 # no PYTHONSTARTUP run here
+ child.sendline('myvalue2')
+ child.expect('Traceback')
+ child.expect('NameError')
+
+ def test_pythonstartup_file1(self, monkeypatch):
+ monkeypatch.setenv('PYTHONPATH', None)
+ monkeypatch.setenv('PYTHONSTARTUP', demo_script)
+ child = self.spawn([])
+ child.expect('File: [^\n]+\.py')
+ child.expect('goodbye')
+ child.expect('>>> ')
+ child.sendline('[myvalue]')
+ child.expect(re.escape('[42]'))
+ child.expect('>>> ')
+ child.sendline('__file__')
+ child.expect('Traceback')
+ child.expect('NameError')
+
+ def test_pythonstartup_file2(self, monkeypatch):
+ monkeypatch.setenv('PYTHONPATH', None)
+ monkeypatch.setenv('PYTHONSTARTUP', crashing_demo_script)
+ child = self.spawn([])
+ child.expect('Traceback')
+ child.expect('>>> ')
+ child.sendline('__file__')
+ child.expect('Traceback')
+ child.expect('NameError')
+
+ def test_ignore_python_startup(self):
+ old = os.environ.get('PYTHONSTARTUP', '')
+ try:
+ os.environ['PYTHONSTARTUP'] = crashing_demo_script
+ child = self.spawn(['-E'])
+ child.expect(re.escape(banner))
+ index = child.expect(['Traceback', '>>> '])
+ assert index == 1 # no traceback
+ finally:
+ os.environ['PYTHONSTARTUP'] = old
+
+ def test_ignore_python_inspect(self):
+ os.environ['PYTHONINSPECT_'] = '1'
+ try:
+ child = self.spawn(['-E', '-c', 'pass'])
+ from pexpect import EOF
+ index = child.expect(['>>> ', EOF])
+ assert index == 1 # no prompt
+ finally:
+ del os.environ['PYTHONINSPECT_']
+
+ def test_python_path_keeps_duplicates(self):
+ old = os.environ.get('PYTHONPATH', '')
+ try:
+ os.environ['PYTHONPATH'] = 'foobarbaz:foobarbaz'
+ child = self.spawn(['-c', 'import sys; print sys.path'])
+ child.expect(r"\['', 'foobarbaz', 'foobarbaz', ")
+ finally:
+ os.environ['PYTHONPATH'] = old
+
+ def test_ignore_python_path(self):
+ old = os.environ.get('PYTHONPATH', '')
+ try:
+ os.environ['PYTHONPATH'] = 'foobarbaz'
+ child = self.spawn(['-E', '-c', 'import sys; print sys.path'])
+ from pexpect import EOF
+ index = child.expect(['foobarbaz', EOF])
+ assert index == 1 # no foobarbaz
+ finally:
+ os.environ['PYTHONPATH'] = old
+
+ def test_unbuffered(self):
+ line = 'import os,sys;sys.stdout.write(str(789));os.read(0,1)'
+ child = self.spawn(['-u', '-c', line])
+ child.expect('789') # expect to see it before the timeout hits
+ child.sendline('X')
+
+ def test_options_i_m(self, monkeypatch):
+ if sys.platform == "win32":
+ skip("close_fds is not supported on Windows platforms")
+ if not hasattr(runpy, '_run_module_as_main'):
+ skip("requires CPython >= 2.6")
+ p = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'mymodule.py')
+ p = os.path.abspath(p)
+ monkeypatch.chdir(os.path.dirname(app_main))
+ child = self.spawn(['-i',
+ '-m', 'test.mymodule',
+ 'extra'])
+ child.expect('mymodule running')
+ child.expect('Name: __main__')
+ child.expect(re.escape('File: ' + p))
+ child.expect(re.escape('Argv: ' + repr([p, 'extra'])))
+ child.expect('>>> ')
+ child.sendline('somevalue')
+ child.expect(re.escape(repr("foobar")))
+ child.expect('>>> ')
+ child.sendline('import sys')
+ child.sendline('"test" in sys.modules')
+ child.expect('True')
+ child.sendline('"test.mymodule" in sys.modules')
+ child.expect('False')
+ child.sendline('sys.path[0]')
+ child.expect("''")
+
+ def test_option_i_noexit(self):
+ child = self.spawn(['-i', '-c', 'import sys; sys.exit(1)'])
+ child.expect('Traceback')
+ child.expect('SystemExit: 1')
+
+ def test_options_u_i(self):
+ if sys.platform == "win32":
+ skip("close_fds is not supported on Windows platforms")
+ import subprocess, select, os
+ python = sys.executable
+ pipe = subprocess.Popen([python, app_main, "-u", "-i"],
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ bufsize=0, close_fds=True)
+ iwtd, owtd, ewtd = select.select([pipe.stdout], [], [], 5)
+ assert iwtd # else we timed out
+ data = os.read(pipe.stdout.fileno(), 1024)
+ assert data.startswith('Python')
+
+ def test_paste_several_lines_doesnt_mess_prompt(self):
+ py.test.skip("this can only work if readline is enabled")
+ child = self.spawn([])
+ child.expect('>>> ')
+ child.sendline('if 1:\n print 42\n')
+ child.expect('... print 42')
+ child.expect('... ')
+ child.expect('42')
+ child.expect('>>> ')
+
+ def test_pythoninspect(self):
+ os.environ['PYTHONINSPECT_'] = '1'
+ try:
+ path = getscript("""
+ print 6*7
+ """)
+ child = self.spawn([path])
+ child.expect('42')
+ child.expect('>>> ')
+ finally:
+ del os.environ['PYTHONINSPECT_']
+
+ def test_set_pythoninspect(self):
+ path = getscript("""
+ import os
+ os.environ['PYTHONINSPECT'] = '1'
+ print 6*7
+ """)
+ child = self.spawn([path])
+ child.expect('42')
+ child.expect('>>> ')
+
+ def test_clear_pythoninspect(self):
+ os.environ['PYTHONINSPECT_'] = '1'
+ try:
+ path = getscript("""
+ import os
+ del os.environ['PYTHONINSPECT']
+ """)
+ child = self.spawn([path])
+ child.expect('>>> ')
+ finally:
+ del os.environ['PYTHONINSPECT_']
+
+ def test_stdout_flushes_before_stdin_blocks(self):
+ # This doesn't really test app_main.py, but a behavior that
+ # can only be checked on top of py.py with pexpect.
+ path = getscript("""
+ import sys
+ sys.stdout.write('Are you suggesting coconuts migrate? ')
+ line = sys.stdin.readline()
+ assert line.rstrip() == 'Not at all. They could be carried.'
+ print 'A five ounce bird could not carry a one pound coconut.'
+ """)
+ py_py = os.path.join(pypydir, 'bin', 'pyinteractive.py')
+ child = self._spawn(sys.executable, [py_py, '-S', path])
+ child.expect('Are you suggesting coconuts migrate?', timeout=120)
+ child.sendline('Not at all. They could be carried.')
+ child.expect('A five ounce bird could not carry a one pound coconut.')
+
+ def test_no_space_before_argument(self, monkeypatch):
+ if not hasattr(runpy, '_run_module_as_main'):
+ skip("requires CPython >= 2.6")
+ child = self.spawn(['-cprint "hel" + "lo"'])
+ child.expect('hello')
+
+ monkeypatch.chdir(os.path.dirname(app_main))
+ child = self.spawn(['-mtest.mymodule'])
+ child.expect('mymodule running')
+
+ def test_ps1_only_if_interactive(self):
+ argv = ['-c', 'import sys; print hasattr(sys, "ps1")']
+ child = self.spawn(argv)
+ child.expect('False')
+
+
+class TestNonInteractive:
+ def run_with_status_code(self, cmdline, senddata='', expect_prompt=False,
+ expect_banner=False, python_flags='', env=None):
+ cmdline = '%s %s "%s" %s' % (sys.executable, python_flags,
+ app_main, cmdline)
+ print 'POPEN:', cmdline
+ process = subprocess.Popen(
+ cmdline,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ shell=True, env=env,
+ universal_newlines=True
+ )
+ child_in, child_out_err = process.stdin, process.stdout
+ child_in.write(senddata)
+ child_in.close()
+ data = child_out_err.read()
+ child_out_err.close()
+ process.wait()
+ assert (banner in data) == expect_banner # no banner unless expected
+ assert ('>>> ' in data) == expect_prompt # no prompt unless expected
+ return data, process.returncode
+
+ def run(self, *args, **kwargs):
+ data, status = self.run_with_status_code(*args, **kwargs)
+ return data
+
+ def test_script_on_stdin(self):
+ for extraargs, expected_argv in [
+ ('', ['']),
+ ('-', ['-']),
+ ('- hello world', ['-', 'hello', 'world']),
+ ]:
+ data = self.run('%s < "%s"' % (extraargs, demo_script))
+ assert "hello" in data
+ assert "Name: __main__" in data
+ assert "File: <stdin>" in data
+ assert ("Exec: " + app_main) in data
+ assert ("Argv: " + repr(expected_argv)) in data
+ assert "goodbye" in data
+
+ def test_run_crashing_script(self):
+ data = self.run('"%s"' % (crashing_demo_script,))
+ assert 'Hello2' in data
+ assert 'NameError' in data
+ assert 'Goodbye2' not in data
+
+ def test_crashing_script_on_stdin(self):
+ data = self.run(' < "%s"' % (crashing_demo_script,))
+ assert 'Hello2' in data
+ assert 'NameError' in data
+ assert 'Goodbye2' not in data
+
+ def test_option_W(self):
+ data = self.run('-W d -c "print 42"')
+ assert '42' in data
+ data = self.run('-Wd -c "print 42"')
+ assert '42' in data
+
+ def test_option_W_crashing(self):
+ data = self.run('-W')
+ assert "Argument expected for the '-W' option" in data
+
+ def test_option_W_arg_ignored(self):
+ data = self.run('-Wc')
+ assert "Invalid -W option ignored: invalid action: 'c'" in data
+
+ def test_option_W_arg_ignored2(self):
+ data = self.run('-W-W')
+ assert "Invalid -W option ignored: invalid action:" in data
+
+ def test_option_c(self):
+ data = self.run('-c "print 6**5"')
+ assert '7776' in data
+
+ def test_no_pythonstartup(self, monkeypatch):
+ monkeypatch.setenv('PYTHONSTARTUP', crashing_demo_script)
+ data = self.run('"%s"' % (demo_script,))
+ assert 'Hello2' not in data
+ data = self.run('-c pass')
+ assert 'Hello2' not in data
+
+ def test_pythonwarnings(self, monkeypatch):
+ # PYTHONWARNINGS_ is special cased by app_main: we cannot directly set
+ # PYTHONWARNINGS because else the warnings raised from within pypy are
+ # turned in errors.
+ monkeypatch.setenv('PYTHONWARNINGS_', "once,error")
+ data = self.run('-W ignore -W default '
+ '-c "import sys; print sys.warnoptions"')
+ assert "['ignore', 'default', 'once', 'error']" in data
+
+ def test_option_m(self, monkeypatch):
+ if not hasattr(runpy, '_run_module_as_main'):
+ skip("requires CPython >= 2.6")
+ p = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'mymodule.py')
+ p = os.path.abspath(p)
+ monkeypatch.chdir(os.path.dirname(app_main))
+ data = self.run('-m test.mymodule extra')
+ assert 'mymodule running' in data
+ assert 'Name: __main__' in data
+ # ignoring case for windows. abspath behaves different from autopath
+ # concerning drive letters right now.
+ assert ('File: ' + p) in data
+ assert ('Argv: ' + repr([p, 'extra'])) in data
+
+ def test_pythoninspect_doesnt_override_isatty(self):
+ os.environ['PYTHONINSPECT_'] = '1'
+ try:
+ data = self.run('', senddata='6*7\nprint 2+3\n')
+ assert data == '5\n'
+ finally:
+ del os.environ['PYTHONINSPECT_']
+
+ def test_i_flag_overrides_isatty(self):
+ data = self.run('-i', senddata='6*7\nraise SystemExit\n',
+ expect_prompt=True, expect_banner=True)
+ assert '42\n' in data
+ # if a file name is passed, the banner is never printed but
+ # we get a prompt anyway
+ cmdline = '-i %s' % getscript("""
+ print 'hello world'
+ """)
+ data = self.run(cmdline, senddata='6*7\nraise SystemExit\n',
+ expect_prompt=True, expect_banner=False)
+ assert 'hello world\n' in data
+ assert '42\n' in data
+
+ def test_option_S_copyright(self):
+ data = self.run('-S -i', expect_prompt=True, expect_banner=True)
+ assert 'copyright' not in data
+
+ def test_non_interactive_stdout_fully_buffered(self):
+ path = getscript(r"""
+ import sys, time
+ sys.stdout.write('\x00(STDOUT)\n\x00') # stays in buffers
+ time.sleep(1)
+ sys.stderr.write('\x00[STDERR]\n\x00')
+ time.sleep(1)
+ # stdout flushed automatically here
+ """)
+ cmdline = '%s -u "%s" %s' % (sys.executable, app_main, path)
+ print 'POPEN:', cmdline
+ child_in, child_out_err = os.popen4(cmdline)
+ data = child_out_err.read(11)
+ assert data == '\x00[STDERR]\n\x00' # from stderr
+ child_in.close()
+ data = child_out_err.read(11)
+ assert data == '\x00(STDOUT)\n\x00' # from stdout
+ child_out_err.close()
+
+ def test_non_interactive_stdout_unbuffered(self, monkeypatch):
+ monkeypatch.setenv('PYTHONUNBUFFERED', '1')
+ path = getscript(r"""
+ import sys, time
+ sys.stdout.write('\x00(STDOUT)\n\x00')
+ time.sleep(1)
+ sys.stderr.write('\x00[STDERR]\n\x00')
+ time.sleep(1)
+ # stdout flushed automatically here
+ """)
+ cmdline = '%s -E "%s" %s' % (sys.executable, app_main, path)
+ print 'POPEN:', cmdline
+ child_in, child_out_err = os.popen4(cmdline)
+ data = child_out_err.read(11)
+ assert data == '\x00(STDOUT)\n\x00' # from stderr
+ data = child_out_err.read(11)
+ assert data == '\x00[STDERR]\n\x00' # from stdout
+ child_out_err.close()
+ child_in.close()
+
+ def test_proper_sys_path(self, tmpdir):
+ data = self.run('-c "import _ctypes"', python_flags='-S')
+ if data.startswith('Traceback'):
+ py.test.skip("'python -S' cannot import extension modules: "
+ "see probably http://bugs.python.org/issue586680")
+
+ @contextmanager
+ def chdir_and_unset_pythonpath(new_cwd):
+ old_cwd = new_cwd.chdir()
+ old_pythonpath = os.getenv('PYTHONPATH')
+ os.unsetenv('PYTHONPATH')
+ try:
+ yield
+ finally:
+ old_cwd.chdir()
+ # Can't call putenv with a None argument.
+ if old_pythonpath is not None:
+ os.putenv('PYTHONPATH', old_pythonpath)
+
+ tmpdir.join('site.py').write('print "SHOULD NOT RUN"')
+ runme_py = tmpdir.join('runme.py')
+ runme_py.write('print "some text"')
+
+ cmdline = str(runme_py)
+
+ with chdir_and_unset_pythonpath(tmpdir):
+ data = self.run(cmdline, python_flags='-S')
+
+ assert data == "some text\n"
+
+ runme2_py = tmpdir.mkdir('otherpath').join('runme2.py')
+ runme2_py.write('print "some new text"\n'
+ 'import sys\n'
+ 'print sys.path\n')
+
+ cmdline2 = str(runme2_py)
+
+ with chdir_and_unset_pythonpath(tmpdir):
+ data = self.run(cmdline2, python_flags='-S')
+ assert data.startswith("some new text\n")
+ assert repr(str(tmpdir.join('otherpath'))) in data
+ assert "''" not in data
+
+ data = self.run('-c "import sys; print sys.path"')
+ assert data.startswith("[''")
+
+ def test_pyc_commandline_argument(self):
+ p = getscript_pyc(self.space, "print 6*7\n")
+ assert os.path.isfile(p) and p.endswith('.pyc')
+ data = self.run(p)
+ assert data == 'in _run_compiled_module\n'
+
+ def test_main_in_dir_commandline_argument(self):
+ if not hasattr(runpy, '_run_module_as_main'):
+ skip("requires CPython >= 2.6")
+ p = getscript_in_dir('import sys; print sys.argv[0]\n')
+ data = self.run(p)
+ assert data == p + '\n'
+ data = self.run(p + os.sep)
+ assert data == p + os.sep + '\n'
+
+ def test_getfilesystemencoding(self):
+ py.test.skip("encoding is only set if stdout.isatty(), test is flawed")
+ if sys.version_info < (2, 7):
+ skip("test requires Python >= 2.7")
+ p = getscript_in_dir("""
+ import sys
+ sys.stdout.write(u'15\u20ac')
+ sys.stdout.flush()
+ """)
+ env = os.environ.copy()
+ env["LC_CTYPE"] = 'en_US.UTF-8'
+ data = self.run(p, env=env)
+ assert data == '15\xe2\x82\xac'
+
+ def test_pythonioencoding(self):
+ if sys.version_info < (2, 7):
+ skip("test requires Python >= 2.7")
+ for encoding, expected in [
+ ("iso-8859-15", "15\xa4"),
+ ("utf-8", '15\xe2\x82\xac'),
+ ("utf-16-le", '1\x005\x00\xac\x20'),
+ ("iso-8859-1:ignore", "15"),
+ ("iso-8859-1:replace", "15?"),
+ ("iso-8859-1:backslashreplace", "15\\u20ac"),
+ ]:
+ p = getscript_in_dir("""
+ import sys
+ sys.stdout.write(u'15\u20ac')
+ sys.stdout.flush()
+ """)
+ env = os.environ.copy()
+ env["PYTHONIOENCODING"] = encoding
+ data = self.run(p, env=env)
+ assert data == expected
+
+ def test_sys_exit_pythonioencoding(self):
+ if sys.version_info < (2, 7):
+ skip("test required Python >= 2.7")
+ p = getscript_in_dir("""
+ import sys
+ sys.exit(u'15\u20ac')
+ """)
+ env = os.environ.copy()
+ env["PYTHONIOENCODING"] = "utf-8"
+ data, status = self.run_with_status_code(p, env=env)
+ assert status == 1
+ assert data.startswith("15\xe2\x82\xac")
+
+
+class TestAppMain:
+ def test_print_info(self):
+ from pypy.interpreter import app_main
+ import sys, cStringIO
+ prev_so = sys.stdout
+ prev_ti = getattr(sys, 'pypy_translation_info', 'missing')
+ sys.pypy_translation_info = {
+ 'translation.foo': True,
+ 'translation.bar': 42,
+ 'translation.egg.something': None,
+ 'objspace.x': 'hello',
+ }
+ try:
+ sys.stdout = f = cStringIO.StringIO()
+ py.test.raises(SystemExit, app_main.print_info)
+ finally:
+ sys.stdout = prev_so
+ if prev_ti == 'missing':
+ del sys.pypy_translation_info
+ else:
+ sys.pypy_translation_info = prev_ti
+ assert f.getvalue() == ("[objspace]\n"
+ " x = 'hello'\n"
+ "[translation]\n"
+ " bar = 42\n"
+ " [egg]\n"
+ " something = None\n"
+ " foo = True\n")
+
+
+class AppTestAppMain:
+ def setup_class(self):
+ # ----------------------------------------
+ # setup code for test_setup_bootstrap_path
+ # ----------------------------------------
+ from pypy.module.sys.version import CPYTHON_VERSION, PYPY_VERSION
+ cpy_ver = '%d.%d' % CPYTHON_VERSION[:2]
+
+ goal_dir = os.path.dirname(app_main)
+ # build a directory hierarchy like which contains both bin/pypy-c and
+ # lib/pypy1.2/*
+ prefix = udir.join('pathtest').ensure(dir=1)
+ fake_exe = 'bin/pypy-c'
+ if sys.platform == 'win32':
+ fake_exe += '.exe'
+ fake_exe = prefix.join(fake_exe).ensure(file=1)
+ expected_path = [str(prefix.join(subdir).ensure(dir=1))
+ for subdir in ('lib_pypy',
+ 'lib-python/%s' % cpy_ver)]
+
+ self.w_goal_dir = self.space.wrap(goal_dir)
+ self.w_fake_exe = self.space.wrap(str(fake_exe))
+ self.w_expected_path = self.space.wrap(expected_path)
+ self.w_trunkdir = self.space.wrap(os.path.dirname(pypydir))
+
+ foo_py = prefix.join('foo.py').write("pass")
+ self.w_foo_py = self.space.wrap(str(foo_py))
+
+ def test_setup_bootstrap_path(self):
+ import sys
+ old_sys_path = sys.path[:]
+ sys.path.append(self.goal_dir)
+ try:
+ import app_main
+ app_main.setup_bootstrap_path('/tmp/pypy-c') # stdlib not found
+ assert sys.executable == ''
+ assert sys.path == old_sys_path + [self.goal_dir]
+
+ app_main.setup_bootstrap_path(self.fake_exe)
+ assert sys.executable == self.fake_exe
+ assert self.goal_dir not in sys.path
+
+ newpath = sys.path[:]
+ if newpath[0].endswith('__extensions__'):
+ newpath = newpath[1:]
+ # we get at least 'expected_path', and maybe more (e.g.plat-linux2)
+ assert newpath[:len(self.expected_path)] == self.expected_path
+ finally:
+ sys.path[:] = old_sys_path
+
+ def test_trunk_can_be_prefix(self):
+ import sys
+ import os
+ old_sys_path = sys.path[:]
+ sys.path.append(self.goal_dir)
+ try:
+ import app_main
+ pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', 'pypy-c')
+ app_main.setup_bootstrap_path(pypy_c)
+ newpath = sys.path[:]
+ # we get at least lib_pypy
+ # lib-python/X.Y.Z, and maybe more (e.g. plat-linux2)
+ assert len(newpath) >= 2
+ for p in newpath:
+ assert p.startswith(self.trunkdir)
+ finally:
+ sys.path[:] = old_sys_path
+
+ def test_entry_point(self):
+ import sys
+ import os
+ old_sys_path = sys.path[:]
+ sys.path.append(self.goal_dir)
+ try:
+ import app_main
+ pypy_c = os.path.join(self.trunkdir, 'pypy', 'goal', 'pypy-c')
+ app_main.entry_point(pypy_c, [self.foo_py])
+ # assert it did not crash
+ finally:
+ sys.path[:] = old_sys_path
diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -135,18 +135,39 @@
def test_interpindirect2app(self):
space = self.space
+
class BaseA(W_Root):
def method(self, space, x):
+ "This is a method"
+ pass
+
+ def method_with_default(self, space, x=5):
+ pass
+
+ @gateway.unwrap_spec(x=int)
+ def method_with_unwrap_spec(self, space, x):
pass
class A(BaseA):
def method(self, space, x):
return space.wrap(x + 2)
+ def method_with_default(self, space, x):
+ return space.wrap(x + 2)
+
+ def method_with_unwrap_spec(self, space, x):
+ return space.wrap(x + 2)
+
class B(BaseA):
def method(self, space, x):
return space.wrap(x + 1)
+ def method_with_default(self, space, x):
+ return space.wrap(x + 1)
+
+ def method_with_unwrap_spec(self, space, x):
+ return space.wrap(x + 1)
+
class FakeTypeDef(object):
rawdict = {}
bases = {}
@@ -163,6 +184,23 @@
assert space.int_w(space.call_function(w_c, w_a, space.wrap(1))) == 1 + 2
assert space.int_w(space.call_function(w_c, w_b, space.wrap(-10))) == -10 + 1
+ doc = space.str_w(space.getattr(w_c, space.wrap('__doc__')))
+ assert doc == "This is a method"
+
+ meth_with_default = gateway.interpindirect2app(
+ BaseA.method_with_default, {'x': int})
+ w_d = space.wrap(meth_with_default)
+
+ assert space.int_w(space.call_function(w_d, w_a, space.wrap(4))) == 4 + 2
+ assert space.int_w(space.call_function(w_d, w_b, space.wrap(-10))) == -10 + 1
+ assert space.int_w(space.call_function(w_d, w_a)) == 5 + 2
+ assert space.int_w(space.call_function(w_d, w_b)) == 5 + 1
+
+ meth_with_unwrap_spec = gateway.interpindirect2app(
+ BaseA.method_with_unwrap_spec)
+ w_e = space.wrap(meth_with_unwrap_spec)
+ assert space.int_w(space.call_function(w_e, w_a, space.wrap(4))) == 4 + 2
+
def test_interp2app_unwrap_spec(self):
space = self.space
w = space.wrap
diff --git a/pypy/interpreter/test/test_targetpypy.py b/pypy/interpreter/test/test_targetpypy.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/test_targetpypy.py
@@ -0,0 +1,28 @@
+from pypy.goal.targetpypystandalone import get_entry_point, create_entry_point
+from pypy.config.pypyoption import get_pypy_config
+from rpython.rtyper.lltypesystem import rffi, lltype
+
+class TestTargetPyPy(object):
+ def test_run(self):
+ config = get_pypy_config(translating=False)
+ entry_point = get_entry_point(config)[0]
+ entry_point(['pypy-c' , '-S', '-c', 'print 3'])
+
+def test_exeucte_source(space):
+ _, d = create_entry_point(space, None)
+ execute_source = d['pypy_execute_source']
+ lls = rffi.str2charp("import sys; sys.modules['xyz'] = 3")
+ execute_source(lls)
+ lltype.free(lls, flavor='raw')
+ x = space.int_w(space.getitem(space.getattr(space.builtin_modules['sys'],
+ space.wrap('modules')),
+ space.wrap('xyz')))
+ assert x == 3
+ lls = rffi.str2charp("sys")
+ execute_source(lls)
+ lltype.free(lls, flavor='raw')
+ # did not crash - the same globals
+ pypy_setup_home = d['pypy_setup_home']
+ lls = rffi.str2charp(__file__)
+ pypy_setup_home(lls, 1)
+ lltype.free(lls, flavor='raw')
diff --git a/pypy/interpreter/test/test_zzpickle_and_slow.py b/pypy/interpreter/test/test_zzpickle_and_slow.py
--- a/pypy/interpreter/test/test_zzpickle_and_slow.py
+++ b/pypy/interpreter/test/test_zzpickle_and_slow.py
@@ -485,3 +485,68 @@
pckl = pickle.dumps(pack.mod)
result = pickle.loads(pckl)
assert pack.mod is result
+
+
+class AppTestGeneratorCloning:
+
+ def setup_class(cls):
+ try:
+ cls.space.appexec([], """():
+ def f(): yield 42
+ f().__reduce__()
+ """)
+ except TypeError, e:
+ if 'pickle generator' not in str(e):
+ raise
+ py.test.skip("Frames can't be __reduce__()-ed")
+
+ def test_deepcopy_generator(self):
+ import copy
+
+ def f(n):
+ for i in range(n):
+ yield 42 + i
+ g = f(4)
+ g2 = copy.deepcopy(g)
+ res = g.next()
+ assert res == 42
+ res = g2.next()
+ assert res == 42
+ g3 = copy.deepcopy(g)
+ res = g.next()
+ assert res == 43
+ res = g2.next()
+ assert res == 43
+ res = g3.next()
+ assert res == 43
+
+ def test_shallowcopy_generator(self):
+ """Note: shallow copies of generators are often confusing.
+ To start with, 'for' loops have an iterator that will not
+ be copied, and so create tons of confusion.
+ """
+ import copy
+
+ def f(n):
+ while n > 0:
+ yield 42 + n
+ n -= 1
+ g = f(2)
+ g2 = copy.copy(g)
+ res = g.next()
+ assert res == 44
+ res = g2.next()
+ assert res == 44
+ g3 = copy.copy(g)
+ res = g.next()
+ assert res == 43
+ res = g2.next()
+ assert res == 43
+ res = g3.next()
+ assert res == 43
+ g4 = copy.copy(g2)
+ for i in range(2):
+ raises(StopIteration, g.next)
+ raises(StopIteration, g2.next)
+ raises(StopIteration, g3.next)
+ raises(StopIteration, g4.next)
diff --git a/pypy/interpreter/test2/__init__.py b/pypy/interpreter/test2/__init__.py
deleted file mode 100644
--- a/pypy/interpreter/test2/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-#empty
diff --git a/pypy/interpreter/test2/test_app_main.py b/pypy/interpreter/test2/test_app_main.py
deleted file mode 100644
--- a/pypy/interpreter/test2/test_app_main.py
+++ /dev/null
@@ -1,966 +0,0 @@
-"""
-Tests for the entry point of pypy-c, app_main.py.
-"""
-from __future__ import with_statement
-import py
-import sys, os, re, runpy, subprocess
-from rpython.tool.udir import udir
-from contextlib import contextmanager
-from pypy.conftest import pypydir
-
-banner = sys.version.splitlines()[0]
-
-app_main = os.path.join(os.path.realpath(os.path.dirname(__file__)), os.pardir, 'app_main.py')
-app_main = os.path.abspath(app_main)
-
-_counter = 0
-def _get_next_path(ext='.py'):
- global _counter
- p = udir.join('demo_test_app_main_%d%s' % (_counter, ext))
- _counter += 1
- return p
-
-def getscript(source):
- p = _get_next_path()
- p.write(str(py.code.Source(source)))
- return str(p)
-
-def getscript_pyc(space, source):
- p = _get_next_path()
- p.write(str(py.code.Source(source)))
- w_dir = space.wrap(str(p.dirpath()))
- w_modname = space.wrap(p.purebasename)
- space.appexec([w_dir, w_modname], """(dir, modname):
- import sys
- d = sys.modules.copy()
- sys.path.insert(0, dir)
- __import__(modname)
- sys.path.pop(0)
- for key in sys.modules.keys():
- if key not in d:
- del sys.modules[key]
- """)
- p = str(p) + 'c'
- assert os.path.isfile(p) # the .pyc file should have been created above
- return p
-
-def getscript_in_dir(source):
- pdir = _get_next_path(ext='')
- p = pdir.ensure(dir=1).join('__main__.py')
- p.write(str(py.code.Source(source)))
- # return relative path for testing purposes
- return py.path.local().bestrelpath(pdir)
-
-demo_script = getscript("""
- print 'hello'
- print 'Name:', __name__
- print 'File:', __file__
- import sys
- print 'Exec:', sys.executable
- print 'Argv:', sys.argv
- print 'goodbye'
- myvalue = 6*7
- """)
-
-crashing_demo_script = getscript("""
- print 'Hello2'
- myvalue2 = 11
- ooups
- myvalue2 = 22
- print 'Goodbye2' # should not be reached
- """)
-
-
-class TestParseCommandLine:
- def check_options(self, options, sys_argv, **expected):
- assert sys.argv == sys_argv
- for key, value in expected.items():
- assert options[key] == value
- for key, value in options.items():
- if key not in expected:
- assert not value, (
- "option %r has unexpectedly the value %r" % (key, value))
-
- def check(self, argv, env, **expected):
- import StringIO
- from pypy.interpreter import app_main
- saved_env = os.environ.copy()
- saved_sys_argv = sys.argv[:]
- saved_sys_stdout = sys.stdout
- saved_sys_stderr = sys.stdout
- app_main.os = os
- try:
- os.environ.update(env)
- sys.stdout = sys.stderr = StringIO.StringIO()
- try:
- options = app_main.parse_command_line(argv)
- except SystemExit:
- output = expected['output_contains']
- assert output in sys.stdout.getvalue()
- else:
- self.check_options(options, **expected)
- finally:
- os.environ.clear()
- os.environ.update(saved_env)
- sys.argv[:] = saved_sys_argv
- sys.stdout = saved_sys_stdout
- sys.stderr = saved_sys_stderr
-
- def test_all_combinations_I_can_think_of(self):
- self.check([], {}, sys_argv=[''], run_stdin=True)
- self.check(['-'], {}, sys_argv=['-'], run_stdin=True)
- self.check(['-S'], {}, sys_argv=[''], run_stdin=True, no_site=1)
- self.check(['-OO'], {}, sys_argv=[''], run_stdin=True, optimize=2)
- self.check(['-O', '-O'], {}, sys_argv=[''], run_stdin=True, optimize=2)
- self.check(['-Qnew'], {}, sys_argv=[''], run_stdin=True, division_new=1)
- self.check(['-Qold'], {}, sys_argv=[''], run_stdin=True, division_new=0)
- self.check(['-Qwarn'], {}, sys_argv=[''], run_stdin=True, division_warning=1)
- self.check(['-Qwarnall'], {}, sys_argv=[''], run_stdin=True,
- division_warning=2)
- self.check(['-Q', 'new'], {}, sys_argv=[''], run_stdin=True, division_new=1)
- self.check(['-SOQnew'], {}, sys_argv=[''], run_stdin=True,
- no_site=1, optimize=1, division_new=1)
- self.check(['-SOQ', 'new'], {}, sys_argv=[''], run_stdin=True,
- no_site=1, optimize=1, division_new=1)
- self.check(['-i'], {}, sys_argv=[''], run_stdin=True,
- interactive=1, inspect=1)
- self.check(['-?'], {}, output_contains='usage:')
- self.check(['-h'], {}, output_contains='usage:')
- self.check(['-S', '-tO', '-h'], {}, output_contains='usage:')
- self.check(['-S', '-thO'], {}, output_contains='usage:')
- self.check(['-S', '-tO', '--help'], {}, output_contains='usage:')
- self.check(['-S', '-tO', '--info'], {}, output_contains='translation')
- self.check(['-S', '-tO', '--version'], {}, output_contains='Python')
- self.check(['-S', '-tOV'], {}, output_contains='Python')
- self.check(['--jit', 'foobar', '-S'], {}, sys_argv=[''],
- run_stdin=True, no_site=1)
- self.check(['-c', 'pass'], {}, sys_argv=['-c'], run_command='pass')
- self.check(['-cpass'], {}, sys_argv=['-c'], run_command='pass')
- self.check(['-cpass','x'], {}, sys_argv=['-c','x'], run_command='pass')
- self.check(['-Sc', 'pass'], {}, sys_argv=['-c'], run_command='pass',
- no_site=1)
- self.check(['-Scpass'], {}, sys_argv=['-c'], run_command='pass', no_site=1)
- self.check(['-c', '', ''], {}, sys_argv=['-c', ''], run_command='')
- self.check(['-mfoo', 'bar', 'baz'], {}, sys_argv=['foo', 'bar', 'baz'],
- run_module=True)
- self.check(['-m', 'foo', 'bar', 'baz'], {}, sys_argv=['foo', 'bar', 'baz'],
- run_module=True)
- self.check(['-Smfoo', 'bar', 'baz'], {}, sys_argv=['foo', 'bar', 'baz'],
- run_module=True, no_site=1)
- self.check(['-Sm', 'foo', 'bar', 'baz'], {}, sys_argv=['foo', 'bar', 'baz'],
- run_module=True, no_site=1)
- self.check(['-', 'foo', 'bar'], {}, sys_argv=['-', 'foo', 'bar'],
- run_stdin=True)
- self.check(['foo', 'bar'], {}, sys_argv=['foo', 'bar'])
- self.check(['foo', '-i'], {}, sys_argv=['foo', '-i'])
- self.check(['-i', 'foo'], {}, sys_argv=['foo'], interactive=1, inspect=1)
- self.check(['--', 'foo'], {}, sys_argv=['foo'])
- self.check(['--', '-i', 'foo'], {}, sys_argv=['-i', 'foo'])
- self.check(['--', '-', 'foo'], {}, sys_argv=['-', 'foo'], run_stdin=True)
- self.check(['-Wbog'], {}, sys_argv=[''], warnoptions=['bog'], run_stdin=True)
- self.check(['-W', 'ab', '-SWc'], {}, sys_argv=[''], warnoptions=['ab', 'c'],
- run_stdin=True, no_site=1)
-
- self.check([], {'PYTHONDEBUG': '1'}, sys_argv=[''], run_stdin=True, debug=1)
- self.check([], {'PYTHONDONTWRITEBYTECODE': '1'}, sys_argv=[''], run_stdin=True, dont_write_bytecode=1)
- self.check([], {'PYTHONNOUSERSITE': '1'}, sys_argv=[''], run_stdin=True, no_user_site=1)
- self.check([], {'PYTHONUNBUFFERED': '1'}, sys_argv=[''], run_stdin=True, unbuffered=1)
- self.check([], {'PYTHONVERBOSE': '1'}, sys_argv=[''], run_stdin=True, verbose=1)
-
- def test_sysflags(self):
- flags = (
- ("debug", "-d", "1"),
- ("py3k_warning", "-3", "1"),
- ("division_warning", "-Qwarn", "1"),
- ("division_warning", "-Qwarnall", "2"),
- ("division_new", "-Qnew", "1"),
- (["inspect", "interactive"], "-i", "1"),
- ("optimize", "-O", "1"),
- ("optimize", "-OO", "2"),
- ("dont_write_bytecode", "-B", "1"),
- ("no_user_site", "-s", "1"),
- ("no_site", "-S", "1"),
- ("ignore_environment", "-E", "1"),
- ("tabcheck", "-t", "1"),
- ("tabcheck", "-tt", "2"),
- ("verbose", "-v", "1"),
- ("unicode", "-U", "1"),
- ("bytes_warning", "-b", "1"),
- )
- for flag, opt, value in flags:
- if isinstance(flag, list): # this is for inspect&interactive
- expected = {}
- for flag1 in flag:
- expected[flag1] = int(value)
- else:
- expected = {flag: int(value)}
- self.check([opt, '-c', 'pass'], {}, sys_argv=['-c'],
- run_command='pass', **expected)
-
- def test_sysflags_envvar(self, monkeypatch):
- monkeypatch.setenv('PYTHONNOUSERSITE', '1')
- expected = {"no_user_site": True}
- self.check(['-c', 'pass'], {}, sys_argv=['-c'], run_command='pass', **expected)
-
-
-class TestInteraction:
- """
- These tests require pexpect (UNIX-only).
- http://pexpect.sourceforge.net/
- """
- def _spawn(self, *args, **kwds):
- try:
- import pexpect
- except ImportError, e:
- py.test.skip(str(e))
- else:
- # Version is of the style "0.999" or "2.1". Older versions of
- # pexpect try to get the fileno of stdin, which generally won't
- # work with py.test (due to sys.stdin being a DontReadFromInput
- # instance).
- version = map(int, pexpect.__version__.split('.'))
-
- # I only tested 0.999 and 2.1. The former does not work, the
- # latter does. Feel free to refine this measurement.
- # -exarkun, 17/12/2007
- if version < [2, 1]:
- py.test.skip(
- "pexpect version too old, requires 2.1 or newer: %r" % (
- pexpect.__version__,))
-
- kwds.setdefault('timeout', 10)
- print 'SPAWN:', ' '.join([args[0]] + args[1]), kwds
- child = pexpect.spawn(*args, **kwds)
- child.logfile = sys.stdout
- return child
-
- def spawn(self, argv):
- return self._spawn(sys.executable, [app_main] + argv)
-
- def test_interactive(self):
- child = self.spawn([])
- child.expect('Python ') # banner
- child.expect('>>> ') # prompt
- child.sendline('[6*7]')
- child.expect(re.escape('[42]'))
- child.sendline('def f(x):')
- child.expect(re.escape('... '))
- child.sendline(' return x + 100')
- child.expect(re.escape('... '))
- child.sendline('')
- child.expect('>>> ')
- child.sendline('f(98)')
- child.expect('198')
- child.expect('>>> ')
- child.sendline('__name__')
- child.expect("'__main__'")
- child.expect('>>> ')
- child.sendline('import sys')
- child.expect('>>> ')
- child.sendline("'' in sys.path")
- child.expect("True")
-
- def test_help(self):
- # test that -h prints the usage, including the name of the executable
- # which should be /full/path/to/app_main.py in this case
- child = self.spawn(['-h'])
- child.expect(r'usage: .*app_main.py \[option\]')
- child.expect('PyPy options and arguments:')
-
- def test_run_script(self):
- child = self.spawn([demo_script])
- idx = child.expect(['hello', 'Python ', '>>> '])
- assert idx == 0 # no banner or prompt
- child.expect(re.escape("Name: __main__"))
- child.expect(re.escape('File: ' + demo_script))
- child.expect(re.escape('Exec: ' + app_main))
- child.expect(re.escape('Argv: ' + repr([demo_script])))
- child.expect('goodbye')
-
- def test_run_script_with_args(self):
- argv = [demo_script, 'hello', 'world']
- child = self.spawn(argv)
- child.expect(re.escape('Argv: ' + repr(argv)))
- child.expect('goodbye')
-
- def test_no_such_script(self):
- import errno
- msg = os.strerror(errno.ENOENT) # 'No such file or directory'
- child = self.spawn(['xxx-no-such-file-xxx'])
- child.expect(re.escape(msg))
-
- def test_option_i(self):
- argv = [demo_script, 'foo', 'bar']
- child = self.spawn(['-i'] + argv)
- idx = child.expect(['hello', re.escape(banner)])
- assert idx == 0 # no banner
- child.expect(re.escape('File: ' + demo_script))
- child.expect(re.escape('Argv: ' + repr(argv)))
- child.expect('goodbye')
- idx = child.expect(['>>> ', re.escape(banner)])
- assert idx == 0 # prompt, but still no banner
- child.sendline('myvalue * 102')
- child.expect('4284')
- child.sendline('__name__')
- child.expect('__main__')
-
- def test_option_i_crashing(self):
- argv = [crashing_demo_script, 'foo', 'bar']
- child = self.spawn(['-i'] + argv)
- idx = child.expect(['Hello2', re.escape(banner)])
- assert idx == 0 # no banner
- child.expect('NameError')
- child.sendline('myvalue2 * 1001')
- child.expect('11011')
- child.sendline('import sys; sys.argv')
- child.expect(re.escape(repr(argv)))
- child.sendline('sys.last_type.__name__')
- child.expect(re.escape(repr('NameError')))
-
- def test_options_i_c(self):
- child = self.spawn(['-i', '-c', 'x=555'])
- idx = child.expect(['>>> ', re.escape(banner)])
- assert idx == 0 # prompt, but no banner
- child.sendline('x')
- child.expect('555')
- child.sendline('__name__')
- child.expect('__main__')
- child.sendline('import sys; sys.argv')
- child.expect(re.escape("['-c']"))
-
- def test_options_i_c_crashing(self, monkeypatch):
- monkeypatch.setenv('PYTHONPATH', None)
- child = self.spawn(['-i', '-c', 'x=666;foobar'])
- child.expect('NameError')
- idx = child.expect(['>>> ', re.escape(banner)])
- assert idx == 0 # prompt, but no banner
- child.sendline('x')
- child.expect('666')
- child.sendline('__name__')
- child.expect('__main__')
- child.sendline('import sys; sys.argv')
- child.expect(re.escape("['-c']"))
- child.sendline('sys.last_type.__name__')
- child.expect(re.escape(repr('NameError')))
-
- def test_atexit(self):
- child = self.spawn([])
- child.expect('>>> ')
- child.sendline('def f(): print "foobye"')
- child.sendline('')
- child.sendline('import atexit; atexit.register(f)')
- child.sendline('6*7')
- child.expect('42')
- # pexpect's sendeof() is confused by py.test capturing, though
- # I think that it is a bug of sendeof()
- old = sys.stdin
- try:
- sys.stdin = child
- child.sendeof()
- finally:
- sys.stdin = old
- child.expect('foobye')
-
- def test_pythonstartup(self, monkeypatch):
- monkeypatch.setenv('PYTHONPATH', None)
- monkeypatch.setenv('PYTHONSTARTUP', crashing_demo_script)
- child = self.spawn([])
- child.expect(re.escape(banner))
- child.expect('Traceback')
- child.expect('NameError')
- child.expect('>>> ')
- child.sendline('[myvalue2]')
- child.expect(re.escape('[11]'))
- child.expect('>>> ')
-
- child = self.spawn(['-i', demo_script])
- for line in ['hello', 'goodbye', '>>> ']:
- idx = child.expect([line, 'Hello2'])
- assert idx == 0 # no PYTHONSTARTUP run here
- child.sendline('myvalue2')
- child.expect('Traceback')
- child.expect('NameError')
-
- def test_pythonstartup_file1(self, monkeypatch):
- monkeypatch.setenv('PYTHONPATH', None)
- monkeypatch.setenv('PYTHONSTARTUP', demo_script)
More information about the pypy-commit
mailing list