diff --git a/.azure-pipelines/azure-pipelines-linux.yml b/.azure-pipelines/azure-pipelines-linux.yml index f02b96c..b5ca579 100755 --- a/.azure-pipelines/azure-pipelines-linux.yml +++ b/.azure-pipelines/azure-pipelines-linux.yml @@ -21,11 +21,6 @@ jobs: timeoutInMinutes: 360 steps: - - script: | - rm -rf /opt/ghc - df -h - displayName: Manage disk space - # configure qemu binfmt-misc running. This allows us to run docker containers # embedded qemu-static - script: | diff --git a/.azure-pipelines/azure-pipelines-win.yml b/.azure-pipelines/azure-pipelines-win.yml index 9fa1336..6b53edc 100755 --- a/.azure-pipelines/azure-pipelines-win.yml +++ b/.azure-pipelines/azure-pipelines-win.yml @@ -65,7 +65,7 @@ jobs: if EXIST LICENSE.txt ( copy LICENSE.txt "recipe\\recipe-scripts-license.txt" ) - conda.exe mambabuild "recipe" -m .ci_support\%CONFIG%.yaml --suppress-variables + conda.exe mambabuild "recipe" -m .ci_support\%CONFIG%.yaml --suppress-variables %EXTRA_CB_OPTIONS% displayName: Build recipe env: PYTHONUNBUFFERED: 1 diff --git a/.scripts/run_osx_build.sh b/.scripts/run_osx_build.sh index f169576..5ef2a19 100755 --- a/.scripts/run_osx_build.sh +++ b/.scripts/run_osx_build.sh @@ -55,7 +55,6 @@ source run_conda_forge_build_setup echo -e "\n\nMaking the build clobber file" make_build_number ./ ./recipe ./.ci_support/${CONFIG}.yaml - if [[ -f LICENSE.txt ]]; then cp LICENSE.txt "recipe/recipe-scripts-license.txt" fi @@ -71,6 +70,7 @@ if [[ "${BUILD_WITH_CONDA_DEBUG:-0}" == 1 ]]; then # Drop into an interactive shell /bin/bash else + conda mambabuild ./recipe -m ./.ci_support/${CONFIG}.yaml \ --suppress-variables ${EXTRA_CB_OPTIONS:-} \ --clobber-file ./.ci_support/clobber_${CONFIG}.yaml diff --git a/recipe/bld.bat b/recipe/bld.bat index 030875e..8dc6e47 100644 --- a/recipe/bld.bat +++ b/recipe/bld.bat @@ -44,8 +44,6 @@ copy /b *.dll %GOAL_DIR% copy /b *.exe %GOAL_DIR% REM lib goes elsewhere copy /b *.lib %PYPY3_SRC_DIR%\libs\python%PY_VERSION_NODOTS%.lib || exit /b 11 -REM how big is the lib? It should be about 200k -dir *.lib cd /d %GOAL_DIR% @@ -66,32 +64,11 @@ REM License is packaged separately del %PREFIX%\LICENSE -if exist %PREFIX%\lib_pypy ( - REM Make sure the site-packages dir SP_DIR matches with cpython - REM See patch site-and-sysconfig-conda.patch - mkdir %SP_DIR% - echo Adjusting layout for pre-python3.8 - move %PREFIX%\README.rst %PREFIX%\lib_pypy\ - move %PREFIX%\site-packages\README %SP_DIR% - rmdir /q /s %PREFIX%\site-packages - - REM Use conda tcl/tk installation in Library/lib - rmdir /q /s %PREFIX%\tcl - cd %PREFIX%\lib_pypy - ..\pypy3 -m compileall . - IF %ERRORLEVEL% NEQ 0 (Echo ERROR while compiling &exit /b 11) - cd %PREFIX%\lib-python - ..\pypy3 -m lib2to3.pgen2.driver 3\lib2to3\Grammar.txt - IF %ERRORLEVEL% NEQ 0 (Echo ERROR while compiling &exit /b 11) - ..\pypy3 -m lib2to3.pgen2.driver 3\lib2to3\PatternGrammar.txt - IF %ERRORLEVEL% NEQ 0 (Echo ERROR while compiling &exit /b 11) -) else ( - cd %PREFIX%\Lib - ..\pypy3 -m lib2to3.pgen2.driver lib2to3\Grammar.txt - IF %ERRORLEVEL% NEQ 0 (Echo ERROR while compiling &exit /b 11) - ..\pypy3 -m lib2to3.pgen2.driver lib2to3\PatternGrammar.txt - IF %ERRORLEVEL% NEQ 0 (Echo ERROR while compiling &exit /b 11) -) +cd %PREFIX%\Lib +..\pypy3 -m lib2to3.pgen2.driver lib2to3\Grammar.txt +IF %ERRORLEVEL% NEQ 0 (Echo ERROR while compiling &exit /b 11) +..\pypy3 -m lib2to3.pgen2.driver lib2to3\PatternGrammar.txt +IF %ERRORLEVEL% NEQ 0 (Echo ERROR while compiling &exit /b 11) rem still in lib-python or Lib ..\pypy3 -m compileall . @@ -108,9 +85,15 @@ REM timeout 60m pypy3 -m test --pgo -j%CPU_COUNT% || true; REM Build the cache for the standard library pypy -c "import _testcapi" IF %ERRORLEVEL% NEQ 0 (Echo ERROR while building &exit /b 11) -pypy -c "import _ctypes_test" -IF %ERRORLEVEL% NEQ 0 (Echo ERROR while building &exit /b 11) -pypy -c "import _testmultiphase" +if "%PY_VERSION%" == "3.8" ( + pypy -c "import _ctypes_test" + IF %ERRORLEVEL% NEQ 0 (Echo ERROR while building &exit /b 11) + pypy -c "import _testmultiphase" +) else ( + pypy -c "import _ctypes_test_build" + IF %ERRORLEVEL% NEQ 0 (Echo ERROR while building &exit /b 11) + pypy -c "import _testmultiphase_build" +) IF %ERRORLEVEL% NEQ 0 (Echo ERROR while building &exit /b 11) REM Include a %PREFIX%\Scripts directory in the package. This ensures @@ -126,3 +109,9 @@ pypy -m venv destination destination\Scripts\python -c "import sqlite3" if errorlevel 1 exit 1 rmdir /q /s destination + +REM Copy required DLLs so pypy can be used without activating the environment +REM This would fix issue #101 but did not pass reivew +REM copy /b %PREFIX%\Library\bin\libexpat.dll %PREFIX% +REM copy /b %PREFIX%\Library\bin\libbz2.dll %PREFIX% +REM copy /b %PREFIX%\Library\bin\ffi-8.dll %PREFIX% diff --git a/recipe/build.sh b/recipe/build.sh index 408598d..d6c9d26 100755 --- a/recipe/build.sh +++ b/recipe/build.sh @@ -95,31 +95,15 @@ fi rm $PREFIX/LICENSE PY_VERSION=$(echo $PKG_NAME | cut -c 5-) -if [[ -d $PREFIX/lib_pypy ]]; then - # For pypy<3.8, the layout needs to be fixed up. - - # Move the generic file name to somewhere that's specific to pypy - mv $PREFIX/README.rst $PREFIX/lib_pypy/ - # Make sure the site-packages dir match with cpython - mkdir -p $PREFIX/lib/python${PY_VERSION}/site-packages - mv $PREFIX/site-packages/README $PREFIX/lib/python${PY_VERSION}/site-packages/ - rm -rf $PREFIX/site-packages - ln -sf $PREFIX/lib/python${PY_VERSION}/site-packages $PREFIX/site-packages - pushd $PREFIX - pypy -m lib2to3.pgen2.driver lib-python/3/lib2to3/Grammar.txt - pypy -m lib2to3.pgen2.driver lib-python/3/lib2to3/PatternGrammar.txt - popd -else - # Make sure the site-packages dir match with cpython - mkdir -p $PREFIX/lib/python${PY_VERSION}/site-packages - mv $PREFIX/lib/pypy${PY_VERSION}/site-packages/README $PREFIX/lib/python${PY_VERSION}/site-packages/ - rm -rf $PREFIX/lib/pypy${PY_VERSION}/site-packages - ln -sf $PREFIX/lib/python${PY_VERSION}/site-packages $PREFIX/lib/pypy${PY_VERSION}/site-packages - pushd $PREFIX - pypy -m lib2to3.pgen2.driver lib/pypy${PY_VERSION}/lib2to3/Grammar.txt - pypy -m lib2to3.pgen2.driver lib/pypy${PY_VERSION}/lib2to3/PatternGrammar.txt - popd -fi +# Make sure the site-packages dir match with cpython +mkdir -p $PREFIX/lib/python${PY_VERSION}/site-packages +mv $PREFIX/lib/pypy${PY_VERSION}/site-packages/README $PREFIX/lib/python${PY_VERSION}/site-packages/ +rm -rf $PREFIX/lib/pypy${PY_VERSION}/site-packages +ln -sf $PREFIX/lib/python${PY_VERSION}/site-packages $PREFIX/lib/pypy${PY_VERSION}/site-packages +pushd $PREFIX +pypy -m lib2to3.pgen2.driver lib/pypy${PY_VERSION}/lib2to3/Grammar.txt +pypy -m lib2to3.pgen2.driver lib/pypy${PY_VERSION}/lib2to3/PatternGrammar.txt +popd # Regenerate the sysconfigdata__*.py file with paths from $PREFIX, at install # those paths will be replaced with the actual user's paths. The generator @@ -137,10 +121,19 @@ echo INCLUDEPY $(pypy -c "from distutils import sysconfig; print(sysconfig.get_c ls $(pypy -c "from distutils import sysconfig; print(sysconfig.get_config_var('INCLUDEPY'))") _PYTHON_SYSCONFIGDATA_NAME=$sysconfigdata_name pypy -c "from distutils import sysconfig; assert sysconfig.get_config_var('HOST_GNU_TYPE') != None" -# Build the c-extension modules for the standard library +# Build the test c-extension modules +# PyPy uses a wrapper for _ctypes_test to trick the import system into getting +# the c-extension from `/tmp`, so we need to copy it into LIB pypy -c "import _testcapi" -pypy -c "import _ctypes_test" -pypy -c "import _testmultiphase" +cp $(pypy -c "import _testcapi; print(_testcapi.__file__)") $PREFIX/lib/pypy${PY_VERSION} +if [[ "${PY_VERSION}" == "3.8" ]]; then + pypy -c "import _ctypes_test, _testmultiphase" + cp $(pypy -c "import _ctypes_test; print(_ctypes_test.__file__)") $PREFIX/lib/pypy${PY_VERSION} +else + pypy -c "import _ctypes_test_build, _testmultiphase_build" + # Need to import the *build module to properly import the built module from `/tmp` + cp $(pypy -c "import _ctypes_test_build, _ctypes_test; print(_ctypes_test.__file__)") $PREFIX/lib/pypy${PY_VERSION} +fi # Run the python stdlib tests # no timeout on darwin diff --git a/recipe/meta.yaml b/recipe/meta.yaml index b9b14be..3735a4c 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -1,25 +1,26 @@ {% if name_suffix is not defined %} -{% set name_suffix = "3.8" %} +{% set name_suffix = "3.9" %} {% endif %} {% set name = "pypy" ~ name_suffix %} -{% set version = "7.3.11" %} package: name: {{ name }} - version: {{ version }} + version: 7.3.11 # [name_suffix == "3.8"] + version: 7.3.12 # [name_suffix == "3.9"] source: - - url: https://downloads.python.org/pypy/{{ name }}-v{{ version }}-src.tar.bz2 + - folder: pypy3 + url: https://downloads.python.org/pypy/{{ name }}-v7.3.11-src.tar.bz2 # [name_suffix == "3.8"] + url: https://downloads.python.org/pypy/{{ name }}-v7.3.12-src.tar.bz2 # [name_suffix == "3.9"] sha256: 4d6769bfca73734e8666fd70503b7ceb06a6e259110e617331bb3899ca4e6058 # [name_suffix == "3.8"] - sha256: b0f3166fb2a5aadfd5ceb9db5cdd5f7929a0eccca02b4a26c0dae0492f7ca8ea # [name_suffix == "3.9"] - folder: pypy3 + sha256: e7a2046c7e6c25fc386abbb5132e92a7cc2491e3935699a946cb5dcbb342c2aa # [name_suffix == "3.9"] patches: - patches/fficurses.patch - patches/tklib_build.patch - patches/tk_app.patch - patches/lzma_build.patch # [win] - patches/clibffi.patch # [osx] - - patches/darwin.patch # [osx] + - patches/darwin.patch # [osx and name_suffix == "3.8"] - patches/0001-Add-conda-forge-version.patch - patches/0021-Adapt-platform-to-patch-0001.patch - patches/0023a-Fix-LIBDIR.patch # [name_suffix=="3.8"] @@ -32,17 +33,29 @@ source: - patches/0014-Add-CondaEcosystemModifyDllSearchPath.patch - patches/0020-Use-ranlib-from-env-if-env-variable-is-set.patch - patches/0024-Fix-LDSHARED-when-CC-is-overriden-on-Linux-too.patch - # Patches to be removed for the next version - - patches/0019-Disable-copying-dlls.patch - - patches/0020-Use-private-attribute-in-datetime_delta.patch - - patches/0031-Fix-pthread_t-casting.patch + # Patches for 3.8 only + - patches/0019-Disable-copying-dlls.patch # [name_suffix == "3.8"] + - patches/0020-Use-private-attribute-in-datetime_delta.patch # [name_suffix == "3.8"] + - patches/0031-Fix-pthread_t-casting.patch # [name_suffix == "3.8"] + # Patches after 7.3.12 + - patches/pypy_107654.patch + - patches/pypy_107655.patch + - patches/pypy_107656.patch + - patches/pypy_107657.patch + - patches/pypy_107658.patch + - patches/pypy_107659.patch # [name_suffix == "3.9"] + - patches/pypy_107663.patch # [name_suffix == "3.8"] + - patches/pypy_107660.patch # [name_suffix == "3.9"] + - patches/pypy_107661.patch + - patches/pypy_107668.patch # [name_suffix == "3.9"] + - url: https://downloads.python.org/pypy/pypy2.7-v7.3.6-win64.zip # [win] sha256: fcc8f6b3b472a77eaa754951f288fe234b4953bfba845888dd839b9b862cb891 # [win] folder: pypy2-binary # [win] build: - number: 1 + number: 2 skip_compile_pyc: - lib* @@ -86,7 +99,7 @@ requirements: - pypy3.7 ==99999999999 - pypy3.8 ==99999999999 # [name_suffix=="3.9"] - pypy3.9 ==99999999999 # [name_suffix=="3.8"] - - python {{ name_suffix }}.* *_{{ "".join(version.split(".")[:2]) }}_pypy + - python {{ name_suffix }}.* *_7.3_pypy test: commands: diff --git a/recipe/patches/pypy_107654.patch b/recipe/patches/pypy_107654.patch new file mode 100644 index 0000000..3ec9d6a --- /dev/null +++ b/recipe/patches/pypy_107654.patch @@ -0,0 +1,66 @@ +# HG changeset patch +# User Carl Friedrich Bolz-Tereick +# Date 1689079860 -7200 +# Tue Jul 11 14:51:00 2023 +0200 +# Branch conda-3.9-v7.3.12 +# Node ID 163544ab2a142b8e7e040a098ec9013963c9fb64 +# Parent 3f3f2298ddc56db44bbdb4551ce992d8e9401646 +#3961: don't uselessly compile a regex for *every* parsed email message. the +pattern is anyway always the same, apart from a variable prefix. Instead, first +check the prefix with str.startswith, and only if that returns True, match the +rest of the regular expression. + +diff -r 3f3f2298ddc5 -r 163544ab2a14 lib-python/3/email/feedparser.py +--- a/lib-python/3/email/feedparser.py Thu Jun 15 12:31:24 2023 +0300 ++++ b/lib-python/3/email/feedparser.py Tue Jul 11 14:51:00 2023 +0200 +@@ -37,6 +37,7 @@ + headerRE = re.compile(r'^(From |[\041-\071\073-\176]*:|[\t ])') + EMPTYSTRING = '' + NL = '\n' ++boundaryend_re = re.compile(r'(?P--)?(?P[ \t]*)(?P\r\n|\r|\n)?$') + + NeedMoreData = object() + +@@ -329,9 +330,14 @@ + # this onto the input stream until we've scanned past the + # preamble. + separator = '--' + boundary +- boundaryre = re.compile( +- '(?P' + re.escape(separator) + +- r')(?P--)?(?P[ \t]*)(?P\r\n|\r|\n)?$') ++ # PyPy difference: don't compile a new regular expression for every ++ # single message, instead just use str.startswith and a generic re ++ # this prevents the JIT compiling more and more traces for all the ++ # different (random) boundaries of messages ++ def boundarymatch(line): ++ if not line.startswith(separator): ++ return None ++ return boundaryend_re.match(line, len(separator)) + capturing_preamble = True + preamble = [] + linesep = False +@@ -343,7 +349,7 @@ + continue + if line == '': + break +- mo = boundaryre.match(line) ++ mo = boundarymatch(line) + if mo: + # If we're looking at the end boundary, we're done with + # this multipart. If there was a newline at the end of +@@ -375,13 +381,13 @@ + if line is NeedMoreData: + yield NeedMoreData + continue +- mo = boundaryre.match(line) ++ mo = boundarymatch(line) + if not mo: + self._input.unreadline(line) + break + # Recurse to parse this subpart; the input stream points + # at the subpart's first line. +- self._input.push_eof_matcher(boundaryre.match) ++ self._input.push_eof_matcher(boundarymatch) + for retval in self._parsegen(): + if retval is NeedMoreData: + yield NeedMoreData diff --git a/recipe/patches/pypy_107655.patch b/recipe/patches/pypy_107655.patch new file mode 100644 index 0000000..0edf103 --- /dev/null +++ b/recipe/patches/pypy_107655.patch @@ -0,0 +1,40 @@ +# HG changeset patch +# User Carl Friedrich Bolz-Tereick +# Date 1689148718 -7200 +# Wed Jul 12 09:58:38 2023 +0200 +# Branch conda-3.9-v7.3.12 +# Node ID f371f05be18aedeeb966fd9b657e72a7dbbc5126 +# Parent 163544ab2a142b8e7e040a098ec9013963c9fb64 +#3961: precompile res in csv module + +diff -r 163544ab2a14 -r f371f05be18a lib-python/3/csv.py +--- a/lib-python/3/csv.py Tue Jul 11 14:51:00 2023 +0200 ++++ b/lib-python/3/csv.py Wed Jul 12 09:58:38 2023 +0200 +@@ -162,6 +162,12 @@ + except NameError: + complex = float + ++_SNIFFER_RES = [re.compile(restr, re.DOTALL | re.MULTILINE) for restr in ++ (r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?P=delim)', # ,".*?", ++ r'(?:^|\n)(?P["\']).*?(?P=quote)(?P[^\w\n"\'])(?P ?)', # ".*?", ++ r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" ++ r'(?:^|\n)(?P["\']).*?(?P=quote)(?:$|\n)')] # ".*?" (no delim, no space) ++ + class Sniffer: + ''' + "Sniffs" the format of a CSV file (i.e. delimiter, quotechar) +@@ -214,11 +220,9 @@ + """ + + matches = [] +- for restr in (r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?P=delim)', # ,".*?", +- r'(?:^|\n)(?P["\']).*?(?P=quote)(?P[^\w\n"\'])(?P ?)', # ".*?", +- r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" +- r'(?:^|\n)(?P["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space) +- regexp = re.compile(restr, re.DOTALL | re.MULTILINE) ++ # PyPy difference: compile the regular expressions only once, globally, ++ # instead of on every call to sniff ++ for regexp in _SNIFFER_RES: + matches = regexp.findall(data) + if matches: + break diff --git a/recipe/patches/pypy_107656.patch b/recipe/patches/pypy_107656.patch new file mode 100644 index 0000000..e49b9a9 --- /dev/null +++ b/recipe/patches/pypy_107656.patch @@ -0,0 +1,42 @@ +# HG changeset patch +# User Matti Picus +# Date 1691873148 -10800 +# Sat Aug 12 23:45:48 2023 +0300 +# Branch conda-3.9-v7.3.12 +# Node ID 98f0ac5929217a22f7c911160b7c21ec18ee6ed2 +# Parent f371f05be18aedeeb966fd9b657e72a7dbbc5126 +Let tp_iternext raise StopIteration more selectively + +diff -r f371f05be18a -r 98f0ac592921 pypy/module/cpyext/slotdefs.py +--- a/pypy/module/cpyext/slotdefs.py Wed Jul 12 09:58:38 2023 +0200 ++++ b/pypy/module/cpyext/slotdefs.py Sat Aug 12 23:45:48 2023 +0300 +@@ -712,6 +712,12 @@ + return space.call_args(call_fn, args) + return slot_tp_call + ++# issue 3956 ++TP_ITERNEXT_RAISES_STOPITERATION = ( ++ "coroutine_wrapper", ++ "generator", ++) ++ + @slot_factory('tp_iternext') + def make_tp_iternext(space, typedef, name, attr): + w_type = space.gettypeobject(typedef) +@@ -719,13 +725,15 @@ + if iternext_fn is None: + return + ++ raises_stopiter = w_type.name in TP_ITERNEXT_RAISES_STOPITERATION ++ + @slot_function([PyObject], PyObject) + @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) + def slot_tp_iternext(space, w_self): + try: + return space.call_function(iternext_fn, w_self) + except OperationError as e: +- if not e.match(space, space.w_StopIteration): ++ if raises_stopiter or not e.match(space, space.w_StopIteration): + raise + return None + return slot_tp_iternext diff --git a/recipe/patches/pypy_107657.patch b/recipe/patches/pypy_107657.patch new file mode 100644 index 0000000..be87406 --- /dev/null +++ b/recipe/patches/pypy_107657.patch @@ -0,0 +1,65 @@ +# HG changeset patch +# User Matti Picus +# Date 1689757045 -7200 +# Wed Jul 19 10:57:25 2023 +0200 +# Branch conda-3.9-v7.3.12 +# Node ID 8e51bb8ff5066cfcc145c74aaaaf012c39dbc510 +# Parent 98f0ac5929217a22f7c911160b7c21ec18ee6ed2 +on macos sendifle can return an error while sending part of the file (issue 3964) + +diff -r 98f0ac592921 -r 8e51bb8ff506 rpython/rlib/rposix.py +--- a/rpython/rlib/rposix.py Sat Aug 12 23:45:48 2023 +0300 ++++ b/rpython/rlib/rposix.py Wed Jul 19 10:57:25 2023 +0200 +@@ -3039,11 +3039,12 @@ + with lltype.scoped_alloc(_OFF_PTR_T.TO, 1) as p_len: + p_len[0] = rffi.cast(OFF_T, count) + res = c_sendfile(in_fd, out_fd, offset, p_len, lltype.nullptr(rffi.VOIDP.TO), 0) ++ sbytes = p_len[0] + if res != 0: ++ if get_saved_errno() in (errno.EAGAIN, errno.EBUSY) and sbytes != 0: ++ return sbytes + return handle_posix_error('sendfile', res) +- res = p_len[0] +- return res +- ++ return sbytes + + # ____________________________________________________________ + # Support for *xattr functions +diff -r 98f0ac592921 -r 8e51bb8ff506 rpython/rlib/test/test_rposix.py +--- a/rpython/rlib/test/test_rposix.py Sat Aug 12 23:45:48 2023 +0300 ++++ b/rpython/rlib/test/test_rposix.py Wed Jul 19 10:57:25 2023 +0200 +@@ -736,6 +736,33 @@ + s2.close() + s1.close() + ++if sys.platform == "darwin": ++ def test_sendfile_partial(tmpdir): ++ # issue 3964 ++ from rpython.rlib.rsocket import socketpair ++ wsock, rsock = socketpair() ++ wsock.setblocking(False) ++ rsock.setblocking(False) ++ ++ recvd = 0 ++ with open(str(tmpdir / "sendfile.txt"), "wb+") as file: ++ file.write(b"x" * 131072) ++ file.flush() ++ file.seek(0) ++ ++ sent = rposix.sendfile(wsock.fd, file.fileno(), ++ offset=0, count=131072) ++ assert sent > 0 ++ try: ++ chunk = rsock.recv(1024) ++ while chunk: ++ recvd += len(chunk) ++ chunk = rsock.recv(1024) ++ except Exception as e: ++ pass ++ assert recvd == sent ++ ++ + @rposix_requires('pread') + def test_pread(): + fname = str(udir.join('os_test.txt')) diff --git a/recipe/patches/pypy_107658.patch b/recipe/patches/pypy_107658.patch new file mode 100644 index 0000000..dcd6011 --- /dev/null +++ b/recipe/patches/pypy_107658.patch @@ -0,0 +1,42 @@ +# HG changeset patch +# User Matti Picus +# Date 1691873417 -10800 +# Sat Aug 12 23:50:17 2023 +0300 +# Branch conda-3.9-v7.3.12 +# Node ID 7a1d0ec8c2b0c1dba4cfa57fb98065e960321d23 +# Parent 8e51bb8ff5066cfcc145c74aaaaf012c39dbc510 +#3978: report exceptions that are created when forcing an oefmt as unraisable + +diff -r 8e51bb8ff506 -r 7a1d0ec8c2b0 pypy/interpreter/error.py +--- a/pypy/interpreter/error.py Wed Jul 19 10:57:25 2023 +0200 ++++ b/pypy/interpreter/error.py Sat Aug 12 23:50:17 2023 +0300 +@@ -569,13 +569,23 @@ + result = str(value) + lgt += len(result) + elif fmt == 'R': +- s = space.repr(value) +- result = space.utf8_w(s) +- lgt += space.len_w(s) ++ try: ++ w_s = space.repr(value) ++ result = space.utf8_w(w_s) ++ lgt += space.len_w(w_s) ++ except OperationError as e: ++ e.write_unraisable(space, "exception formatting: ", value) ++ result = '' ++ lgt += len(result) + elif fmt == 'S': +- s = space.str(value) +- result = space.utf8_w(s) +- lgt += space.len_w(s) ++ try: ++ s = space.str(value) ++ result = space.utf8_w(s) ++ lgt += space.len_w(s) ++ except OperationError as e: ++ e.write_unraisable(space, "exception formatting: ", value) ++ result = '' ++ lgt += len(result) + elif fmt == 'T': + result = space.type(value).name + lgt += rutf8.codepoints_in_utf8(result) diff --git a/recipe/patches/pypy_107659.patch b/recipe/patches/pypy_107659.patch new file mode 100644 index 0000000..5c92269 --- /dev/null +++ b/recipe/patches/pypy_107659.patch @@ -0,0 +1,110 @@ +# HG changeset patch +# User Matti Picus +# Date 1691873583 -10800 +# Sat Aug 12 23:53:03 2023 +0300 +# Branch conda-3.9-v7.3.12 +# Node ID f160114383d06721f8231e5e9b0ec5a147867816 +# Parent 7a1d0ec8c2b0c1dba4cfa57fb98065e960321d23 +fixes on both app-level and C level for Py_TPFLAGS_BASETYPE=0 (issue 2742) + +diff -r 7a1d0ec8c2b0 -r f160114383d0 pypy/module/cpyext/typeobject.py +--- a/pypy/module/cpyext/typeobject.py Sat Aug 12 23:50:17 2023 +0300 ++++ b/pypy/module/cpyext/typeobject.py Sat Aug 12 23:53:03 2023 +0300 +@@ -20,7 +20,7 @@ + Py_TPFLAGS_TUPLE_SUBCLASS, Py_TPFLAGS_UNICODE_SUBCLASS, + Py_TPFLAGS_DICT_SUBCLASS, Py_TPFLAGS_BASE_EXC_SUBCLASS, + Py_TPFLAGS_TYPE_SUBCLASS, +- Py_TPFLAGS_BYTES_SUBCLASS, ++ Py_TPFLAGS_BYTES_SUBCLASS, Py_TPFLAGS_BASETYPE, + Py_TPPYPYFLAGS_FLOAT_SUBCLASS, + ) + +@@ -613,11 +613,11 @@ + else: + minsize = rffi.sizeof(PyObject.TO) + new_layout = (pto.c_tp_basicsize > minsize or pto.c_tp_itemsize > 0) +- + self.flag_cpytype = True + W_TypeObject.__init__(self, space, name, + bases_w or [space.w_object], dict_w, force_new_layout=new_layout, + is_heaptype=flag_heaptype) ++ + # if a sequence or a mapping, then set the flag to force it + if pto.c_tp_as_sequence and pto.c_tp_as_sequence.c_sq_item: + self.flag_map_or_seq = 'S' +@@ -632,6 +632,15 @@ + self._cpy_ref = py_obj + rawrefcount.create_link_pyobj(self, py_obj) + ++ def acceptable_as_base_class(self, space): ++ if not self.layout.typedef.acceptable_as_base_class: ++ return False ++ pyref = make_ref(space, self) ++ pto = rffi.cast(PyTypeObjectPtr, pyref) ++ acceptable_as_base_class = bool(widen(pto.c_tp_flags) & Py_TPFLAGS_BASETYPE) ++ decref(space, pyref) ++ return acceptable_as_base_class ++ + @bootstrap_function + def init_typeobject(space): + make_typedescr(space.w_type.layout.typedef, +@@ -707,6 +716,8 @@ + pto.c_tp_free = state.C.PyObject_Free + pto.c_tp_alloc = state.C.PyType_GenericAlloc + builder = state.builder ++ if w_type.layout.typedef.acceptable_as_base_class: ++ pto.c_tp_flags = rffi.cast(rffi.ULONG, widen(pto.c_tp_flags) | Py_TPFLAGS_BASETYPE) + if ((widen(pto.c_tp_flags) & Py_TPFLAGS_HEAPTYPE) != 0 + and builder.cpyext_type_init is None): + # this ^^^ is not None only during startup of cpyext. At that +@@ -983,12 +994,12 @@ + PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)""", + result_is_ll=True) + def PyType_FromSpecWithBases(space, spec, bases): +- return PyType_FromSpecWithBases(space, None, spec, bases) ++ return PyType_FromModuleAndSpec(space, None, spec, bases) + + @cts.decl("""PyObject * +- PyType_FromModuleAndSpec(PyObject *, PyType_Spec *spec, PyObject *bases)""", ++ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)""", + result_is_ll=True) +-def PyType_FromSpecWithBases(space, module, spec, bases): ++def PyType_FromModuleAndSpec(space, module, spec, bases): + from pypy.module.cpyext.unicodeobject import PyUnicode_FromString + state = space.fromcache(State) + p_type = cts.cast('PyTypeObject*', make_ref(space, space.w_type)) +@@ -1033,10 +1044,10 @@ + bases_w = space.fixedview(from_ref(space, bases)) + w_base = best_base(space, bases_w) + base = cts.cast('PyTypeObject*', make_ref(space, w_base)) +- if False: # not widen(base.c_tp_flags) & Py_TPFLAGS_BASETYPE: ++ if not widen(base.c_tp_flags) & Py_TPFLAGS_BASETYPE: + raise oefmt(space.w_TypeError, + "type '%s' is not an acceptable base type", +- rffi.charp2str(base.c_tp_name)) ++ rffi.constcharp2str(base.c_tp_name)) + + typ.c_tp_as_async = res.c_as_async + typ.c_tp_as_number = res.c_as_number +diff -r 7a1d0ec8c2b0 -r f160114383d0 pypy/objspace/std/typeobject.py +--- a/pypy/objspace/std/typeobject.py Sat Aug 12 23:50:17 2023 +0300 ++++ b/pypy/objspace/std/typeobject.py Sat Aug 12 23:53:03 2023 +0300 +@@ -769,6 +769,9 @@ + raise oefmt_attribute_error( + space, self, w_name, "type object '%N' has no attribute %R") + ++ def acceptable_as_base_class(self, space): ++ # Overridden by cpyext W_PyCTypeObject ++ return self.layout.typedef.acceptable_as_base_class + + def descr__new__(space, w_typetype, __args__): + """This is used to create user-defined classes only.""" +@@ -1217,7 +1220,7 @@ + if w_bestbase is None: + raise oefmt(space.w_TypeError, + "a new-style class can't have only classic bases") +- if not w_bestbase.layout.typedef.acceptable_as_base_class: ++ if not w_bestbase.acceptable_as_base_class(space): + raise oefmt(space.w_TypeError, + "type '%s' is not an acceptable base type", w_bestbase.name) + diff --git a/recipe/patches/pypy_107660.patch b/recipe/patches/pypy_107660.patch new file mode 100644 index 0000000..b17d1e6 --- /dev/null +++ b/recipe/patches/pypy_107660.patch @@ -0,0 +1,78 @@ +# HG changeset patch +# User Matti Picus +# Date 1691742889 -10800 +# Fri Aug 11 11:34:49 2023 +0300 +# Branch conda-3.9-v7.3.12 +# Node ID fa9fb672e6d8938f9f9e62137c1e3473711a5d40 +# Parent f160114383d06721f8231e5e9b0ec5a147867816 +hide functools.partial from the stack (issue 3988) + +diff -r f160114383d0 -r fa9fb672e6d8 extra_tests/test_functools.py +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/extra_tests/test_functools.py Fri Aug 11 11:34:49 2023 +0300 +@@ -0,0 +1,19 @@ ++import functools ++import sys ++import os ++ ++def test_partial_stack(): ++ # issue 3988 ++ stack = [] ++ def multiply(a, b): ++ frame = sys._getframe() ++ while frame: ++ stack.append(frame.f_code.co_name) ++ frame = frame.f_back ++ return a * b ++ ++ penta = functools.partial(multiply, 5) ++ assert penta(2) == 10 ++ assert len(stack) > 1 ++ # Make sure partial.__call__ is not in the first few stack functions ++ assert all([f != "__call__" for f in stack[:3]]) +diff -r f160114383d0 -r fa9fb672e6d8 lib-python/3/functools.py +--- a/lib-python/3/functools.py Sat Aug 12 23:53:03 2023 +0300 ++++ b/lib-python/3/functools.py Fri Aug 11 11:34:49 2023 +0300 +@@ -20,6 +20,8 @@ + from reprlib import recursive_repr + from _thread import RLock + from types import GenericAlias ++try: from __pypy__ import hidden_applevel ++except ImportError: builtinify = lambda f: f + + + ################################################################################ +@@ -203,6 +205,7 @@ + ### cmp_to_key() function converter + ################################################################################ + ++@hidden_applevel + def cmp_to_key(mycmp): + """Convert a cmp= function into a key= function""" + class K(object): +@@ -234,6 +237,7 @@ + + _initial_missing = object() + ++@hidden_applevel + def reduce(function, sequence, initial=_initial_missing): + """ + reduce(function, sequence[, initial]) -> value +@@ -297,6 +301,7 @@ + self.keywords = keywords + return self + ++ @hidden_applevel + def __call__(self, /, *args, **keywords): + keywords = {**self.keywords, **keywords} + return self.func(*self.args, *args, **keywords) +@@ -640,7 +645,7 @@ + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear +- return wrapper ++ return hidden_applevel(wrapper) + + try: + from _functools import _lru_cache_wrapper + diff --git a/recipe/patches/pypy_107661.patch b/recipe/patches/pypy_107661.patch new file mode 100644 index 0000000..613d98c --- /dev/null +++ b/recipe/patches/pypy_107661.patch @@ -0,0 +1,21 @@ +# HG changeset patch +# User Matti Picus +# Date 1691871129 -10800 +# Sat Aug 12 23:12:09 2023 +0300 +# Branch conda-3.9-v7.3.12 +# Node ID 80484c5f1f9cea6785223928bfe33e324cd3d166 +# Parent 744a279accbe082338dd6aba52332b60a3d56863 +fix edge case of datetime isoformat parsing (issue 3989) + +diff -r 744a279accbe -r 80484c5f1f9c lib-python/3/datetime.py +--- a/lib-python/3/datetime.py Fri Aug 11 11:34:49 2023 +0300 ++++ b/lib-python/3/datetime.py Sat Aug 12 23:12:09 2023 +0300 +@@ -270,6 +270,8 @@ + def _parse_isoformat_date(dtstr): + # It is assumed that this function will only be called with a + # string of length exactly 10, and (though this is not used) ASCII-only ++ if len(dtstr) < 10: ++ raise ValueError('isoformat expects a string of length 10') + year = int(dtstr[0:4]) + if dtstr[4] != '-': + raise ValueError('Invalid date separator: %s' % dtstr[4]) diff --git a/recipe/patches/pypy_107663.patch b/recipe/patches/pypy_107663.patch new file mode 100644 index 0000000..94f7362 --- /dev/null +++ b/recipe/patches/pypy_107663.patch @@ -0,0 +1,54 @@ +# HG changeset patch +# User Matti Picus +# Date 1691910266 -10800 +# Sun Aug 13 10:04:26 2023 +0300 +# Branch conda-3.8 +# Node ID 342e6f68228fb912be4bcb609d55896ce043cb85 +# Parent c20fe3f310f1d209d69a71d903dd17e5c3cf0de9 +hide functools.partial from the stack (issue 3988) + +diff -r c20fe3f310f1 -r 342e6f68228f lib-python/3/functools.py +--- a/lib-python/3/functools.py Sun Dec 04 10:41:06 2022 +0200 ++++ b/lib-python/3/functools.py Sun Aug 13 10:04:26 2023 +0300 +@@ -19,6 +19,8 @@ + # import types, weakref # Deferred to single_dispatch() + from reprlib import recursive_repr + from _thread import RLock ++try: from __pypy__ import hidden_applevel ++except ImportError: builtinify = lambda f: f + + + ################################################################################ +@@ -198,6 +200,7 @@ + ### cmp_to_key() function converter + ################################################################################ + ++@hidden_applevel + def cmp_to_key(mycmp): + """Convert a cmp= function into a key= function""" + class K(object): +@@ -229,6 +232,7 @@ + + _initial_missing = object() + ++@hidden_applevel + def reduce(function, sequence, initial=_initial_missing): + """ + reduce(function, sequence[, initial]) -> value +@@ -290,6 +294,7 @@ + self.keywords = keywords + return self + ++ @hidden_applevel + def __call__(self, /, *args, **keywords): + keywords = {**self.keywords, **keywords} + return self.func(*self.args, *args, **keywords) +@@ -642,7 +647,7 @@ + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear +- return wrapper ++ return hidden_applevel(wrapper) + + try: + from _functools import _lru_cache_wrapper diff --git a/recipe/patches/pypy_107668.patch b/recipe/patches/pypy_107668.patch new file mode 100644 index 0000000..309bdb5 --- /dev/null +++ b/recipe/patches/pypy_107668.patch @@ -0,0 +1,24 @@ +# HG changeset patch +# User Matti Picus +# Date 1692026252 -10800 +# Mon Aug 14 18:17:32 2023 +0300 +# Branch conda-3.9-v7.3.12 +# Node ID 56b6319f7d74c233348a2109a3de883d5d38a581 +# Parent 9563129b6f7d3d60334f3a5d42a8e9a74f5f31da +do not create c-extensions when running tests + +diff -r 9563129b6f7d -r 56b6319f7d74 lib-python/3/test/support/__init__.py +--- a/lib-python/3/test/support/__init__.py Sat Aug 12 23:12:09 2023 +0300 ++++ b/lib-python/3/test/support/__init__.py Mon Aug 14 18:17:32 2023 +0300 +@@ -28,11 +28,6 @@ + + from .testresult import get_test_runner + +-# This will create the _testmultiphaseimport c-extension module if it does not exist +-import _testmultiphase_build +-# This will create the _ctypes_test c-extension module if it does not exist +-import _ctypes_test_build +- + __all__ = [ + # globals + "PIPE_MAX_SIZE", "verbose", "max_memuse", "use_resources", "failfast",