Author: Ronan Lamy <ronan.l...@gmail.com> Branch: py3.5 Changeset: r93216:fcf5d3fb56f4 Date: 2017-11-29 18:34 +0000 http://bitbucket.org/pypy/pypy/changeset/fcf5d3fb56f4/
Log: hg merge default diff --git a/extra_tests/test_textio.py b/extra_tests/test_textio.py --- a/extra_tests/test_textio.py +++ b/extra_tests/test_textio.py @@ -1,28 +1,48 @@ from hypothesis import given, strategies as st from io import BytesIO, TextIOWrapper +import os -LINESEP = ['', '\r', '\n', '\r\n'] +def translate_newlines(text): + text = text.replace('\r\n', '\n') + text = text.replace('\r', '\n') + return text.replace('\n', os.linesep) @st.composite -def text_with_newlines(draw): - sep = draw(st.sampled_from(LINESEP)) - lines = draw(st.lists(st.text(max_size=10), max_size=10)) - return sep.join(lines) +def st_readline_universal( + draw, st_nlines=st.integers(min_value=0, max_value=10)): + n_lines = draw(st_nlines) + lines = draw(st.lists( + st.text(st.characters(blacklist_characters='\r\n')), + min_size=n_lines, max_size=n_lines)) + limits = [] + for line in lines: + limit = draw(st.integers(min_value=0, max_value=len(line) + 5)) + limits.append(limit) + limits.append(-1) + endings = draw(st.lists( + st.sampled_from(['\n', '\r', '\r\n']), + min_size=n_lines, max_size=n_lines)) + return ( + ''.join(line + ending for line, ending in zip(lines, endings)), + limits) -@given(txt=text_with_newlines(), - mode=st.sampled_from(['\r', '\n', '\r\n', '']), - limit=st.integers(min_value=-1)) -def test_readline(txt, mode, limit): +@given(data=st_readline_universal(), + mode=st.sampled_from(['\r', '\n', '\r\n', '', None])) +def test_readline(data, mode): + txt, limits = data textio = TextIOWrapper( - BytesIO(txt.encode('utf-8')), encoding='utf-8', newline=mode) + BytesIO(txt.encode('utf-8', 'surrogatepass')), + encoding='utf-8', errors='surrogatepass', newline=mode) lines = [] - while True: + for limit in limits: line = textio.readline(limit) - if limit > 0: - assert len(line) < limit + if limit >= 0: + assert len(line) <= limit if line: lines.append(line) - else: + elif limit: break - assert u''.join(lines) == txt + if mode is None: + txt = translate_newlines(txt) + assert txt.startswith(u''.join(lines)) 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 @@ -26,3 +26,6 @@ .. branch: fix-vmprof-stacklet-switch Fix a vmprof+continulets (i.e. greenelts, eventlet, gevent, ...) + +.. branch: win32-vcvars + diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst --- a/pypy/doc/windows.rst +++ b/pypy/doc/windows.rst @@ -25,8 +25,10 @@ This compiler, while the standard one for Python 2.7, is deprecated. Microsoft has made it available as the `Microsoft Visual C++ Compiler for Python 2.7`_ (the link -was checked in Nov 2016). Note that the compiler suite will be installed in -``C:\Users\<user name>\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python``. +was checked in Nov 2016). Note that the compiler suite may be installed in +``C:\Users\<user name>\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python`` +or in +``C:\Program Files (x86)\Common Files\Microsoft\Visual C++ for Python``. A current version of ``setuptools`` will be able to find it there. For Windows 10, you must right-click the download, and under ``Properties`` -> ``Compatibility`` mark it as ``Run run this program in comatibility mode for`` @@ -41,7 +43,6 @@ ----------------------------------- We routinely test translation using v9, also known as Visual Studio 2008. -Our buildbot is still using the Express Edition, not the compiler noted above. Other configurations may work as well. The translation scripts will set up the appropriate environment variables @@ -81,6 +82,30 @@ .. _build instructions: http://pypy.org/download.html#building-from-source +Setting Up Visual Studio for building SSL in Python3 +---------------------------------------------------- + +On Python3, the ``ssl`` module is based on ``cffi``, and requires a build step after +translation. However ``distutils`` does not support the Micorosft-provided Visual C +compiler, and ``cffi`` depends on ``distutils`` to find the compiler. The +traditional solution to this problem is to install the ``setuptools`` module +via running ``-m ensurepip`` which installs ``pip`` and ``setuptools``. However +``pip`` requires ``ssl``. So we have a chicken-and-egg problem: ``ssl`` depends on +``cffi`` which depends on ``setuptools``, which depends on ``ensurepip``, which +depends on ``ssl``. + +In order to solve this, the buildbot sets an environment varaible that helps +``distutils`` find the compiler without ``setuptools``:: + + set VS90COMNTOOLS=C:\Program Files (x86)\Common Files\Microsoft\Visual C++ for Python\9.0\VC\bin + +or whatever is appropriate for your machine. Note that this is not enough, you +must also copy the ``vcvarsall.bat`` file fron the ``...\9.0`` directory to the +``...\9.0\VC`` directory, and edit it, changing the lines that set +``VCINSTALLDIR`` and ``WindowsSdkDir``:: + set VCINSTALLDIR=%~dp0\ + set WindowsSdkDir=%~dp0\..\WinSDK\ + Preparing Windows for the large build ------------------------------------- diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -368,6 +368,7 @@ while scanned < limit: try: ch = self.next_char() + scanned += 1 except StopIteration: return False if ch == u'\n': @@ -780,7 +781,7 @@ remnant = None continue - if limit > 0: + if limit >= 0: remaining = limit - builder.getlength() assert remaining >= 0 else: diff --git a/pypy/module/_io/test/test_interp_textio.py b/pypy/module/_io/test/test_interp_textio.py --- a/pypy/module/_io/test/test_interp_textio.py +++ b/pypy/module/_io/test/test_interp_textio.py @@ -1,40 +1,53 @@ import pytest try: - from hypothesis import given, strategies as st, assume + from hypothesis import given, strategies as st except ImportError: pytest.skip("hypothesis required") +import os from pypy.module._io.interp_bytesio import W_BytesIO from pypy.module._io.interp_textio import W_TextIOWrapper, DecodeBuffer -LINESEP = ['', '\r', '\n', '\r\n'] +def translate_newlines(text): + text = text.replace(u'\r\n', u'\n') + text = text.replace(u'\r', u'\n') + return text.replace(u'\n', os.linesep) @st.composite -def text_with_newlines(draw): - sep = draw(st.sampled_from(LINESEP)) - lines = draw(st.lists(st.text(max_size=10), max_size=10)) - return sep.join(lines) +def st_readline(draw, st_nlines=st.integers(min_value=0, max_value=10)): + n_lines = draw(st_nlines) + fragments = [] + limits = [] + for _ in range(n_lines): + line = draw(st.text(st.characters(blacklist_characters=u'\r\n'))) + fragments.append(line) + ending = draw(st.sampled_from([u'\n', u'\r', u'\r\n'])) + fragments.append(ending) + limit = draw(st.integers(min_value=0, max_value=len(line) + 5)) + limits.append(limit) + limits.append(-1) + return (u''.join(fragments), limits) -@given(txt=text_with_newlines(), - mode=st.sampled_from(['\r', '\n', '\r\n', '']), - limit=st.integers(min_value=-1)) -def test_readline(space, txt, mode, limit): - assume(limit != 0) +@given(data=st_readline(), + mode=st.sampled_from(['\r', '\n', '\r\n', ''])) +def test_readline(space, data, mode): + txt, limits = data w_stream = W_BytesIO(space) w_stream.descr_init(space, space.newbytes(txt.encode('utf-8'))) w_textio = W_TextIOWrapper(space) w_textio.descr_init( - space, w_stream, encoding='utf-8', + space, w_stream, + encoding='utf-8', w_errors=space.newtext('surrogatepass'), w_newline=space.newtext(mode)) lines = [] - while True: + for limit in limits: line = space.unicode_w(w_textio.readline_w(space, space.newint(limit))) - if limit > 0: + if limit >= 0: assert len(line) <= limit if line: lines.append(line) - else: + elif limit: break - assert u''.join(lines) == txt + assert txt.startswith(u''.join(lines)) @given(st.text()) def test_read_buffer(text): diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py --- a/rpython/jit/metainterp/optimizeopt/intbounds.py +++ b/rpython/jit/metainterp/optimizeopt/intbounds.py @@ -25,19 +25,6 @@ return (1 << ((byte_size << 3) - 1)) - 1 -IS_64_BIT = sys.maxint > 2**32 - -def next_pow2_m1(n): - """Calculate next power of 2 greater than n minus one.""" - n |= n >> 1 - n |= n >> 2 - n |= n >> 4 - n |= n >> 8 - n |= n >> 16 - if IS_64_BIT: - n |= n >> 32 - return n - class OptIntBounds(Optimization): """Keeps track of the bounds placed on integers by guards and remove @@ -50,7 +37,7 @@ return dispatch_postprocess(self, op) def propagate_bounds_backward(self, box): - # FIXME: This takes care of the instruction where box is the reuslt + # FIXME: This takes care of the instruction where box is the result # but the bounds produced by all instructions where box is # an argument might also be tighten b = self.getintbound(box) @@ -91,14 +78,8 @@ b1 = self.getintbound(v1) v2 = self.get_box_replacement(op.getarg(1)) b2 = self.getintbound(v2) - if b1.known_ge(IntBound(0, 0)) and \ - b2.known_ge(IntBound(0, 0)): - r = self.getintbound(op) - if b1.has_upper and b2.has_upper: - mostsignificant = b1.upper | b2.upper - r.intersect(IntBound(0, next_pow2_m1(mostsignificant))) - else: - r.make_ge(IntBound(0, 0)) + b = b1.or_bound(b2) + self.getintbound(op).intersect(b) optimize_INT_OR = optimize_INT_OR_or_XOR optimize_INT_XOR = optimize_INT_OR_or_XOR @@ -112,15 +93,8 @@ def postprocess_INT_AND(self, op): b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) - r = self.getintbound(op) - pos1 = b1.known_ge(IntBound(0, 0)) - pos2 = b2.known_ge(IntBound(0, 0)) - if pos1 or pos2: - r.make_ge(IntBound(0, 0)) - if pos1: - r.make_le(b1) - if pos2: - r.make_le(b2) + b = b1.and_bound(b2) + self.getintbound(op).intersect(b) def optimize_INT_SUB(self, op): return self.emit(op) @@ -211,16 +185,10 @@ r.intersect(b1.py_div_bound(b2)) def post_call_INT_PY_MOD(self, op): + b1 = self.getintbound(op.getarg(1)) b2 = self.getintbound(op.getarg(2)) - if b2.is_constant(): - val = b2.getint() - r = self.getintbound(op) - if val >= 0: # with Python's modulo: 0 <= (x % pos) < pos - r.make_ge(IntBound(0, 0)) - r.make_lt(IntBound(val, val)) - else: # with Python's modulo: neg < (x % neg) <= 0 - r.make_gt(IntBound(val, val)) - r.make_le(IntBound(0, 0)) + r = self.getintbound(op) + r.intersect(b1.mod_bound(b2)) def optimize_INT_LSHIFT(self, op): return self.emit(op) @@ -436,7 +404,7 @@ def optimize_INT_FORCE_GE_ZERO(self, op): b = self.getintbound(op.getarg(0)) - if b.known_ge(IntBound(0, 0)): + if b.known_nonnegative(): self.make_equal_to(op, op.getarg(0)) else: return self.emit(op) @@ -647,7 +615,7 @@ if r.is_constant(): if r.getint() == valnonzero: b1 = self.getintbound(op.getarg(0)) - if b1.known_ge(IntBound(0, 0)): + if b1.known_nonnegative(): b1.make_gt(IntBound(0, 0)) self.propagate_bounds_backward(op.getarg(0)) elif r.getint() == valzero: diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py b/rpython/jit/metainterp/optimizeopt/intutils.py --- a/rpython/jit/metainterp/optimizeopt/intutils.py +++ b/rpython/jit/metainterp/optimizeopt/intutils.py @@ -12,6 +12,19 @@ MAXINT = maxint MININT = -maxint - 1 +IS_64_BIT = sys.maxint > 2**32 + +def next_pow2_m1(n): + """Calculate next power of 2 greater than n minus one.""" + n |= n >> 1 + n |= n >> 2 + n |= n >> 4 + n |= n >> 8 + n |= n >> 16 + if IS_64_BIT: + n |= n >> 32 + return n + class IntBound(AbstractInfo): _attrs_ = ('has_upper', 'has_lower', 'upper', 'lower') @@ -92,6 +105,9 @@ def known_ge(self, other): return other.known_le(self) + def known_nonnegative(self): + return self.has_lower and 0 <= self.lower + def intersect(self, other): r = False @@ -192,10 +208,22 @@ else: return IntUnbounded() + def mod_bound(self, other): + r = IntUnbounded() + if other.is_constant(): + val = other.getint() + if val >= 0: # with Python's modulo: 0 <= (x % pos) < pos + r.make_ge(IntBound(0, 0)) + r.make_lt(IntBound(val, val)) + else: # with Python's modulo: neg < (x % neg) <= 0 + r.make_gt(IntBound(val, val)) + r.make_le(IntBound(0, 0)) + return r + def lshift_bound(self, other): if self.has_upper and self.has_lower and \ other.has_upper and other.has_lower and \ - other.known_ge(IntBound(0, 0)) and \ + other.known_nonnegative() and \ other.known_lt(IntBound(LONG_BIT, LONG_BIT)): try: vals = (ovfcheck(self.upper << other.upper), @@ -211,7 +239,7 @@ def rshift_bound(self, other): if self.has_upper and self.has_lower and \ other.has_upper and other.has_lower and \ - other.known_ge(IntBound(0, 0)) and \ + other.known_nonnegative() and \ other.known_lt(IntBound(LONG_BIT, LONG_BIT)): vals = (self.upper >> other.upper, self.upper >> other.lower, @@ -221,7 +249,31 @@ else: return IntUnbounded() + def and_bound(self, other): + pos1 = self.known_nonnegative() + pos2 = other.known_nonnegative() + r = IntUnbounded() + if pos1 or pos2: + r.make_ge(IntBound(0, 0)) + if pos1: + r.make_le(self) + if pos2: + r.make_le(other) + return r + + def or_bound(self, other): + r = IntUnbounded() + if self.known_nonnegative() and \ + other.known_nonnegative(): + if self.has_upper and other.has_upper: + mostsignificant = self.upper | other.upper + r.intersect(IntBound(0, next_pow2_m1(mostsignificant))) + else: + r.make_ge(IntBound(0, 0)) + return r + def contains(self, val): + assert not isinstance(val, long) if not isinstance(val, int): if ((not self.has_lower or self.lower == MININT) and not self.has_upper or self.upper == MAXINT): @@ -282,7 +334,7 @@ guards.append(op) def is_bool(self): - return (self.bounded() and self.known_ge(ConstIntBound(0)) and + return (self.bounded() and self.known_nonnegative() and self.known_le(ConstIntBound(1))) def make_bool(self): @@ -297,7 +349,7 @@ if self.known_gt(IntBound(0, 0)) or \ self.known_lt(IntBound(0, 0)): return INFO_NONNULL - if self.known_ge(IntBound(0, 0)) and \ + if self.known_nonnegative() and \ self.known_le(IntBound(0, 0)): return INFO_NULL return INFO_UNKNOWN diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py --- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py @@ -1,12 +1,34 @@ from rpython.jit.metainterp.optimizeopt.intutils import IntBound, IntUpperBound, \ - IntLowerBound, IntUnbounded -from rpython.jit.metainterp.optimizeopt.intbounds import next_pow2_m1 + IntLowerBound, IntUnbounded, next_pow2_m1 from copy import copy import sys -from rpython.rlib.rarithmetic import LONG_BIT +from rpython.rlib.rarithmetic import LONG_BIT, ovfcheck -def bound(a,b): +from hypothesis import given, strategies + +special_values = ( + range(-100, 100) + + [2 ** i for i in range(1, LONG_BIT)] + + [-2 ** i for i in range(1, LONG_BIT)] + + [2 ** i - 1 for i in range(1, LONG_BIT)] + + [-2 ** i - 1 for i in range(1, LONG_BIT)] + + [2 ** i + 1 for i in range(1, LONG_BIT)] + + [-2 ** i + 1 for i in range(1, LONG_BIT)] + + [sys.maxint, -sys.maxint-1]) + +special_values = strategies.sampled_from( + [int(v) for v in special_values if type(int(v)) is int]) + +ints = strategies.builds( + int, # strategies.integers sometimes returns a long? + special_values | strategies.integers( + min_value=int(-sys.maxint-1), max_value=sys.maxint)) + +ints_or_none = strategies.none() | ints + + +def bound(a, b): if a is None and b is None: return IntUnbounded() elif a is None: @@ -14,11 +36,55 @@ elif b is None: return IntLowerBound(a) else: - return IntBound(a,b) + return IntBound(a, b) def const(a): return bound(a,a) + +def build_bound_with_contained_number(a, b, c): + a, b, c = sorted([a, b, c]) + r = bound(a, c) + assert r.contains(b) + return r, b + +bound_with_contained_number = strategies.builds( + build_bound_with_contained_number, + ints_or_none, + ints_or_none, + ints +) + +unbounded = strategies.builds( + lambda x: (bound(None, None), int(x)), + ints +) + +lower_bounded = strategies.builds( + lambda x, y: (bound(min(x, y), None), max(x, y)), + ints, + ints +) + +upper_bounded = strategies.builds( + lambda x, y: (bound(None, max(x, y)), min(x, y)), + ints, + ints +) + +bounded = strategies.builds( + build_bound_with_contained_number, + ints, ints, ints +) + +constant = strategies.builds( + lambda x: (const(x), x), + ints +) + +bound_with_contained_number = strategies.one_of( + unbounded, lower_bounded, upper_bounded, constant, bounded) + def some_bounds(): brd = [None] + range(-2, 3) for lower in brd: @@ -240,8 +306,6 @@ def test_div_bound(): - from rpython.rtyper.lltypesystem import lltype - from rpython.rtyper.lltypesystem.lloperation import llop for _, _, b1 in some_bounds(): for _, _, b2 in some_bounds(): b3 = b1.py_div_bound(b2) @@ -261,6 +325,15 @@ assert a.contains(-3) assert a.contains(0) +def test_mod_bound(): + for _, _, b1 in some_bounds(): + for _, _, b2 in some_bounds(): + b3 = b1.mod_bound(b2) + for n1 in nbr: + for n2 in nbr: + if b1.contains(n1) and b2.contains(n2): + if n2 != 0: + assert b3.contains(n1 % n2) # Python-style div def test_sub_bound(): for _, _, b1 in some_bounds(): @@ -275,6 +348,25 @@ assert not a.contains(-1) assert not a.contains(4) +def test_and_bound(): + for _, _, b1 in some_bounds(): + for _, _, b2 in some_bounds(): + b3 = b1.and_bound(b2) + for n1 in nbr: + for n2 in nbr: + if b1.contains(n1) and b2.contains(n2): + assert b3.contains(n1 & n2) + +def test_or_bound(): + for _, _, b1 in some_bounds(): + for _, _, b2 in some_bounds(): + b3 = b1.or_bound(b2) + for n1 in nbr: + for n2 in nbr: + if b1.contains(n1) and b2.contains(n2): + assert b3.contains(n1 | n2) + assert b3.contains(n1 ^ n2) # we use it for xor too + def test_next_pow2_m1(): assert next_pow2_m1(0) == 0 @@ -285,3 +377,82 @@ assert next_pow2_m1(80) == 127 assert next_pow2_m1((1 << 32) - 5) == (1 << 32) - 1 assert next_pow2_m1((1 << 64) - 1) == (1 << 64) - 1 + + +@given(bound_with_contained_number, bound_with_contained_number) +def test_add_bound_random(t1, t2): + b1, n1 = t1 + b2, n2 = t2 + print b1, n1 + print b2, n2 + b3 = b1.add_bound(b2) + try: + r = ovfcheck(n1 + n2) + except OverflowError: + assert not b3.bounded() + else: + assert b3.contains(r) + +@given(bound_with_contained_number, bound_with_contained_number) +def test_sub_bound_random(t1, t2): + b1, n1 = t1 + b2, n2 = t2 + print b1, n1 + print b2, n2 + b3 = b1.sub_bound(b2) + try: + r = ovfcheck(n1 - n2) + except OverflowError: + assert not b3.bounded() + else: + assert b3.contains(r) + +@given(bound_with_contained_number, bound_with_contained_number) +def test_mul_bound_random(t1, t2): + b1, n1 = t1 + b2, n2 = t2 + b3 = b1.mul_bound(b2) + try: + r = ovfcheck(n1 * n2) + except OverflowError: + assert not b3.bounded() + else: + assert b3.contains(r) + +@given(bound_with_contained_number, bound_with_contained_number) +def test_div_bound_random(t1, t2): + b1, n1 = t1 + b2, n2 = t2 + b3 = b1.py_div_bound(b2) + if n1 == -sys.maxint-1 and n2 == -1: + return # overflow + if n2 != 0: + assert b3.contains(n1 / n2) # Python-style div + +@given(bound_with_contained_number, bound_with_contained_number) +def test_mod_bound_random(t1, t2): + b1, n1 = t1 + b2, n2 = t2 + b3 = b1.mod_bound(b2) + if n1 == -sys.maxint-1 and n2 == -1: + return # overflow + if n2 != 0: + assert b3.contains(n1 % n2) # Python-style mod + +@given(bound_with_contained_number, bound_with_contained_number) +def test_and_bound_random(t1, t2): + b1, n1 = t1 + b2, n2 = t2 + b3 = b1.and_bound(b2) + r = n1 & n2 + assert b3.contains(r) + +@given(bound_with_contained_number, bound_with_contained_number) +def test_or_bound_random(t1, t2): + b1, n1 = t1 + b2, n2 = t2 + b3 = b1.or_bound(b2) + r = n1 | n2 + assert b3.contains(r) + r = n1 ^ n2 + assert b3.contains(r) diff --git a/rpython/translator/platform/test/test_platform.py b/rpython/translator/platform/test/test_platform.py --- a/rpython/translator/platform/test/test_platform.py +++ b/rpython/translator/platform/test/test_platform.py @@ -113,8 +113,10 @@ def test_environment_inheritance(self): # make sure that environment is inherited cmd = 'import os; print os.environ["_SOME_VARIABLE_%d"]' + env = {'_SOME_VARIABLE_1':'xyz'} + env['PATH'] = os.environ['PATH'] res = self.platform.execute(sys.executable, ['-c', cmd % 1], - env={'_SOME_VARIABLE_1':'xyz'}) + env=env) assert 'xyz' in res.out os.environ['_SOME_VARIABLE_2'] = 'zyz' try: diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py --- a/rpython/translator/platform/windows.py +++ b/rpython/translator/platform/windows.py @@ -10,21 +10,13 @@ rpydir = str(py.path.local(rpython.__file__).join('..')) def _get_compiler_type(cc, x64_flag): - import subprocess if not cc: cc = os.environ.get('CC','') if not cc: return MsvcPlatform(x64=x64_flag) elif cc.startswith('mingw') or cc == 'gcc': return MingwPlatform(cc) - else: - return MsvcPlatform(cc=cc, x64=x64_flag) - try: - subprocess.check_output([cc, '--version']) - except: - raise ValueError("Could not find compiler specified by cc option '%s'," - " it must be a valid exe file on your path" % cc) - return MingwPlatform(cc) + return MsvcPlatform(cc=cc, x64=x64_flag) def Windows(cc=None): return _get_compiler_type(cc, False) @@ -74,6 +66,11 @@ vcvars = os.path.join(vcbindir, 'amd64', 'vcvarsamd64.bat') else: vcvars = os.path.join(toolsdir, 'vsvars32.bat') + if not os.path.exists(vcvars): + # even msdn does not know which to run + # see https://msdn.microsoft.com/en-us/library/1700bbwd(v=vs.90).aspx + # wich names both + vcvars = os.path.join(toolsdir, 'vcvars32.bat') import subprocess try: @@ -95,25 +92,21 @@ key, value = line.split('=', 1) if key.upper() in ['PATH', 'INCLUDE', 'LIB']: env[key.upper()] = value - ## log.msg("Updated environment with %s" % (vcvars,)) + log.msg("Updated environment with %s" % (vcvars,)) return env def find_msvc_env(x64flag=False): + vcvers = [140, 100, 90, 80, 71, 70] # First, try to get the compiler which served to compile python msc_pos = sys.version.find('MSC v.') if msc_pos != -1: msc_ver = int(sys.version[msc_pos+6:msc_pos+10]) - # 1300 -> 70, 1310 -> 71, 1400 -> 80, 1500 -> 90 + # 1500 -> 90, 1900 -> 140 vsver = (msc_ver / 10) - 60 + vcvers.insert(0, vsver) + errs = [] + for vsver in vcvers: env = _get_msvc_env(vsver, x64flag) - - if env is not None: - return env - - # Then, try any other version - for vsver in (100, 90, 80, 71, 70): # All the versions I know - env = _get_msvc_env(vsver, x64flag) - if env is not None: return env log.error("Could not find a Microsoft Compiler") _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit