From: Hyunjee Kim Date: Thu, 23 May 2019 06:39:18 +0000 (+0900) Subject: Imported Upstream version 3.7.3 X-Git-Tag: upstream/3.7.4~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3dffe06f346f17f0db246e1e742baea968b4401d;p=platform%2Fupstream%2Fpython3.git Imported Upstream version 3.7.3 Change-Id: Ia54a7d028b4c80beea0ab8e39646da0aafaa8bcd Signed-off-by: Hyunjee Kim --- diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 49a7bb62..15a83dd0 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -2,6 +2,11 @@ variables: manylinux: false coverage: false +resources: + containers: + - container: manylinux1 + image: pyca/cryptography-manylinux1:x86_64 + jobs: - job: Prebuild displayName: Pre-build checks @@ -54,10 +59,12 @@ jobs: variables: testRunTitle: '$(build.sourceBranchName)-linux' testRunPlatform: linux - openssl_version: 1.1.0g + openssl_version: 1.1.0j steps: - template: ./posix-steps.yml + parameters: + dependencies: apt - job: ManyLinux1_CI_Tests @@ -75,13 +82,20 @@ jobs: pool: vmImage: ubuntu-16.04 + container: manylinux1 + variables: testRunTitle: '$(build.sourceBranchName)-manylinux1' testRunPlatform: manylinux1 - imageName: 'dockcross/manylinux-x64' + openssl_version: '' steps: - - template: ./docker-steps.yml + - template: ./posix-steps.yml + parameters: + dependencies: yum + sudo_dependencies: '' + xvfb: false + patchcheck: false - job: Ubuntu_Coverage_CI_Tests @@ -102,11 +116,12 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.0g + openssl_version: 1.1.0j steps: - template: ./posix-steps.yml parameters: + dependencies: apt coverage: true @@ -134,3 +149,14 @@ jobs: steps: - template: ./windows-steps.yml + + - template: ./windows-layout-steps.yml + parameters: + kind: nuget + - template: ./windows-layout-steps.yml + parameters: + kind: embed + - template: ./windows-layout-steps.yml + parameters: + kind: appx + fulltest: true diff --git a/.azure-pipelines/docker-steps.yml b/.azure-pipelines/docker-steps.yml deleted file mode 100644 index ba4dfd72..00000000 --- a/.azure-pipelines/docker-steps.yml +++ /dev/null @@ -1,76 +0,0 @@ -steps: -- checkout: self - clean: true - fetchDepth: 5 - -- ${{ if ne(parameters.targetBranch, '') }}: - - script: | - git fetch -q origin ${{ parameters.targetbranch }} - if ! git diff --name-only HEAD $(git merge-base HEAD FETCH_HEAD) | grep -qvE '(\.rst$|^Doc|^Misc)' - then - echo "Only docs were updated, stopping build process." - echo "##vso[task.setvariable variable=DocOnly]true" - exit - fi - displayName: Detect doc-only changes - -- task: docker@0 - displayName: 'Configure CPython (debug)' - inputs: - action: 'Run an image' - imageName: $(imageName) - volumes: | - $(build.sourcesDirectory):/src - $(build.binariesDirectory):/build - workDir: '/src' - containerCommand: './configure --with-pydebug' - detached: false - condition: and(succeeded(), ne(variables['DocOnly'], 'true')) - -- task: docker@0 - displayName: 'Build CPython' - inputs: - action: 'Run an image' - imageName: $(imageName) - volumes: | - $(build.sourcesDirectory):/src - $(build.binariesDirectory):/build - workDir: '/src' - containerCommand: 'make -s -j4' - detached: false - condition: and(succeeded(), ne(variables['DocOnly'], 'true')) - -- task: docker@0 - displayName: 'Display build info' - inputs: - action: 'Run an image' - imageName: $(imageName) - volumes: | - $(build.sourcesDirectory):/src - $(build.binariesDirectory):/build - workDir: '/src' - containerCommand: 'make pythoninfo' - detached: false - condition: and(succeeded(), ne(variables['DocOnly'], 'true')) - -- task: docker@0 - displayName: 'Tests' - inputs: - action: 'Run an image' - imageName: $(imageName) - volumes: | - $(build.sourcesDirectory):/src - $(build.binariesDirectory):/build - workDir: '/src' - containerCommand: 'make buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=/build/test-results.xml"' - detached: false - condition: and(succeeded(), ne(variables['DocOnly'], 'true')) - -- task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '$(build.binariesDirectory)/test-results.xml' - mergeTestResults: true - testRunTitle: $(testRunTitle) - platform: $(testRunPlatform) - condition: and(succeededOrFailed(), ne(variables['DocOnly'], 'true')) diff --git a/.azure-pipelines/posix-deps-apt.sh b/.azure-pipelines/posix-deps-apt.sh new file mode 100755 index 00000000..4f489903 --- /dev/null +++ b/.azure-pipelines/posix-deps-apt.sh @@ -0,0 +1,26 @@ +apt-get update + +apt-get -yq install \ + build-essential \ + zlib1g-dev \ + libbz2-dev \ + liblzma-dev \ + libncurses5-dev \ + libreadline6-dev \ + libsqlite3-dev \ + libssl-dev \ + libgdbm-dev \ + tk-dev \ + lzma \ + lzma-dev \ + liblzma-dev \ + libffi-dev \ + uuid-dev \ + xvfb + +if [ ! -z "$1" ] +then + echo ##vso[task.prependpath]$PWD/multissl/openssl/$1 + echo ##vso[task.setvariable variable=OPENSSL_DIR]$PWD/multissl/openssl/$1 + python3 Tools/ssl/multissltests.py --steps=library --base-directory $PWD/multissl --openssl $1 --system Linux +fi diff --git a/.azure-pipelines/posix-deps.sh b/.azure-pipelines/posix-deps.sh deleted file mode 100755 index a5721075..00000000 --- a/.azure-pipelines/posix-deps.sh +++ /dev/null @@ -1,26 +0,0 @@ -sudo apt-get update - -sudo apt-get -yq install \ - build-essential \ - zlib1g-dev \ - libbz2-dev \ - liblzma-dev \ - libncurses5-dev \ - libreadline6-dev \ - libsqlite3-dev \ - libssl-dev \ - libgdbm-dev \ - tk-dev \ - lzma \ - lzma-dev \ - liblzma-dev \ - libffi-dev \ - uuid-dev \ - xvfb - -if [ ! -z "$1" ] -then - echo ##vso[task.prependpath]$PWD/multissl/openssl/$1 - echo ##vso[task.setvariable variable=OPENSSL_DIR]$PWD/multissl/openssl/$1 - python3 Tools/ssl/multissltests.py --steps=library --base-directory $PWD/multissl --openssl $1 --system Linux -fi diff --git a/.azure-pipelines/posix-steps.yml b/.azure-pipelines/posix-steps.yml index 9fec9be8..a4160e5a 100644 --- a/.azure-pipelines/posix-steps.yml +++ b/.azure-pipelines/posix-steps.yml @@ -1,12 +1,16 @@ parameters: coverage: false + sudo_dependencies: sudo + dependencies: apt + patchcheck: true + xvfb: true steps: - checkout: self clean: true fetchDepth: 5 -- script: ./.azure-pipelines/posix-deps.sh $(openssl_version) +- script: ${{ parameters.sudo_dependencies }} ./.azure-pipelines/posix-deps-${{ parameters.dependencies }}.sh $(openssl_version) displayName: 'Install dependencies' - script: ./configure --with-pydebug @@ -23,7 +27,7 @@ steps: displayName: 'Display build info' - script: | - xvfb-run ./venv/bin/python -m coverage run --pylib -m test \ + $COMMAND -m coverage run --pylib -m test \ --fail-env-changed \ -uall,-cpu \ --junit-xml=$(build.binariesDirectory)/test-results.xml" \ @@ -32,6 +36,11 @@ steps: -x test_multiprocessing_spawn \ -x test_concurrent_futures displayName: 'Tests with coverage' + env: + ${{ if eq(parameters.xvfb, 'true') }}: + COMMAND: xvfb-run ./venv/bin/python + ${{ if ne(parameters.xvfb, 'true') }}: + COMMAND: ./venv/bin/python - script: ./venv/bin/python -m coverage xml displayName: 'Generate coverage.xml' @@ -44,13 +53,18 @@ steps: - script: make pythoninfo displayName: 'Display build info' - - script: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml" + - script: $COMMAND buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml" displayName: 'Tests' - - -- script: ./python Tools/scripts/patchcheck.py --travis true - displayName: 'Run patchcheck.py' - condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) + env: + ${{ if eq(parameters.xvfb, 'true') }}: + COMMAND: xvfb-run make + ${{ if ne(parameters.xvfb, 'true') }}: + COMMAND: make + +- ${{ if eq(parameters.patchcheck, 'true') }}: + - script: ./python Tools/scripts/patchcheck.py --travis true + displayName: 'Run patchcheck.py' + condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) - task: PublishTestResults@2 diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 2d7fba9c..0bd7921b 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -1,3 +1,12 @@ +variables: + manylinux: false + coverage: false + +resources: + containers: + - container: manylinux1 + image: pyca/cryptography-manylinux1:x86_64 + jobs: - job: Prebuild displayName: Pre-build checks @@ -50,12 +59,70 @@ jobs: variables: testRunTitle: '$(system.pullRequest.TargetBranch)-linux' testRunPlatform: linux - openssl_version: 1.1.0g + openssl_version: 1.1.0j steps: - template: ./posix-steps.yml parameters: - targetBranch: $(System.PullRequest.TargetBranch) + dependencies: apt + + +- job: ManyLinux1_PR_Tests + displayName: ManyLinux1 PR Tests + dependsOn: Prebuild + condition: | + and( + and( + succeeded(), + eq(variables['manylinux'], 'true') + ), + eq(dependencies.Prebuild.outputs['tests.run'], 'true') + ) + + pool: + vmImage: ubuntu-16.04 + + container: manylinux1 + + variables: + testRunTitle: '$(system.pullRequest.TargetBranch)-manylinux1' + testRunPlatform: manylinux1 + openssl_version: '' + + steps: + - template: ./posix-steps.yml + parameters: + dependencies: yum + sudo_dependencies: '' + xvfb: false + patchcheck: false + + +- job: Ubuntu_Coverage_PR_Tests + displayName: Ubuntu PR Tests (coverage) + dependsOn: Prebuild + condition: | + and( + and( + succeeded(), + eq(variables['coverage'], 'true') + ), + eq(dependencies.Prebuild.outputs['tests.run'], 'true') + ) + + pool: + vmImage: ubuntu-16.04 + + variables: + testRunTitle: '$(Build.SourceBranchName)-linux-coverage' + testRunPlatform: linux-coverage + openssl_version: 1.1.0j + + steps: + - template: ./posix-steps.yml + parameters: + dependencies: apt + coverage: true - job: Windows_PR_Tests diff --git a/.azure-pipelines/windows-appx-test.yml b/.azure-pipelines/windows-appx-test.yml deleted file mode 100644 index 5f3fe6c9..00000000 --- a/.azure-pipelines/windows-appx-test.yml +++ /dev/null @@ -1,67 +0,0 @@ -jobs: -- job: Prebuild - displayName: Pre-build checks - - pool: - vmImage: ubuntu-16.04 - - steps: - - template: ./prebuild-checks.yml - - -- job: Windows_Appx_Tests - displayName: Windows Appx Tests - dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) - - pool: - vmImage: vs2017-win2016 - - strategy: - matrix: - win64: - arch: amd64 - buildOpt: '-p x64' - testRunTitle: '$(Build.SourceBranchName)-win64-appx' - testRunPlatform: win64 - maxParallel: 2 - - steps: - - checkout: self - clean: true - fetchDepth: 5 - - - powershell: | - # Relocate build outputs outside of source directory to make cleaning faster - Write-Host '##vso[task.setvariable variable=Py_IntDir]$(Build.BinariesDirectory)\obj' - # UNDONE: Do not build to a different directory because of broken tests - Write-Host '##vso[task.setvariable variable=Py_OutDir]$(Build.SourcesDirectory)\PCbuild' - Write-Host '##vso[task.setvariable variable=EXTERNAL_DIR]$(Build.BinariesDirectory)\externals' - displayName: Update build locations - - - script: PCbuild\build.bat -e $(buildOpt) - displayName: 'Build CPython' - env: - IncludeUwp: true - - - script: python.bat PC\layout -vv -s "$(Build.SourcesDirectory)" -b "$(Py_OutDir)\$(arch)" -t "$(Py_IntDir)\layout-tmp-$(arch)" --copy "$(Py_IntDir)\layout-$(arch)" --precompile --preset-appx --include-tests - displayName: 'Create APPX layout' - - - script: .\python.exe -m test.pythoninfo - workingDirectory: $(Py_IntDir)\layout-$(arch) - displayName: 'Display build info' - - - script: .\python.exe -m test -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 --junit-xml="$(Build.BinariesDirectory)\test-results.xml" --tempdir "$(Py_IntDir)\tmp-$(arch)" - workingDirectory: $(Py_IntDir)\layout-$(arch) - displayName: 'Tests' - env: - PREFIX: $(Py_IntDir)\layout-$(arch) - - - task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '$(Build.BinariesDirectory)\test-results.xml' - mergeTestResults: true - testRunTitle: $(testRunTitle) - platform: $(testRunPlatform) - condition: succeededOrFailed() diff --git a/.azure-pipelines/windows-layout-steps.yml b/.azure-pipelines/windows-layout-steps.yml new file mode 100644 index 00000000..e15729fa --- /dev/null +++ b/.azure-pipelines/windows-layout-steps.yml @@ -0,0 +1,28 @@ +parameters: + kind: nuget + extraOpts: --precompile + fulltest: false + +steps: +- script: .\python.bat PC\layout -vv -s "$(Build.SourcesDirectory)" -b "$(Py_OutDir)\$(arch)" -t "$(Build.BinariesDirectory)\layout-tmp-${{ parameters.kind }}-$(arch)" --copy "$(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch)" ${{ parameters.extraOpts }} --preset-${{ parameters.kind }} --include-tests + displayName: Create ${{ parameters.kind }} layout + +- script: .\python.exe -m test.pythoninfo + workingDirectory: $(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch) + displayName: Show layout info (${{ parameters.kind }}) + +- ${{ if eq(parameters.fulltest, 'true') }}: + - script: .\python.exe -m test -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 --junit-xml="$(Build.BinariesDirectory)\test-results-${{ parameters.kind }}.xml" --tempdir "$(Build.BinariesDirectory)\tmp-${{ parameters.kind }}-$(arch)" + workingDirectory: $(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch) + displayName: ${{ parameters.kind }} Tests + env: + PREFIX: $(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch) + + - task: PublishTestResults@2 + displayName: Publish ${{ parameters.kind }} Test Results + inputs: + testResultsFiles: $(Build.BinariesDirectory)\test-results-${{ parameters.kind }}.xml + mergeTestResults: true + testRunTitle: ${{ parameters.kind }}-$(testRunTitle) + platform: $(testRunPlatform) + condition: succeededOrFailed() diff --git a/.azure-pipelines/windows-steps.yml b/.azure-pipelines/windows-steps.yml index cba00158..794a23a5 100644 --- a/.azure-pipelines/windows-steps.yml +++ b/.azure-pipelines/windows-steps.yml @@ -1,6 +1,6 @@ steps: - checkout: self - clean: true + clean: false fetchDepth: 5 - powershell: | @@ -8,7 +8,8 @@ steps: Write-Host '##vso[task.setvariable variable=Py_IntDir]$(Build.BinariesDirectory)\obj' # UNDONE: Do not build to a different directory because of broken tests Write-Host '##vso[task.setvariable variable=Py_OutDir]$(Build.SourcesDirectory)\PCbuild' - Write-Host '##vso[task.setvariable variable=EXTERNAL_DIR]$(Build.BinariesDirectory)\externals' + #Write-Host '##vso[task.setvariable variable=Py_OutDir]$(Build.BinariesDirectory)\bin' + Write-Host '##vso[task.setvariable variable=EXTERNALS_DIR]$(Build.BinariesDirectory)\externals' displayName: Update build locations - script: PCbuild\build.bat -e $(buildOpt) diff --git a/Doc/bugs.rst b/Doc/bugs.rst index 109e9eb2..c449ba2e 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -17,7 +17,7 @@ Documentation bugs If you find a bug in this documentation or would like to propose an improvement, please submit a bug report on the :ref:`tracker `. If you -have a suggestion how to fix it, include that as well. +have a suggestion on how to fix it, include that as well. If you're short on time, you can also email documentation bug reports to docs@python.org (behavioral bugs can be sent to python-list@python.org). @@ -89,4 +89,4 @@ any and all questions pertaining to the process of fixing issues in Python. .. _Documentation bugs: https://bugs.python.org/issue?@filter=status&@filter=components&components=4&status=1&@columns=id,activity,title,status&@sort=-activity .. _Python Developer's Guide: https://devguide.python.org/ -.. _core-mentorship mailing list: https://mail.python.org/mailman/listinfo/core-mentorship/ +.. _core-mentorship mailing list: https://mail.python.org/mailman3/lists/core-mentorship.python.org/ diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index 33abb5bb..c7c1e3cc 100644 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -429,7 +429,7 @@ Buffer-related functions Return ``1`` if *obj* supports the buffer interface otherwise ``0``. When ``1`` is returned, it doesn't guarantee that :c:func:`PyObject_GetBuffer` will - succeed. + succeed. This function always succeeds. .. c:function:: int PyObject_GetBuffer(PyObject *exporter, Py_buffer *view, int flags) @@ -470,7 +470,7 @@ Buffer-related functions Return ``1`` if the memory defined by the *view* is C-style (*order* is ``'C'``) or Fortran-style (*order* is ``'F'``) :term:`contiguous` or either one - (*order* is ``'A'``). Return ``0`` otherwise. + (*order* is ``'A'``). Return ``0`` otherwise. This function always succeeds. .. c:function:: int PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order) diff --git a/Doc/c-api/codec.rst b/Doc/c-api/codec.rst index dfe3d436..c55f1997 100644 --- a/Doc/c-api/codec.rst +++ b/Doc/c-api/codec.rst @@ -13,7 +13,7 @@ Codec registry and support functions .. c:function:: int PyCodec_KnownEncoding(const char *encoding) Return ``1`` or ``0`` depending on whether there is a registered codec for - the given *encoding*. + the given *encoding*. This function always succeeds. .. c:function:: PyObject* PyCodec_Encode(PyObject *object, const char *encoding, const char *errors) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index b7225faf..0ced5a5f 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -95,6 +95,10 @@ Dictionary Objects Return the object from dictionary *p* which has a key *key*. Return *NULL* if the key *key* is not present, but *without* setting an exception. + Note that exceptions which occur while calling :meth:`__hash__` and + :meth:`__eq__` methods will get suppressed. + To get error reporting use :c:func:`PyDict_GetItemWithError()` instead. + .. c:function:: PyObject* PyDict_GetItemWithError(PyObject *p, PyObject *key) @@ -109,8 +113,13 @@ Dictionary Objects This is the same as :c:func:`PyDict_GetItem`, but *key* is specified as a :c:type:`const char\*`, rather than a :c:type:`PyObject\*`. + Note that exceptions which occur while calling :meth:`__hash__` and + :meth:`__eq__` methods and creating a temporary string object + will get suppressed. + To get error reporting use :c:func:`PyDict_GetItemWithError()` instead. + -.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *default) +.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *defaultobj) This is the same as the Python-level :meth:`dict.setdefault`. If present, it returns the value corresponding to *key* from the dictionary *p*. If the key diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index dd1e026c..cd06096e 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -53,8 +53,12 @@ Printing and clearing .. c:function:: void PyErr_PrintEx(int set_sys_last_vars) Print a standard traceback to ``sys.stderr`` and clear the error indicator. - Call this function only when the error indicator is set. (Otherwise it will - cause a fatal error!) + **Unless** the error is a ``SystemExit``. In that case the no traceback + is printed and Python process will exit with the error code specified by + the ``SystemExit`` instance. + + Call this function **only** when the error indicator is set. Otherwise it + will cause a fatal error! If *set_sys_last_vars* is nonzero, the variables :data:`sys.last_type`, :data:`sys.last_value` and :data:`sys.last_traceback` will be set to the diff --git a/Doc/c-api/mapping.rst b/Doc/c-api/mapping.rst index b8eaadbd..e37dec99 100644 --- a/Doc/c-api/mapping.rst +++ b/Doc/c-api/mapping.rst @@ -60,6 +60,10 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and This is equivalent to the Python expression ``key in o``. This function always succeeds. + Note that exceptions which occur while calling the :meth:`__getitem__` + method will get suppressed. + To get error reporting use :c:func:`PyObject_GetItem()` instead. + .. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) @@ -67,6 +71,10 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and This is equivalent to the Python expression ``key in o``. This function always succeeds. + Note that exceptions which occur while calling the :meth:`__getitem__` + method and creating a temporary string object will get suppressed. + To get error reporting use :c:func:`PyMapping_GetItemString()` instead. + .. c:function:: PyObject* PyMapping_Keys(PyObject *o) diff --git a/Doc/c-api/number.rst b/Doc/c-api/number.rst index 3c7605a6..296b21c1 100644 --- a/Doc/c-api/number.rst +++ b/Doc/c-api/number.rst @@ -280,3 +280,4 @@ Number Protocol Returns ``1`` if *o* is an index integer (has the nb_index slot of the tp_as_number structure filled in), and ``0`` otherwise. + This function always succeeds. diff --git a/Doc/c-api/objbuffer.rst b/Doc/c-api/objbuffer.rst index e7f4fde0..3572564b 100644 --- a/Doc/c-api/objbuffer.rst +++ b/Doc/c-api/objbuffer.rst @@ -39,7 +39,11 @@ an object, and :c:func:`PyBuffer_Release` when the buffer view can be released. .. c:function:: int PyObject_CheckReadBuffer(PyObject *o) Returns ``1`` if *o* supports the single-segment readable buffer interface. - Otherwise returns ``0``. + Otherwise returns ``0``. This function always succeeds. + + Note that this function tries to get and release a buffer, and exceptions + which occur while calling corresponding functions will get suppressed. + To get error reporting use :c:func:`PyObject_GetBuffer()` instead. .. c:function:: int PyObject_AsWriteBuffer(PyObject *obj, void **buffer, Py_ssize_t *buffer_len) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index f0b2005f..a64ff2e6 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -33,6 +33,10 @@ Object Protocol is equivalent to the Python expression ``hasattr(o, attr_name)``. This function always succeeds. + Note that exceptions which occur while calling :meth:`__getattr__` and + :meth:`__getattribute__` methods will get suppressed. + To get error reporting use :c:func:`PyObject_GetAttr()` instead. + .. c:function:: int PyObject_HasAttrString(PyObject *o, const char *attr_name) @@ -40,6 +44,11 @@ Object Protocol is equivalent to the Python expression ``hasattr(o, attr_name)``. This function always succeeds. + Note that exceptions which occur while calling :meth:`__getattr__` and + :meth:`__getattribute__` methods and creating a temporary string object + will get suppressed. + To get error reporting use :c:func:`PyObject_GetAttrString()` instead. + .. c:function:: PyObject* PyObject_GetAttr(PyObject *o, PyObject *attr_name) diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst index a66832cf..20bf9f0b 100644 --- a/Doc/c-api/tuple.rst +++ b/Doc/c-api/tuple.rst @@ -209,7 +209,7 @@ type. This function "steals" a reference to *o*. -.. c:function:: PyObject* PyStructSequence_SET_ITEM(PyObject *p, Py_ssize_t *pos, PyObject *o) +.. c:function:: void PyStructSequence_SET_ITEM(PyObject *p, Py_ssize_t *pos, PyObject *o) Macro equivalent of :c:func:`PyStructSequence_SetItem`. diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index 92e22b16..39c067d4 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -935,7 +935,7 @@ wchar_t Support Return *NULL* on failure. -.. c:function:: Py_ssize_t PyUnicode_AsWideChar(PyUnicodeObject *unicode, wchar_t *w, Py_ssize_t size) +.. c:function:: Py_ssize_t PyUnicode_AsWideChar(PyObject *unicode, wchar_t *w, Py_ssize_t size) Copy the Unicode object contents into the :c:type:`wchar_t` buffer *w*. At most *size* :c:type:`wchar_t` characters are copied (excluding a possibly trailing @@ -1346,7 +1346,7 @@ These are the "Raw Unicode Escape" codec APIs: .. c:function:: PyObject* PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s, \ - Py_ssize_t size, const char *errors) + Py_ssize_t size) Encode the :c:type:`Py_UNICODE` buffer of the given *size* using Raw-Unicode-Escape and return a bytes object. Return *NULL* if an exception was raised by the codec. @@ -1515,8 +1515,8 @@ the user settings on the machine running the codec. Return *NULL* if an exception was raised by the codec. -.. c:function:: PyObject* PyUnicode_DecodeMBCSStateful(const char *s, int size, \ - const char *errors, int *consumed) +.. c:function:: PyObject* PyUnicode_DecodeMBCSStateful(const char *s, Py_ssize_t size, \ + const char *errors, Py_ssize_t *consumed) If *consumed* is *NULL*, behave like :c:func:`PyUnicode_DecodeMBCS`. If *consumed* is not *NULL*, :c:func:`PyUnicode_DecodeMBCSStateful` will not decode diff --git a/Doc/copyright.rst b/Doc/copyright.rst index 540ff5ef..393a1f03 100644 --- a/Doc/copyright.rst +++ b/Doc/copyright.rst @@ -4,7 +4,7 @@ Copyright Python and this documentation is: -Copyright © 2001-2018 Python Software Foundation. All rights reserved. +Copyright © 2001-2019 Python Software Foundation. All rights reserved. Copyright © 2000 BeOpen.com. All rights reserved. diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 62cc9383..35527c17 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -31,29 +31,130 @@ # The parameter names are as they appear in the API manual, not the source # code. +PyAnySet_Check:int::: +PyAnySet_Check:PyObject*:p:0: + +PyAnySet_CheckExact:int::: +PyAnySet_CheckExact:PyObject*:p:0: + +PyBool_Check:int::: +PyBool_Check:PyObject*:o:0: + PyBool_FromLong:PyObject*::+1: -PyBool_FromLong:long:v:0: +PyBool_FromLong:long:v:: + +PyBuffer_FillContiguousStrides:void::: +PyBuffer_FillContiguousStrides:int:ndims:: +PyBuffer_FillContiguousStrides:Py_ssize_t*:shape:: +PyBuffer_FillContiguousStrides:Py_ssize_t*:strides:: +PyBuffer_FillContiguousStrides:int:itemsize:: +PyBuffer_FillContiguousStrides:char:order:: + +PyBuffer_FillInfo:int::: +PyBuffer_FillInfo:Py_buffer*:view:: +PyBuffer_FillInfo:PyObject*:exporter:0: +PyBuffer_FillInfo:void*:buf:: +PyBuffer_FillInfo:Py_ssize_t:len:: +PyBuffer_FillInfo:int:readonly:: +PyBuffer_FillInfo:int:flags:: + +PyBuffer_IsContiguous:int::: +PyBuffer_IsContiguous:Py_buffer*:view:: +PyBuffer_IsContiguous:char:order:: + +PyBuffer_Release:void::: +PyBuffer_Release:Py_buffer*:view:: + +PyBuffer_ToContiguous:int::: +PyBuffer_ToContiguous:void*:buf:: +PyBuffer_ToContiguous:Py_buffer*:src:: +PyBuffer_ToContiguous:Py_ssize_t:len:: +PyBuffer_ToContiguous:char:order:: + +PyByteArray_AS_STRING:char*::: +PyByteArray_AS_STRING:PyObject*:bytearray:0: + +PyByteArray_AsString:char*::: +PyByteArray_AsString:PyObject*:bytearray:0: + +PyByteArray_Check:int::: +PyByteArray_Check:PyObject*:o:0: + +PyByteArray_CheckExact:int::: +PyByteArray_CheckExact:PyObject*:o:0: + +PyByteArray_Concat:PyObject*::+1: +PyByteArray_Concat:PyObject*:a:0: +PyByteArray_Concat:PyObject*:b:0: + +PyByteArray_FromObject:PyObject*::+1: +PyByteArray_FromObject:PyObject*:o:0: + +PyByteArray_FromStringAndSize:PyObject*::+1: +PyByteArray_FromStringAndSize:const char*:string:: +PyByteArray_FromStringAndSize:Py_ssize_t:len:: + +PyByteArray_GET_SIZE:Py_ssize_t::: +PyByteArray_GET_SIZE:PyObject*:bytearray:0: + +PyByteArray_Resize:int::: +PyByteArray_Resize:PyObject*:bytearray:0: +PyByteArray_Resize:Py_ssize_t:len:: + +PyByteArray_Size:Py_ssize_t::: +PyByteArray_Size:PyObject*:bytearray:0: + +PyBytes_AS_STRING:char*::: +PyBytes_AS_STRING:PyObject*:string:0: -PyBuffer_FromObject:PyObject*::+1: -PyBuffer_FromObject:PyObject*:base:+1: -PyBuffer_FromObject:int:offset:: -PyBuffer_FromObject:int:size:: +PyBytes_AsString:char*::: +PyBytes_AsString:PyObject*:o:0: -PyBuffer_FromReadWriteObject:PyObject*::+1: -PyBuffer_FromReadWriteObject:PyObject*:base:+1: -PyBuffer_FromReadWriteObject:int:offset:: -PyBuffer_FromReadWriteObject:int:size:: +PyBytes_AsStringAndSize:int::: +PyBytes_AsStringAndSize:PyObject*:obj:0: +PyBytes_AsStringAndSize:char**:buffer:: +PyBytes_AsStringAndSize:Py_ssize_t*:length:: -PyBuffer_FromMemory:PyObject*::+1: -PyBuffer_FromMemory:void*:ptr:: -PyBuffer_FromMemory:int:size:: +PyBytes_Check:int::: +PyBytes_Check:PyObject*:o:0: -PyBuffer_FromReadWriteMemory:PyObject*::+1: -PyBuffer_FromReadWriteMemory:void*:ptr:: -PyBuffer_FromReadWriteMemory:int:size:: +PyBytes_CheckExact:int::: +PyBytes_CheckExact:PyObject*:o:0: -PyBuffer_New:PyObject*::+1: -PyBuffer_New:int:size:: +PyBytes_Concat:void::: +PyBytes_Concat:PyObject**:bytes:0: +PyBytes_Concat:PyObject*:newpart:0: + +PyBytes_ConcatAndDel:void::: +PyBytes_ConcatAndDel:PyObject**:bytes:0: +PyBytes_ConcatAndDel:PyObject*:newpart:-1: + +PyBytes_FromString:PyObject*::+1: +PyBytes_FromString:const char*:v:: + +PyBytes_FromStringAndSize:PyObject*::+1: +PyBytes_FromStringAndSize:const char*:v:: +PyBytes_FromStringAndSize:Py_ssize_t:len:: + +PyBytes_FromFormat:PyObject*::+1: +PyBytes_FromFormat:const char*:format:: +PyBytes_FromFormat::...:: + +PyBytes_FromFormatV:PyObject*::+1: +PyBytes_FromFormatV:const char*:format:: +PyBytes_FromFormatV:va_list:vargs:: + +PyBytes_FromObject:PyObject*::+1: +PyBytes_FromObject:PyObject*:o:0: + +PyBytes_GET_SIZE:Py_ssize_t::: +PyBytes_GET_SIZE:PyObject*:o:0: + +PyBytes_Size:Py_ssize_t::: +PyBytes_Size:PyObject*:o:0: + +PyCapsule_CheckExact:int::: +PyCapsule_CheckExact:PyObject*:p:0: PyCapsule_GetContext:void *::: PyCapsule_GetContext:PyObject*:self:0: @@ -72,6 +173,10 @@ PyCapsule_Import:void *::: PyCapsule_Import:const char *:name:: PyCapsule_Import:int:no_block:: +PyCapsule_IsValid:int::: +PyCapsule_IsValid:PyObject*:capsule:0: +PyCapsule_IsValid:const char*:name:: + PyCapsule_New:PyObject*::+1: PyCapsule_New:void*:pointer:: PyCapsule_New:const char *:name:: @@ -93,21 +198,8 @@ PyCapsule_SetPointer:int::: PyCapsule_SetPointer:PyObject*:self:0: PyCapsule_SetPointer:void*:pointer:: - -PyCObject_AsVoidPtr:void*::: -PyCObject_AsVoidPtr:PyObject*:self:0: - -PyCObject_FromVoidPtr:PyObject*::+1: -PyCObject_FromVoidPtr:void*:cobj:: -PyCObject_FromVoidPtr::void (* destr)(void* ):: - -PyCObject_FromVoidPtrAndDesc:PyObject*::+1: -PyCObject_FromVoidPtrAndDesc:void*:cobj:: -PyCObject_FromVoidPtrAndDesc:void*:desc:: -PyCObject_FromVoidPtrAndDesc:void(*)(void*,void*):destr:: - -PyCObject_GetDesc:void*::: -PyCObject_GetDesc:PyObject*:self:0: +PyCell_Check:int::: +PyCell_Check::ob:: PyCell_New:PyObject*::+1: PyCell_New:PyObject*:ob:0: @@ -126,19 +218,118 @@ PyCell_Set:int::: PyCell_Set:PyObject*:cell:0: PyCell_Set:PyObject*:value:0: +PyCallIter_Check:int::: +PyCallIter_Check::op:: + PyCallIter_New:PyObject*::+1: -PyCallIter_New:PyObject*:callable:: -PyCallIter_New:PyObject*:sentinel:: +PyCallIter_New:PyObject*:callable:+1: +PyCallIter_New:PyObject*:sentinel:+1: PyCallable_Check:int::: PyCallable_Check:PyObject*:o:0: +PyCode_Check:int::: +PyCode_Check:PyObject*:co:0: + +PyCode_GetNumFree:int::: +PyCode_GetNumFree:PyCodeObject*:co:0: + +PyCode_New:PyCodeObject*::+1: +PyCode_New:int:argcount:: +PyCode_New:int:kwonlyargcount:: +PyCode_New:int:nlocals:: +PyCode_New:int:stacksize:: +PyCode_New:int:flags:: +PyCode_New:PyObject*:code:0: +PyCode_New:PyObject*:consts:0: +PyCode_New:PyObject*:names:0: +PyCode_New:PyObject*:varnames:0: +PyCode_New:PyObject*:freevars:0: +PyCode_New:PyObject*:cellvars:0: +PyCode_New:PyObject*:filename:0: +PyCode_New:PyObject*:name:0: +PyCode_New:int:firstlineno:: +PyCode_New:PyObject*:lnotab:0: + +PyCode_NewEmpty:PyCodeObject*::+1: +PyCode_NewEmpty:const char*:filename:: +PyCode_NewEmpty:const char*:funcname:: +PyCode_NewEmpty:int:firstlineno:: + +PyCodec_Register:int::: +PyCodec_Register:PyObject*:search_function:+1: + +PyCodec_KnownEncoding:int::: +PyCodec_KnownEncoding:const char*:encoding:: + +PyCodec_Encode:PyObject*::+1: +PyCodec_Encode:PyObject*:object:0: +PyCodec_Encode:const char*:encoding:: +PyCodec_Encode:const char*:errors:: + +PyCodec_Decode:PyObject*::+1: +PyCodec_Decode:PyObject*:object:0: +PyCodec_Decode:const char*:encoding:: +PyCodec_Decode:const char*:errors:: + +PyCodec_Encoder:PyObject*::+1: +PyCodec_Encoder:const char*:encoding:: + +PyCodec_Decoder:PyObject*::+1: +PyCodec_Decoder:const char*:encoding:: + +PyCodec_IncrementalEncoder:PyObject*::+1: +PyCodec_IncrementalEncoder:const char*:encoding:: +PyCodec_IncrementalEncoder:const char*:errors:: + +PyCodec_IncrementalDecoder:PyObject*::+1: +PyCodec_IncrementalDecoder:const char*:encoding:: +PyCodec_IncrementalDecoder:const char*:errors:: + +PyCodec_StreamReader:PyObject*::+1: +PyCodec_StreamReader:const char*:encoding:: +PyCodec_StreamReader:PyObject*:stream:0: +PyCodec_StreamReader:const char*:errors:: + +PyCodec_StreamWriter:PyObject*::+1: +PyCodec_StreamWriter:const char*:encoding:: +PyCodec_StreamWriter:PyObject*:stream:0: +PyCodec_StreamWriter:const char*:errors:: + +PyCodec_RegisterError:int::: +PyCodec_RegisterError:const char*:name:: +PyCodec_RegisterError:PyObject*:error:+1: + +PyCodec_LookupError:PyObject*::+1: +PyCodec_LookupError:const char*:name:: + +PyCodec_StrictErrors:PyObject*::null: +PyCodec_StrictErrors:PyObject*:exc:0: + +PyCodec_IgnoreErrors:PyObject*::+1: +PyCodec_IgnoreErrors:PyObject*:exc:0: + +PyCodec_ReplaceErrors:PyObject*::+1: +PyCodec_ReplaceErrors:PyObject*:exc:0: + +PyCodec_XMLCharRefReplaceErrors:PyObject*::+1: +PyCodec_XMLCharRefReplaceErrors:PyObject*:exc:0: + +PyCodec_BackslashReplaceErrors:PyObject*::+1: +PyCodec_BackslashReplaceErrors:PyObject*:exc:0: + +PyCodec_NameReplaceErrors:PyObject*::+1: +PyCodec_NameReplaceErrors:PyObject*:exc:0: + PyComplex_AsCComplex:Py_complex::: PyComplex_AsCComplex:PyObject*:op:0: PyComplex_Check:int::: PyComplex_Check:PyObject*:p:0: +PyComplex_CheckExact:int::: +PyComplex_CheckExact:PyObject*:p:0: + PyComplex_FromCComplex:PyObject*::+1: PyComplex_FromCComplex::Py_complex v:: @@ -193,6 +384,12 @@ PyContextVar_Reset:int::: PyContextVar_Reset:PyObject*:var:0: PyContextVar_Reset:PyObject*:token:-1: +PyDate_Check:int::: +PyDate_Check:PyObject*:ob:0: + +PyDate_CheckExact:int::: +PyDate_CheckExact:PyObject*:ob:0: + PyDate_FromDate:PyObject*::+1: PyDate_FromDate:int:year:: PyDate_FromDate:int:month:: @@ -201,6 +398,12 @@ PyDate_FromDate:int:day:: PyDate_FromTimestamp:PyObject*::+1: PyDate_FromTimestamp:PyObject*:args:0: +PyDateTime_Check:int::: +PyDateTime_Check:PyObject*:ob:0: + +PyDateTime_CheckExact:int::: +PyDateTime_CheckExact:PyObject*:ob:0: + PyDateTime_FromDateAndTime:PyObject*::+1: PyDateTime_FromDateAndTime:int:year:: PyDateTime_FromDateAndTime:int:month:: @@ -213,46 +416,62 @@ PyDateTime_FromDateAndTime:int:usecond:: PyDateTime_FromTimestamp:PyObject*::+1: PyDateTime_FromTimestamp:PyObject*:args:0: +PyDelta_Check:int::: +PyDelta_Check:PyObject*:ob:0: + +PyDelta_CheckExact:int::: +PyDelta_CheckExact:PyObject*:ob:0: + PyDelta_FromDSU:PyObject*::+1: PyDelta_FromDSU:int:days:: PyDelta_FromDSU:int:seconds:: PyDelta_FromDSU:int:useconds:: PyTimeZone_FromOffset:PyObject*::+1: -PyTimeZone_FromOffset:PyDateTime_DeltaType*:offset:+1:Reference count not increased if offset is +00:00 +PyTimeZone_FromOffset:PyObject*:offset:+1:Reference count not increased if offset is +00:00 PyTimeZone_FromOffsetAndName:PyObject*::+1: -PyTimeZone_FromOffsetAndName:PyDateTime_DeltaType*:offset:+1:Reference count not increased if offset is +00:00 and name == NULL -PyTimeZone_FromOffsetAndName:PyUnicode*:name:+1: +PyTimeZone_FromOffsetAndName:PyObject*:offset:+1:Reference count not increased if offset is +00:00 and name == NULL +PyTimeZone_FromOffsetAndName:PyObject*:name:+1: +PyDescr_IsData:int::: +PyDescr_IsData:PyObject*:descr:0: + PyDescr_NewClassMethod:PyObject*::+1: -PyDescr_NewClassMethod:PyTypeObject*:type:: +PyDescr_NewClassMethod:PyTypeObject*:type:+1: PyDescr_NewClassMethod:PyMethodDef*:method:: PyDescr_NewGetSet:PyObject*::+1: -PyDescr_NewGetSet:PyTypeObject*:type:: +PyDescr_NewGetSet:PyTypeObject*:type:+1: PyDescr_NewGetSet:PyGetSetDef*:getset:: PyDescr_NewMember:PyObject*::+1: -PyDescr_NewMember:PyTypeObject*:type:: +PyDescr_NewMember:PyTypeObject*:type:+1: PyDescr_NewMember:PyMemberDef*:member:: PyDescr_NewMethod:PyObject*::+1: -PyDescr_NewMethod:PyTypeObject*:type:: +PyDescr_NewMethod:PyTypeObject*:type:+1: PyDescr_NewMethod:PyMethodDef*:meth:: PyDescr_NewWrapper:PyObject*::+1: -PyDescr_NewWrapper:PyTypeObject*:type:: +PyDescr_NewWrapper:PyTypeObject*:type:+1: PyDescr_NewWrapper:struct wrapperbase*:base:: PyDescr_NewWrapper:void*:wrapped:: PyDict_Check:int::: PyDict_Check:PyObject*:p:0: +PyDict_CheckExact:int::: +PyDict_CheckExact:PyObject*:p:0: + PyDict_Clear:void::: PyDict_Clear:PyObject*:p:0: +PyDict_Contains:int::: +PyDict_Contains:PyObject*:p:0: +PyDict_Contains:PyObject*:key:0: + PyDict_DelItem:int::: PyDict_DelItem:PyObject*:p:0: PyDict_DelItem:PyObject*:key:0: @@ -261,7 +480,7 @@ PyDict_DelItemString:int::: PyDict_DelItemString:PyObject*:p:0: PyDict_DelItemString:const char*:key:: -PyDict_GetItem:PyObject*::0:0 +PyDict_GetItem:PyObject*::0: PyDict_GetItem:PyObject*:p:0: PyDict_GetItem:PyObject*:key:0: @@ -289,9 +508,19 @@ PyDict_New:PyObject*::+1: PyDict_Copy:PyObject*::+1: PyDict_Copy:PyObject*:p:0: +PyDict_Merge:int::: +PyDict_Merge:PyObject*:a:0: +PyDict_Merge:PyObject*:b:0: +PyDict_Merge:int:override:: + +PyDict_MergeFromSeq2:int::: +PyDict_MergeFromSeq2:PyObject*:a:0: +PyDict_MergeFromSeq2:PyObject*:seq2:0: +PyDict_MergeFromSeq2:int:override:: + PyDict_Next:int::: PyDict_Next:PyObject*:p:0: -PyDict_Next:int:ppos:: +PyDict_Next:Py_ssize_t:ppos:: PyDict_Next:PyObject**:pkey:0: PyDict_Next:PyObject**:pvalue:0: @@ -305,8 +534,12 @@ PyDict_SetItemString:PyObject*:p:0: PyDict_SetItemString:const char*:key:: PyDict_SetItemString:PyObject*:val:+1: -PyDict_Size:int::: -PyDict_Size:PyObject*:p:: +PyDict_Size:Py_ssize_t::: +PyDict_Size:PyObject*:p:0: + +PyDict_Update:int::: +PyDict_Update:PyObject*:a:0: +PyDict_Update:PyObject*:b:0: PyDict_Values:PyObject*::+1: PyDict_Values:PyObject*:p:0: @@ -330,6 +563,21 @@ PyErr_Fetch:PyObject**:ptype:0: PyErr_Fetch:PyObject**:pvalue:0: PyErr_Fetch:PyObject**:ptraceback:0: +PyErr_Format:PyObject*::null: +PyErr_Format:PyObject*:exception:+1: +PyErr_Format:const char*:format:: +PyErr_Format::...:: + +PyErr_FormatV:PyObject*::null: +PyErr_FormatV:PyObject*:exception:+1: +PyErr_FormatV:const char*:format:: +PyErr_FormatV:va_list:vargs:: + +PyErr_GetExcInfo:void::: +PyErr_GetExcInfo:PyObject**:ptype:+1: +PyErr_GetExcInfo:PyObject**:pvalue:+1: +PyErr_GetExcInfo:PyObject**:ptraceback:+1: + PyErr_GivenExceptionMatches:int::: PyErr_GivenExceptionMatches:PyObject*:given:0: PyErr_GivenExceptionMatches:PyObject*:exc:0: @@ -356,27 +604,61 @@ PyErr_Occurred:PyObject*::0: PyErr_Print:void::: +PyErr_PrintEx:void::: +PyErr_PrintEx:int:set_sys_last_vars:: + +PyErr_ResourceWarning:int::: +PyErr_ResourceWarning:PyObject*:source:0: +PyErr_ResourceWarning:Py_ssize_t:stack_level:: +PyErr_ResourceWarning:const char*:format:: +PyErr_ResourceWarning::...:: + PyErr_Restore:void::: PyErr_Restore:PyObject*:type:-1: PyErr_Restore:PyObject*:value:-1: PyErr_Restore:PyObject*:traceback:-1: PyErr_SetExcFromWindowsErr:PyObject*::null: -PyErr_SetExcFromWindowsErr:PyObject*:type:0: +PyErr_SetExcFromWindowsErr:PyObject*:type:+1: PyErr_SetExcFromWindowsErr:int:ierr:: PyErr_SetExcFromWindowsErrWithFilename:PyObject*::null: -PyErr_SetExcFromWindowsErrWithFilename:PyObject*:type:0: +PyErr_SetExcFromWindowsErrWithFilename:PyObject*:type:+1: PyErr_SetExcFromWindowsErrWithFilename:int:ierr:: PyErr_SetExcFromWindowsErrWithFilename:const char*:filename:: +PyErr_SetExcFromWindowsErrWithFilenameObject:PyObject*::null: +PyErr_SetExcFromWindowsErrWithFilenameObject:PyObject*:type:+1: +PyErr_SetExcFromWindowsErrWithFilenameObject:int:ierr:: +PyErr_SetExcFromWindowsErrWithFilenameObject:PyObject*:filename:+1: + +PyErr_SetExcFromWindowsErrWithFilenameObjects:PyObject*::null: +PyErr_SetExcFromWindowsErrWithFilenameObjects:PyObject*:type:+1: +PyErr_SetExcFromWindowsErrWithFilenameObjects:int:ierr:: +PyErr_SetExcFromWindowsErrWithFilenameObjects:PyObject*:filename:+1: +PyErr_SetExcFromWindowsErrWithFilenameObjects:PyObject*:filename2:+1: + +PyErr_SetExcInfo:void::: +PyErr_SetExcInfo:PyObject*:type:0: +PyErr_SetExcInfo:PyObject*:value:0: +PyErr_SetExcInfo:PyObject*:traceback:0: + PyErr_SetFromErrno:PyObject*::null: -PyErr_SetFromErrno:PyObject*:type:0: +PyErr_SetFromErrno:PyObject*:type:+1: PyErr_SetFromErrnoWithFilename:PyObject*::null: -PyErr_SetFromErrnoWithFilename:PyObject*:type:0: +PyErr_SetFromErrnoWithFilename:PyObject*:type:+1: PyErr_SetFromErrnoWithFilename:const char*:filename:: +PyErr_SetFromErrnoWithFilenameObject:PyObject*::null: +PyErr_SetFromErrnoWithFilenameObject:PyObject*:type:+1: +PyErr_SetFromErrnoWithFilenameObject:PyObject*:filenameObject:+1: + +PyErr_SetFromErrnoWithFilenameObjects:PyObject*::null: +PyErr_SetFromErrnoWithFilenameObjects:PyObject*:type:+1: +PyErr_SetFromErrnoWithFilenameObjects:PyObject*:filenameObject:+1: +PyErr_SetFromErrnoWithFilenameObjects:PyObject*:filenameObject2:+1: + PyErr_SetFromWindowsErr:PyObject*::null: PyErr_SetFromWindowsErr:int:ierr:: @@ -384,6 +666,16 @@ PyErr_SetFromWindowsErrWithFilename:PyObject*::null: PyErr_SetFromWindowsErrWithFilename:int:ierr:: PyErr_SetFromWindowsErrWithFilename:const char*:filename:: +PyErr_SetImportError:PyObject*::null: +PyErr_SetImportError:PyObject*:msg:+1: +PyErr_SetImportError:PyObject*:name:+1: +PyErr_SetImportError:PyObject*:path:+1: + +PyErr_SetImportErrorSubclass:PyObject*::null: +PyErr_SetImportErrorSubclass:PyObject*:msg:+1: +PyErr_SetImportErrorSubclass:PyObject*:name:+1: +PyErr_SetImportErrorSubclass:PyObject*:path:+1: + PyErr_SetInterrupt:void::: PyErr_SetNone:void::: @@ -397,31 +689,69 @@ PyErr_SetString:void::: PyErr_SetString:PyObject*:type:+1: PyErr_SetString:const char*:message:: -PyErr_Format:PyObject*::null: -PyErr_Format:PyObject*:exception:+1: -PyErr_Format:const char*:format:: -PyErr_Format::...:: +PyErr_SyntaxLocation:void::: +PyErr_SyntaxLocation:const char*:filename:: +PyErr_SyntaxLocation:int:lineno:: -PyErr_FormatV:PyObject*::null: -PyErr_FormatV:PyObject*:exception:+1: -PyErr_FormatV:const char*:format:: -PyErr_FormatV:va_list:vargs:: +PyErr_SyntaxLocationEx:void::: +PyErr_SyntaxLocationEx:const char*:filename:: +PyErr_SyntaxLocationEx:int:lineno:: +PyErr_SyntaxLocationEx:int:col_offset:: + +PyErr_SyntaxLocationObject:void::: +PyErr_SyntaxLocationObject:PyObject*:filename:+1: +PyErr_SyntaxLocationObject:int:lineno:: +PyErr_SyntaxLocationObject:int:col_offset:: PyErr_WarnEx:int::: PyErr_WarnEx:PyObject*:category:0: PyErr_WarnEx:const char*:message:: PyErr_WarnEx:Py_ssize_t:stack_level:: +PyErr_WarnExplicit:int::: +PyErr_WarnExplicit:PyObject*:category:0: +PyErr_WarnExplicit:const char*:message:: +PyErr_WarnExplicit:const char*:filename:: +PyErr_WarnExplicit:int:lineno:: +PyErr_WarnExplicit:const char*:module:: +PyErr_WarnExplicit:PyObject*:registry:0: + +PyErr_WarnExplicitObject:int::: +PyErr_WarnExplicitObject:PyObject*:category:0: +PyErr_WarnExplicitObject:PyObject*:message:0: +PyErr_WarnExplicitObject:PyObject*:filename:0: +PyErr_WarnExplicitObject:int:lineno:: +PyErr_WarnExplicitObject:PyObject*:module:0: +PyErr_WarnExplicitObject:PyObject*:registry:0: + +PyErr_WarnFormat:int::: +PyErr_WarnFormat:PyObject*:category:0: +PyErr_WarnFormat:Py_ssize_t:stack_level:: +PyErr_WarnFormat:const char*:format:: +PyErr_WarnFormat::...:: + +PyErr_WriteUnraisable:void::: +PyErr_WriteUnraisable:PyObject*:obj:0: + PyEval_AcquireLock:void::: PyEval_AcquireThread:void::: PyEval_AcquireThread:PyThreadState*:tstate:: PyEval_GetBuiltins:PyObject*::0: + PyEval_GetLocals:PyObject*::0: + PyEval_GetGlobals:PyObject*::0: + PyEval_GetFrame:PyObject*::0: +PyEval_GetFuncDesc:const char*::: +PyEval_GetFuncDesc:PyObject*:func:0: + +PyEval_GetFuncName:const char*::: +PyEval_GetFuncName:PyObject*:func:0: + PyEval_InitThreads:void::: PyEval_ReleaseLock:void::: @@ -434,61 +764,85 @@ PyEval_RestoreThread:PyThreadState*:tstate:: PyEval_SaveThread:PyThreadState*::: +PyEval_SetProfile:void::: +PyEval_SetProfile:Py_tracefunc:func:: +PyEval_SetProfile:PyObject*:obj:+1: + +PyEval_SetTrace:void::: +PyEval_SetTrace:Py_tracefunc:func:: +PyEval_SetTrace:PyObject*:obj:+1: + PyEval_EvalCode:PyObject*::+1: -PyEval_EvalCode:PyCodeObject*:co:0: +PyEval_EvalCode:PyObject*:co:0: PyEval_EvalCode:PyObject*:globals:0: PyEval_EvalCode:PyObject*:locals:0: -PyException_GetTraceback:PyObject*::+1: +PyEval_EvalCodeEx:PyObject*::+1: +PyEval_EvalCodeEx:PyObject*:co:0: +PyEval_EvalCodeEx:PyObject*:globals:0: +PyEval_EvalCodeEx:PyObject*:locals:0: +PyEval_EvalCodeEx:PyObject*const*:args:: +PyEval_EvalCodeEx:int:argcount:: +PyEval_EvalCodeEx:PyObject*const*:kws:: +PyEval_EvalCodeEx:int:kwcount:: +PyEval_EvalCodeEx:PyObject*const*:defs:: +PyEval_EvalCodeEx:int:defcount:: +PyEval_EvalCodeEx:PyObject*:kwdefs:0: +PyEval_EvalCodeEx:PyObject*:closure:0: -PyFile_AsFile:FILE*::: -PyFile_AsFile:PyFileObject*:p:0: +PyEval_EvalFrame:PyObject*::+1: +PyEval_EvalFrame:PyFrameObject*:f:0: -PyFile_Check:int::: -PyFile_Check:PyObject*:p:0: +PyEval_EvalFrameEx:PyObject*::+1: +PyEval_EvalFrameEx:PyFrameObject*:f:0: +PyEval_EvalFrameEx:int:throwflag:: -PyFile_FromFile:PyObject*::+1: -PyFile_FromFile:FILE*:fp:: -PyFile_FromFile:const char*:name:: -PyFile_FromFile:const char*:mode:: -PyFile_FromFile:int(*:close):: +PyEval_MergeCompilerFlags:int::: +PyEval_MergeCompilerFlags:PyCompilerFlags*:cf:: -PyFile_FromFileEx:PyObject*::+1: -PyFile_FromFileEx:FILE*:fp:: -PyFile_FromFileEx:const char*:name:: -PyFile_FromFileEx:const char*:mode:: -PyFile_FromFileEx:int(*:close):: -PyFile_FromFileEx:int:buffering:: -PyFile_FromFileEx:const char*:encoding:: -PyFile_FromFileEx:const char*:newline:: +PyException_GetCause:PyObject*::+1: +PyException_GetCause:PyObject*:ex:0: -PyFile_FromString:PyObject*::+1: -PyFile_FromString:const char*:name:: -PyFile_FromString:const char*:mode:: +PyException_GetContext:PyObject*::+1: +PyException_GetContext:PyObject*:ex:0: + +PyException_GetTraceback:PyObject*::+1: +PyException_GetTraceback:PyObject*:ex:0: + +PyException_SetCause:void::: +PyException_SetCause:PyObject*:ex:0: +PyException_SetCause:PyObject*:cause:+1: + +PyException_SetContext:void::: +PyException_SetContext:PyObject*:ex:0: +PyException_SetContext:PyObject*:ctx:+1: + +PyException_SetTraceback:int::: +PyException_SetTraceback:PyObject*:ex:0: +PyException_SetTraceback:PyObject*:tb:+1: + +PyFile_FromFd:PyObject*::+1: +PyFile_FromFd:int:fd:: +PyFile_FromFd:const char*:name:: +PyFile_FromFd:const char*:mode:: +PyFile_FromFd:int:buffering:: +PyFile_FromFd:const char*:encoding:: +PyFile_FromFd:const char*:errors:: +PyFile_FromFd:const char*:newline:: +PyFile_FromFd:int:closefd:: PyFile_GetLine:PyObject*::+1: -PyFile_GetLine:PyObject*:p:: +PyFile_GetLine:PyObject*:p:0: PyFile_GetLine:int:n:: -PyFile_Name:PyObject*::0: -PyFile_Name:PyObject*:p:0: - -PyFile_SetBufSize:void::: -PyFile_SetBufSize:PyFileObject*:p:0: -PyFile_SetBufSize:int:n:: - -PyFile_SoftSpace:int::: -PyFile_SoftSpace:PyFileObject*:p:0: -PyFile_SoftSpace:int:newflag:: - PyFile_WriteObject:int::: PyFile_WriteObject:PyObject*:obj:0: -PyFile_WriteObject:PyFileObject*:p:0: +PyFile_WriteObject:PyObject*:p:0: PyFile_WriteObject:int:flags:: PyFile_WriteString:int::: PyFile_WriteString:const char*:s:: -PyFile_WriteString:PyFileObject*:p:0: +PyFile_WriteString:PyObject*:p:0: PyFile_WriteString:int:flags:: PyFloat_AS_DOUBLE:double::: @@ -500,15 +854,33 @@ PyFloat_AsDouble:PyObject*:pyfloat:0: PyFloat_Check:int::: PyFloat_Check:PyObject*:p:0: +PyFloat_CheckExact:int::: +PyFloat_CheckExact:PyObject*:p:0: + PyFloat_FromDouble:PyObject*::+1: PyFloat_FromDouble:double:v:: PyFloat_FromString:PyObject*::+1: PyFloat_FromString:PyObject*:str:0: +PyFloat_GetInfo:PyObject*::+1: +PyFloat_GetInfo::void:: + +PyFrozenSet_Check:int::: +PyFrozenSet_Check:PyObject*:p:0: + +PyFrozenSet_CheckExact:int::: +PyFrozenSet_CheckExact:PyObject*:p:0: + PyFrozenSet_New:PyObject*::+1: PyFrozenSet_New:PyObject*:iterable:0: +PyFunction_Check:int::: +PyFunction_Check:PyObject*:o:0: + +PyFunction_GetAnnotations:PyObject*::0: +PyFunction_GetAnnotations:PyObject*:op:0: + PyFunction_GetClosure:PyObject*::0: PyFunction_GetClosure:PyObject*:op:0: @@ -533,6 +905,10 @@ PyFunction_NewWithQualName:PyObject*:code:+1: PyFunction_NewWithQualName:PyObject*:globals:+1: PyFunction_NewWithQualName:PyObject*:qualname:+1: +PyFunction_SetAnnotations:int::: +PyFunction_SetAnnotations:PyObject*:op:0: +PyFunction_SetAnnotations:PyObject*:annotations:+1: + PyFunction_SetClosure:int::: PyFunction_SetClosure:PyObject*:op:0: PyFunction_SetClosure:PyObject*:closure:+1: @@ -541,34 +917,34 @@ PyFunction_SetDefaults:int::: PyFunction_SetDefaults:PyObject*:op:0: PyFunction_SetDefaults:PyObject*:defaults:+1: +PyGen_Check:int::: +PyGen_Check:PyObject*:ob:0: + +PyGen_CheckExact:int::: +PyGen_CheckExact:PyObject*:ob:0: + PyGen_New:PyObject*::+1: PyGen_New:PyFrameObject*:frame:0: PyGen_NewWithQualName:PyObject*::+1: PyGen_NewWithQualName:PyFrameObject*:frame:0: +PyGen_NewWithQualName:PyObject*:name:0: +PyGen_NewWithQualName:PyObject*:qualname:0: + +PyCoro_CheckExact:int::: +PyCoro_CheckExact:PyObject*:ob:0: PyCoro_New:PyObject*::+1: PyCoro_New:PyFrameObject*:frame:0: - -Py_InitModule:PyObject*::0: -Py_InitModule:const char*:name:: -Py_InitModule:PyMethodDef[]:methods:: - -Py_InitModule3:PyObject*::0: -Py_InitModule3:const char*:name:: -Py_InitModule3:PyMethodDef[]:methods:: -Py_InitModule3:const char*:doc:: - -Py_InitModule4:PyObject*::0: -Py_InitModule4:const char*:name:: -Py_InitModule4:PyMethodDef[]:methods:: -Py_InitModule4:const char*:doc:: -Py_InitModule4:PyObject*:self:: -Py_InitModule4:int:apiver::usually provided by Py_InitModule or Py_InitModule3 +PyCoro_New:PyObject*:name:0: +PyCoro_New:PyObject*:qualname:0: PyImport_AddModule:PyObject*::0:reference borrowed from sys.modules PyImport_AddModule:const char*:name:: +PyImport_AddModuleObject:PyObject*::0:reference borrowed from sys.modules +PyImport_AddModuleObject:PyObject*:name:0: + PyImport_Cleanup:void::: PyImport_ExecCodeModule:PyObject*::+1: @@ -580,6 +956,21 @@ PyImport_ExecCodeModuleEx:const char*:name:: PyImport_ExecCodeModuleEx:PyObject*:co:0: PyImport_ExecCodeModuleEx:const char*:pathname:: +PyImport_ExecCodeModuleObject:PyObject*::+1: +PyImport_ExecCodeModuleObject:const char*:name:: +PyImport_ExecCodeModuleObject:PyObject*:co:0: +PyImport_ExecCodeModuleObject:PyObject*:pathname:0: +PyImport_ExecCodeModuleObject:PyObject*:cpathname:0: + +PyImport_ExecCodeModuleWithPathnames:PyObject*::+1: +PyImport_ExecCodeModuleWithPathnames:const char*:name:: +PyImport_ExecCodeModuleWithPathnames:PyObject*:co:0: +PyImport_ExecCodeModuleWithPathnames:const char*:pathname:: +PyImport_ExecCodeModuleWithPathnames:const char*:cpathname:: + +PyImport_GetImporter:PyObject*::+1: +PyImport_GetImporter:PyObject*:path:0: + PyImport_GetMagicNumber:long::: PyImport_GetModule:PyObject*::+1: @@ -593,6 +984,9 @@ PyImport_Import:PyObject*:name:0: PyImport_ImportFrozenModule:int::: PyImport_ImportFrozenModule:const char*::: +PyImport_ImportFrozenModuleObject:int::: +PyImport_ImportFrozenModuleObject:PyObject*::+1: + PyImport_ImportModule:PyObject*::+1: PyImport_ImportModule:const char*:name:: @@ -609,39 +1003,33 @@ PyImport_ImportModuleLevel:PyObject*:locals:0:??? PyImport_ImportModuleLevel:PyObject*:fromlist:0:??? PyImport_ImportModuleLevel:int:level:: -PyImport_ReloadModule:PyObject*::+1: -PyImport_ReloadModule:PyObject*:m:0: - -PyInstance_New:PyObject*::+1: -PyInstance_New:PyObject*:klass:+1: -PyInstance_New:PyObject*:arg:0: -PyInstance_New:PyObject*:kw:0: - -PyInstance_NewRaw:PyObject*::+1: -PyInstance_NewRaw:PyObject*:klass:+1: -PyInstance_NewRaw:PyObject*:dict:+1: +PyImport_ImportModuleLevelObject:PyObject*::+1: +PyImport_ImportModuleLevelObject:PyObject*:name:0: +PyImport_ImportModuleLevelObject:PyObject*:globals:0:??? +PyImport_ImportModuleLevelObject:PyObject*:locals:0:??? +PyImport_ImportModuleLevelObject:PyObject*:fromlist:0:??? +PyImport_ImportModuleLevelObject:int:level:: -PyInt_AS_LONG:long::: -PyInt_AS_LONG:PyIntObject*:io:0: +PyImport_ImportModuleNoBlock:PyObject*::+1: +PyImport_ImportModuleNoBlock:const char*:name:: -PyInt_AsLong:long::: -PyInt_AsLong:PyObject*:io:0: +PyImport_ReloadModule:PyObject*::+1: +PyImport_ReloadModule:PyObject*:m:0: -PyInt_Check:int::: -PyInt_Check:PyObject*:op:0: +PyIndex_Check:int::: +PyIndex_Check:PyObject*:o:0: -PyInt_FromLong:PyObject*::+1: -PyInt_FromLong:long:ival:: +PyInstanceMethod_Check:int::: +PyInstanceMethod_Check:PyObject*:o:0: -PyInt_FromString:PyObject*::+1: -PyInt_FromString:char*:str:0: -PyInt_FromString:char**:pend:0: -PyInt_FromString:int:base:0: +PyInstanceMethod_Function:PyObject*::0: +PyInstanceMethod_Function:PyObject*:im:0: -PyInt_FromSsize_t:PyObject*::+1: -PyInt_FromSsize_t:Py_ssize_t:ival:: +PyInstanceMethod_GET_FUNCTION:PyObject*::0: +PyInstanceMethod_GET_FUNCTION:PyObject*:im:0: -PyInt_GetMax:long::: +PyInstanceMethod_New:PyObject*::+1: +PyInstanceMethod_New:PyObject*:func:0: PyInterpreterState_Clear:void::: PyInterpreterState_Clear:PyInterpreterState*:interp:: @@ -654,7 +1042,8 @@ PyInterpreterState_GetID:PyInterpreterState*:interp:: PyInterpreterState_New:PyInterpreterState*::: -PyIter_Check:int:o:0: +PyIter_Check:int::: +PyIter_Check:PyObject*:o:0: PyIter_Next:PyObject*::+1: PyIter_Next:PyObject*:o:0: @@ -669,50 +1058,53 @@ PyList_AsTuple:PyObject*:list:0: PyList_Check:int::: PyList_Check:PyObject*:p:0: +PyList_CheckExact:int::: +PyList_CheckExact:PyObject*:p:0: + PyList_GET_ITEM:PyObject*::0: PyList_GET_ITEM:PyObject*:list:0: -PyList_GET_ITEM:int:i:0: +PyList_GET_ITEM:Py_ssize_t:i:: -PyList_GET_SIZE:int::: +PyList_GET_SIZE:Py_ssize_t::: PyList_GET_SIZE:PyObject*:list:0: PyList_GetItem:PyObject*::0: PyList_GetItem:PyObject*:list:0: -PyList_GetItem:int:index:: +PyList_GetItem:Py_ssize_t:index:: PyList_GetSlice:PyObject*::+1: PyList_GetSlice:PyObject*:list:0: -PyList_GetSlice:int:low:: -PyList_GetSlice:int:high:: +PyList_GetSlice:Py_ssize_t:low:: +PyList_GetSlice:Py_ssize_t:high:: PyList_Insert:int::: PyList_Insert:PyObject*:list:0: -PyList_Insert:int:index:: +PyList_Insert:Py_ssize_t:index:: PyList_Insert:PyObject*:item:+1: PyList_New:PyObject*::+1: -PyList_New:int:len:: +PyList_New:Py_ssize_t:len:: PyList_Reverse:int::: PyList_Reverse:PyObject*:list:0: PyList_SET_ITEM:void::: PyList_SET_ITEM:PyObject*:list:0: -PyList_SET_ITEM:int:i:: +PyList_SET_ITEM:Py_ssize_t:i:: PyList_SET_ITEM:PyObject*:o:0: PyList_SetItem:int::: PyList_SetItem:PyObject*:list:0: -PyList_SetItem:int:index:: +PyList_SetItem:Py_ssize_t:index:: PyList_SetItem:PyObject*:item:0: PyList_SetSlice:int::: PyList_SetSlice:PyObject*:list:0: -PyList_SetSlice:int:low:: -PyList_SetSlice:int:high:: +PyList_SetSlice:Py_ssize_t:low:: +PyList_SetSlice:Py_ssize_t:high:: PyList_SetSlice:PyObject*:itemlist:0:but increfs its elements? -PyList_Size:int::: +PyList_Size:Py_ssize_t::: PyList_Size:PyObject*:list:0: PyList_Sort:int::: @@ -724,12 +1116,44 @@ PyLong_AsDouble:PyObject*:pylong:0: PyLong_AsLong:long::: PyLong_AsLong:PyObject*:pylong:0: +PyLong_AsLongAndOverflow:long::: +PyLong_AsLongAndOverflow:PyObject*:obj:0: +PyLong_AsLongAndOverflow:int*:overflow:: + +PyLong_AsLongLong:long long::: +PyLong_AsLongLong:PyObject*:obj:0: + +PyLong_AsLongLongAndOverflow:long long::: +PyLong_AsLongLongAndOverflow:PyObject*:obj:0: +PyLong_AsLongLongAndOverflow:int*:overflow:: + +PyLong_AsSize_t:size_t::: +PyLong_AsSize_t:PyObject*:pylong:0: + +PyLong_AsSsize_t:Py_ssize_t::: +PyLong_AsSsize_t:PyObject*:pylong:0: + PyLong_AsUnsignedLong:unsigned long::: PyLong_AsUnsignedLong:PyObject*:pylong:0: +PyLong_AsUnsignedLongLong:unsigned long long::: +PyLong_AsUnsignedLongLong:PyObject*:pylong:0: + +PyLong_AsUnsignedLongMask:unsigned long::: +PyLong_AsUnsignedLongMask:PyObject*:obj:0: + +PyLong_AsUnsignedLongLongMask:unsigned long long::: +PyLong_AsUnsignedLongLongMask:PyObject*:obj:0: + +PyLong_AsVoidPtr:void*::: +PyLong_AsVoidPtr:PyObject*:pylong:0: + PyLong_Check:int::: PyLong_Check:PyObject*:p:0: +PyLong_CheckExact:int::: +PyLong_CheckExact:PyObject*:p:0: + PyLong_FromDouble:PyObject*::+1: PyLong_FromDouble:double:v:: @@ -742,16 +1166,26 @@ PyLong_FromLongLong:long long:v:: PyLong_FromUnsignedLongLong:PyObject*::+1: PyLong_FromUnsignedLongLong:unsigned long long:v:: +PyLong_FromSize_t:PyObject*::+1: +PyLong_FromSize_t:size_t:v:: + +PyLong_FromSsize_t:PyObject*::+1: +PyLong_FromSsize_t:Py_ssize_t:v:: + PyLong_FromString:PyObject*::+1: PyLong_FromString:const char*:str:: PyLong_FromString:char**:pend:: PyLong_FromString:int:base:: PyLong_FromUnicode:PyObject*::+1: -PyLong_FromUnicode:Py_UNICODE:u:: -PyLong_FromUnicode:int:length:: +PyLong_FromUnicode:Py_UNICODE*:u:: +PyLong_FromUnicode:Py_ssize_t:length:: PyLong_FromUnicode:int:base:: +PyLong_FromUnicodeObject:PyObject*::+1: +PyLong_FromUnicodeObject:PyObject*:u:0: +PyLong_FromUnicodeObject:int:base:: + PyLong_FromUnsignedLong:PyObject*::+1: PyLong_FromUnsignedLong:unsignedlong:v:: @@ -787,7 +1221,7 @@ PyMapping_Items:PyObject*:o:0: PyMapping_Keys:PyObject*::+1: PyMapping_Keys:PyObject*:o:0: -PyMapping_Length:int::: +PyMapping_Length:Py_ssize_t::: PyMapping_Length:PyObject*:o:0: PyMapping_SetItemString:int::: @@ -795,6 +1229,9 @@ PyMapping_SetItemString:PyObject*:o:0: PyMapping_SetItemString:const char*:key:: PyMapping_SetItemString:PyObject*:v:+1: +PyMapping_Size:Py_ssize_t::: +PyMapping_Size:PyObject*:o:0: + PyMapping_Values:PyObject*::+1: PyMapping_Values:PyObject*:o:0: @@ -806,20 +1243,43 @@ PyMarshal_ReadObjectFromFile:FILE*:file:: PyMarshal_ReadObjectFromString:PyObject*::+1: PyMarshal_ReadObjectFromString:const char*:string:: -PyMarshal_ReadObjectFromString:int:len:: +PyMarshal_ReadObjectFromString:Py_ssize_t:len:: PyMarshal_WriteObjectToString:PyObject*::+1: PyMarshal_WriteObjectToString:PyObject*:value:0: +PyMarshal_WriteObjectToString:int:version:: + +PyMemoryView_Check:int::: +PyMemoryView_Check:PyObject*:obj:0: + +PyMemoryView_FromBuffer:PyObject*::+1: +PyMemoryView_FromBuffer:Py_buffer*:view:: + +PyMemoryView_FromMemory:PyObject*::+1: +PyMemoryView_FromMemory:char*:mem:: +PyMemoryView_FromMemory:Py_ssize_t:size:: +PyMemoryView_FromMemory:int:flags:: + +PyMemoryView_FromObject:PyObject*::+1: +PyMemoryView_FromObject:PyObject*:obj:0: + +PyMemoryView_GET_BASE:Py_buffer*::: +PyMemoryView_GET_BASE:PyObject*:mview:0: + +PyMemoryView_GET_BUFFER:Py_buffer*::: +PyMemoryView_GET_BUFFER:PyObject*:mview:0: -PyMethod_Class:PyObject*::0: -PyMethod_Class:PyObject*:im:0: +PyMemoryView_GetContiguous:PyObject*::+1: +PyMemoryView_GetContiguous:PyObject*:obj:0: +PyMemoryView_GetContiguous:int:buffertype:: +PyMemoryView_GetContiguous:char:order:: + +PyMethod_Check:int::: +PyMethod_Check:PyObject*:o:0: PyMethod_Function:PyObject*::0: PyMethod_Function:PyObject*:im:0: -PyMethod_GET_CLASS:PyObject*::0: -PyMethod_GET_CLASS:PyObject*:im:0: - PyMethod_GET_FUNCTION:PyObject*::0: PyMethod_GET_FUNCTION:PyObject*:im:0: @@ -834,18 +1294,93 @@ PyMethod_New:PyObject*:class:0: PyMethod_Self:PyObject*::0: PyMethod_Self:PyObject*:im:0: +PyModule_AddFunctions:int::: +PyModule_AddFunctions:PyObject*:module:0: +PyModule_AddFunctions:PyMethodDef*:functions:: + +PyModule_AddIntConstant:int::: +PyModule_AddIntConstant:PyObject*:module:0: +PyModule_AddIntConstant:const char*:name:: +PyModule_AddIntConstant:long:value:: + +PyModule_AddIntMacro:int::: +PyModule_AddIntMacro:PyObject*:module:0: +PyModule_AddIntMacro::macro:: + +PyModule_AddObject:int::: +PyModule_AddObject:PyObject*:module:0: +PyModule_AddObject:const char*:name:: +PyModule_AddObject:PyObject*:value:+1: + +PyModule_AddStringConstant:int::: +PyModule_AddStringConstant:PyObject*:module:0: +PyModule_AddStringConstant:const char*:name:: +PyModule_AddStringConstant:const char*:value:: + +PyModule_AddStringMacro:int::: +PyModule_AddStringMacro:PyObject*:module:0: +PyModule_AddStringMacro::macro:: + +PyModule_Check:int::: +PyModule_Check:PyObject*:p:0: + +PyModule_CheckExact:int::: +PyModule_CheckExact:PyObject*:p:0: + +PyModule_Create:PyObject*::+1: +PyModule_Create:PyModuleDef*:def:: + +PyModule_Create2:PyObject*::+1: +PyModule_Create2:PyModuleDef*:def:: +PyModule_Create2:int:module_api_version:: + +PyModule_ExecDef:int::: +PyModule_ExecDef:PyObject*:module:0: +PyModule_ExecDef:PyModuleDef*:def:: + +PyModule_FromDefAndSpec:PyObject*::+1: +PyModule_FromDefAndSpec:PyModuleDef*:def:: +PyModule_FromDefAndSpec:PyObject*:spec:0: + +PyModule_FromDefAndSpec2:PyObject*::+1: +PyModule_FromDefAndSpec2:PyModuleDef*:def:: +PyModule_FromDefAndSpec2:PyObject*:spec:0: +PyModule_FromDefAndSpec2:int:module_api_version:: + +PyModule_GetDef:PyModuleDef*::0: +PyModule_GetDef:PyObject*:module:0: + PyModule_GetDict:PyObject*::0: -PyModule_GetDict::PyObject* module:0: +PyModule_GetDict:PyObject*:module:0: PyModule_GetFilename:const char*::: PyModule_GetFilename:PyObject*:module:0: +PyModule_GetFilenameObject:PyObject*::+1: +PyModule_GetFilenameObject:PyObject*:module:0: + PyModule_GetName:const char*::: PyModule_GetName:PyObject*:module:0: +PyModule_GetNameObject:PyObject*::+1: +PyModule_GetNameObject:PyObject*:module:0: + +PyModule_GetState:void*::: +PyModule_GetState:PyObject*:module:0: + PyModule_New:PyObject*::+1: PyModule_New::char* name:: +PyModule_NewObject:PyObject*::+1: +PyModule_NewObject:PyObject*:name:+1: + +PyModule_SetDocString:int::: +PyModule_SetDocString:PyObject*:module:0: +PyModule_SetDocString:const char*:docstring:: + +PyModuleDef_Init:PyObject*::0: +PyModuleDef_Init:PyModuleDef*:def:0: + PyNumber_Absolute:PyObject*::+1: PyNumber_Absolute:PyObject*:o:0: @@ -857,12 +1392,12 @@ PyNumber_And:PyObject*::+1: PyNumber_And:PyObject*:o1:0: PyNumber_And:PyObject*:o2:0: -PyNumber_Check:PyObject*:o:0: -PyNumber_Check:int::: +PyNumber_AsSsize_t:Py_ssize_t::: +PyNumber_AsSsize_t:PyObject*:o:0: +PyNumber_AsSsize_t:PyObject*:exc:0: -PyNumber_Divide:PyObject*::+1: -PyNumber_Divide:PyObject*:o1:0: -PyNumber_Divide:PyObject*:o2:0: +PyNumber_Check:int::: +PyNumber_Check:PyObject*:o:0: PyNumber_Divmod:PyObject*::+1: PyNumber_Divmod:PyObject*:o1:0: @@ -875,6 +1410,9 @@ PyNumber_FloorDivide:PyObject*::+1: PyNumber_FloorDivide:PyObject*:v:0: PyNumber_FloorDivide:PyObject*:w:0: +PyNumber_Index:PyObject*::+1: +PyNumber_Index:PyObject*:o:0: + PyNumber_InPlaceAdd:PyObject*::+1: PyNumber_InPlaceAdd:PyObject*:v:0: PyNumber_InPlaceAdd:PyObject*:w:0: @@ -883,10 +1421,6 @@ PyNumber_InPlaceAnd:PyObject*::+1: PyNumber_InPlaceAnd:PyObject*:v:0: PyNumber_InPlaceAnd:PyObject*:w:0: -PyNumber_InPlaceDivide:PyObject*::+1: -PyNumber_InPlaceDivide:PyObject*:v:0: -PyNumber_InPlaceDivide:PyObject*:w:0: - PyNumber_InPlaceFloorDivide:PyObject*::+1: PyNumber_InPlaceFloorDivide:PyObject*:v:0: PyNumber_InPlaceFloorDivide:PyObject*:w:0: @@ -895,6 +1429,10 @@ PyNumber_InPlaceLshift:PyObject*::+1: PyNumber_InPlaceLshift:PyObject*:v:0: PyNumber_InPlaceLshift:PyObject*:w:0: +PyNumber_InPlaceMatrixMultiply:PyObject*::+1: +PyNumber_InPlaceMatrixMultiply:PyObject*:o1:0: +PyNumber_InPlaceMatrixMultiply:PyObject*:o2:0: + PyNumber_InPlaceMultiply:PyObject*::+1: PyNumber_InPlaceMultiply:PyObject*:v:0: PyNumber_InPlaceMultiply:PyObject*:w:0: @@ -938,6 +1476,10 @@ PyNumber_Lshift:PyObject*::+1: PyNumber_Lshift:PyObject*:o1:0: PyNumber_Lshift:PyObject*:o2:0: +PyNumber_MatrixMultiply:PyObject*::+1: +PyNumber_MatrixMultiply:PyObject*:o1:0: +PyNumber_MatrixMultiply:PyObject*:o2:0: + PyNumber_Multiply:PyObject*::+1: PyNumber_Multiply:PyObject*:o1:0: PyNumber_Multiply:PyObject*:o2:0: @@ -969,6 +1511,10 @@ PyNumber_Subtract:PyObject*::+1: PyNumber_Subtract:PyObject*:o1:0: PyNumber_Subtract:PyObject*:o2:0: +PyNumber_ToBase:PyObject*::+1: +PyNumber_ToBase:PyObject*:n:0: +PyNumber_ToBase:int:base:: + PyNumber_TrueDivide:PyObject*::+1: PyNumber_TrueDivide:PyObject*:v:0: PyNumber_TrueDivide:PyObject*:w:0: @@ -991,6 +1537,27 @@ PyOS_BeforeFork:void::: PyOS_FSPath:PyObject*::+1: PyOS_FSPath:PyObject*:path:0: +PyObject_ASCII:PyObject*::+1: +PyObject_ASCII:PyObject*:o:0: + +PyObject_AsCharBuffer:int::: +PyObject_AsCharBuffer:PyObject*:obj:0: +PyObject_AsCharBuffer:const char**:buffer:: +PyObject_AsCharBuffer:Py_ssize_t*:buffer_len:: + +PyObject_AsReadBuffer:int::: +PyObject_AsReadBuffer:PyObject*:obj:0: +PyObject_AsReadBuffer:const void**:buffer:: +PyObject_AsReadBuffer:Py_ssize_t*:buffer_len:: + +PyObject_AsWriteBuffer:int::: +PyObject_AsWriteBuffer:PyObject*:obj:0: +PyObject_AsWriteBuffer:void**:buffer:: +PyObject_AsWriteBuffer:Py_ssize_t*:buffer_len:: + +PyObject_Bytes:PyObject*::+1: +PyObject_Bytes:PyObject*:o:0: + PyObject_Call:PyObject*::+1: PyObject_Call:PyObject*:callable_object:0: PyObject_Call:PyObject*:args:0: @@ -1020,14 +1587,11 @@ PyObject_CallObject:PyObject*::+1: PyObject_CallObject:PyObject*:callable_object:0: PyObject_CallObject:PyObject*:args:0: -PyObject_Cmp:int::: -PyObject_Cmp:PyObject*:o1:0: -PyObject_Cmp:PyObject*:o2:0: -PyObject_Cmp:int*:result:: +PyObject_CheckBuffer:int::: +PyObject_CheckBuffer:PyObject*:obj:0: -PyObject_Compare:int::: -PyObject_Compare:PyObject*:o1:0: -PyObject_Compare:PyObject*:o2:0: +PyObject_CheckReadBuffer:int::: +PyObject_CheckReadBuffer:PyObject*:o:0: PyObject_DelAttr:int::: PyObject_DelAttr:PyObject*:o:0: @@ -1044,6 +1608,46 @@ PyObject_DelItem:PyObject*:key:0: PyObject_Dir:PyObject*::+1: PyObject_Dir:PyObject*:o:0: +PyObject_GC_Del:void::: +PyObject_GC_Del:void*:op:: + +PyObject_GC_New:TYPE*::+1: +PyObject_GC_New::TYPE:: +PyObject_GC_New:PyTypeObject*:type:0: + +PyObject_GC_NewVar:TYPE*::+1: +PyObject_GC_NewVar::TYPE:: +PyObject_GC_NewVar:PyTypeObject*:type:0: +PyObject_GC_NewVar:Py_ssize_t:size:: + +PyObject_GC_Resize:TYPE*::0: +PyObject_GC_Resize::TYPE:: +PyObject_GC_Resize:PyVarObject*:op:0: +PyObject_GC_Resize:Py_ssize_t:newsize:: + +PyObject_GC_Track:void::: +PyObject_GC_Track:PyObject*:op:0: + +PyObject_GC_UnTrack:void::: +PyObject_GC_UnTrack:void*:op:: + +PyObject_GenericGetAttr:PyObject*::+1: +PyObject_GenericGetAttr:PyObject*:o:0: +PyObject_GenericGetAttr:PyObject*:name:0: + +PyObject_GenericGetDict:PyObject*::+1: +PyObject_GenericGetDict:PyObject*:o:0: +PyObject_GenericGetDict:void*:context:: + +PyObject_GenericSetAttr:int::: +PyObject_GenericSetAttr:PyObject*:o:0: +PyObject_GenericSetAttr:PyObject*:name:0: +PyObject_GenericSetAttr:PyObject*:value:+1: + +PyObject_GenericSetDict:int::: +PyObject_GenericSetDict:PyObject*:o:+1: +PyObject_GenericSetDict:void*:context:: + PyObject_GetAttr:PyObject*::+1: PyObject_GetAttr:PyObject*:o:0: PyObject_GetAttr:PyObject*:attr_name:0: @@ -1052,6 +1656,11 @@ PyObject_GetAttrString:PyObject*::+1: PyObject_GetAttrString:PyObject*:o:0: PyObject_GetAttrString:const char*:attr_name:: +PyObject_GetBuffer:int::: +PyObject_GetBuffer:PyObject*:exporter:0: +PyObject_GetBuffer:Py_buffer*:view:: +PyObject_GetBuffer:int:flags:: + PyObject_GetItem:PyObject*::+1: PyObject_GetItem:PyObject*:o:0: PyObject_GetItem:PyObject*:key:0: @@ -1065,30 +1674,59 @@ PyObject_HasAttr:PyObject*:attr_name:0: PyObject_HasAttrString:int::: PyObject_HasAttrString:PyObject*:o:0: -PyObject_HasAttrString:const char*:attr_name:0: +PyObject_HasAttrString:const char*:attr_name:: PyObject_Hash:int::: PyObject_Hash:PyObject*:o:0: +PyObject_HashNotImplemented:Py_hash_t::: +PyObject_HashNotImplemented:PyObject*:o:0: + +PyObject_IsInstance:int::: +PyObject_IsInstance:PyObject*:inst:0: +PyObject_IsInstance:PyObject*:cls:0: + +PyObject_IsSubclass:int::: +PyObject_IsSubclass:PyObject*:derived:0: +PyObject_IsSubclass:PyObject*:cls:0: + PyObject_IsTrue:int::: PyObject_IsTrue:PyObject*:o:0: PyObject_Init:PyObject*::0: PyObject_Init:PyObject*:op:0: +PyObject_Init:PyTypeObject*:type:0: PyObject_InitVar:PyVarObject*::0: PyObject_InitVar:PyVarObject*:op:0: -PyObject_Length:int::: +PyObject_Length:Py_ssize_t::: PyObject_Length:PyObject*:o:0: +PyObject_LengthHint:Py_ssize_t::: +PyObject_LengthHint:PyObject*:o:0: +PyObject_LengthHint:Py_ssize_t:default:: + PyObject_NEW:PyObject*::+1: +PyObject_NEW::TYPE:: +PyObject_NEW:PyTypeObject*:type:0: PyObject_New:PyObject*::+1: +PyObject_New::TYPE:: +PyObject_New:PyTypeObject*:type:0: PyObject_NEW_VAR:PyObject*::+1: +PyObject_NEW_VAR::TYPE:: +PyObject_NEW_VAR:PyTypeObject*:type:0: +PyObject_NEW_VAR:Py_ssize_t:size:: PyObject_NewVar:PyObject*::+1: +PyObject_NewVar::TYPE:: +PyObject_NewVar:PyTypeObject*:type:0: +PyObject_NewVar:Py_ssize_t:size:: + +PyObject_Not:int::: +PyObject_Not:PyObject*:o:0: PyObject_Print:int::: PyObject_Print:PyObject*:o:0: @@ -1123,28 +1761,65 @@ PyObject_SetItem:PyObject*:o:0: PyObject_SetItem:PyObject*:key:0: PyObject_SetItem:PyObject*:v:+1: +PyObject_Size:Py_ssize_t::: +PyObject_Size:PyObject*:o:0: + PyObject_Str:PyObject*::+1: PyObject_Str:PyObject*:o:0: PyObject_Type:PyObject*::+1: PyObject_Type:PyObject*:o:0: -PyObject_Unicode:PyObject*::+1: -PyObject_Unicode:PyObject*:o:0: +PyObject_TypeCheck:int::: +PyObject_TypeCheck:PyObject*:o:0: +PyObject_TypeCheck:PyTypeObject*:type:0: PyParser_SimpleParseFile:struct _node*::: PyParser_SimpleParseFile:FILE*:fp:: PyParser_SimpleParseFile:const char*:filename:: PyParser_SimpleParseFile:int:start:: +PyParser_SimpleParseFileFlags:struct _node*::: +PyParser_SimpleParseFileFlags:FILE*:fp:: +PyParser_SimpleParseFileFlags:const char*:filename:: +PyParser_SimpleParseFileFlags:int:start:: +PyParser_SimpleParseFileFlags:int:flags:: + PyParser_SimpleParseString:struct _node*::: PyParser_SimpleParseString:const char*:str:: PyParser_SimpleParseString:int:start:: +PyParser_SimpleParseStringFlags:struct _node*::: +PyParser_SimpleParseStringFlags:const char*:str:: +PyParser_SimpleParseStringFlags:int:start:: +PyParser_SimpleParseStringFlags:int:flags:: + +PyParser_SimpleParseStringFlagsFilename:struct _node*::: +PyParser_SimpleParseStringFlagsFilename:const char*:str:: +PyParser_SimpleParseStringFlagsFilename:const char*:filename:: +PyParser_SimpleParseStringFlagsFilename:int:start:: +PyParser_SimpleParseStringFlagsFilename:int:flags:: + PyRun_AnyFile:int::: PyRun_AnyFile:FILE*:fp:: PyRun_AnyFile:const char*:filename:: +PyRun_AnyFileFlags:int::: +PyRun_AnyFileFlags:FILE*:fp:: +PyRun_AnyFileFlags:const char*:filename:: +PyRun_AnyFileFlags:PyCompilerFlags*:flags:: + +PyRun_AnyFileEx:int::: +PyRun_AnyFileEx:FILE*:fp:: +PyRun_AnyFileEx:const char*:filename:: +PyRun_AnyFileEx:int:closeit:: + +PyRun_AnyFileExFlags:int::: +PyRun_AnyFileExFlags:FILE*:fp:: +PyRun_AnyFileExFlags:const char*:filename:: +PyRun_AnyFileExFlags:int:closeit:: +PyRun_AnyFileExFlags:PyCompilerFlags*:flags:: + PyRun_File:PyObject*::+1:??? -- same as eval_code2() PyRun_File:FILE*:fp:: PyRun_File:const char*:filename:: @@ -1181,17 +1856,42 @@ PyRun_InteractiveLoop:int::: PyRun_InteractiveLoop:FILE*:fp:: PyRun_InteractiveLoop:const char*:filename:: +PyRun_InteractiveLoopFlags:int::: +PyRun_InteractiveLoopFlags:FILE*:fp:: +PyRun_InteractiveLoopFlags:const char*:filename:: +PyRun_InteractiveLoopFlags:PyCompilerFlags*:flags:: + PyRun_InteractiveOne:int::: PyRun_InteractiveOne:FILE*:fp:: PyRun_InteractiveOne:const char*:filename:: +PyRun_InteractiveOneFlags:int::: +PyRun_InteractiveOneFlags:FILE*:fp:: +PyRun_InteractiveOneFlags:const char*:filename:: +PyRun_InteractiveOneFlags:PyCompilerFlags*:flags:: + PyRun_SimpleFile:int::: PyRun_SimpleFile:FILE*:fp:: PyRun_SimpleFile:const char*:filename:: +PyRun_SimpleFileEx:int::: +PyRun_SimpleFileEx:FILE*:fp:: +PyRun_SimpleFileEx:const char*:filename:: +PyRun_SimpleFileEx:int:closeit:: + +PyRun_SimpleFileExFlags:int::: +PyRun_SimpleFileExFlags:FILE*:fp:: +PyRun_SimpleFileExFlags:const char*:filename:: +PyRun_SimpleFileExFlags:int:closeit:: +PyRun_SimpleFileExFlags:PyCompilerFlags*:flags:: + PyRun_SimpleString:int::: PyRun_SimpleString:const char*:command:: +PyRun_SimpleStringFlags:int::: +PyRun_SimpleStringFlags:const char*:command:: +PyRun_SimpleStringFlags:PyCompilerFlags*:flags:: + PyRun_String:PyObject*::+1:??? -- same as eval_code2() PyRun_String:const char*:str:: PyRun_String:int:start:: @@ -1205,6 +1905,9 @@ PyRun_StringFlags:PyObject*:globals:0: PyRun_StringFlags:PyObject*:locals:0: PyRun_StringFlags:PyCompilerFlags*:flags:: +PySeqIter_Check:int::: +PySeqIter_Check::op:: + PySeqIter_New:PyObject*::+1: PySeqIter_New:PyObject*:seq:: @@ -1215,18 +1918,22 @@ PySequence_Concat:PyObject*::+1: PySequence_Concat:PyObject*:o1:0: PySequence_Concat:PyObject*:o2:0: -PySequence_Count:int::: +PySequence_Contains:int::: +PySequence_Contains:PyObject*:o:0: +PySequence_Contains:PyObject*:value:0: + +PySequence_Count:Py_ssize_t::: PySequence_Count:PyObject*:o:0: PySequence_Count:PyObject*:value:0: PySequence_DelItem:int::: PySequence_DelItem:PyObject*:o:0: -PySequence_DelItem:int:i:: +PySequence_DelItem:Py_ssize_t:i:: PySequence_DelSlice:int::: PySequence_DelSlice:PyObject*:o:0: -PySequence_DelSlice:int:i1:: -PySequence_DelSlice:int:i2:: +PySequence_DelSlice:Py_ssize_t:i1:: +PySequence_DelSlice:Py_ssize_t:i2:: PySequence_Fast:PyObject*::+1: PySequence_Fast:PyObject*:v:0: @@ -1234,22 +1941,28 @@ PySequence_Fast:const char*:m:: PySequence_Fast_GET_ITEM:PyObject*::0: PySequence_Fast_GET_ITEM:PyObject*:o:0: -PySequence_Fast_GET_ITEM:int:i:: +PySequence_Fast_GET_ITEM:Py_ssize_t:i:: + +PySequence_Fast_GET_SIZE:Py_ssize_t::: +PySequence_Fast_GET_SIZE:PyObject*:o:0: + +PySequence_Fast_ITEMS:PyObject**::: +PySequence_Fast_ITEMS:PyObject*:o:0: PySequence_GetItem:PyObject*::+1: PySequence_GetItem:PyObject*:o:0: -PySequence_GetItem:int:i:: +PySequence_GetItem:Py_ssize_t:i:: PySequence_GetSlice:PyObject*::+1: PySequence_GetSlice:PyObject*:o:0: -PySequence_GetSlice:int:i1:: -PySequence_GetSlice:int:i2:: +PySequence_GetSlice:Py_ssize_t:i1:: +PySequence_GetSlice:Py_ssize_t:i2:: PySequence_In:int::: PySequence_In:PyObject*:o:0: PySequence_In:PyObject*:value:0: -PySequence_Index:int::: +PySequence_Index:Py_ssize_t::: PySequence_Index:PyObject*:o:0: PySequence_Index:PyObject*:value:0: @@ -1263,22 +1976,25 @@ PySequence_InPlaceRepeat:PyObject*:o:0: PySequence_ITEM:PyObject*::+1: PySequence_ITEM:PyObject*:o:0: -PySequence_ITEM:int:i:: +PySequence_ITEM:Py_ssize_t:i:: PySequence_Repeat:PyObject*::+1: PySequence_Repeat:PyObject*:o:0: -PySequence_Repeat:int:count:: +PySequence_Repeat:Py_ssize_t:count:: PySequence_SetItem:int::: PySequence_SetItem:PyObject*:o:0: -PySequence_SetItem:int:i:: +PySequence_SetItem:Py_ssize_t:i:: PySequence_SetItem:PyObject*:v:+1: PySequence_SetSlice:int::: PySequence_SetSlice:PyObject*:o:0: -PySequence_SetSlice:int:i1:: -PySequence_SetSlice:int:i2:: -PySequence_SetSlice:PyObject*:v:+1: +PySequence_SetSlice:Py_ssize_t:i1:: +PySequence_SetSlice:Py_ssize_t:i2:: +PySequence_SetSlice:PyObject*:v:0: + +PySequence_Size:Py_ssize_t::: +PySequence_Size:PyObject*:o:0: PySequence_List:PyObject*::+1: PySequence_List:PyObject*:o:0: @@ -1286,9 +2002,15 @@ PySequence_List:PyObject*:o:0: PySequence_Tuple:PyObject*::+1: PySequence_Tuple:PyObject*:o:0: -PySet_Append:int::: -PySet_Append:PyObject*:set:0: -PySet_Append:PyObject*:key:+1: +PySet_Add:int::: +PySet_Add:PyObject*:set:0: +PySet_Add:PyObject*:key:+1: + +PySet_Check:int::: +PySet_Check:PyObject*:p:0: + +PySet_Clear:int::: +PySet_Clear:PyObject*:set:0: PySet_Contains:int::: PySet_Contains:PyObject*:anyset:0: @@ -1298,15 +2020,21 @@ PySet_Discard:int::: PySet_Discard:PyObject*:set:0: PySet_Discard:PyObject*:key:-1:no effect if key not found +PySet_GET_SIZE:Py_ssize_t::: +PySet_GET_SIZE:PyObject*:anyset:0: + PySet_New:PyObject*::+1: PySet_New:PyObject*:iterable:0: PySet_Pop:PyObject*::+1:or returns NULL and raises KeyError if set is empty PySet_Pop:PyObject*:set:0: -PySet_Size:int::: +PySet_Size:Py_ssize_t::: PySet_Size:PyObject*:anyset:0: +PySignal_SetWakeupFd:int::: +PySignal_SetWakeupFd:int:fd:: + PySlice_AdjustIndices:Py_ssize_t::: PySlice_AdjustIndices:Py_ssize_t:length:: PySlice_AdjustIndices:Py_ssize_t*:start:: @@ -1316,6 +2044,21 @@ PySlice_AdjustIndices:Py_ssize_t*:step:: PySlice_Check:int::: PySlice_Check:PyObject*:ob:0: +PySlice_GetIndices:int::: +PySlice_GetIndices:PyObject*:slice:0: +PySlice_GetIndices:Py_ssize_t:length:: +PySlice_GetIndices:Py_ssize_t*:start:: +PySlice_GetIndices:Py_ssize_t*:stop:: +PySlice_GetIndices:Py_ssize_t*:step:: + +PySlice_GetIndicesEx:int::: +PySlice_GetIndicesEx:PyObject*:slice:0: +PySlice_GetIndicesEx:Py_ssize_t:length:: +PySlice_GetIndicesEx:Py_ssize_t*:start:: +PySlice_GetIndicesEx:Py_ssize_t*:stop:: +PySlice_GetIndicesEx:Py_ssize_t*:step:: +PySlice_GetIndicesEx:Py_ssize_t*:slicelength:: + PySlice_New:PyObject*::+1: PySlice_New:PyObject*:start:0: PySlice_New:PyObject*:stop:0: @@ -1327,100 +2070,78 @@ PySlice_Unpack:Py_ssize_t*:start:: PySlice_Unpack:Py_ssize_t*:stop:: PySlice_Unpack:Py_ssize_t*:step:: -PyString_AS_STRING:const char*::: -PyString_AS_STRING:PyObject*:string:0: - -PyString_AsDecodedObject:PyObject*::+1: -PyString_AsDecodedObject:PyObject*:str:0: -PyString_AsDecodedObject:const char*:encoding:: -PyString_AsDecodedObject:const char*:errors:: - -PyString_AsEncodedObject:PyObject*::+1: -PyString_AsEncodedObject:PyObject*:str:0: -PyString_AsEncodedObject:const char*:encoding:: -PyString_AsEncodedObject:const char*:errors:: - -PyString_AsString:const char*::: -PyString_AsString:PyObject*:string:0: - -PyString_AsStringAndSize:int::: -PyString_AsStringAndSize:PyObject*:obj:0: -PyString_AsStringAndSize:char**:buffer:: -PyString_AsStringAndSize:int*:length:: - -PyString_Check:int::: -PyString_Check:PyObject*:o:0: - -PyString_Concat:void::: -PyString_Concat:PyObject**:string:0:??? -- replaces w/ new string or NULL -PyString_Concat:PyObject*:newpart:0: - -PyString_ConcatAndDel:void::: -PyString_ConcatAndDel:PyObject**:string:0:??? -- replaces w/ new string or NULL -PyString_ConcatAndDel:PyObject*:newpart:-1: - -PyString_Format:PyObject*::+1: -PyString_Format:PyObject*:format:0: -PyString_Format:PyObject*:args:0: - -PyString_FromString:PyObject*::+1: -PyString_FromString:const char*:v:: +PyState_AddModule:int::: +PyState_AddModule:PyObject*:module:+1: +PyState_AddModule:PyModuleDef*:def:: -PyString_FromStringAndSize:PyObject*::+1: -PyString_FromStringAndSize:const char*:v:: -PyString_FromStringAndSize:int:len:: +PyState_FindModule:PyObject*::0: +PyState_FindModule:PyModuleDef*:def:: -PyString_FromFormat:PyObject*::+1: -PyString_FromFormat:const char*:format:: -PyString_FromFormat::...:: +PyState_RemoveModule:int::: +PyState_RemoveModule:PyModuleDef*:def:: -PyString_FromFormatV:PyObject*::+1: -PyString_FromFormatV:const char*:format:: -PyString_FromFormatV:va_list:vargs:: +PyStructSequence_GET_ITEM:PyObject*::0: +PyStructSequence_GET_ITEM:PyObject*:p:0: +PyStructSequence_GET_ITEM:Py_ssize_t:pos:: -PyString_GET_SIZE:int::: -PyString_GET_SIZE:PyObject*:string:0: +PyStructSequence_GetItem:PyObject*::0: +PyStructSequence_GetItem:PyObject*:p:0: +PyStructSequence_GetItem:Py_ssize_t:pos:: -PyString_InternFromString:PyObject*::+1: -PyString_InternFromString:const char*:v:: +PyStructSequence_InitType:void::: +PyStructSequence_InitType:PyTypeObject*:type:+1: +PyStructSequence_InitType:PyStructSequence_Desc*:desc:: -PyString_InternInPlace:void::: -PyString_InternInPlace:PyObject**:string:+1:??? +PyStructSequence_InitType2:int::: +PyStructSequence_InitType2:PyTypeObject*:type:+1: +PyStructSequence_InitType2:PyStructSequence_Desc*:desc:: -PyString_Size:int::: -PyString_Size:PyObject*:string:0: +PyStructSequence_New:PyObject*::+1: +PyStructSequence_New:PyTypeObject*:type:0: -PyString_Decode:PyObject*::+1: -PyString_Decode:const char*:s:: -PyString_Decode:int:size:: -PyString_Decode:const char*:encoding:: -PyString_Decode:const char*:errors:: +PyStructSequence_NewType:PyTypeObject*::+1: +PyStructSequence_NewType:PyStructSequence_Desc*:desc:: -PyString_Encode:PyObject*::+1: -PyString_Encode:const char*:s:: -PyString_Encode:int:size:: -PyString_Encode:const char*:encoding:: -PyString_Encode:const char*:errors:: +PyStructSequence_SET_ITEM:void::: +PyStructSequence_SET_ITEM:PyObject*:p:0: +PyStructSequence_SET_ITEM:Py_ssize_t*:pos:: +PyStructSequence_SET_ITEM:PyObject*:o:0: -PyString_AsEncodedString:PyObject*::+1: -PyString_AsEncodedString:PyObject*:str:: -PyString_AsEncodedString:const char*:encoding:: -PyString_AsEncodedString:const char*:errors:: +PyStructSequence_SetItem:void::: +PyStructSequence_SetItem:PyObject*:p:0: +PyStructSequence_SetItem:Py_ssize_t:pos:: +PyStructSequence_SetItem:PyObject*:o:0: PySys_AddWarnOption:void::: -PySys_AddWarnOption:const char*:s:: +PySys_AddWarnOption:const wchar_t*:s:: + +PySys_AddWarnOptionUnicode:void::: +PySys_AddWarnOptionUnicode:PyObject*:unicode:0: PySys_AddXOption:void::: PySys_AddXOption:const wchar_t*:s:: +PySys_FormatStderr:void::: +PySys_FormatStderr:const char*:format:: +PySys_FormatStderr::...:: + +PySys_FormatStdout:void::: +PySys_FormatStdout:const char*:format:: +PySys_FormatStdout::...:: + PySys_GetObject:PyObject*::0: PySys_GetObject:const char*:name:: PySys_GetXOptions:PyObject*::0: -PySys_SetArgv:int::: +PySys_SetArgv:void::: PySys_SetArgv:int:argc:: -PySys_SetArgv:char**:argv:: +PySys_SetArgv:wchar_t**:argv:: + +PySys_SetArgvEx:void::: +PySys_SetArgvEx:int:argc:: +PySys_SetArgvEx:wchar_t**:argv:: +PySys_SetArgvEx:int:updatepath:: PySys_SetObject:int::: PySys_SetObject:const char*:name:: @@ -1430,9 +2151,11 @@ PySys_ResetWarnOptions:void::: PySys_WriteStdout:void::: PySys_WriteStdout:const char*:format:: +PySys_WriteStdout::...:: PySys_WriteStderr:void::: PySys_WriteStderr:const char*:format:: +PySys_WriteStderr::...:: PyThreadState_Clear:void::: PyThreadState_Clear:PyThreadState*:tstate:: @@ -1447,6 +2170,10 @@ PyThreadState_GetDict:PyObject*::0: PyThreadState_New:PyThreadState*::: PyThreadState_New:PyInterpreterState*:interp:: +PyThreadState_SetAsyncExc:int::: +PyThreadState_SetAsyncExc:unsigned long:id:: +PyThreadState_SetAsyncExc:PyObject*:exc:+1: + PyThreadState_Swap:PyThreadState*::: PyThreadState_Swap:PyThreadState*:tstate:: @@ -1471,6 +2198,12 @@ PyThread_tss_set:int::: PyThread_tss_set:Py_tss_t*:key:: PyThread_tss_set:void*:value:: +PyTime_Check:int::: +PyTime_Check:PyObject*:ob:0: + +PyTime_CheckExact:int::: +PyTime_CheckExact:PyObject*:ob:0: + PyTime_FromTime:PyObject*::+1: PyTime_FromTime:int:hour:: PyTime_FromTime:int:minute:: @@ -1489,63 +2222,130 @@ PyTraceMalloc_Untrack:uintptr_t:ptr:: PyTuple_Check:int::: PyTuple_Check:PyObject*:p:0: +PyTuple_CheckExact:int::: +PyTuple_CheckExact:PyObject*:p:0: + PyTuple_GET_ITEM:PyObject*::0: -PyTuple_GET_ITEM:PyTupleObject*:p:0: -PyTuple_GET_ITEM:int:pos:: +PyTuple_GET_ITEM:PyObject*:p:0: +PyTuple_GET_ITEM:Py_ssize_t:pos:: PyTuple_GetItem:PyObject*::0: -PyTuple_GetItem:PyTupleObject*:p:0: -PyTuple_GetItem:int:pos:: +PyTuple_GetItem:PyObject*:p:0: +PyTuple_GetItem:Py_ssize_t:pos:: + +PyTuple_GET_SIZE:Py_ssize_t::: +PyTuple_GET_SIZE:PyObject*:p:0: PyTuple_GetSlice:PyObject*::+1: -PyTuple_GetSlice:PyTupleObject*:p:0: -PyTuple_GetSlice:int:low:: -PyTuple_GetSlice:int:high:: +PyTuple_GetSlice:PyObject*:p:0: +PyTuple_GetSlice:Py_ssize_t:low:: +PyTuple_GetSlice:Py_ssize_t:high:: PyTuple_New:PyObject*::+1: -PyTuple_New:int:len:: +PyTuple_New:Py_ssize_t:len:: PyTuple_Pack:PyObject*::+1: -PyTuple_Pack:int:len:: +PyTuple_Pack:Py_ssize_t:len:: PyTuple_Pack:PyObject*:...:0: PyTuple_SET_ITEM:void::: -PyTuple_SET_ITEM:PyTupleObject*:p:0: -PyTuple_SET_ITEM:int:pos:: +PyTuple_SET_ITEM:PyObject*:p:0: +PyTuple_SET_ITEM:Py_ssize_t:pos:: PyTuple_SET_ITEM:PyObject*:o:0: PyTuple_SetItem:int::: -PyTuple_SetItem:PyTupleObject*:p:0: -PyTuple_SetItem:int:pos:: +PyTuple_SetItem:PyObject*:p:0: +PyTuple_SetItem:Py_ssize_t:pos:: PyTuple_SetItem:PyObject*:o:0: -PyTuple_Size:int::: -PyTuple_Size:PyTupleObject*:p:0: +PyTuple_Size:Py_ssize_t::: +PyTuple_Size:PyObject*:p:0: + +PyType_Check:int::: +PyType_Check:PyObject*:o:0: + +PyType_CheckExact:int::: +PyType_CheckExact:PyObject*:o:0: + +PyType_FromSpec:PyObject*::+1: +PyType_FromSpec:PyType_Spec*:spec:: + +PyType_FromSpecWithBases:PyObject*::+1: +PyType_FromSpecWithBases:PyType_Spec*:spec:: +PyType_FromSpecWithBases:PyObject*:bases:0: PyType_GenericAlloc:PyObject*::+1: PyType_GenericAlloc:PyObject*:type:0: -PyType_GenericAlloc:int:nitems:0: +PyType_GenericAlloc:Py_ssize_t:nitems:: PyType_GenericNew:PyObject*::+1: PyType_GenericNew:PyObject*:type:0: PyType_GenericNew:PyObject*:args:0: PyType_GenericNew:PyObject*:kwds:0: +PyType_GetFlags:unsigned long::: +PyType_GetFlags:PyTypeObject*:type:0: + +PyType_GetSlot:void*::: +PyType_GetSlot:PyTypeObject*:type:0: +PyType_GetSlot:int:slot:: + +PyType_HasFeature:int::: +PyType_HasFeature:PyTypeObject*:o:0: +PyType_HasFeature:int:feature:: + +PyType_IS_GC:int::: +PyType_IS_GC:PyTypeObject*:o:0: + +PyType_IsSubtype:int::: +PyType_IsSubtype:PyTypeObject*:a:0: +PyType_IsSubtype:PyTypeObject*:b:0: + +PyType_Modified:void::: +PyType_Modified:PyTypeObject*:type:0: + +PyType_Ready:int::: +PyType_Ready:PyTypeObject*:type:0: + +PyUnicode_1BYTE_DATA:Py_UCS1*::: +PyUnicode_1BYTE_DATA:PyObject*:o:0: + PyUnicode_Check:int::: PyUnicode_Check:PyObject*:o:0: -PyUnicode_GET_SIZE:int::: +PyUnicode_CheckExact:int::: +PyUnicode_CheckExact:PyObject*:o:0: + +PyUnicode_DATA:void*::: +PyUnicode_DATA:PyObject*:o:0: + +PyUnicode_GET_LENGTH:Py_ssize_t::: +PyUnicode_GET_LENGTH:PyObject*:o:0: + +PyUnicode_GET_SIZE:Py_ssize_t::: PyUnicode_GET_SIZE:PyObject*:o:0: -PyUnicode_GET_DATA_SIZE:int::: +PyUnicode_GET_DATA_SIZE:Py_ssize_t::: PyUnicode_GET_DATA_SIZE:PyObject*:o:0: +PyUnicode_KIND:int::: +PyUnicode_KIND:PyObject*:o:0: + +PyUnicode_MAX_CHAR_VALUE:::: +PyUnicode_MAX_CHAR_VALUE:PyObject*:o:0: + PyUnicode_AS_UNICODE:Py_UNICODE*::: PyUnicode_AS_UNICODE:PyObject*:o:0: PyUnicode_AS_DATA:const char*::: PyUnicode_AS_DATA:PyObject*:o:0: +Py_UNICODE_ISALNUM:int::: +Py_UNICODE_ISALNUM:Py_UNICODE:ch:: + +Py_UNICODE_ISALPHA:int::: +Py_UNICODE_ISALPHA:Py_UNICODE:ch:: + Py_UNICODE_ISSPACE:int::: Py_UNICODE_ISSPACE:Py_UNICODE:ch:: @@ -1570,6 +2370,9 @@ Py_UNICODE_ISDIGIT:Py_UNICODE:ch:: Py_UNICODE_ISNUMERIC:int::: Py_UNICODE_ISNUMERIC:Py_UNICODE:ch:: +Py_UNICODE_ISPRINTABLE:int::: +Py_UNICODE_ISPRINTABLE:Py_UNICODE:ch:: + Py_UNICODE_TOLOWER:Py_UNICODE::: Py_UNICODE_TOLOWER:Py_UNICODE:ch:: @@ -1590,150 +2393,210 @@ Py_UNICODE_TONUMERIC:Py_UNICODE:ch:: PyUnicode_FromUnicode:PyObject*::+1: PyUnicode_FromUnicode:const Py_UNICODE*:u:: -PyUnicode_FromUnicode:int:size:: +PyUnicode_FromUnicode:Py_ssize_t:size:: PyUnicode_AsUnicode:Py_UNICODE*::: -PyUnicode_AsUnicode:PyObject :*unicode:0: +PyUnicode_AsUnicode:PyObject*:unicode:0: + +PyUnicode_TransformDecimalToASCII:PyObject*::+1: +PyUnicode_TransformDecimalToASCII:Py_UNICODE*:s:: +PyUnicode_TransformDecimalToASCII:Py_ssize_t:size:: + +PyUnicode_AsUnicodeAndSize:Py_UNICODE*::: +PyUnicode_AsUnicodeAndSize:PyObject*:unicode:0: +PyUnicode_AsUnicodeAndSize:Py_ssize_t*:size:: + +PyUnicode_AsUnicodeCopy:Py_UNICODE*::: +PyUnicode_AsUnicodeCopy:PyObject*:unicode:0: -PyUnicode_GetSize:int::: -PyUnicode_GetSize:PyObject :*unicode:0: +PyUnicode_GetSize:Py_ssize_t::: +PyUnicode_GetSize:PyObject*:unicode:0: PyUnicode_FromObject:PyObject*::+1: -PyUnicode_FromObject:PyObject*:*obj:0: +PyUnicode_FromObject:PyObject*:obj:0: PyUnicode_FromEncodedObject:PyObject*::+1: -PyUnicode_FromEncodedObject:PyObject*:*obj:0: +PyUnicode_FromEncodedObject:PyObject*:obj:0: PyUnicode_FromEncodedObject:const char*:encoding:: PyUnicode_FromEncodedObject:const char*:errors:: PyUnicode_FromWideChar:PyObject*::+1: PyUnicode_FromWideChar:const wchar_t*:w:: -PyUnicode_FromWideChar:int:size:: +PyUnicode_FromWideChar:Py_ssize_t:size:: -PyUnicode_AsWideChar:int::: +PyUnicode_AsWideChar:Py_ssize_t::: PyUnicode_AsWideChar:PyObject*:*unicode:0: PyUnicode_AsWideChar:wchar_t*:w:: -PyUnicode_AsWideChar:int:size:: +PyUnicode_AsWideChar:Pyssize_t:size:: + +PyUnicode_AsWideCharString:wchar_t*::: +PyUnicode_AsWideCharString:PyObject*:unicode:0: +PyUnicode_AsWideCharString:Py_ssize_t*:size:: PyUnicode_Decode:PyObject*::+1: PyUnicode_Decode:const char*:s:: -PyUnicode_Decode:int:size:: +PyUnicode_Decode:Py_ssize_t:size:: PyUnicode_Decode:const char*:encoding:: PyUnicode_Decode:const char*:errors:: PyUnicode_DecodeUTF16Stateful:PyObject*::+1: PyUnicode_DecodeUTF16Stateful:const char*:s:: -PyUnicode_DecodeUTF16Stateful:int:size:: +PyUnicode_DecodeUTF16Stateful:Py_ssize_t:size:: PyUnicode_DecodeUTF16Stateful:const char*:errors:: PyUnicode_DecodeUTF16Stateful:int*:byteorder:: -PyUnicode_DecodeUTF16Stateful:int*:consumed:: +PyUnicode_DecodeUTF16Stateful:Py_ssize_t*:consumed:: PyUnicode_DecodeUTF8Stateful:PyObject*::+1: PyUnicode_DecodeUTF8Stateful:const char*:s:: -PyUnicode_DecodeUTF8Stateful:int:size:: +PyUnicode_DecodeUTF8Stateful:Py_ssize_t:size:: PyUnicode_DecodeUTF8Stateful:const char*:errors:: -PyUnicode_DecodeUTF8Stateful:int*:consumed:: +PyUnicode_DecodeUTF8Stateful:Py_ssize_t*:consumed:: PyUnicode_Encode:PyObject*::+1: PyUnicode_Encode:const Py_UNICODE*:s:: -PyUnicode_Encode:int:size:: +PyUnicode_Encode:Py_ssize_t:size:: PyUnicode_Encode:const char*:encoding:: PyUnicode_Encode:const char*:errors:: PyUnicode_AsEncodedString:PyObject*::+1: -PyUnicode_AsEncodedString:PyObject*:unicode:: +PyUnicode_AsEncodedString:PyObject*:unicode:0: PyUnicode_AsEncodedString:const char*:encoding:: PyUnicode_AsEncodedString:const char*:errors:: +PyUnicode_DecodeUTF7:PyObject*::+1: +PyUnicode_DecodeUTF7:const char*:s:: +PyUnicode_DecodeUTF7:Py_ssize_t:size:: +PyUnicode_DecodeUTF7:const char*:errors:: + +PyUnicode_DecodeUTF7Stateful:PyObject*::+1: +PyUnicode_DecodeUTF7Stateful:const char*:s:: +PyUnicode_DecodeUTF7Stateful:Py_ssize_t:size:: +PyUnicode_DecodeUTF7Stateful:const char*:errors:: +PyUnicode_DecodeUTF7Stateful:Py_ssize_t*:consumed:: + +PyUnicode_EncodeUTF7:PyObject*::+1: +PyUnicode_EncodeUTF7:const Py_UNICODE*:s:: +PyUnicode_EncodeUTF7:Py_ssize_t:size:: +PyUnicode_EncodeUTF7:int:base64SetO:: +PyUnicode_EncodeUTF7:int:base64WhiteSpace:: +PyUnicode_EncodeUTF7:const char*:errors:: + PyUnicode_DecodeUTF8:PyObject*::+1: PyUnicode_DecodeUTF8:const char*:s:: -PyUnicode_DecodeUTF8:int:size:: +PyUnicode_DecodeUTF8:Py_ssize_t:size:: PyUnicode_DecodeUTF8:const char*:errors:: PyUnicode_EncodeUTF8:PyObject*::+1: PyUnicode_EncodeUTF8:const Py_UNICODE*:s:: -PyUnicode_EncodeUTF8:int:size:: +PyUnicode_EncodeUTF8:Py_ssize_t:size:: PyUnicode_EncodeUTF8:const char*:errors:: PyUnicode_AsUTF8String:PyObject*::+1: -PyUnicode_AsUTF8String:PyObject*:unicode:: +PyUnicode_AsUTF8String:PyObject*:unicode:0: + +PyUnicode_AsUTF8AndSize:const char*::: +PyUnicode_AsUTF8AndSize:PyObject*:unicode:0: +PyUnicode_AsUTF8AndSize:Py_ssize_t*:size:0: + +PyUnicode_AsUTF8:const char*::: +PyUnicode_AsUTF8:PyObject*:unicode:0: PyUnicode_DecodeUTF16:PyObject*::+1: PyUnicode_DecodeUTF16:const char*:s:: -PyUnicode_DecodeUTF16:int:size:: +PyUnicode_DecodeUTF16:Py_ssize_t:size:: PyUnicode_DecodeUTF16:const char*:errors:: PyUnicode_DecodeUTF16:int*:byteorder:: PyUnicode_EncodeUTF16:PyObject*::+1: PyUnicode_EncodeUTF16:const Py_UNICODE*:s:: -PyUnicode_EncodeUTF16:int:size:: +PyUnicode_EncodeUTF16:Py_ssize_t:size:: PyUnicode_EncodeUTF16:const char*:errors:: PyUnicode_EncodeUTF16:int:byteorder:: PyUnicode_AsUTF16String:PyObject*::+1: -PyUnicode_AsUTF16String:PyObject*:unicode:: +PyUnicode_AsUTF16String:PyObject*:unicode:0: + +PyUnicode_DecodeUTF32:PyObject*::+1: +PyUnicode_DecodeUTF32:const char*:s:: +PyUnicode_DecodeUTF32:Py_ssize_t:size:: +PyUnicode_DecodeUTF32:const char*:errors:: +PyUnicode_DecodeUTF32:int*:byteorder:: + +PyUnicode_DecodeUTF32Stateful:PyObject*::+1: +PyUnicode_DecodeUTF32Stateful:const char*:s:: +PyUnicode_DecodeUTF32Stateful:Py_ssize_t:size:: +PyUnicode_DecodeUTF32Stateful:const char*:errors:: +PyUnicode_DecodeUTF32Stateful:int*:byteorder:: +PyUnicode_DecodeUTF32Stateful:Py_ssize_t*:consumed:: + +PyUnicode_AsUTF32String:PyObject*::+1: +PyUnicode_AsUTF32String:PyObject*:unicode:0: + +PyUnicode_EncodeUTF32:PyObject*::+1: +PyUnicode_EncodeUTF32:const Py_UNICODE*:s:: +PyUnicode_EncodeUTF32:Py_ssize_t:size:: +PyUnicode_EncodeUTF32:const char*:errors:: +PyUnicode_EncodeUTF32:int:byteorder:: PyUnicode_DecodeUnicodeEscape:PyObject*::+1: PyUnicode_DecodeUnicodeEscape:const char*:s:: -PyUnicode_DecodeUnicodeEscape:int:size:: +PyUnicode_DecodeUnicodeEscape:Py_ssize_t:size:: PyUnicode_DecodeUnicodeEscape:const char*:errors:: PyUnicode_EncodeUnicodeEscape:PyObject*::+1: PyUnicode_EncodeUnicodeEscape:const Py_UNICODE*:s:: -PyUnicode_EncodeUnicodeEscape:int:size:: -PyUnicode_EncodeUnicodeEscape:const char*:errors:: +PyUnicode_EncodeUnicodeEscape:Py_ssize_t:size:: PyUnicode_AsUnicodeEscapeString:PyObject*::+1: -PyUnicode_AsUnicodeEscapeString:PyObject*:unicode:: +PyUnicode_AsUnicodeEscapeString:PyObject*:unicode:0: PyUnicode_DecodeRawUnicodeEscape:PyObject*::+1: PyUnicode_DecodeRawUnicodeEscape:const char*:s:: -PyUnicode_DecodeRawUnicodeEscape:int:size:: +PyUnicode_DecodeRawUnicodeEscape:Py_ssize_t:size:: PyUnicode_DecodeRawUnicodeEscape:const char*:errors:: PyUnicode_EncodeRawUnicodeEscape:PyObject*::+1: PyUnicode_EncodeRawUnicodeEscape:const Py_UNICODE*:s:: -PyUnicode_EncodeRawUnicodeEscape:int:size:: -PyUnicode_EncodeRawUnicodeEscape:const char*:errors:: +PyUnicode_EncodeRawUnicodeEscape:Py_ssize_t:size:: PyUnicode_AsRawUnicodeEscapeString:PyObject*::+1: -PyUnicode_AsRawUnicodeEscapeString:PyObject*:unicode:: +PyUnicode_AsRawUnicodeEscapeString:PyObject*:unicode:0: PyUnicode_DecodeLatin1:PyObject*::+1: PyUnicode_DecodeLatin1:const char*:s:: -PyUnicode_DecodeLatin1:int:size:: +PyUnicode_DecodeLatin1:Py_ssize_t:size:: PyUnicode_DecodeLatin1:const char*:errors:: PyUnicode_EncodeLatin1:PyObject*::+1: PyUnicode_EncodeLatin1:const Py_UNICODE*:s:: -PyUnicode_EncodeLatin1:int:size:: +PyUnicode_EncodeLatin1:Py_ssize_t:size:: PyUnicode_EncodeLatin1:const char*:errors:: PyUnicode_AsLatin1String:PyObject*::+1: -PyUnicode_AsLatin1String:PyObject*:unicode:: +PyUnicode_AsLatin1String:PyObject*:unicode:0: PyUnicode_DecodeASCII:PyObject*::+1: PyUnicode_DecodeASCII:const char*:s:: -PyUnicode_DecodeASCII:int:size:: +PyUnicode_DecodeASCII:Py_ssize_t:size:: PyUnicode_DecodeASCII:const char*:errors:: PyUnicode_EncodeASCII:PyObject*::+1: PyUnicode_EncodeASCII:const Py_UNICODE*:s:: -PyUnicode_EncodeASCII:int:size:: +PyUnicode_EncodeASCII:Py_ssize_t:size:: PyUnicode_EncodeASCII:const char*:errors:: PyUnicode_AsASCIIString:PyObject*::+1: -PyUnicode_AsASCIIString:PyObject*:unicode:: +PyUnicode_AsASCIIString:PyObject*:unicode:0: PyUnicode_DecodeCharmap:PyObject*::+1: PyUnicode_DecodeCharmap:const char*:s:: -PyUnicode_DecodeCharmap:int:size:: +PyUnicode_DecodeCharmap:Py_ssize_t:size:: PyUnicode_DecodeCharmap:PyObject*:mapping:0: PyUnicode_DecodeCharmap:const char*:errors:: PyUnicode_EncodeCharmap:PyObject*::+1: PyUnicode_EncodeCharmap:const Py_UNICODE*:s:: -PyUnicode_EncodeCharmap:int:size:: +PyUnicode_EncodeCharmap:Py_ssize_t:size:: PyUnicode_EncodeCharmap:PyObject*:mapping:0: PyUnicode_EncodeCharmap:const char*:errors:: @@ -1743,22 +2606,33 @@ PyUnicode_AsCharmapString:PyObject*:mapping:0: PyUnicode_TranslateCharmap:PyObject*::+1: PyUnicode_TranslateCharmap:const Py_UNICODE*:s:: -PyUnicode_TranslateCharmap:int:size:: -PyUnicode_TranslateCharmap:PyObject*:table:0: +PyUnicode_TranslateCharmap:Py_ssize_t:size:: +PyUnicode_TranslateCharmap:PyObject*:mapping:0: PyUnicode_TranslateCharmap:const char*:errors:: PyUnicode_DecodeMBCS:PyObject*::+1: PyUnicode_DecodeMBCS:const char*:s:: -PyUnicode_DecodeMBCS:int:size:: +PyUnicode_DecodeMBCS:Py_ssize_t:size:: PyUnicode_DecodeMBCS:const char*:errors:: +PyUnicode_DecodeMBCSStateful:PyObject*::+1: +PyUnicode_DecodeMBCSStateful:const char*:s:: +PyUnicode_DecodeMBCSStateful:Py_ssize_t:size:: +PyUnicode_DecodeMBCSStateful:const char*:errors:: +PyUnicode_DecodeMBCSStateful:Py_ssize_t*:consumed:: + +PyUnicode_EncodeCodePage:PyObject*::+1: +PyUnicode_EncodeCodePage:int:code_page:: +PyUnicode_EncodeCodePage:PyObject*:unicode:0: +PyUnicode_EncodeCodePage:const char*:errors:: + PyUnicode_EncodeMBCS:PyObject*::+1: PyUnicode_EncodeMBCS:const Py_UNICODE*:s:: -PyUnicode_EncodeMBCS:int:size:: +PyUnicode_EncodeMBCS:Py_ssize_t:size:: PyUnicode_EncodeMBCS:const char*:errors:: PyUnicode_AsMBCSString:PyObject*::+1: -PyUnicode_AsMBCSString:PyObject*:unicode:: +PyUnicode_AsMBCSString:PyObject*:unicode:0: PyUnicode_Concat:PyObject*::+1: PyUnicode_Concat:PyObject*:left:0: @@ -1767,11 +2641,11 @@ PyUnicode_Concat:PyObject*:right:0: PyUnicode_Split:PyObject*::+1: PyUnicode_Split:PyObject*:left:0: PyUnicode_Split:PyObject*:right:0: -PyUnicode_Split:int:maxsplit:: +PyUnicode_Split:Py_ssize_t:maxsplit:: PyUnicode_Splitlines:PyObject*::+1: PyUnicode_Splitlines:PyObject*:s:0: -PyUnicode_Splitlines:int:maxsplit:: +PyUnicode_Splitlines:int:keepend:: PyUnicode_Translate:PyObject*::+1: PyUnicode_Translate:PyObject*:str:0: @@ -1782,36 +2656,52 @@ PyUnicode_Join:PyObject*::+1: PyUnicode_Join:PyObject*:separator:0: PyUnicode_Join:PyObject*:seq:0: -PyUnicode_Tailmatch:int::: +PyUnicode_Tailmatch:Py_ssize_t::: PyUnicode_Tailmatch:PyObject*:str:0: PyUnicode_Tailmatch:PyObject*:substr:0: -PyUnicode_Tailmatch:int:start:: -PyUnicode_Tailmatch:int:end:: +PyUnicode_Tailmatch:Py_ssize_t:start:: +PyUnicode_Tailmatch:Py_ssize_t:end:: PyUnicode_Tailmatch:int:direction:: -PyUnicode_Find:int::: +PyUnicode_Find:Py_ssize_t::: PyUnicode_Find:PyObject*:str:0: PyUnicode_Find:PyObject*:substr:0: -PyUnicode_Find:int:start:: -PyUnicode_Find:int:end:: +PyUnicode_Find:Py_ssize_t:start:: +PyUnicode_Find:Py_ssize_t:end:: PyUnicode_Find:int:direction:: -PyUnicode_Count:int::: +PyUnicode_FindChar:Py_ssize_t::: +PyUnicode_FindChar:PyObject*:str:0: +PyUnicode_FindChar:Py_UCS4:ch:: +PyUnicode_FindChar:Py_ssize_t:start:: +PyUnicode_FindChar:Py_ssize_t:end:: +PyUnicode_FindChar:int:direction:: + +PyUnicode_Count:Py_ssize_t::: PyUnicode_Count:PyObject*:str:0: PyUnicode_Count:PyObject*:substr:0: -PyUnicode_Count:int:start:: -PyUnicode_Count:int:end:: +PyUnicode_Count:Py_ssize_t:start:: +PyUnicode_Count:Py_ssize_t:end:: PyUnicode_Replace:PyObject*::+1: PyUnicode_Replace:PyObject*:str:0: PyUnicode_Replace:PyObject*:substr:0: PyUnicode_Replace:PyObject*:replstr:0: -PyUnicode_Replace:int:maxcount:: +PyUnicode_Replace:Py_ssize_t:maxcount:: PyUnicode_Compare:int::: PyUnicode_Compare:PyObject*:left:0: PyUnicode_Compare:PyObject*:right:0: +PyUnicode_CompareWithASCIIString:int::: +PyUnicode_CompareWithASCIIString:PyObject*:uni:0: +PyUnicode_CompareWithASCIIString:const char*:string:: + +PyUnicode_RichCompare:PyObject*::+1: +PyUnicode_RichCompare:PyObject*:left:0: +PyUnicode_RichCompare:PyObject*:right:0: +PyUnicode_RichCompare:int:op:: + PyUnicode_Format:PyObject*::+1: PyUnicode_Format:PyObject*:format:0: PyUnicode_Format:PyObject*:args:0: @@ -1820,6 +2710,185 @@ PyUnicode_Contains:int::: PyUnicode_Contains:PyObject*:container:0: PyUnicode_Contains:PyObject*:element:0: +PyUnicode_InternInPlace:void::: +PyUnicode_InternInPlace:PyObject**:string:+1: + +PyUnicode_InternFromString:PyObject*::+1: +PyUnicode_InternFromString:const char*:v:: + +PyUnicode_New:PyObject*::+1: +PyUnicode_New:Py_ssize_t:size:: +PyUnicode_New:Py_UCS4:maxchar:: + +PyUnicode_FromKindAndData:PyObject*::+1: +PyUnicode_FromKindAndData:int:kind:: +PyUnicode_FromKindAndData:const void*:buffer:: +PyUnicode_FromKindAndData:Py_ssize_t:size:: + +PyUnicode_FromStringAndSize:PyObject*::+1: +PyUnicode_FromStringAndSize:const char*:u:: +PyUnicode_FromStringAndSize:Py_ssize_t:size:: + +PyUnicode_FromString:PyObject*::+1: +PyUnicode_FromString:const char*:u:: + +PyUnicode_FromFormat:PyObject*::+1: +PyUnicode_FromFormat:const char*:format:: +PyUnicode_FromFormat::...:: + +PyUnicode_FromFormatV:PyObject*::+1: +PyUnicode_FromFormatV:const char*:format:: +PyUnicode_FromFormatV:va_list:args:: + +PyUnicode_GetLength:Py_ssize_t::: +PyUnicode_GetLength:PyObject*:unicode:0: + +PyUnicode_CopyCharacters:Py_ssize_t::: +PyUnicode_CopyCharacters:PyObject*:to:0: +PyUnicode_CopyCharacters:Py_ssize_t:to_start:: +PyUnicode_CopyCharacters:PyObject*:from:0: +PyUnicode_CopyCharacters:Py_ssize_t:from_start:: +PyUnicode_CopyCharacters:Py_ssize_t:how_many:: + +PyUnicode_Fill:Py_ssize_t::: +PyUnicode_Fill:PyObject*:unicode:0: +PyUnicode_Fill:Py_ssize_t:start:: +PyUnicode_Fill:Py_ssize_t:length:: +PyUnicode_Fill:Py_UCS4:fill_char:: + +PyUnicode_READ:Py_UCS4::: +PyUnicode_READ:int:kind:: +PyUnicode_READ:void*:data:: +PyUnicode_READ:Py_ssize_t:index:: + +PyUnicode_READ_CHAR:Py_UCS4::: +PyUnicode_READ_CHAR:PyObject*:o:0: +PyUnicode_READ_CHAR:Py_ssize_t:index:: + +PyUnicode_ReadChar:Py_UCS4::: +PyUnicode_ReadChar:PyObject*:unicode:0: +PyUnicode_ReadChar:Py_ssize_t:index:: + +PyUnicode_WRITE:void::: +PyUnicode_WRITE:int:kind:: +PyUnicode_WRITE:void*:data:: +PyUnicode_WRITE:Py_ssize_t:index:: +PyUnicode_WRITE:Py_UCS4:value:: + +PyUnicode_WriteChar:int::: +PyUnicode_WriteChar:PyObject*:unicode:0: +PyUnicode_WriteChar:Py_ssize_t:index:: +PyUnicode_WriteChar:Py_UCS4:character:: + +PyUnicode_READY:int::: +PyUnicode_READY:PyObject*:o:0: + +PyUnicode_Substring:PyObject*::+1: +PyUnicode_Substring:PyObject*:str:0: +PyUnicode_Substring:Py_ssize_t:start:: +PyUnicode_Substring:Py_ssize_t:end:: + +PyUnicode_AsUCS4:Py_UCS4*::: +PyUnicode_AsUCS4:PyObject*:u:0: +PyUnicode_AsUCS4:Py_UCS4*:buffer:: +PyUnicode_AsUCS4:Py_ssize_t:buflen:: +PyUnicode_AsUCS4:int:copy_null:: + +PyUnicode_AsUCS4Copy:Py_UCS4*::: +PyUnicode_AsUCS4Copy:PyObject*:u:0: + +PyUnicode_DecodeLocaleAndSize:PyObject*::+1: +PyUnicode_DecodeLocaleAndSize:const char*:str:: +PyUnicode_DecodeLocaleAndSize:Py_ssize_t:len:: +PyUnicode_DecodeLocaleAndSize:const char*:errors:: + +PyUnicode_DecodeLocale:PyObject*::+1: +PyUnicode_DecodeLocale:const char*:str:: +PyUnicode_DecodeLocale:const char*:errors:: + +PyUnicode_EncodeLocale:PyObject*::+1: +PyUnicode_EncodeLocale:PyObject*:unicode:0: +PyUnicode_EncodeLocale:const char*:errors:: + +PyUnicode_FSConverter:int::: +PyUnicode_FSConverter:PyObject*:obj:0: +PyUnicode_FSConverter:void*:result:: + +PyUnicode_FSDecoder:int::: +PyUnicode_FSDecoder:PyObject*:obj:0: +PyUnicode_FSDecoder:void*:result:: + +PyUnicode_DecodeFSDefaultAndSize:PyObject*::+1: +PyUnicode_DecodeFSDefaultAndSize:const char*:s:: +PyUnicode_DecodeFSDefaultAndSize:Py_ssize_t:size:: + +PyUnicode_DecodeFSDefault:PyObject*::+1: +PyUnicode_DecodeFSDefault:const char*:s:: + +PyUnicode_EncodeFSDefault:PyObject*::+1: +PyUnicode_EncodeFSDefault:PyObject*:unicode:0: + +PyUnicodeDecodeError_Create:PyObject*::+1: +PyUnicodeDecodeError_Create:const char*:encoding:: +PyUnicodeDecodeError_Create:const char*:object:: +PyUnicodeDecodeError_Create:Py_ssize_t:length:: +PyUnicodeDecodeError_Create:Py_ssize_t:start:: +PyUnicodeDecodeError_Create:Py_ssize_t:end:: +PyUnicodeDecodeError_Create:const char*:reason:: + +PyUnicodeDecodeError_GetEncoding:PyObject*::+1: +PyUnicodeDecodeError_GetEncoding:PyObject*:exc:0: + +PyUnicodeDecodeError_GetEnd:Py_ssize_t::: +PyUnicodeDecodeError_GetEnd:PyObject*:exc:0: +PyUnicodeDecodeError_GetEnd:Py_ssize_t*:end:: + +PyUnicodeDecodeError_GetObject:PyObject*::+1: +PyUnicodeDecodeError_GetObject:PyObject*:exc:0: + +PyUnicodeDecodeError_GetReason:PyObject*::+1: +PyUnicodeDecodeError_GetReason:PyObject*:exc:0: + +PyUnicodeDecodeError_GetStart:Py_ssize_t::: +PyUnicodeDecodeError_GetStart:PyObject*:exc:0: +PyUnicodeDecodeError_GetStart:Py_ssize_t*:start:: + +PyUnicodeDecodeError_SetEnd:int::: +PyUnicodeDecodeError_SetEnd:PyObject*:exc:0: +PyUnicodeDecodeError_SetEnd:Py_ssize_t:end:: + +PyUnicodeDecodeError_SetReason:int::: +PyUnicodeDecodeError_SetReason:PyObject*:exc:0: +PyUnicodeDecodeError_SetReason:const char*:reason:: + +PyUnicodeDecodeError_SetStart:int::: +PyUnicodeDecodeError_SetStart:PyObject*:exc:0: +PyUnicodeDecodeError_SetStart:Py_ssize_t:start:: + +PyUnicodeEncodeError_Create:PyObject*::+1: +PyUnicodeEncodeError_Create:const char*:encoding:: +PyUnicodeEncodeError_Create:const Py_UNICODE*:object:: +PyUnicodeEncodeError_Create:Py_ssize_t:length:: +PyUnicodeEncodeError_Create:Py_ssize_t:start:: +PyUnicodeEncodeError_Create:Py_ssize_t:end:: +PyUnicodeEncodeError_Create:const char*:reason:: + +PyUnicodeTranslateError_Create:PyObject*::+1: +PyUnicodeTranslateError_Create:const Py_UNICODE*:object:: +PyUnicodeTranslateError_Create:Py_ssize_t:length:: +PyUnicodeTranslateError_Create:Py_ssize_t:start:: +PyUnicodeTranslateError_Create:Py_ssize_t:end:: +PyUnicodeTranslateError_Create:const char*:reason:: + +PyWeakref_Check:int::: +PyWeakref_Check:PyObject*:ob:: + +PyWeakref_CheckProxy:int::: +PyWeakref_CheckProxy:PyObject*:ob:: + +PyWeakref_CheckRef:int::: +PyWeakref_CheckRef:PyObject*:ob:: + PyWeakref_GET_OBJECT:PyObject*::0: PyWeakref_GET_OBJECT:PyObject*:ref:0: @@ -1843,18 +2912,40 @@ Py_AtExit:void (*)():func:: Py_BuildValue:PyObject*::+1: Py_BuildValue:const char*:format:: +Py_BuildValue::...:: + +Py_VaBuildValue:PyObject*::+1: +Py_VaBuildValue:const char*:format:: +Py_VaBuildValue:va_list:vargs:: + +Py_CLEAR:void::: +Py_CLEAR:PyObject*:o:-1: Py_CompileString:PyObject*::+1: Py_CompileString:const char*:str:: Py_CompileString:const char*:filename:: Py_CompileString:int:start:: +Py_CompileStringExFlags:PyObject*::+1: +Py_CompileStringExFlags:const char*:str:: +Py_CompileStringExFlags:const char*:filename:: +Py_CompileStringExFlags:int:start:: +Py_CompileStringExFlags:PyCompilerFlags*:flags:: +Py_CompileStringExFlags:int:optimize:: + Py_CompileStringFlags:PyObject*::+1: Py_CompileStringFlags:const char*:str:: Py_CompileStringFlags:const char*:filename:: Py_CompileStringFlags:int:start:: Py_CompileStringFlags:PyCompilerFlags*:flags:: +Py_CompileStringObject:PyObject*::+1: +Py_CompileStringObject:const char*:str:: +Py_CompileStringObject:PyObject*:filename:0: +Py_CompileStringObject:int:start:: +Py_CompileStringObject:PyCompilerFlags*:flags:: +Py_CompileStringObject:int:optimize:: + Py_DECREF:void::: Py_DECREF:PyObject*:o:-1: @@ -1873,25 +2964,25 @@ Py_FdIsInteractive:const char*:filename:: Py_Finalize:void::: -Py_GetBuildInfoconst:const char*::: +Py_GetBuildInfo:const char*::: -Py_GetCompilerconst:const char*::: +Py_GetCompiler:const char*::: -Py_GetCopyrightconst:const char*::: +Py_GetCopyright:const char*::: -Py_GetExecPrefix:const char*::: +Py_GetExecPrefix:wchar_t*::: -Py_GetPath:const char*::: +Py_GetPath:wchar_t*::: -Py_GetPlatformconst:const char*::: +Py_GetPlatform:const char*::: -Py_GetPrefix:const char*::: +Py_GetPrefix:wchar_t*::: -Py_GetProgramFullPath:const char*::: +Py_GetProgramFullPath:wchar_t*::: -Py_GetProgramName:const char*::: +Py_GetProgramName:wchar_t*::: -Py_GetVersionconst:const char*::: +Py_GetVersion:const char*::: Py_INCREF:void::: Py_INCREF:PyObject*:o:+1: @@ -1902,8 +2993,14 @@ Py_IsInitialized:int::: Py_NewInterpreter:PyThreadState*::: +Py_ReprEnter:int::: +Py_ReprEnter:PyObject*:object:+1: + +Py_ReprLeave:void::: +Py_ReprLeave:PyObject*:object:-1: + Py_SetProgramName:void::: -Py_SetProgramName:const char*:name:: +Py_SetProgramName:const wchar_t*:name:: Py_XDECREF:void::: Py_XDECREF:PyObject*:o:-1:if o is not NULL @@ -1911,32 +3008,24 @@ Py_XDECREF:PyObject*:o:-1:if o is not NULL Py_XINCREF:void::: Py_XINCREF:PyObject*:o:+1:if o is not NULL -_PyImport_FindExtension:PyObject*::0:??? see PyImport_AddModule -_PyImport_FindExtension:const char*::: -_PyImport_FindExtension:const char*::: - _PyImport_Fini:void::: -_PyImport_FixupExtension:PyObject*:::??? -_PyImport_FixupExtension:const char*::: -_PyImport_FixupExtension:const char*::: - _PyImport_Init:void::: _PyObject_New:PyObject*::+1: _PyObject_New:PyTypeObject*:type:0: -_PyObject_NewVar:PyObject*::+1: +_PyObject_NewVar:PyVarObject*::+1: _PyObject_NewVar:PyTypeObject*:type:0: -_PyObject_NewVar:int:size:: +_PyObject_NewVar:Py_ssize_t:size:: -_PyString_Resize:int::: -_PyString_Resize:PyObject**:string:+1: -_PyString_Resize:int:newsize:: +_PyBytes_Resize:int::: +_PyBytes_Resize:PyObject**:bytes:0: +_PyBytes_Resize:Py_ssize_t:newsize:: _PyTuple_Resize:int::: -_PyTuple_Resize:PyTupleObject**:p:+1: -_PyTuple_Resize:int:new:: +_PyTuple_Resize:PyObject**:p:0: +_PyTuple_Resize:Py_ssize_t:new:: _Py_c_diff:Py_complex::: _Py_c_diff:Py_complex:left:: diff --git a/Doc/distutils/setupscript.rst b/Doc/distutils/setupscript.rst index c1051d2e..54ed1aeb 100644 --- a/Doc/distutils/setupscript.rst +++ b/Doc/distutils/setupscript.rst @@ -524,20 +524,23 @@ following way:: setup(..., data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']), ('config', ['cfg/data.cfg']), - ('/etc/init.d', ['init-script'])] ) -Note that you can specify the directory names where the data files will be -installed, but you cannot rename the data files themselves. - Each (*directory*, *files*) pair in the sequence specifies the installation -directory and the files to install there. If *directory* is a relative path, it -is interpreted relative to the installation prefix (Python's ``sys.prefix`` for -pure-Python packages, ``sys.exec_prefix`` for packages that contain extension -modules). Each file name in *files* is interpreted relative to the -:file:`setup.py` script at the top of the package source distribution. No -directory information from *files* is used to determine the final location of -the installed file; only the name of the file is used. +directory and the files to install there. + +Each file name in *files* is interpreted relative to the :file:`setup.py` +script at the top of the package source distribution. Note that you can +specify the directory where the data files will be installed, but you cannot +rename the data files themselves. + +The *directory* should be a relative path. It is interpreted relative to the +installation prefix (Python's ``sys.prefix`` for system installations; +``site.USER_BASE`` for user installations). Distutils allows *directory* to be +an absolute installation path, but this is discouraged since it is +incompatible with the wheel packaging format. No directory information from +*files* is used to determine the final location of the installed file; only +the name of the file is used. You can specify the ``data_files`` options as a simple sequence of files without specifying a target directory, but this is not recommended, and the diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index 90fd69e7..7ee340d7 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -268,14 +268,8 @@ Python references; or perhaps search for "Python" and "language". Where in the world is www.python.org located? --------------------------------------------- -The Python project's infrastructure is located all over the world. -`www.python.org `_ is graciously hosted by `Rackspace -`_, with CDN caching provided by `Fastly -`_. `Upfront Systems -`_ hosts `bugs.python.org -`_. Many other Python services like `the Wiki -`_ are hosted by `Oregon State -University Open Source Lab `_. +The Python project's infrastructure is located all over the world and is managed +by the Python Infrastructure Team. Details `here `__. Why is it called Python? diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index fd720c1a..31614189 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -738,7 +738,7 @@ Is it possible to write obfuscated one-liners in Python? -------------------------------------------------------- Yes. Usually this is done by nesting :keyword:`lambda` within -:keyword:`lambda`. See the following three examples, due to Ulf Bartelt:: +:keyword:`!lambda`. See the following three examples, due to Ulf Bartelt:: from functools import reduce @@ -767,6 +767,41 @@ Yes. Usually this is done by nesting :keyword:`lambda` within Don't try this at home, kids! +.. _faq-positional-only-arguments: + +What does the slash(/) in the parameter list of a function mean? +---------------------------------------------------------------- + +A slash in the argument list of a function denotes that the parameters prior to +it are positional-only. Positional-only parameters are the ones without an +externally-usable name. Upon calling a function that accepts positional-only +parameters, arguments are mapped to parameters based solely on their position. +For example, :func:`pow` is a function that accepts positional-only parameters. +Its documentation looks like this:: + + >>> help(pow) + Help on built-in function pow in module builtins: + + pow(x, y, z=None, /) + Equivalent to x**y (with two arguments) or x**y % z (with three arguments) + + Some types, such as ints, are able to use a more efficient algorithm when + invoked using the three argument form. + +The slash at the end of the parameter list means that all three parameters are +positional-only. Thus, calling :func:`pow` with keyword aguments would lead to +an error:: + + >>> pow(x=3, y=4) + Traceback (most recent call last): + File "", line 1, in + TypeError: pow() takes no keyword arguments + +Note that as of this writing this is only documentational and no valid syntax +in Python, although there is :pep:`570`, which proposes a syntax for +position-only parameters in Python. + + Numbers and strings =================== @@ -1317,9 +1352,6 @@ The ``__iadd__`` succeeds, and thus the list is extended, but even though that final assignment still results in an error, because tuples are immutable. -Dictionaries -============ - I want to do a complicated sort: can you do a Schwartzian Transform in Python? ------------------------------------------------------------------------------ diff --git a/Doc/glossary.rst b/Doc/glossary.rst index b8d98dd3..fb8ff2a7 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -332,7 +332,7 @@ Glossary names, attribute access, operators or function calls which all return a value. In contrast to many other languages, not all language constructs are expressions. There are also :term:`statement`\s which cannot be used - as expressions, such as :keyword:`if`. Assignments are also statements, + as expressions, such as :keyword:`while`. Assignments are also statements, not expressions. extension module @@ -444,8 +444,8 @@ Glossary generator expression An expression that returns an iterator. It looks like a normal expression - followed by a :keyword:`for` expression defining a loop variable, range, - and an optional :keyword:`if` expression. The combined expression + followed by a :keyword:`!for` clause defining a loop variable, range, + and an optional :keyword:`!if` clause. The combined expression generates values for an enclosing function:: >>> sum(i*i for i in range(10)) # sum of squares 0, 1, 4, ... 81 diff --git a/Doc/howto/functional.rst b/Doc/howto/functional.rst index 2efe4537..f8f2aac7 100644 --- a/Doc/howto/functional.rst +++ b/Doc/howto/functional.rst @@ -1108,7 +1108,7 @@ need to define a new function at all:: existing_files = filter(os.path.exists, file_list) If the function you need doesn't exist, you need to write it. One way to write -small functions is to use the :keyword:`lambda` statement. ``lambda`` takes a +small functions is to use the :keyword:`lambda` expression. ``lambda`` takes a number of parameters and an expression combining these parameters, and creates an anonymous function that returns the value of the expression:: diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index b1930a79..e391506c 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -186,7 +186,7 @@ previous simple module-based configuration example:: # 'application' code logger.debug('debug message') logger.info('info message') - logger.warn('warn message') + logger.warning('warn message') logger.error('error message') logger.critical('critical message') @@ -295,7 +295,7 @@ Here is an example of a module using the logging configuration server:: while True: logger.debug('debug message') logger.info('info message') - logger.warn('warn message') + logger.warning('warn message') logger.error('error message') logger.critical('critical message') time.sleep(5) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index 2a2282e9..7a68ca89 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -610,7 +610,7 @@ logger, a console handler, and a simple formatter using Python code:: # 'application' code logger.debug('debug message') logger.info('info message') - logger.warn('warn message') + logger.warning('warn message') logger.error('error message') logger.critical('critical message') @@ -640,7 +640,7 @@ the names of the objects:: # 'application' code logger.debug('debug message') logger.info('info message') - logger.warn('warn message') + logger.warning('warn message') logger.error('error message') logger.critical('critical message') @@ -695,15 +695,15 @@ noncoders to easily modify the logging properties. .. warning:: The :func:`fileConfig` function takes a default parameter, ``disable_existing_loggers``, which defaults to ``True`` for reasons of backward compatibility. This may or may not be what you want, since it - will cause any loggers existing before the :func:`fileConfig` call to - be disabled unless they (or an ancestor) are explicitly named in the - configuration. Please refer to the reference documentation for more + will cause any non-root loggers existing before the :func:`fileConfig` + call to be disabled unless they (or an ancestor) are explicitly named in + the configuration. Please refer to the reference documentation for more information, and specify ``False`` for this parameter if you wish. The dictionary passed to :func:`dictConfig` can also specify a Boolean value with key ``disable_existing_loggers``, which if not specified explicitly in the dictionary also defaults to being interpreted as - ``True``. This leads to the logger-disabling behaviour described above, + ``True``. This leads to the logger-disabling behaviour described above, which may not be what you want - in which case, provide the key explicitly with a value of ``False``. @@ -802,7 +802,7 @@ the best default behaviour. If for some reason you *don't* want these messages printed in the absence of any logging configuration, you can attach a do-nothing handler to the top-level logger for your library. This avoids the message being printed, since a handler -will be always be found for the library's events: it just doesn't produce any +will always be found for the library's events: it just doesn't produce any output. If the library user configures logging for application use, presumably that configuration will add some handlers, and if levels are suitably configured then logging calls made in library code will send output to those diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index b09f748a..d385d991 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -96,8 +96,9 @@ special nature. You can match the characters not listed within the class by :dfn:`complementing` the set. This is indicated by including a ``'^'`` as the first character of the -class; ``'^'`` outside a character class will simply match the ``'^'`` -character. For example, ``[^5]`` will match any character except ``'5'``. +class. For example, ``[^5]`` will match any character except ``'5'``. If the +caret appears elsewhere in a character class, it does not have special meaning. +For example: ``[5^]`` will match either a ``'5'`` or a ``'^'``. Perhaps the most important metacharacter is the backslash, ``\``. As in Python string literals, the backslash can be followed by various characters to signal diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst index be1fefb3..5339bf45 100644 --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -6,95 +6,48 @@ :Release: 1.12 -This HOWTO discusses Python support for Unicode, and explains -various problems that people commonly encounter when trying to work -with Unicode. +This HOWTO discusses Python's support for the Unicode specification +for representing textual data, and explains various problems that +people commonly encounter when trying to work with Unicode. + Introduction to Unicode ======================= -History of Character Codes --------------------------- - -In 1968, the American Standard Code for Information Interchange, better known by -its acronym ASCII, was standardized. ASCII defined numeric codes for various -characters, with the numeric values running from 0 to 127. For example, the -lowercase letter 'a' is assigned 97 as its code value. - -ASCII was an American-developed standard, so it only defined unaccented -characters. There was an 'e', but no 'é' or 'Í'. This meant that languages -which required accented characters couldn't be faithfully represented in ASCII. -(Actually the missing accents matter for English, too, which contains words such -as 'naïve' and 'café', and some publications have house styles which require -spellings such as 'coöperate'.) - -For a while people just wrote programs that didn't display accents. -In the mid-1980s an Apple II BASIC program written by a French speaker -might have lines like these: - -.. code-block:: basic - - PRINT "MISE A JOUR TERMINEE" - PRINT "PARAMETRES ENREGISTRES" - -Those messages should contain accents (terminée, paramètre, enregistrés) and -they just look wrong to someone who can read French. - -In the 1980s, almost all personal computers were 8-bit, meaning that bytes could -hold values ranging from 0 to 255. ASCII codes only went up to 127, so some -machines assigned values between 128 and 255 to accented characters. Different -machines had different codes, however, which led to problems exchanging files. -Eventually various commonly used sets of values for the 128--255 range emerged. -Some were true standards, defined by the International Organization for -Standardization, and some were *de facto* conventions that were invented by one -company or another and managed to catch on. - -255 characters aren't very many. For example, you can't fit both the accented -characters used in Western Europe and the Cyrillic alphabet used for Russian -into the 128--255 range because there are more than 128 such characters. - -You could write files using different codes (all your Russian files in a coding -system called KOI8, all your French files in a different coding system called -Latin1), but what if you wanted to write a French document that quotes some -Russian text? In the 1980s people began to want to solve this problem, and the -Unicode standardization effort began. - -Unicode started out using 16-bit characters instead of 8-bit characters. 16 -bits means you have 2^16 = 65,536 distinct values available, making it possible -to represent many different characters from many different alphabets; an initial -goal was to have Unicode contain the alphabets for every single human language. -It turns out that even 16 bits isn't enough to meet that goal, and the modern -Unicode specification uses a wider range of codes, 0 through 1,114,111 ( -``0x10FFFF`` in base 16). - -There's a related ISO standard, ISO 10646. Unicode and ISO 10646 were -originally separate efforts, but the specifications were merged with the 1.1 -revision of Unicode. - -(This discussion of Unicode's history is highly simplified. The -precise historical details aren't necessary for understanding how to -use Unicode effectively, but if you're curious, consult the Unicode -consortium site listed in the References or -the `Wikipedia entry for Unicode `_ -for more information.) - - Definitions ----------- +Today's programs need to be able to handle a wide variety of +characters. Applications are often internationalized to display +messages and output in a variety of user-selectable languages; the +same program might need to output an error message in English, French, +Japanese, Hebrew, or Russian. Web content can be written in any of +these languages and can also include a variety of emoji symbols. +Python's string type uses the Unicode Standard for representing +characters, which lets Python programs work with all these different +possible characters. + +Unicode (https://www.unicode.org/) is a specification that aims to +list every character used by human languages and give each character +its own unique code. The Unicode specifications are continually +revised and updated to add new languages and symbols. + A **character** is the smallest possible component of a text. 'A', 'B', 'C', -etc., are all different characters. So are 'È' and 'Í'. Characters are -abstractions, and vary depending on the language or context you're talking -about. For example, the symbol for ohms (Ω) is usually drawn much like the -capital letter omega (Ω) in the Greek alphabet (they may even be the same in -some fonts), but these are two different characters that have different -meanings. - -The Unicode standard describes how characters are represented by **code -points**. A code point is an integer value, usually denoted in base 16. In the -standard, a code point is written using the notation ``U+12CA`` to mean the -character with value ``0x12ca`` (4,810 decimal). The Unicode standard contains -a lot of tables listing characters and their corresponding code points: +etc., are all different characters. So are 'È' and 'Í'. Characters vary +depending on the language or context you're talking +about. For example, there's a character for "Roman Numeral One", 'Ⅰ', that's +separate from the uppercase letter 'I'. They'll usually look the same, +but these are two different characters that have different meanings. + +The Unicode standard describes how characters are represented by +**code points**. A code point value is an integer in the range 0 to +0x10FFFF (about 1.1 million values, with some 110 thousand assigned so +far). In the standard and in this document, a code point is written +using the notation ``U+265E`` to mean the character with value +``0x265e`` (9,822 in decimal). + +The Unicode standard contains a lot of tables listing characters and +their corresponding code points: .. code-block:: none @@ -103,10 +56,21 @@ a lot of tables listing characters and their corresponding code points: 0063 'c'; LATIN SMALL LETTER C ... 007B '{'; LEFT CURLY BRACKET + ... + 2167 'Ⅶ': ROMAN NUMERAL EIGHT + 2168 'Ⅸ': ROMAN NUMERAL NINE + ... + 265E '♞': BLACK CHESS KNIGHT + 265F '♟': BLACK CHESS PAWN + ... + 1F600 '😀': GRINNING FACE + 1F609 '😉': WINKING FACE + ... Strictly, these definitions imply that it's meaningless to say 'this is -character ``U+12CA``'. ``U+12CA`` is a code point, which represents some particular -character; in this case, it represents the character 'ETHIOPIC SYLLABLE WI'. In +character ``U+265E``'. ``U+265E`` is a code point, which represents some particular +character; in this case, it represents the character 'BLACK CHESS KNIGHT', +'♞'. In informal contexts, this distinction between code points and characters will sometimes be forgotten. @@ -121,14 +85,17 @@ toolkit or a terminal's font renderer. Encodings --------- -To summarize the previous section: a Unicode string is a sequence of code -points, which are numbers from 0 through ``0x10FFFF`` (1,114,111 decimal). This -sequence needs to be represented as a set of bytes (meaning, values -from 0 through 255) in memory. The rules for translating a Unicode string -into a sequence of bytes are called an **encoding**. +To summarize the previous section: a Unicode string is a sequence of +code points, which are numbers from 0 through ``0x10FFFF`` (1,114,111 +decimal). This sequence of code points needs to be represented in +memory as a set of **code units**, and **code units** are then mapped +to 8-bit bytes. The rules for translating a Unicode string into a +sequence of bytes are called a **character encoding**, or just +an **encoding**. -The first encoding you might think of is an array of 32-bit integers. In this -representation, the string "Python" would look like this: +The first encoding you might think of is using 32-bit integers as the +code unit, and then using the CPU's representation of 32-bit integers. +In this representation, the string "Python" might look like this: .. code-block:: none @@ -152,40 +119,14 @@ problems. 3. It's not compatible with existing C functions such as ``strlen()``, so a new family of wide string functions would need to be used. -4. Many Internet standards are defined in terms of textual data, and can't - handle content with embedded zero bytes. - -Generally people don't use this encoding, instead choosing other -encodings that are more efficient and convenient. UTF-8 is probably -the most commonly supported encoding; it will be discussed below. - -Encodings don't have to handle every possible Unicode character, and most -encodings don't. The rules for converting a Unicode string into the ASCII -encoding, for example, are simple; for each code point: - -1. If the code point is < 128, each byte is the same as the value of the code - point. +Therefore this encoding isn't used very much, and people instead choose other +encodings that are more efficient and convenient, such as UTF-8. -2. If the code point is 128 or greater, the Unicode string can't be represented - in this encoding. (Python raises a :exc:`UnicodeEncodeError` exception in this - case.) - -Latin-1, also known as ISO-8859-1, is a similar encoding. Unicode code points -0--255 are identical to the Latin-1 values, so converting to this encoding simply -requires converting code points to byte values; if a code point larger than 255 -is encountered, the string can't be encoded into Latin-1. - -Encodings don't have to be simple one-to-one mappings like Latin-1. Consider -IBM's EBCDIC, which was used on IBM mainframes. Letter values weren't in one -block: 'a' through 'i' had values from 129 to 137, but 'j' through 'r' were 145 -through 153. If you wanted to use EBCDIC as an encoding, you'd probably use -some sort of lookup table to perform the conversion, but this is largely an -internal detail. - -UTF-8 is one of the most commonly used encodings. UTF stands for "Unicode -Transformation Format", and the '8' means that 8-bit numbers are used in the -encoding. (There are also a UTF-16 and UTF-32 encodings, but they are less -frequently used than UTF-8.) UTF-8 uses the following rules: +UTF-8 is one of the most commonly used encodings, and Python often +defaults to using it. UTF stands for "Unicode Transformation Format", +and the '8' means that 8-bit values are used in the encoding. (There +are also UTF-16 and UTF-32 encodings, but they are less frequently +used than UTF-8.) UTF-8 uses the following rules: 1. If the code point is < 128, it's represented by the corresponding byte value. 2. If the code point is >= 128, it's turned into a sequence of two, three, or @@ -215,6 +156,10 @@ glossary, and PDF versions of the Unicode specification. Be prepared for some difficult reading. `A chronology `_ of the origin and development of Unicode is also available on the site. +On the Computerphile Youtube channel, Tom Scott briefly +`discusses the history of Unicode and UTF-8 ` +(9 minutes 36 seconds). + To help understand the standard, Jukka Korpela has written `an introductory guide `_ to reading the Unicode character tables. @@ -238,7 +183,7 @@ Unicode features. The String Type --------------- -Since Python 3.0, the language features a :class:`str` type that contain Unicode +Since Python 3.0, the language's :class:`str` type contains Unicode characters, meaning any string created using ``"unicode rocks!"``, ``'unicode rocks!'``, or the triple-quoted string syntax is stored as Unicode. @@ -252,11 +197,6 @@ include a Unicode character in a string literal:: # 'File not found' error message. print("Fichier non trouvé") -You can use a different encoding from UTF-8 by putting a specially-formatted -comment as the first or second line of the source code:: - - # -*- coding: -*- - Side note: Python 3 also supports using Unicode characters in identifiers:: répertoire = "/tmp/records.log" @@ -299,7 +239,7 @@ The following examples show the differences:: >>> b'\x80abc'.decode("utf-8", "ignore") 'abc' -Encodings are specified as strings containing the encoding's name. Python 3.2 +Encodings are specified as strings containing the encoding's name. Python comes with roughly 100 different encodings; see the Python Library Reference at :ref:`standard-encodings` for a list. Some encodings have multiple names; for example, ``'latin-1'``, ``'iso_8859_1'`` and ``'8859``' are all synonyms for @@ -409,12 +349,13 @@ already mentioned. See also :pep:`263` for more information. Unicode Properties ------------------ -The Unicode specification includes a database of information about code points. -For each defined code point, the information includes the character's -name, its category, the numeric value if applicable (Unicode has characters -representing the Roman numerals and fractions such as one-third and -four-fifths). There are also properties related to the code point's use in -bidirectional text and other display-related properties. +The Unicode specification includes a database of information about +code points. For each defined code point, the information includes +the character's name, its category, the numeric value if applicable +(for characters representing numeric concepts such as the Roman +numerals, fractions such as one-third and four-fifths, etc.). There +are also display-related properties, such as how to use the code point +in bidirectional text. The following program displays some information about several characters, and prints the numeric value of one particular character:: @@ -451,6 +392,88 @@ other". See list of category codes. +Comparing Strings +----------------- + +Unicode adds some complication to comparing strings, because the same +set of characters can be represented by different sequences of code +points. For example, a letter like 'ê' can be represented as a single +code point U+00EA, or as U+0065 U+0302, which is the code point for +'e' followed by a code point for 'COMBINING CIRCUMFLEX ACCENT'. These +will produce the same output when printed, but one is a string of +length 1 and the other is of length 2. + +One tool for a case-insensitive comparison is the +:meth:`~str.casefold` string method that converts a string to a +case-insensitive form following an algorithm described by the Unicode +Standard. This algorithm has special handling for characters such as +the German letter 'ß' (code point U+00DF), which becomes the pair of +lowercase letters 'ss'. + +:: + + >>> street = 'Gürzenichstraße' + >>> street.casefold() + 'gürzenichstrasse' + +A second tool is the :mod:`unicodedata` module's +:func:`~unicodedata.normalize` function that converts strings to one +of several normal forms, where letters followed by a combining +character are replaced with single characters. :func:`normalize` can +be used to perform string comparisons that won't falsely report +inequality if two strings use combining characters differently: + +:: + + import unicodedata + + def compare_strs(s1, s2): + def NFD(s): + return unicodedata.normalize('NFD', s) + + return NFD(s1) == NFD(s2) + + single_char = 'ê' + multiple_chars = '\N{LATIN SMALL LETTER E}\N{COMBINING CIRCUMFLEX ACCENT}' + print('length of first string=', len(single_char)) + print('length of second string=', len(multiple_chars)) + print(compare_strs(single_char, multiple_chars)) + +When run, this outputs: + +.. code-block:: shell-session + + $ python3 compare-strs.py + length of first string= 1 + length of second string= 2 + True + +The first argument to the :func:`~unicodedata.normalize` function is a +string giving the desired normalization form, which can be one of +'NFC', 'NFKC', 'NFD', and 'NFKD'. + +The Unicode Standard also specifies how to do caseless comparisons:: + + import unicodedata + + def compare_caseless(s1, s2): + def NFD(s): + return unicodedata.normalize('NFD', s) + + return NFD(NFD(s1).casefold()) == NFD(NFD(s2).casefold()) + + # Example usage + single_char = 'ê' + multiple_chars = '\N{LATIN CAPITAL LETTER E}\N{COMBINING CIRCUMFLEX ACCENT}' + + print(compare_caseless(single_char, multiple_chars)) + +This will print ``True``. (Why is :func:`NFD` invoked twice? Because +there are a few characters that make :meth:`casefold` return a +non-normalized string, so the result needs to be normalized again. See +section 3.13 of the Unicode Standard for a discussion and an example.) + + Unicode Regular Expressions --------------------------- @@ -567,22 +590,22 @@ particular byte ordering and don't skip the BOM. In some areas, it is also convention to use a "BOM" at the start of UTF-8 encoded files; the name is misleading since UTF-8 is not byte-order dependent. -The mark simply announces that the file is encoded in UTF-8. Use the -'utf-8-sig' codec to automatically skip the mark if present for reading such -files. +The mark simply announces that the file is encoded in UTF-8. For reading such +files, use the 'utf-8-sig' codec to automatically skip the mark if present. Unicode filenames ----------------- -Most of the operating systems in common use today support filenames that contain -arbitrary Unicode characters. Usually this is implemented by converting the -Unicode string into some encoding that varies depending on the system. For -example, Mac OS X uses UTF-8 while Windows uses a configurable encoding; on -Windows, Python uses the name "mbcs" to refer to whatever the currently -configured encoding is. On Unix systems, there will only be a filesystem -encoding if you've set the ``LANG`` or ``LC_CTYPE`` environment variables; if -you haven't, the default encoding is UTF-8. +Most of the operating systems in common use today support filenames +that contain arbitrary Unicode characters. Usually this is +implemented by converting the Unicode string into some encoding that +varies depending on the system. Today Python is converging on using +UTF-8: Python on MacOS has used UTF-8 for several versions, and Python +3.6 switched to using UTF-8 on Windows as well. On Unix systems, +there will only be a filesystem encoding if you've set the ``LANG`` or +``LC_CTYPE`` environment variables; if you haven't, the default +encoding is again UTF-8. The :func:`sys.getfilesystemencoding` function returns the encoding to use on your current system, in case you want to do the encoding manually, but there's @@ -597,9 +620,9 @@ automatically converted to the right encoding for you:: Functions in the :mod:`os` module such as :func:`os.stat` will also accept Unicode filenames. -The :func:`os.listdir` function returns filenames and raises an issue: should it return +The :func:`os.listdir` function returns filenames, which raises an issue: should it return the Unicode version of filenames, or should it return bytes containing -the encoded versions? :func:`os.listdir` will do both, depending on whether you +the encoded versions? :func:`os.listdir` can do both, depending on whether you provided the directory path as bytes or a Unicode string. If you pass a Unicode string as the path, filenames will be decoded using the filesystem's encoding and a list of Unicode strings will be returned, while passing a byte @@ -619,16 +642,17 @@ will produce the following output: .. code-block:: shell-session - amk:~$ python t.py + $ python listdir-test.py [b'filename\xe4\x94\x80abc', ...] ['filename\u4500abc', ...] The first list contains UTF-8-encoded filenames, and the second list contains the Unicode versions. -Note that on most occasions, the Unicode APIs should be used. The bytes APIs -should only be used on systems where undecodable file names can be present, -i.e. Unix systems. +Note that on most occasions, you should can just stick with using +Unicode with these APIs. The bytes APIs should only be used on +systems where undecodable file names can be present; that's +pretty much only Unix systems now. Tips for Writing Unicode-aware Programs @@ -695,10 +719,10 @@ with the ``surrogateescape`` error handler:: f.write(data) The ``surrogateescape`` error handler will decode any non-ASCII bytes -as code points in the Unicode Private Use Area ranging from U+DC80 to -U+DCFF. These private code points will then be turned back into the -same bytes when the ``surrogateescape`` error handler is used when -encoding the data and writing it back out. +as code points in a special range running from U+DC80 to +U+DCFF. These code points will then turn back into the +same bytes when the ``surrogateescape`` error handler is used to +encode the data and write it back out. References @@ -730,4 +754,5 @@ Andrew Kuchling, and Ezio Melotti. Thanks to the following people who have noted errors or offered suggestions on this article: Éric Araujo, Nicholas Bastin, Nick Coghlan, Marius Gedminas, Kent Johnson, Ken Krugler, Marc-André -Lemburg, Martin von Löwis, Terry J. Reedy, Chad Whitacre. +Lemburg, Martin von Löwis, Terry J. Reedy, Serhiy Storchaka, +Eryk Sun, Chad Whitacre, Graham Wideman. diff --git a/Doc/library/aifc.rst b/Doc/library/aifc.rst index 970a7aeb..73289077 100644 --- a/Doc/library/aifc.rst +++ b/Doc/library/aifc.rst @@ -45,7 +45,7 @@ Module :mod:`aifc` defines the following function: time how many samples you are going to write in total and use :meth:`writeframesraw` and :meth:`setnframes`. The :func:`.open` function may be used in a :keyword:`with` statement. When - the :keyword:`with` block completes, the :meth:`~aifc.close` method is called. + the :keyword:`!with` block completes, the :meth:`~aifc.close` method is called. .. versionchanged:: 3.4 Support for the :keyword:`with` statement was added. diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 647b7fc5..d59cf055 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -960,12 +960,20 @@ Unix signals Set *callback* as the handler for the *signum* signal. + The callback will be invoked by *loop*, along with other queued callbacks + and runnable coroutines of that event loop. Unlike signal handlers + registered using :func:`signal.signal`, a callback registered with this + function is allowed to interact with the event loop. + Raise :exc:`ValueError` if the signal number is invalid or uncatchable. Raise :exc:`RuntimeError` if there is a problem setting up the handler. Use :func:`functools.partial` :ref:`to pass keyword arguments ` to *callback*. + Like :func:`signal.signal`, this function must be invoked in the main + thread. + .. method:: loop.remove_signal_handler(sig) Remove the handler for the *sig* signal. diff --git a/Doc/library/asyncio-exceptions.rst b/Doc/library/asyncio-exceptions.rst index dbd5df72..e49577a2 100644 --- a/Doc/library/asyncio-exceptions.rst +++ b/Doc/library/asyncio-exceptions.rst @@ -65,11 +65,11 @@ Exceptions .. exception:: IncompleteReadError - The requested read operation did not complete fully. + The requested read operation did not complete fully. - Raised by the :ref:`asyncio stream APIs`. + Raised by the :ref:`asyncio stream APIs`. - This exception is a subclass of :exc:`EOFError`. + This exception is a subclass of :exc:`EOFError`. .. attribute:: expected diff --git a/Doc/library/asyncio-policy.rst b/Doc/library/asyncio-policy.rst index cab25934..07842daa 100644 --- a/Doc/library/asyncio-policy.rst +++ b/Doc/library/asyncio-policy.rst @@ -81,7 +81,7 @@ The abstract event loop policy base class is defined as follows: .. method:: set_child_watcher(watcher) - Get the current child process watcher to *watcher*. + Set the current child process watcher to *watcher*. This function is Unix specific. diff --git a/Doc/library/asyncio-queue.rst b/Doc/library/asyncio-queue.rst index bd0e70c0..7be1023c 100644 --- a/Doc/library/asyncio-queue.rst +++ b/Doc/library/asyncio-queue.rst @@ -64,7 +64,7 @@ Queue Block until all items in the queue have been received and processed. The count of unfinished tasks goes up whenever an item is added - to the queue. The count goes down whenever a consumer thread calls + to the queue. The count goes down whenever a consumer coroutine calls :meth:`task_done` to indicate that the item was retrieved and all work on it is complete. When the count of unfinished tasks drops to zero, :meth:`join` unblocks. diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 376de8f4..9e685b17 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -604,7 +604,7 @@ Scheduling From Other Threads See the :ref:`concurrency and multithreading ` section of the documentation. - Unlike other asyncio functions this functions requires the *loop* + Unlike other asyncio functions this function requires the *loop* argument to be passed explicitly. .. versionadded:: 3.5.1 diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index a4efef84..89ecddc7 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -152,6 +152,8 @@ The :mod:`binascii` module defines the following functions: *data* is converted into the corresponding 2-digit hex representation. The returned bytes object is therefore twice as long as the length of *data*. + Similar functionality (but returning a text string) is also conveniently + accessible using the :meth:`bytes.hex` method. .. function:: a2b_hex(hexstr) unhexlify(hexstr) @@ -161,6 +163,9 @@ The :mod:`binascii` module defines the following functions: of hexadecimal digits (which can be upper or lower case), otherwise an :exc:`Error` exception is raised. + Similar functionality (accepting only text string arguments, but more + liberal towards whitespace) is also accessible using the + :meth:`bytes.fromhex` class method. .. exception:: Error diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 016e56c4..0413f469 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -100,6 +100,21 @@ The class can be used to simulate nested scopes and is useful in templating. :func:`super` function. A reference to ``d.parents`` is equivalent to: ``ChainMap(*d.maps[1:])``. + Note, the iteration order of a :class:`ChainMap()` is determined by + scanning the mappings last to first:: + + >>> baseline = {'music': 'bach', 'art': 'rembrandt'} + >>> adjustments = {'art': 'van gogh', 'opera': 'carmen'} + >>> list(ChainMap(adjustments, baseline)) + ['music', 'art', 'opera'] + + This gives the same ordering as a series of :meth:`dict.update` calls + starting with the last mapping:: + + >>> combined = baseline.copy() + >>> combined.update(adjustments) + >>> list(combined) + ['music', 'art', 'opera'] .. seealso:: @@ -163,8 +178,8 @@ contexts:: e.maps[-1] # Root context -- like Python's globals() e.parents # Enclosing context chain -- like Python's nonlocals - d['x'] # Get first key in the chain of contexts d['x'] = 1 # Set value in current context + d['x'] # Get first key in the chain of contexts del d['x'] # Delete from current context list(d) # All nested values k in d # Check all nested values @@ -887,7 +902,7 @@ field names, the method and attribute names start with an underscore. .. method:: somenamedtuple._asdict() - Return a new :class:`OrderedDict` which maps field names to their corresponding + Return a new :class:`dict` which maps field names to their corresponding values: .. doctest:: @@ -1017,17 +1032,41 @@ customize a prototype instance: :class:`OrderedDict` objects ---------------------------- -Ordered dictionaries are just like regular dictionaries but they remember the -order that items were inserted. When iterating over an ordered dictionary, -the items are returned in the order their keys were first added. +Ordered dictionaries are just like regular dictionaries but have some extra +capabilities relating to ordering operations. They have become less +important now that the built-in :class:`dict` class gained the ability +to remember insertion order (this new behavior became guaranteed in +Python 3.7). + +Some differences from :class:`dict` still remain: + +* The regular :class:`dict` was designed to be very good at mapping + operations. Tracking insertion order was secondary. + +* The :class:`OrderedDict` was designed to be good at reordering operations. + Space efficiency, iteration speed, and the performance of update + operations were secondary. + +* Algorithmically, :class:`OrderedDict` can handle frequent reordering + operations better than :class:`dict`. This makes it suitable for tracking + recent accesses (for example in an `LRU cache + `_). + +* The equality operation for :class:`OrderedDict` checks for matching order. + +* The :meth:`popitem` method of :class:`OrderedDict` has a different + signature. It accepts an optional argument to specify which item is popped. + +* :class:`OrderedDict` has a :meth:`move_to_end` method to + efficiently reposition an element to an endpoint. + +* Until Python 3.8, :class:`dict` lacked a :meth:`__reversed__` method. + .. class:: OrderedDict([items]) - Return an instance of a dict subclass, supporting the usual :class:`dict` - methods. An *OrderedDict* is a dict that remembers the order that keys - were first inserted. If a new entry overwrites an existing entry, the - original insertion position is left unchanged. Deleting an entry and - reinserting it will move it to the end. + Return an instance of a :class:`dict` subclass that has methods + specialized for rearranging dictionary order. .. versionadded:: 3.1 @@ -1077,29 +1116,7 @@ anywhere a regular dictionary is used. :class:`OrderedDict` Examples and Recipes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Since an ordered dictionary remembers its insertion order, it can be used -in conjunction with sorting to make a sorted dictionary:: - - >>> # regular unsorted dictionary - >>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2} - - >>> # dictionary sorted by key - >>> OrderedDict(sorted(d.items(), key=lambda t: t[0])) - OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)]) - - >>> # dictionary sorted by value - >>> OrderedDict(sorted(d.items(), key=lambda t: t[1])) - OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)]) - - >>> # dictionary sorted by length of the key string - >>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0]))) - OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)]) - -The new sorted dictionaries maintain their sort order when entries -are deleted. But when new keys are added, the keys are appended -to the end and the sort is not maintained. - -It is also straight-forward to create an ordered dictionary variant +It is straightforward to create an ordered dictionary variant that remembers the order the keys were *last* inserted. If a new entry overwrites an existing entry, the original insertion position is changed and moved to the end:: @@ -1108,21 +1125,29 @@ original insertion position is changed and moved to the end:: 'Store items in the order the keys were last added' def __setitem__(self, key, value): - if key in self: - del self[key] - OrderedDict.__setitem__(self, key, value) + super().__setitem__(key, value) + super().move_to_end(key) -An ordered dictionary can be combined with the :class:`Counter` class -so that the counter remembers the order elements are first encountered:: +An :class:`OrderedDict` would also be useful for implementing +variants of :func:`functools.lru_cache`:: - class OrderedCounter(Counter, OrderedDict): - 'Counter that remembers the order elements are first encountered' + class LRU(OrderedDict): + 'Limit size, evicting the least recently looked-up key when full' - def __repr__(self): - return '%s(%r)' % (self.__class__.__name__, OrderedDict(self)) + def __init__(self, maxsize=128, *args, **kwds): + self.maxsize = maxsize + super().__init__(*args, **kwds) - def __reduce__(self): - return self.__class__, (OrderedDict(self),) + def __getitem__(self, key): + value = super().__getitem__(key) + self.move_to_end(key) + return value + + def __setitem__(self, key, value): + super().__setitem__(key, value) + if len(self) > self.maxsize: + oldest = next(iter(self)) + del self[oldest] :class:`UserDict` objects diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst index 5151f3a5..258de28e 100644 --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -105,7 +105,7 @@ compile Python sources. byte-code file ending in ``.pyc``, never ``.pyo``. .. versionchanged:: 3.7 - Added the ``--invalidation-mode`` parameter. + Added the ``--invalidation-mode`` option. There is no command-line option to control the optimization level used by the diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index 32177024..95cc3520 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -462,7 +462,8 @@ the :meth:`__init__` options: Please note: there are ways to add a set of key-value pairs in a single operation. When you use a regular dictionary in those operations, the order - of the keys may be random. For example: + of the keys will be ordered because dict preserves order from Python 3.7. + For example: .. doctest:: @@ -477,41 +478,10 @@ the :meth:`__init__` options: ... 'bar': 'y', ... 'baz': 'z'} ... }) - >>> parser.sections() # doctest: +SKIP - ['section3', 'section2', 'section1'] - >>> [option for option in parser['section3']] # doctest: +SKIP - ['baz', 'foo', 'bar'] - - In these operations you need to use an ordered dictionary as well: - - .. doctest:: - - >>> from collections import OrderedDict - >>> parser = configparser.ConfigParser() - >>> parser.read_dict( - ... OrderedDict(( - ... ('s1', - ... OrderedDict(( - ... ('1', '2'), - ... ('3', '4'), - ... ('5', '6'), - ... )) - ... ), - ... ('s2', - ... OrderedDict(( - ... ('a', 'b'), - ... ('c', 'd'), - ... ('e', 'f'), - ... )) - ... ), - ... )) - ... ) - >>> parser.sections() # doctest: +SKIP - ['s1', 's2'] - >>> [option for option in parser['s1']] # doctest: +SKIP - ['1', '3', '5'] - >>> [option for option in parser['s2'].values()] # doctest: +SKIP - ['b', 'd', 'f'] + >>> parser.sections() + ['section1', 'section2', 'section3'] + >>> [option for option in parser['section3']] + ['foo', 'bar', 'baz'] * *allow_no_value*, default value: ``False`` @@ -891,7 +861,7 @@ interpolation if an option used is not defined elsewhere. :: ConfigParser Objects -------------------- -.. class:: ConfigParser(defaults=None, dict_type=dict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BasicInterpolation(), converters={}) +.. class:: ConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BasicInterpolation(), converters={}) The main configuration parser. When *defaults* is given, it is initialized into the dictionary of intrinsic defaults. When *dict_type* is given, it @@ -953,10 +923,6 @@ ConfigParser Objects providing consistent behavior across the parser: non-string keys and values are implicitly converted to strings. - .. versionchanged:: 3.7 - The default *dict_type* is :class:`dict`, since it now preserves - insertion order. - .. method:: defaults() Return a dictionary containing the instance-wide defaults. @@ -1213,7 +1179,7 @@ ConfigParser Objects RawConfigParser Objects ----------------------- -.. class:: RawConfigParser(defaults=None, dict_type=dict, \ +.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, \ allow_no_value=False, *, delimiters=('=', ':'), \ comment_prefixes=('#', ';'), \ inline_comment_prefixes=None, strict=True, \ @@ -1226,10 +1192,6 @@ RawConfigParser Objects names, and values via its unsafe ``add_section`` and ``set`` methods, as well as the legacy ``defaults=`` keyword argument handling. - .. versionchanged:: 3.7 - The default *dict_type* is :class:`dict`, since it now preserves - insertion order. - .. note:: Consider using :class:`ConfigParser` instead which checks types of the values to be stored internally. If you don't want interpolation, you diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index 930c9735..017a87a5 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -1,5 +1,5 @@ -:mod:`contextlib` --- Utilities for :keyword:`with`\ -statement contexts -======================================================================== +:mod:`!contextlib` --- Utilities for :keyword:`!with`\ -statement contexts +========================================================================== .. module:: contextlib :synopsis: Utilities for with-statement contexts. @@ -72,7 +72,7 @@ Functions and classes provided: The function being decorated must return a :term:`generator`-iterator when called. This iterator must yield exactly one value, which will be bound to - the targets in the :keyword:`with` statement's :keyword:`as` clause, if any. + the targets in the :keyword:`with` statement's :keyword:`!as` clause, if any. At the point where the generator yields, the block nested in the :keyword:`with` statement is executed. The generator is then resumed after the block is exited. @@ -82,9 +82,9 @@ Functions and classes provided: the error (if any), or ensure that some cleanup takes place. If an exception is trapped merely in order to log it or to perform some action (rather than to suppress it entirely), the generator must reraise that exception. Otherwise the - generator context manager will indicate to the :keyword:`with` statement that + generator context manager will indicate to the :keyword:`!with` statement that the exception has been handled, and execution will resume with the statement - immediately following the :keyword:`with` statement. + immediately following the :keyword:`!with` statement. :func:`contextmanager` uses :class:`ContextDecorator` so the context managers it creates can be used as decorators as well as in :keyword:`with` statements. @@ -346,7 +346,7 @@ Functions and classes provided: As the decorated function must be able to be called multiple times, the underlying context manager must support use in multiple :keyword:`with` statements. If this is not the case, then the original construct with the - explicit :keyword:`with` statement inside the function should be used. + explicit :keyword:`!with` statement inside the function should be used. .. versionadded:: 3.2 @@ -771,7 +771,7 @@ Reentrant context managers More sophisticated context managers may be "reentrant". These context managers can not only be used in multiple :keyword:`with` statements, -but may also be used *inside* a :keyword:`with` statement that is already +but may also be used *inside* a :keyword:`!with` statement that is already using the same context manager. :class:`threading.RLock` is an example of a reentrant context manager, as are diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index fe0feeda..6af60b6e 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -51,9 +51,9 @@ Module-level decorators, classes, and functions The :func:`dataclass` decorator examines the class to find ``field``\s. A ``field`` is defined as class variable that has a - type annotation. With two exceptions described below, nothing in - :func:`dataclass` examines the type specified in the variable - annotation. + :term:`type annotation `. With two + exceptions described below, nothing in :func:`dataclass` + examines the type specified in the variable annotation. The order of the fields in all of the generated methods is the order in which they appear in the class definition. diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index db3a6522..121f73bb 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2034,6 +2034,12 @@ calls the platform C library's :func:`strftime` function, and platform variations are common. To see the full set of format codes supported on your platform, consult the :manpage:`strftime(3)` documentation. +For the same reason, handling of format strings containing Unicode code points +that can't be represented in the charset of the current locale is also +platform-dependent. On some platforms such code points are preserved intact in +the output, while on others ``strftime`` may raise :exc:`UnicodeError` or return +an empty string instead. + The following is a list of all the format codes that the C standard (1989 version) requires, and these work on all platforms with a standard C implementation. Note that the 1999 version of the C standard added additional diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst index f2a677e6..bcae55eb 100644 --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -2115,3 +2115,23 @@ Alternatively, inputs can be rounded upon creation using the >>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678') Decimal('1.2345') + +Q. Is the CPython implementation fast for large numbers? + +A. Yes. In the CPython and PyPy3 implementations, the C/CFFI versions of +the decimal module integrate the high speed `libmpdec +`_ library for +arbitrary precision correctly-rounded decimal floating point arithmetic. +``libmpdec`` uses `Karatsuba multiplication +`_ +for medium-sized numbers and the `Number Theoretic Transform +`_ +for very large numbers. However, to realize this performance gain, the +context needs to be set for unrounded calculations. + + >>> c = getcontext() + >>> c.prec = MAX_PREC + >>> c.Emax = MAX_EMAX + >>> c.Emin = MIN_EMIN + +.. versionadded:: 3.3 \ No newline at end of file diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 81e9766e..a6285ffa 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -394,7 +394,7 @@ A new :class:`Enum` class must have one base Enum class, up to one concrete data type, and as many :class:`object`-based mixin classes as needed. The order of these base classes is:: - def EnumName([mix-in, ...,] [data-type,] base-enum): + class EnumName([mix-in, ...,] [data-type,] base-enum): pass Also, subclassing an enumeration is allowed only if the enumeration does not define diff --git a/Doc/library/fileinput.rst b/Doc/library/fileinput.rst index 5881fefe..1fc11ffc 100644 --- a/Doc/library/fileinput.rst +++ b/Doc/library/fileinput.rst @@ -63,7 +63,7 @@ The following function is the primary interface of this module: The :class:`FileInput` instance can be used as a context manager in the :keyword:`with` statement. In this example, *input* is closed after the - :keyword:`with` statement is exited, even if an exception occurs:: + :keyword:`!with` statement is exited, even if an exception occurs:: with fileinput.input(files=('spam.txt', 'eggs.txt')) as f: for line in f: @@ -155,7 +155,7 @@ available for subclassing as well: A :class:`FileInput` instance can be used as a context manager in the :keyword:`with` statement. In this example, *input* is closed after the - :keyword:`with` statement is exited, even if an exception occurs:: + :keyword:`!with` statement is exited, even if an exception occurs:: with FileInput(files=('spam.txt', 'eggs.txt')) as input: process(input) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index c0f4ffd2..9326b8d0 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -668,6 +668,11 @@ are always available. They are listed here in alphabetical order. topic, and a help page is printed on the console. If the argument is any other kind of object, a help page on the object is generated. + Note that if a slash(/) appears in the parameter list of a function, when + invoking :func:`help`, it means that the parameters prior to the slash are + positional-only. For more info, see + :ref:`the FAQ entry on positional-only parameters `. + This function is added to the built-in namespace by the :mod:`site` module. .. versionchanged:: 3.4 @@ -809,13 +814,14 @@ are always available. They are listed here in alphabetical order. See also :ref:`typeiter`. - One useful application of the second form of :func:`iter` is to read lines of - a file until a certain line is reached. The following example reads a file - until the :meth:`~io.TextIOBase.readline` method returns an empty string:: + One useful application of the second form of :func:`iter` is to build a + block-reader. For example, reading fixed-width blocks from a binary + database file until the end of file is reached:: - with open('mydata.txt') as fp: - for line in iter(fp.readline, ''): - process_line(line) + from functools import partial + with open('mydata.db', 'rb') as f: + for block in iter(partial(f.read, 64), b''): + process_block(block) .. function:: len(s) @@ -996,7 +1002,6 @@ are always available. They are listed here in alphabetical order. ``'b'`` binary mode ``'t'`` text mode (default) ``'+'`` open a disk file for updating (reading and writing) - ``'U'`` :term:`universal newlines` mode (deprecated) ========= =============================================================== The default mode is ``'r'`` (open for reading text, synonym of ``'rt'``). @@ -1011,6 +1016,12 @@ are always available. They are listed here in alphabetical order. first decoded using a platform-dependent encoding or using the specified *encoding* if given. + There is an additional mode character permitted, ``'U'``, which no longer + has any effect, and is considered deprecated. It previously enabled + :term:`universal newlines` in text mode, which became the default behaviour + in Python 3.0. Refer to the documentation of the + :ref:`newline ` parameter for further details. + .. note:: Python doesn't depend on the underlying operating system's notion of text @@ -1077,6 +1088,8 @@ are always available. They are listed here in alphabetical order. .. index:: single: universal newlines; open() built-in function + .. _open-newline-parameter: + *newline* controls how :term:`universal newlines` mode works (it only applies to text mode). It can be ``None``, ``''``, ``'\n'``, ``'\r'``, and ``'\r\n'``. It works as follows: @@ -1655,7 +1668,7 @@ are always available. They are listed here in alphabetical order. This function is invoked by the :keyword:`import` statement. It can be replaced (by importing the :mod:`builtins` module and assigning to ``builtins.__import__``) in order to change semantics of the - :keyword:`import` statement, but doing so is **strongly** discouraged as it + :keyword:`!import` statement, but doing so is **strongly** discouraged as it is usually simpler to use import hooks (see :pep:`302`) to attain the same goals and does not cause issues with code which assumes the default import implementation is in use. Direct use of :func:`__import__` is also diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst index c4b7c797..3408c103 100644 --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -497,6 +497,7 @@ Here is an example session that uses the ``GET`` method:: b'\n one new dict self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index ff6060c6..9c83459f 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1737,23 +1737,33 @@ class TestCase(unittest.TestCase): i: int = field(metadata=0) # Make sure an empty dict works. + d = {} @dataclass class C: - i: int = field(metadata={}) + i: int = field(metadata=d) self.assertFalse(fields(C)[0].metadata) self.assertEqual(len(fields(C)[0].metadata), 0) + # Update should work (see bpo-35960). + d['foo'] = 1 + self.assertEqual(len(fields(C)[0].metadata), 1) + self.assertEqual(fields(C)[0].metadata['foo'], 1) with self.assertRaisesRegex(TypeError, 'does not support item assignment'): fields(C)[0].metadata['test'] = 3 # Make sure a non-empty dict works. + d = {'test': 10, 'bar': '42', 3: 'three'} @dataclass class C: - i: int = field(metadata={'test': 10, 'bar': '42', 3: 'three'}) + i: int = field(metadata=d) self.assertEqual(len(fields(C)[0].metadata), 3) self.assertEqual(fields(C)[0].metadata['test'], 10) self.assertEqual(fields(C)[0].metadata['bar'], '42') self.assertEqual(fields(C)[0].metadata[3], 'three') + # Update should work. + d['foo'] = 1 + self.assertEqual(len(fields(C)[0].metadata), 4) + self.assertEqual(fields(C)[0].metadata['foo'], 1) with self.assertRaises(KeyError): # Non-existent key. fields(C)[0].metadata['baz'] diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 83941c12..4a3c4887 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2450,6 +2450,10 @@ def test_unittest_reportflags(): Then the default eporting options are ignored: >>> result = suite.run(unittest.TestResult()) + + *NOTE*: These doctest are intentionally not placed in raw string to depict + the trailing whitespace using `\x20` in the diff below. + >>> print(result.failures[0][1]) # doctest: +ELLIPSIS Traceback ... Failed example: @@ -2463,7 +2467,7 @@ def test_unittest_reportflags(): Differences (ndiff with -expected +actual): a - - + + +\x20 b @@ -2952,6 +2956,47 @@ Invalid doctest option: """ +def test_no_trailing_whitespace_stripping(): + r""" + The fancy reports had a bug for a long time where any trailing whitespace on + the reported diff lines was stripped, making it impossible to see the + differences in line reported as different that differed only in the amount of + trailing whitespace. The whitespace still isn't particularly visible unless + you use NDIFF, but at least it is now there to be found. + + *NOTE*: This snippet was intentionally put inside a raw string to get rid of + leading whitespace error in executing the example below + + >>> def f(x): + ... r''' + ... >>> print('\n'.join(['a ', 'b'])) + ... a + ... b + ... ''' + """ + """ + *NOTE*: These doctest are not placed in raw string to depict the trailing whitespace + using `\x20` + + >>> test = doctest.DocTestFinder().find(f)[0] + >>> flags = doctest.REPORT_NDIFF + >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test) + ... # doctest: +ELLIPSIS + ********************************************************************** + File ..., line 3, in f + Failed example: + print('\n'.join(['a ', 'b'])) + Differences (ndiff with -expected +actual): + - a + + a + b + TestResults(failed=1, attempted=1) + + *NOTE*: `\x20` is for checking the trailing whitespace on the +a line above. + We cannot use actual spaces there, as a commit hook prevents from committing + patches that contain trailing whitespace. More info on Issue 24746. + """ + ###################################################################### ## Main ###################################################################### diff --git a/Lib/test/test_dummy_thread.py b/Lib/test/test_dummy_thread.py index 0840be67..da512167 100644 --- a/Lib/test/test_dummy_thread.py +++ b/Lib/test/test_dummy_thread.py @@ -70,14 +70,14 @@ class LockTests(unittest.TestCase): to_unlock.release() self.lock.acquire() - start_time = int(time.time()) + start_time = int(time.monotonic()) _thread.start_new_thread(delay_unlock,(self.lock, DELAY)) if support.verbose: print() print("*** Waiting for thread to release the lock "\ "(approx. %s sec.) ***" % DELAY) self.lock.acquire() - end_time = int(time.time()) + end_time = int(time.monotonic()) if support.verbose: print("done") self.assertGreaterEqual(end_time - start_time, DELAY, diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index b2210453..29a429cc 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -1866,6 +1866,15 @@ class TestEnum(unittest.TestCase): REVERT_ALL = "REVERT_ALL" RETRY = "RETRY" + def test_empty_globals(self): + # bpo-35717: sys._getframe(2).f_globals['__name__'] fails with KeyError + # when using compile and exec because f_globals is empty + code = "from enum import Enum; Enum('Animal', 'ANT BEE CAT DOG')" + code = compile(code, "", "exec") + global_ns = {} + local_ls = {} + exec(code, global_ns, local_ls) + class TestOrder(unittest.TestCase): @@ -2729,6 +2738,23 @@ class TestIntFlag(unittest.TestCase): self.assertEqual(256, len(seen), 'too many composite members created') +class TestEmptyAndNonLatinStrings(unittest.TestCase): + + def test_empty_string(self): + with self.assertRaises(ValueError): + empty_abc = Enum('empty_abc', ('', 'B', 'C')) + + def test_non_latin_character_string(self): + greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C')) + item = getattr(greek_abc, '\u03B1') + self.assertEqual(item.value, 1) + + def test_non_latin_number_string(self): + hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3')) + item = getattr(hebrew_123, '\u05D0') + self.assertEqual(item.value, 1) + + class TestUnique(unittest.TestCase): def test_unique_clean(self): diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index d6dc4ba5..700b7ad6 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -5,6 +5,7 @@ import os import signal import subprocess import sys +import sysconfig from test import support from test.support import script_helper, is_android import tempfile @@ -19,6 +20,17 @@ except ImportError: TIMEOUT = 0.5 MS_WINDOWS = (os.name == 'nt') +_cflags = sysconfig.get_config_var('CFLAGS') or '' +_config_args = sysconfig.get_config_var('CONFIG_ARGS') or '' +UB_SANITIZER = ( + '-fsanitize=undefined' in _cflags or + '--with-undefined-behavior-sanitizer' in _config_args +) +MEMORY_SANITIZER = ( + '-fsanitize=memory' in _cflags or + '--with-memory-sanitizer' in _config_args +) + def expected_traceback(lineno1, lineno2, header, min_count=1): regex = header @@ -94,7 +106,7 @@ class FaultHandlerTests(unittest.TestCase): else: header = 'Stack' regex = r""" - ^{fatal_error} + (?m)^{fatal_error} {header} \(most recent call first\): File "", line {lineno} in @@ -252,6 +264,8 @@ class FaultHandlerTests(unittest.TestCase): 3, 'Segmentation fault') + @unittest.skipIf(UB_SANITIZER or MEMORY_SANITIZER, + "sanitizer builds change crashing process output.") @skip_segfault_on_android def test_enable_file(self): with temporary_filename() as filename: @@ -267,6 +281,8 @@ class FaultHandlerTests(unittest.TestCase): @unittest.skipIf(sys.platform == "win32", "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(UB_SANITIZER or MEMORY_SANITIZER, + "sanitizer builds change crashing process output.") @skip_segfault_on_android def test_enable_fd(self): with tempfile.TemporaryFile('wb+') as fp: diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 06ea90c2..49c1fbcd 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -701,6 +701,25 @@ class FormatTestCase(unittest.TestCase): self.assertEqual(format(1234.56, '.4'), '1.235e+03') self.assertEqual(format(12345.6, '.4'), '1.235e+04') + def test_issue35560(self): + self.assertEqual(format(123.0, '00'), '123.0') + self.assertEqual(format(123.34, '00f'), '123.340000') + self.assertEqual(format(123.34, '00e'), '1.233400e+02') + self.assertEqual(format(123.34, '00g'), '123.34') + self.assertEqual(format(123.34, '00.10f'), '123.3400000000') + self.assertEqual(format(123.34, '00.10e'), '1.2334000000e+02') + self.assertEqual(format(123.34, '00.10g'), '123.34') + self.assertEqual(format(123.34, '01f'), '123.340000') + + self.assertEqual(format(-123.0, '00'), '-123.0') + self.assertEqual(format(-123.34, '00f'), '-123.340000') + self.assertEqual(format(-123.34, '00e'), '-1.233400e+02') + self.assertEqual(format(-123.34, '00g'), '-123.34') + self.assertEqual(format(-123.34, '00.10f'), '-123.3400000000') + self.assertEqual(format(-123.34, '00.10f'), '-123.3400000000') + self.assertEqual(format(-123.34, '00.10e'), '-1.2334000000e+02') + self.assertEqual(format(-123.34, '00.10g'), '-123.34') + class ReprTestCase(unittest.TestCase): def test_repr(self): floats_file = open(os.path.join(os.path.split(__file__)[0], diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index fd795085..d6aa2834 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -109,10 +109,7 @@ class ClearTest(unittest.TestCase): self.assertIs(None, wr()) -class FrameLocalsTest(unittest.TestCase): - """ - Tests for the .f_locals attribute. - """ +class FrameAttrsTest(unittest.TestCase): def make_frames(self): def outer(): @@ -159,6 +156,11 @@ class FrameLocalsTest(unittest.TestCase): self.assertEqual(outer.f_locals, {}) self.assertEqual(inner.f_locals, {}) + def test_f_lineno_del_segfault(self): + f, _, _ = self.make_frames() + with self.assertRaises(AttributeError): + del f.f_lineno + class ReprTest(unittest.TestCase): """ diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 7a0757f7..a91c6348 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1226,6 +1226,33 @@ class TestLRU: self.assertEqual(misses, 4) self.assertEqual(currsize, 2) + def test_lru_bug_35780(self): + # C version of the lru_cache was not checking to see if + # the user function call has already modified the cache + # (this arises in recursive calls and in multi-threading). + # This cause the cache to have orphan links not referenced + # by the cache dictionary. + + once = True # Modified by f(x) below + + @self.module.lru_cache(maxsize=10) + def f(x): + nonlocal once + rv = f'.{x}.' + if x == 20 and once: + once = False + rv = f(x) + return rv + + # Fill the cache + for x in range(15): + self.assertEqual(f(x), f'.{x}.') + self.assertEqual(f.cache_info().currsize, 10) + + # Make a recursive call and make sure the cache remains full + self.assertEqual(f(20), '.20.') + self.assertEqual(f.cache_info().currsize, 10) + def test_lru_hash_only_once(self): # To protect against weird reentrancy bugs and to improve # efficiency when faced with slow __hash__ methods, the @@ -1322,7 +1349,7 @@ class TestLRU: for i in (0, 1): self.assertEqual([eq(n) for n in range(150)], list(range(150))) self.assertEqual(eq.cache_info(), - self.module._CacheInfo(hits=0, misses=300, maxsize=-10, currsize=1)) + self.module._CacheInfo(hits=0, misses=300, maxsize=0, currsize=0)) def test_lru_with_exceptions(self): # Verify that user_function exceptions get passed through without diff --git a/Lib/test/test_future4.py b/Lib/test/test_future4.py index 413dd4d9..b27ca40d 100644 --- a/Lib/test/test_future4.py +++ b/Lib/test/test_future4.py @@ -1,6 +1,11 @@ from __future__ import unicode_literals - import unittest + +class Tests(unittest.TestCase): + def test_unicode_literals(self): + self.assertIsInstance("literal", str) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_genericclass.py b/Lib/test/test_genericclass.py index 37e755b1..37a87bc6 100644 --- a/Lib/test/test_genericclass.py +++ b/Lib/test/test_genericclass.py @@ -248,7 +248,14 @@ class TestClassGetitem(unittest.TestCase): return f'{cls.__name__}[{item.__name__}]' self.assertEqual(Meta[int], 'Meta[int]') - def test_class_getitem_metaclass_2(self): + def test_class_getitem_with_metaclass(self): + class Meta(type): pass + class C(metaclass=Meta): + def __class_getitem__(cls, item): + return f'{cls.__name__}[{item.__name__}]' + self.assertEqual(C[int], 'C[int]') + + def test_class_getitem_metaclass_first(self): class Meta(type): def __getitem__(cls, item): return 'from metaclass' diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index abc625d6..16edf34a 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -415,6 +415,7 @@ class CookieTests(unittest.TestCase): ("http://foo.bar.com/", ".foo.bar.com", True), ("http://foo.bar.com/", "foo.bar.com", True), ("http://foo.bar.com/", ".bar.com", True), + ("http://foo.bar.com/", "bar.com", True), ("http://foo.bar.com/", "com", True), ("http://foo.com/", "rhubarb.foo.com", False), ("http://foo.com/", ".foo.com", True), @@ -425,6 +426,8 @@ class CookieTests(unittest.TestCase): ("http://foo/", "foo", True), ("http://foo/", "foo.local", True), ("http://foo/", ".local", True), + ("http://barfoo.com", ".foo.com", False), + ("http://barfoo.com", "foo.com", False), ]: request = urllib.request.Request(url) r = pol.domain_return_ok(domain, request) @@ -692,6 +695,30 @@ class CookieTests(unittest.TestCase): req = urllib.request.Request("http://www.example.com") self.assertEqual(request_path(req), "/") + def test_path_prefix_match(self): + pol = DefaultCookiePolicy() + strict_ns_path_pol = DefaultCookiePolicy(strict_ns_set_path=True) + + c = CookieJar(pol) + base_url = "http://bar.com" + interact_netscape(c, base_url, 'spam=eggs; Path=/foo') + cookie = c._cookies['bar.com']['/foo']['spam'] + + for path, ok in [('/foo', True), + ('/foo/', True), + ('/foo/bar', True), + ('/', False), + ('/foobad/foo', False)]: + url = f'{base_url}{path}' + req = urllib.request.Request(url) + h = interact_netscape(c, url) + if ok: + self.assertIn('spam=eggs', h, f"cookie not set for {path}") + self.assertTrue(strict_ns_path_pol.set_ok_path(cookie, req)) + else: + self.assertNotIn('spam=eggs', h, f"cookie set for {path}") + self.assertFalse(strict_ns_path_pol.set_ok_path(cookie, req)) + def test_request_port(self): req = urllib.request.Request("http://www.acme.com:1234/", headers={"Host": "www.acme.com:4321"}) @@ -959,6 +986,33 @@ class CookieTests(unittest.TestCase): c.add_cookie_header(req) self.assertFalse(req.has_header("Cookie")) + c.clear() + + pol.set_blocked_domains([]) + req = urllib.request.Request("http://acme.com/") + res = FakeResponse(headers, "http://acme.com/") + cookies = c.make_cookies(res, req) + c.extract_cookies(res, req) + self.assertEqual(len(c), 1) + + req = urllib.request.Request("http://acme.com/") + c.add_cookie_header(req) + self.assertTrue(req.has_header("Cookie")) + + req = urllib.request.Request("http://badacme.com/") + c.add_cookie_header(req) + self.assertFalse(pol.return_ok(cookies[0], req)) + self.assertFalse(req.has_header("Cookie")) + + p = pol.set_blocked_domains(["acme.com"]) + req = urllib.request.Request("http://acme.com/") + c.add_cookie_header(req) + self.assertFalse(req.has_header("Cookie")) + + req = urllib.request.Request("http://badacme.com/") + c.add_cookie_header(req) + self.assertFalse(req.has_header("Cookie")) + def test_secure(self): for ns in True, False: for whitespace in " ", "": diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index a0b598d0..a060143e 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -8,6 +8,7 @@ import socketserver import time import calendar import threading +import socket from test.support import (reap_threads, verbose, transient_internet, run_with_tz, run_with_locale, cpython_only) @@ -71,6 +72,15 @@ class TestImaplib(unittest.TestCase): imaplib.Time2Internaldate(t) def test_imap4_host_default_value(self): + # Check whether the IMAP4_PORT is truly unavailable. + with socket.socket() as s: + try: + s.connect(('', imaplib.IMAP4_PORT)) + self.skipTest( + "Cannot run the test with local IMAP server running.") + except socket.error: + pass + expected_errnos = [ # This is the exception that should be raised. errno.ECONNREFUSED, diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index b41141e2..6655576b 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -28,6 +28,7 @@ import pickle import random import signal import sys +import sysconfig import threading import time import unittest @@ -59,6 +60,13 @@ else: class EmptyStruct(ctypes.Structure): pass +_cflags = sysconfig.get_config_var('CFLAGS') or '' +_config_args = sysconfig.get_config_var('CONFIG_ARGS') or '' +MEMORY_SANITIZER = ( + '-fsanitize=memory' in _cflags or + '--with-memory-sanitizer' in _config_args +) + def _default_chunk_size(): """Get the default TextIOWrapper chunk size""" with open(__file__, "r", encoding="latin-1") as f: @@ -1496,6 +1504,8 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests): class CBufferedReaderTest(BufferedReaderTest, SizeofTest): tp = io.BufferedReader + @unittest.skipIf(MEMORY_SANITIZER, "MSan defaults to crashing " + "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedReaderTest.test_constructor(self) # The allocation can succeed on 32-bit builds, e.g. with more @@ -1840,6 +1850,8 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests): class CBufferedWriterTest(BufferedWriterTest, SizeofTest): tp = io.BufferedWriter + @unittest.skipIf(MEMORY_SANITIZER, "MSan defaults to crashing " + "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedWriterTest.test_constructor(self) # The allocation can succeed on 32-bit builds, e.g. with more @@ -2314,6 +2326,8 @@ class BufferedRandomTest(BufferedReaderTest, BufferedWriterTest): class CBufferedRandomTest(BufferedRandomTest, SizeofTest): tp = io.BufferedRandom + @unittest.skipIf(MEMORY_SANITIZER, "MSan defaults to crashing " + "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedRandomTest.test_constructor(self) # The allocation can succeed on 32-bit builds, e.g. with more @@ -3635,6 +3649,11 @@ class CTextIOWrapperTest(TextIOWrapperTest): t2.buddy = t1 support.gc_collect() + def test_del__CHUNK_SIZE_SystemError(self): + t = self.TextIOWrapper(self.BytesIO(), encoding='ascii') + with self.assertRaises(AttributeError): + del t._CHUNK_SIZE + class PyTextIOWrapperTest(TextIOWrapperTest): io = pyio @@ -4116,10 +4135,9 @@ class SignalsTest(unittest.TestCase): in the latter.""" read_results = [] def _read(): - if hasattr(signal, 'pthread_sigmask'): - signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGALRM]) s = os.read(r, 1) read_results.append(s) + t = threading.Thread(target=_read) t.daemon = True r, w = os.pipe() @@ -4127,7 +4145,14 @@ class SignalsTest(unittest.TestCase): large_data = item * (support.PIPE_MAX_SIZE // len(item) + 1) try: wio = self.io.open(w, **fdopen_kwargs) - t.start() + if hasattr(signal, 'pthread_sigmask'): + # create the thread with SIGALRM signal blocked + signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGALRM]) + t.start() + signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGALRM]) + else: + t.start() + # Fill the pipe enough that the write will be blocking. # It will be interrupted by the timer armed above. Since the # other thread has read one byte, the low-level write will diff --git a/Lib/test/test_msilib.py b/Lib/test/test_msilib.py index 6d89ca4b..4aa4753f 100644 --- a/Lib/test/test_msilib.py +++ b/Lib/test/test_msilib.py @@ -1,5 +1,5 @@ """ Test suite for the code in msilib """ -import os.path +import os import unittest from test.support import TESTFN, import_module, unlink msilib = import_module('msilib') @@ -42,6 +42,29 @@ class MsiDatabaseTestCase(unittest.TestCase): ) self.addCleanup(unlink, db_path) + def test_summaryinfo_getproperty_issue1104(self): + db, db_path = init_database() + try: + sum_info = db.GetSummaryInformation(99) + title = sum_info.GetProperty(msilib.PID_TITLE) + self.assertEqual(title, b"Installation Database") + + sum_info.SetProperty(msilib.PID_TITLE, "a" * 999) + title = sum_info.GetProperty(msilib.PID_TITLE) + self.assertEqual(title, b"a" * 999) + + sum_info.SetProperty(msilib.PID_TITLE, "a" * 1000) + title = sum_info.GetProperty(msilib.PID_TITLE) + self.assertEqual(title, b"a" * 1000) + + sum_info.SetProperty(msilib.PID_TITLE, "a" * 1001) + title = sum_info.GetProperty(msilib.PID_TITLE) + self.assertEqual(title, b"a" * 1001) + finally: + db = None + sum_info = None + os.unlink(db_path) + def test_database_open_failed(self): with self.assertRaises(msilib.MSIError) as cm: msilib.OpenDatabase('non-existent.msi', msilib.MSIDBOPEN_READONLY) @@ -92,7 +115,7 @@ class Test_make_id(unittest.TestCase): def test_invalid_any_char(self): self.assertEqual( msilib.make_id(".s\x82ort"), "_.s_ort") - self.assertEqual ( + self.assertEqual( msilib.make_id(".s\x82o?*+rt"), "_.s_o___rt") diff --git a/Lib/test/test_multiprocessing_main_handling.py b/Lib/test/test_multiprocessing_main_handling.py index 9fd5c9fc..b6abfcc7 100644 --- a/Lib/test/test_multiprocessing_main_handling.py +++ b/Lib/test/test_multiprocessing_main_handling.py @@ -54,18 +54,21 @@ if "check_sibling" in __file__: if __name__ == '__main__': start_method = sys.argv[1] set_start_method(start_method) - p = Pool(5) results = [] - p.map_async(f, [1, 2, 3], callback=results.extend) - start_time = time.monotonic() - while not results: - time.sleep(0.05) - # up to 1 min to report the results - dt = time.monotonic() - start_time - if dt > 60.0: - raise RuntimeError("Timed out waiting for results (%.1f sec)" % dt) + with Pool(5) as pool: + pool.map_async(f, [1, 2, 3], callback=results.extend) + start_time = time.monotonic() + while not results: + time.sleep(0.05) + # up to 1 min to report the results + dt = time.monotonic() - start_time + if dt > 60.0: + raise RuntimeError("Timed out waiting for results (%.1f sec)" % dt) + results.sort() print(start_method, "->", results) + + pool.join() """ test_source_main_skipped_in_children = """\ @@ -84,18 +87,21 @@ from multiprocessing import Pool, set_start_method start_method = sys.argv[1] set_start_method(start_method) -p = Pool(5) results = [] -p.map_async(int, [1, 4, 9], callback=results.extend) -start_time = time.monotonic() -while not results: - time.sleep(0.05) - # up to 1 min to report the results - dt = time.monotonic() - start_time - if dt > 60.0: - raise RuntimeError("Timed out waiting for results (%.1f sec)" % dt) +with Pool(5) as pool: + pool.map_async(int, [1, 4, 9], callback=results.extend) + start_time = time.monotonic() + while not results: + time.sleep(0.05) + # up to 1 min to report the results + dt = time.monotonic() - start_time + if dt > 60.0: + raise RuntimeError("Timed out waiting for results (%.1f sec)" % dt) + results.sort() print(start_method, "->", results) + +pool.join() """ # These helpers were copied from test_cmd_line_script & tweaked a bit... diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index fe7261dd..fd9f70e3 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -923,7 +923,7 @@ class WalkTests(unittest.TestCase): ["broken_link", "broken_link2", "broken_link3", "tmp3"]) else: - self.sub2_tree = (sub2_path, [], ["tmp3"]) + self.sub2_tree = (sub2_path, ["SUB21"], ["tmp3"]) os.chmod(sub21_path, 0) try: @@ -1798,36 +1798,46 @@ class LinkTests(unittest.TestCase): @unittest.skipIf(sys.platform == "win32", "Posix specific tests") class PosixUidGidTests(unittest.TestCase): + # uid_t and gid_t are 32-bit unsigned integers on Linux + UID_OVERFLOW = (1 << 32) + GID_OVERFLOW = (1 << 32) + @unittest.skipUnless(hasattr(os, 'setuid'), 'test needs os.setuid()') def test_setuid(self): if os.getuid() != 0: self.assertRaises(OSError, os.setuid, 0) - self.assertRaises(OverflowError, os.setuid, 1<<32) + self.assertRaises(TypeError, os.setuid, 'not an int') + self.assertRaises(OverflowError, os.setuid, self.UID_OVERFLOW) @unittest.skipUnless(hasattr(os, 'setgid'), 'test needs os.setgid()') def test_setgid(self): if os.getuid() != 0 and not HAVE_WHEEL_GROUP: self.assertRaises(OSError, os.setgid, 0) - self.assertRaises(OverflowError, os.setgid, 1<<32) + self.assertRaises(TypeError, os.setgid, 'not an int') + self.assertRaises(OverflowError, os.setgid, self.GID_OVERFLOW) @unittest.skipUnless(hasattr(os, 'seteuid'), 'test needs os.seteuid()') def test_seteuid(self): if os.getuid() != 0: self.assertRaises(OSError, os.seteuid, 0) - self.assertRaises(OverflowError, os.seteuid, 1<<32) + self.assertRaises(TypeError, os.setegid, 'not an int') + self.assertRaises(OverflowError, os.seteuid, self.UID_OVERFLOW) @unittest.skipUnless(hasattr(os, 'setegid'), 'test needs os.setegid()') def test_setegid(self): if os.getuid() != 0 and not HAVE_WHEEL_GROUP: self.assertRaises(OSError, os.setegid, 0) - self.assertRaises(OverflowError, os.setegid, 1<<32) + self.assertRaises(TypeError, os.setegid, 'not an int') + self.assertRaises(OverflowError, os.setegid, self.GID_OVERFLOW) @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()') def test_setreuid(self): if os.getuid() != 0: self.assertRaises(OSError, os.setreuid, 0, 0) - self.assertRaises(OverflowError, os.setreuid, 1<<32, 0) - self.assertRaises(OverflowError, os.setreuid, 0, 1<<32) + self.assertRaises(TypeError, os.setreuid, 'not an int', 0) + self.assertRaises(TypeError, os.setreuid, 0, 'not an int') + self.assertRaises(OverflowError, os.setreuid, self.UID_OVERFLOW, 0) + self.assertRaises(OverflowError, os.setreuid, 0, self.UID_OVERFLOW) @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()') def test_setreuid_neg1(self): @@ -1841,8 +1851,10 @@ class PosixUidGidTests(unittest.TestCase): def test_setregid(self): if os.getuid() != 0 and not HAVE_WHEEL_GROUP: self.assertRaises(OSError, os.setregid, 0, 0) - self.assertRaises(OverflowError, os.setregid, 1<<32, 0) - self.assertRaises(OverflowError, os.setregid, 0, 1<<32) + self.assertRaises(TypeError, os.setregid, 'not an int', 0) + self.assertRaises(TypeError, os.setregid, 0, 'not an int') + self.assertRaises(OverflowError, os.setregid, self.GID_OVERFLOW, 0) + self.assertRaises(OverflowError, os.setregid, 0, self.GID_OVERFLOW) @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()') def test_setregid_neg1(self): @@ -2278,6 +2290,62 @@ class Win32JunctionTests(unittest.TestCase): os.unlink(self.junction) self.assertFalse(os.path.exists(self.junction)) +@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +class Win32NtTests(unittest.TestCase): + def setUp(self): + from test import support + self.nt = support.import_module('nt') + pass + + def tearDown(self): + pass + + def test_getfinalpathname_handles(self): + try: + import ctypes, ctypes.wintypes + except ImportError: + raise unittest.SkipTest('ctypes module is required for this test') + + kernel = ctypes.WinDLL('Kernel32.dll', use_last_error=True) + kernel.GetCurrentProcess.restype = ctypes.wintypes.HANDLE + + kernel.GetProcessHandleCount.restype = ctypes.wintypes.BOOL + kernel.GetProcessHandleCount.argtypes = (ctypes.wintypes.HANDLE, + ctypes.wintypes.LPDWORD) + + # This is a pseudo-handle that doesn't need to be closed + hproc = kernel.GetCurrentProcess() + + handle_count = ctypes.wintypes.DWORD() + ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count)) + self.assertEqual(1, ok) + + before_count = handle_count.value + + # The first two test the error path, __file__ tests the success path + filenames = [ r'\\?\C:', + r'\\?\NUL', + r'\\?\CONIN', + __file__ ] + + for i in range(10): + for name in filenames: + try: + tmp = self.nt._getfinalpathname(name) + except: + # Failure is expected + pass + try: + tmp = os.stat(name) + except: + pass + + ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count)) + self.assertEqual(1, ok) + + handle_delta = handle_count.value - before_count + + self.assertEqual(0, handle_delta) @support.skip_unless_symlink class NonLocalSymlinkTests(unittest.TestCase): @@ -3241,7 +3309,7 @@ class PathTConverterTests(unittest.TestCase): cleanup_fn(result) with self.assertRaisesRegex( - TypeError, 'should be string, bytes'): + TypeError, 'to return str or bytes'): fn(int_fspath, *extra_args) if allow_fd: @@ -3254,6 +3322,15 @@ class PathTConverterTests(unittest.TestCase): 'os.PathLike'): fn(fd, *extra_args) + def test_path_t_converter_and_custom_class(self): + msg = r'__fspath__\(\) to return str or bytes, not %s' + with self.assertRaisesRegex(TypeError, msg % r'int'): + os.stat(FakePath(2)) + with self.assertRaisesRegex(TypeError, msg % r'float'): + os.stat(FakePath(2.34)) + with self.assertRaisesRegex(TypeError, msg % r'object'): + os.stat(FakePath(object())) + @unittest.skipUnless(hasattr(os, 'get_blocking'), 'needs os.get_blocking() and os.set_blocking()') diff --git a/Lib/test/test_ossaudiodev.py b/Lib/test/test_ossaudiodev.py index c9e2a247..624fbf21 100644 --- a/Lib/test/test_ossaudiodev.py +++ b/Lib/test/test_ossaudiodev.py @@ -77,10 +77,10 @@ class OSSAudioDevTests(unittest.TestCase): # set parameters based on .au file headers dsp.setparameters(AFMT_S16_NE, nchannels, rate) self.assertTrue(abs(expected_time - 3.51) < 1e-2, expected_time) - t1 = time.time() + t1 = time.monotonic() dsp.write(data) dsp.close() - t2 = time.time() + t2 = time.monotonic() elapsed_time = t2 - t1 percent_diff = (abs(elapsed_time - expected_time) / expected_time) * 100 diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 9aa38e08..f573f5f5 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -1482,6 +1482,28 @@ class PdbTestCase(unittest.TestCase): stdout, _ = self._run_pdb(['-m', self.module_name + '.runme'], commands) self.assertTrue(any("VAR from module" in l for l in stdout.splitlines()), stdout) + def test_errors_in_command(self): + commands = "\n".join([ + 'print(', + 'debug print(', + 'debug doesnotexist', + 'c', + ]) + stdout, _ = self.run_pdb_script('', commands + '\n') + + self.assertEqual(stdout.splitlines()[1:], [ + '(Pdb) *** SyntaxError: unexpected EOF while parsing', + + '(Pdb) ENTERING RECURSIVE DEBUGGER', + '*** SyntaxError: unexpected EOF while parsing', + 'LEAVING RECURSIVE DEBUGGER', + + '(Pdb) ENTERING RECURSIVE DEBUGGER', + '> (1)()', + "((Pdb)) *** NameError: name 'doesnotexist' is not defined", + 'LEAVING RECURSIVE DEBUGGER', + '(Pdb) ', + ]) def load_tests(*args): from test import test_pdb diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 9bf365ed..198cea93 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -1013,12 +1013,12 @@ class PydocServerTest(unittest.TestCase): serverthread = pydoc._start_server(my_url_handler, hostname='0.0.0.0', port=0) self.assertIn('0.0.0.0', serverthread.docserver.address) - starttime = time.time() + starttime = time.monotonic() timeout = 1 #seconds while serverthread.serving: time.sleep(.01) - if serverthread.serving and time.time() - starttime > timeout: + if serverthread.serving and time.monotonic() - starttime > timeout: serverthread.stop() break diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 9fed4bef..5ef6d7b1 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1516,8 +1516,18 @@ class ReTests(unittest.TestCase): self.assertRaises(re.error, re.compile, r'(?au)\w') def test_locale_flag(self): - import locale - _, enc = locale.getlocale(locale.LC_CTYPE) + # On Windows, Python 3.7 doesn't call setlocale(LC_CTYPE, "") at + # startup and so the LC_CTYPE locale uses Latin1 encoding by default, + # whereas getpreferredencoding() returns the ANSI code page. Set + # temporarily the LC_CTYPE locale to the user preferred encoding to + # ensure that it uses the ANSI code page. + oldloc = locale.setlocale(locale.LC_CTYPE, None) + locale.setlocale(locale.LC_CTYPE, "") + self.addCleanup(locale.setlocale, locale.LC_CTYPE, oldloc) + + # Get the current locale encoding + enc = locale.getpreferredencoding(False) + # Search non-ASCII letter for i in range(128, 256): try: @@ -2031,6 +2041,40 @@ ELSE self.assertEqual(m.group(), b'xyz') self.assertEqual(m2.group(), b'') + def test_bug_34294(self): + # Issue 34294: wrong capturing groups + + # exists since Python 2 + s = "a\tx" + p = r"\b(?=(\t)|(x))x" + self.assertEqual(re.search(p, s).groups(), (None, 'x')) + + # introduced in Python 3.7.0 + s = "ab" + p = r"(?=(.)(.)?)" + self.assertEqual(re.findall(p, s), + [('a', 'b'), ('b', '')]) + self.assertEqual([m.groups() for m in re.finditer(p, s)], + [('a', 'b'), ('b', None)]) + + # test-cases provided by issue34294, introduced in Python 3.7.0 + p = r"(?=<(?P\w+)/?>(?:(?P.+?))?)" + s = "" + self.assertEqual(re.findall(p, s), + [('test', ''), ('foo2', '')]) + self.assertEqual([m.groupdict() for m in re.finditer(p, s)], + [{'tag': 'test', 'text': ''}, + {'tag': 'foo2', 'text': None}]) + s = "Hello" + self.assertEqual([m.groupdict() for m in re.finditer(p, s)], + [{'tag': 'test', 'text': 'Hello'}, + {'tag': 'foo', 'text': None}]) + s = "Hello" + self.assertEqual([m.groupdict() for m in re.finditer(p, s)], + [{'tag': 'test', 'text': 'Hello'}, + {'tag': 'foo', 'text': None}, + {'tag': 'foo', 'text': None}]) + class PatternReprTests(unittest.TestCase): def check(self, pattern, expected): diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index db9bd6df..a6745831 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -1004,6 +1004,7 @@ class ArgsTestCase(BaseTestCase): output = self.run_tests("-w", testname, exitcode=2) self.check_executed_tests(output, [testname], failed=testname, rerun=testname) + def test_no_tests_ran(self): code = textwrap.dedent(""" import unittest @@ -1017,6 +1018,19 @@ class ArgsTestCase(BaseTestCase): output = self.run_tests(testname, "-m", "nosuchtest", exitcode=0) self.check_executed_tests(output, [testname], no_test_ran=testname) + def test_no_tests_ran_skip(self): + code = textwrap.dedent(""" + import unittest + + class Tests(unittest.TestCase): + def test_skipped(self): + self.skipTest("because") + """) + testname = self.create_test(code=code) + + output = self.run_tests(testname, exitcode=0) + self.check_executed_tests(output, [testname]) + def test_no_tests_ran_multiple_tests_nonexistent(self): code = textwrap.dedent(""" import unittest diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 24cab0f8..406684bd 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -1122,18 +1122,18 @@ class StressTest(unittest.TestCase): self.setsig(signal.SIGALRM, second_handler) # for ITIMER_REAL expected_sigs = 0 - deadline = time.time() + 15.0 + deadline = time.monotonic() + 15.0 while expected_sigs < N: os.kill(os.getpid(), signal.SIGPROF) expected_sigs += 1 # Wait for handlers to run to avoid signal coalescing - while len(sigs) < expected_sigs and time.time() < deadline: + while len(sigs) < expected_sigs and time.monotonic() < deadline: time.sleep(1e-5) os.kill(os.getpid(), signal.SIGUSR1) expected_sigs += 1 - while len(sigs) < expected_sigs and time.time() < deadline: + while len(sigs) < expected_sigs and time.monotonic() < deadline: time.sleep(1e-5) # All ITIMER_REAL signals should have been delivered to the @@ -1156,7 +1156,7 @@ class StressTest(unittest.TestCase): self.setsig(signal.SIGALRM, handler) # for ITIMER_REAL expected_sigs = 0 - deadline = time.time() + 15.0 + deadline = time.monotonic() + 15.0 while expected_sigs < N: # Hopefully the SIGALRM will be received somewhere during @@ -1166,7 +1166,7 @@ class StressTest(unittest.TestCase): expected_sigs += 2 # Wait for handlers to run to avoid signal coalescing - while len(sigs) < expected_sigs and time.time() < deadline: + while len(sigs) < expected_sigs and time.monotonic() < deadline: time.sleep(1e-5) # All ITIMER_REAL signals should have been delivered to the diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index a30bd2f0..655a12dd 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -183,7 +183,9 @@ class HelperFunctionsTests(unittest.TestCase): finally: pth_file.cleanup() - def test_getuserbase(self): + # This tests _getuserbase, hence the double underline + # to distinguish from a test for getuserbase + def test__getuserbase(self): self.assertEqual(site._getuserbase(), sysconfig._getuserbase()) def test_get_path(self): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 9b9d1136..38196528 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -5533,7 +5533,7 @@ class SendfileUsingSendTest(ThreadedTCPSocketTest): support.unlink(support.TESTFN) def accept_conn(self): - self.serv.settimeout(self.TIMEOUT) + self.serv.settimeout(MAIN_TIMEOUT) conn, addr = self.serv.accept() conn.settimeout(self.TIMEOUT) self.addCleanup(conn.close) @@ -5717,11 +5717,11 @@ class SendfileUsingSendTest(ThreadedTCPSocketTest): def _testWithTimeoutTriggeredSend(self): address = self.serv.getsockname() - file = open(support.TESTFN, 'rb') - with socket.create_connection(address, timeout=0.01) as sock, \ - file as file: - meth = self.meth_from_sock(sock) - self.assertRaises(socket.timeout, meth, file) + with open(support.TESTFN, 'rb') as file: + with socket.create_connection(address) as sock: + sock.settimeout(0.01) + meth = self.meth_from_sock(sock) + self.assertRaises(socket.timeout, meth, file) def testWithTimeoutTriggeredSend(self): conn = self.accept_conn() diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index f1b9565c..8eab4474 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -34,6 +34,19 @@ IS_OPENSSL_1_1_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0) IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1) PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS') +PROTOCOL_TO_TLS_VERSION = {} +for proto, ver in ( + ("PROTOCOL_SSLv23", "SSLv3"), + ("PROTOCOL_TLSv1", "TLSv1"), + ("PROTOCOL_TLSv1_1", "TLSv1_1"), +): + try: + proto = getattr(ssl, proto) + ver = getattr(ssl.TLSVersion, ver) + except AttributeError: + continue + PROTOCOL_TO_TLS_VERSION[proto] = ver + def data_file(*name): return os.path.join(os.path.dirname(__file__), *name) @@ -116,6 +129,7 @@ NONEXISTINGCERT = data_file("XXXnonexisting.pem") BADKEY = data_file("badkey.pem") NOKIACERT = data_file("nokia.pem") NULLBYTECERT = data_file("nullbytecert.pem") +TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem") DHFILE = data_file("ffdh3072.pem") BYTES_DHFILE = os.fsencode(DHFILE) @@ -365,6 +379,27 @@ class BasicSocketTests(unittest.TestCase): self.assertEqual(p['crlDistributionPoints'], ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',)) + def test_parse_cert_CVE_2019_5010(self): + p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP) + if support.verbose: + sys.stdout.write("\n" + pprint.pformat(p) + "\n") + self.assertEqual( + p, + { + 'issuer': ( + (('countryName', 'UK'),), (('commonName', 'cody-ca'),)), + 'notAfter': 'Jun 14 18:00:58 2028 GMT', + 'notBefore': 'Jun 18 18:00:58 2018 GMT', + 'serialNumber': '02', + 'subject': ((('countryName', 'UK'),), + (('commonName', + 'codenomicon-vm-2.test.lal.cisco.com'),)), + 'subjectAltName': ( + ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),), + 'version': 3 + } + ) + def test_parse_cert_CVE_2013_4238(self): p = ssl._ssl._test_decode_cert(NULLBYTECERT) if support.verbose: @@ -1086,8 +1121,15 @@ class ContextTests(unittest.TestCase): "required OpenSSL 1.1.0g") def test_min_max_version(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - self.assertEqual( - ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED + # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like + # Fedora override the setting to TLS 1.0. + self.assertIn( + ctx.minimum_version, + {ssl.TLSVersion.MINIMUM_SUPPORTED, + # Fedora 29 uses TLS 1.0 by default + ssl.TLSVersion.TLSv1, + # RHEL 8 uses TLS 1.2 by default + ssl.TLSVersion.TLSv1_2} ) self.assertEqual( ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED @@ -2605,6 +2647,17 @@ def try_protocol_combo(server_protocol, client_protocol, expect_success, server_context = ssl.SSLContext(server_protocol) server_context.options |= server_options + min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None) + if (min_version is not None + # SSLContext.minimum_version is only available on recent OpenSSL + # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1) + and hasattr(server_context, 'minimum_version') + and server_protocol == ssl.PROTOCOL_TLS + and server_context.minimum_version > min_version): + # If OpenSSL configuration is strict and requires more recent TLS + # version, we have to change the minimum to test old TLS versions. + server_context.minimum_version = min_version + # NOTE: we must enable "ALL" ciphers on the client, otherwise an # SSLv23 client will send an SSLv3 hello (rather than SSLv2) # starting from OpenSSL 1.0.0 (see issue #8322). diff --git a/Lib/test/test_symbol.py b/Lib/test/test_symbol.py index c1306f54..32564f3d 100644 --- a/Lib/test/test_symbol.py +++ b/Lib/test/test_symbol.py @@ -2,6 +2,7 @@ import unittest from test import support import os import sys +import sysconfig import subprocess @@ -35,8 +36,8 @@ class TestSymbolGeneration(unittest.TestCase): lines2 = fp.readlines() self.assertEqual(lines1, lines2) - @unittest.skipIf(not os.path.exists(GRAMMAR_FILE), - 'test only works from source build directory') + @unittest.skipUnless(sysconfig.is_python_build(), + 'test only works from source build directory') def test_real_grammar_and_symbol_file(self): output = support.TESTFN self.addCleanup(support.unlink, output) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 7d2eec8a..5e4d75ec 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -973,16 +973,21 @@ class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase): def _fs_supports_holes(): # Return True if the platform knows the st_blocks stat attribute and # uses st_blocks units of 512 bytes, and if the filesystem is able to - # store holes in files. + # store holes of 4 KiB in files. + # + # The function returns False if page size is larger than 4 KiB. + # For example, ppc64 uses pages of 64 KiB. if sys.platform.startswith("linux"): # Linux evidentially has 512 byte st_blocks units. name = os.path.join(TEMPDIR, "sparse-test") with open(name, "wb") as fobj: + # Seek to "punch a hole" of 4 KiB fobj.seek(4096) + fobj.write(b'x' * 4096) fobj.truncate() s = os.stat(name) support.unlink(name) - return s.st_blocks == 0 + return (s.st_blocks * 512 < s.st_size) else: return False diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 8160a5af..27f328db 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -415,7 +415,8 @@ class ThreadTests(BaseTestCase): t.setDaemon(True) t.getName() t.setName("name") - t.isAlive() + with self.assertWarnsRegex(PendingDeprecationWarning, 'use is_alive()'): + t.isAlive() e = threading.Event() e.isSet() threading.activeCount() diff --git a/Lib/test/test_threading_local.py b/Lib/test/test_threading_local.py index 984f8dda..2fd14ae2 100644 --- a/Lib/test/test_threading_local.py +++ b/Lib/test/test_threading_local.py @@ -1,3 +1,4 @@ +import sys import unittest from doctest import DocTestSuite from test import support diff --git a/Lib/test/test_threadsignals.py b/Lib/test/test_threadsignals.py index 7e13b172..eeacd369 100644 --- a/Lib/test/test_threadsignals.py +++ b/Lib/test/test_threadsignals.py @@ -95,9 +95,9 @@ class ThreadSignals(unittest.TestCase): lock = thread.allocate_lock() lock.acquire() signal.alarm(1) - t1 = time.time() + t1 = time.monotonic() self.assertRaises(KeyboardInterrupt, lock.acquire, timeout=5) - dt = time.time() - t1 + dt = time.monotonic() - t1 # Checking that KeyboardInterrupt was raised is not sufficient. # We want to assert that lock.acquire() was interrupted because # of the signal, not that the signal handler was called immediately @@ -136,9 +136,9 @@ class ThreadSignals(unittest.TestCase): rlock.release() time.sleep(0.01) signal.alarm(1) - t1 = time.time() + t1 = time.monotonic() self.assertRaises(KeyboardInterrupt, rlock.acquire, timeout=5) - dt = time.time() - t1 + dt = time.monotonic() - t1 # See rationale above in test_lock_acquire_interruption self.assertLess(dt, 3.0) finally: @@ -203,9 +203,9 @@ class ThreadSignals(unittest.TestCase): old_handler = signal.signal(signal.SIGUSR1, my_handler) try: def timed_acquire(): - self.start = time.time() + self.start = time.monotonic() lock.acquire(timeout=0.5) - self.end = time.time() + self.end = time.monotonic() def send_signals(): for _ in range(40): time.sleep(0.02) diff --git a/Lib/test/test_timeout.py b/Lib/test/test_timeout.py index 3c75dcc6..b54fc826 100644 --- a/Lib/test/test_timeout.py +++ b/Lib/test/test_timeout.py @@ -127,11 +127,11 @@ class TimeoutTestCase(unittest.TestCase): self.sock.settimeout(timeout) method = getattr(self.sock, method) for i in range(count): - t1 = time.time() + t1 = time.monotonic() try: method(*args) except socket.timeout as e: - delta = time.time() - t1 + delta = time.monotonic() - t1 break else: self.fail('socket.timeout was not raised') diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 3cc018c0..1aad9334 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -2676,6 +2676,12 @@ class CAPITest(unittest.TestCase): check_format('%.%s', b'%.%s', b'abc') + # Issue #33817: empty strings + check_format('', + b'') + check_format('', + b'%s', b'') + # Test PyUnicode_AsWideChar() @support.cpython_only def test_aswidechar(self): diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index c292d74f..2ac73b58 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -712,7 +712,7 @@ FF with self.assertRaises(urllib.error.ContentTooShortError): try: - urllib.request.urlretrieve('http://example.com/', + urllib.request.urlretrieve(support.TEST_HTTP_URL, reporthook=_reporthook) finally: self.unfakehttp() @@ -729,7 +729,7 @@ FF ''') with self.assertRaises(urllib.error.ContentTooShortError): try: - urllib.request.urlretrieve('http://example.com/') + urllib.request.urlretrieve(support.TEST_HTTP_URL) finally: self.unfakehttp() diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py index 1aa64cbe..0f43d71e 100644 --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -84,7 +84,7 @@ class CloseSocketTest(unittest.TestCase): def test_close(self): # calling .close() on urllib2's response objects should close the # underlying socket - url = "http://www.example.com/" + url = support.TEST_HTTP_URL with support.transient_internet(url): response = _urlopen_with_retry(url) sock = response.fp @@ -173,7 +173,7 @@ class OtherNetworkTests(unittest.TestCase): "http://www.pythontest.net/elsewhere/#frag") def test_custom_headers(self): - url = "http://www.example.com" + url = support.TEST_HTTP_URL with support.transient_internet(url): opener = urllib.request.build_opener() request = urllib.request.Request(url) @@ -259,7 +259,7 @@ class OtherNetworkTests(unittest.TestCase): class TimeoutTest(unittest.TestCase): def test_http_basic(self): self.assertIsNone(socket.getdefaulttimeout()) - url = "http://www.example.com" + url = support.TEST_HTTP_URL with support.transient_internet(url, timeout=None): u = _urlopen_with_retry(url) self.addCleanup(u.close) @@ -267,7 +267,7 @@ class TimeoutTest(unittest.TestCase): def test_http_default_timeout(self): self.assertIsNone(socket.getdefaulttimeout()) - url = "http://www.example.com" + url = support.TEST_HTTP_URL with support.transient_internet(url): socket.setdefaulttimeout(60) try: @@ -279,7 +279,7 @@ class TimeoutTest(unittest.TestCase): def test_http_no_timeout(self): self.assertIsNone(socket.getdefaulttimeout()) - url = "http://www.example.com" + url = support.TEST_HTTP_URL with support.transient_internet(url): socket.setdefaulttimeout(60) try: @@ -290,7 +290,7 @@ class TimeoutTest(unittest.TestCase): self.assertIsNone(u.fp.raw._sock.gettimeout()) def test_http_timeout(self): - url = "http://www.example.com" + url = support.TEST_HTTP_URL with support.transient_internet(url): u = _urlopen_with_retry(url, timeout=120) self.addCleanup(u.close) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py index 4103b6c0..d394cedd 100644 --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -3,6 +3,7 @@ from test import support import contextlib import socket +import urllib.parse import urllib.request import os import email.message @@ -24,8 +25,9 @@ class URLTimeoutTest(unittest.TestCase): socket.setdefaulttimeout(None) def testURLread(self): - with support.transient_internet("www.example.com"): - f = urllib.request.urlopen("http://www.example.com/") + domain = urllib.parse.urlparse(support.TEST_HTTP_URL).netloc + with support.transient_internet(domain): + f = urllib.request.urlopen(support.TEST_HTTP_URL) f.read() diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index be50b476..e6638aee 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -1,3 +1,5 @@ +import sys +import unicodedata import unittest import urllib.parse @@ -984,6 +986,27 @@ class UrlParseTestCase(unittest.TestCase): expected.append(name) self.assertCountEqual(urllib.parse.__all__, expected) + def test_urlsplit_normalization(self): + # Certain characters should never occur in the netloc, + # including under normalization. + # Ensure that ALL of them are detected and cause an error + illegal_chars = '/:#?@' + hex_chars = {'{:04X}'.format(ord(c)) for c in illegal_chars} + denorm_chars = [ + c for c in map(chr, range(128, sys.maxunicode)) + if (hex_chars & set(unicodedata.decomposition(c).split())) + and c not in illegal_chars + ] + # Sanity check that we found at least one such character + self.assertIn('\u2100', denorm_chars) + self.assertIn('\uFF03', denorm_chars) + + for scheme in ["http", "https", "ftp"]: + for c in denorm_chars: + url = "{}://netloc{}false.netloc/path".format(scheme, c) + with self.subTest(url=url, char='{:04X}'.format(ord(c))): + with self.assertRaises(ValueError): + urllib.parse.urlsplit(url) class Utility_Tests(unittest.TestCase): """Testcase to test the various utility functions in the urllib.""" diff --git a/Lib/test/test_uu.py b/Lib/test/test_uu.py index 1147205a..c9f05e5b 100644 --- a/Lib/test/test_uu.py +++ b/Lib/test/test_uu.py @@ -6,6 +6,8 @@ Nick Mathewson import unittest from test import support +import os +import stat import sys import uu import io @@ -218,6 +220,23 @@ class UUFileTest(unittest.TestCase): with open(self.tmpin, 'rb') as f: self.assertRaises(uu.Error, uu.decode, f) + def test_decode_mode(self): + # Verify that decode() will set the given mode for the out_file + expected_mode = 0o444 + with open(self.tmpin, 'wb') as f: + f.write(encodedtextwrapped(expected_mode, self.tmpout)) + + # make file writable again, so it can be removed (Windows only) + self.addCleanup(os.chmod, self.tmpout, expected_mode | stat.S_IWRITE) + + with open(self.tmpin, 'rb') as f: + uu.decode(f) + + self.assertEqual( + stat.S_IMODE(os.stat(self.tmpout).st_mode), + expected_mode + ) + if __name__=="__main__": unittest.main() diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 22a3b788..347544a6 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -52,10 +52,7 @@ class BaseTest(unittest.TestCase): self.bindir = 'bin' self.lib = ('lib', 'python%d.%d' % sys.version_info[:2]) self.include = 'include' - if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in os.environ: - executable = os.environ['__PYVENV_LAUNCHER__'] - else: - executable = sys.executable + executable = getattr(sys, '_base_executable', sys.executable) self.exe = os.path.split(executable)[-1] def tearDown(self): @@ -100,11 +97,7 @@ class BasicTest(BaseTest): else: self.assertFalse(os.path.exists(p)) data = self.get_text_file_contents('pyvenv.cfg') - if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' - in os.environ): - executable = os.environ['__PYVENV_LAUNCHER__'] - else: - executable = sys.executable + executable = getattr(sys, '_base_executable', sys.executable) path = os.path.dirname(executable) self.assertIn('home = %s' % path, data) fn = self.get_env_file(self.bindir, self.exe) @@ -243,7 +236,6 @@ class BasicTest(BaseTest): self.assertIn('include-system-site-packages = %s\n' % s, data) @unittest.skipUnless(can_symlink(), 'Needs symlinks') - @unittest.skipIf(os.name == 'nt', 'Symlinks are never used on Windows') def test_symlinking(self): """ Test symlinking works as expected @@ -306,6 +298,19 @@ class BasicTest(BaseTest): ) self.assertEqual(out.strip(), '0') + def test_multiprocessing(self): + """ + Test that the multiprocessing is able to spawn. + """ + rmtree(self.env_dir) + self.run_with_capture(venv.create, self.env_dir) + envpy = os.path.join(os.path.realpath(self.env_dir), + self.bindir, self.exe) + out, err = check_output([envpy, '-c', + 'from multiprocessing import Pool; ' + + 'print(Pool(1).apply_async("Python".lower).get(3))']) + self.assertEqual(out.strip(), "python".encode()) + @skipInVenv class EnsurePipTest(BaseTest): """Test venv module installation of pip.""" diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index a40a9a29..87cc3a7e 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -940,6 +940,25 @@ class WarningsDisplayTests(BaseTest): file_object, expected_file_line) self.assertEqual(expect, file_object.getvalue()) + def test_formatwarning_override(self): + # bpo-35178: Test that a custom formatwarning function gets the 'line' + # argument as a positional argument, and not only as a keyword argument + def myformatwarning(message, category, filename, lineno, text): + return f'm={message}:c={category}:f={filename}:l={lineno}:t={text}' + + file_name = os.path.splitext(warning_tests.__file__)[0] + '.py' + line_num = 3 + file_line = linecache.getline(file_name, line_num).strip() + message = 'msg' + category = Warning + file_object = StringIO() + expected = f'm={message}:c={category}:f={file_name}:l={line_num}' + \ + f':t={file_line}' + with support.swap_attr(self.module, 'formatwarning', myformatwarning): + self.module.showwarning(message, category, file_name, line_num, + file_object, file_line) + self.assertEqual(file_object.getvalue(), expected) + class CWarningsDisplayTests(WarningsDisplayTests, unittest.TestCase): module = c_warnings diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 9fa0bbd7..1fac08da 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -8,6 +8,7 @@ import contextlib import copy import threading import time +import random from test import support from test.support import script_helper @@ -1688,6 +1689,87 @@ class MappingTestCase(TestBase): self.assertEqual(len(d), 1) o = None # lose ref + def check_threaded_weak_dict_copy(self, type_, deepcopy): + # `type_` should be either WeakKeyDictionary or WeakValueDictionary. + # `deepcopy` should be either True or False. + exc = [] + + class DummyKey: + def __init__(self, ctr): + self.ctr = ctr + + class DummyValue: + def __init__(self, ctr): + self.ctr = ctr + + def dict_copy(d, exc): + try: + if deepcopy is True: + _ = copy.deepcopy(d) + else: + _ = d.copy() + except Exception as ex: + exc.append(ex) + + def pop_and_collect(lst): + gc_ctr = 0 + while lst: + i = random.randint(0, len(lst) - 1) + gc_ctr += 1 + lst.pop(i) + if gc_ctr % 10000 == 0: + gc.collect() # just in case + + self.assertIn(type_, (weakref.WeakKeyDictionary, weakref.WeakValueDictionary)) + + d = type_() + keys = [] + values = [] + # Initialize d with many entries + for i in range(70000): + k, v = DummyKey(i), DummyValue(i) + keys.append(k) + values.append(v) + d[k] = v + del k + del v + + t_copy = threading.Thread(target=dict_copy, args=(d, exc,)) + if type_ is weakref.WeakKeyDictionary: + t_collect = threading.Thread(target=pop_and_collect, args=(keys,)) + else: # weakref.WeakValueDictionary + t_collect = threading.Thread(target=pop_and_collect, args=(values,)) + + t_copy.start() + t_collect.start() + + t_copy.join() + t_collect.join() + + # Test exceptions + if exc: + raise exc[0] + + def test_threaded_weak_key_dict_copy(self): + # Issue #35615: Weakref keys or values getting GC'ed during dict + # copying should not result in a crash. + self.check_threaded_weak_dict_copy(weakref.WeakKeyDictionary, False) + + def test_threaded_weak_key_dict_deepcopy(self): + # Issue #35615: Weakref keys or values getting GC'ed during dict + # copying should not result in a crash. + self.check_threaded_weak_dict_copy(weakref.WeakKeyDictionary, True) + + def test_threaded_weak_value_dict_copy(self): + # Issue #35615: Weakref keys or values getting GC'ed during dict + # copying should not result in a crash. + self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, False) + + def test_threaded_weak_value_dict_deepcopy(self): + # Issue #35615: Weakref keys or values getting GC'ed during dict + # copying should not result in a crash. + self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, True) + from test import mapping_tests diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index e87de609..2144d203 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -1,4 +1,5 @@ # xml.etree test for cElementTree +import io import struct from test import support from test.support import import_fresh_module @@ -133,6 +134,26 @@ class MiscTests(unittest.TestCase): self.assertEqual(len(elem), 1) self.assertEqual(elem[0].tag, 'child') + def test_iterparse_leaks(self): + # Test reference leaks in TreeBuilder (issue #35502). + # The test is written to be executed in the hunting reference leaks + # mode. + XML = '' + parser = cET.iterparse(io.StringIO(XML)) + next(parser) + del parser + support.gc_collect() + + def test_xmlpullparser_leaks(self): + # Test reference leaks in TreeBuilder (issue #35502). + # The test is written to be executed in the hunting reference leaks + # mode. + XML = '' + parser = cET.XMLPullParser() + parser.feed(XML) + del parser + support.gc_collect() + @unittest.skipUnless(cET, 'requires _elementtree') class TestAliasWorking(unittest.TestCase): diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 5f780d88..32263f7f 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -818,11 +818,10 @@ class SimpleServerTestCase(BaseServerTestCase): # protocol error; provide additional information in test output self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) - # [ch] The test 404 is causing lots of false alarms. - def XXXtest_404(self): + def test_404(self): # send POST with http.client, it should return 404 header and # 'Not Found' message. - conn = httplib.client.HTTPConnection(ADDR, PORT) + conn = http.client.HTTPConnection(ADDR, PORT) conn.request('POST', '/this-is-not-valid') response = conn.getresponse() conn.close() diff --git a/Lib/test/test_zipfile64.py b/Lib/test/test_zipfile64.py index cba909f6..524dcf02 100644 --- a/Lib/test/test_zipfile64.py +++ b/Lib/test/test_zipfile64.py @@ -22,7 +22,7 @@ from test.support import TESTFN, requires_zlib TESTFN2 = TESTFN + "2" # How much time in seconds can pass before we print a 'Still working' message. -_PRINT_WORKING_MSG_INTERVAL = 5 * 60 +_PRINT_WORKING_MSG_INTERVAL = 60 class TestsWithSourceFile(unittest.TestCase): def setUp(self): @@ -43,12 +43,12 @@ class TestsWithSourceFile(unittest.TestCase): # raw data to store. filecount = 6*1024**3 // len(self.data) - next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL + next_time = time.monotonic() + _PRINT_WORKING_MSG_INTERVAL for num in range(filecount): zipfp.writestr("testfn%d" % num, self.data) # Print still working message since this test can be really slow - if next_time <= time.time(): - next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL + if next_time <= time.monotonic(): + next_time = time.monotonic() + _PRINT_WORKING_MSG_INTERVAL print(( ' zipTest still writing %d of %d, be patient...' % (num, filecount)), file=sys.__stdout__) @@ -60,8 +60,8 @@ class TestsWithSourceFile(unittest.TestCase): for num in range(filecount): self.assertEqual(zipfp.read("testfn%d" % num), self.data) # Print still working message since this test can be really slow - if next_time <= time.time(): - next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL + if next_time <= time.monotonic(): + next_time = time.monotonic() + _PRINT_WORKING_MSG_INTERVAL print(( ' zipTest still reading %d of %d, be patient...' % (num, filecount)), file=sys.__stdout__) diff --git a/Lib/test/time_hashlib.py b/Lib/test/time_hashlib.py index 2585ecb7..55ebac62 100644 --- a/Lib/test/time_hashlib.py +++ b/Lib/test/time_hashlib.py @@ -14,26 +14,26 @@ def test_scaled_msg(scale, name): longStr = b'Z'*scale localCF = creatorFunc - start = time.time() + start = time.perf_counter() for f in range(iterations): x = localCF(longStr).digest() - end = time.time() + end = time.perf_counter() print(('%2.2f' % (end-start)), "seconds", iterations, "x", len(longStr), "bytes", name) def test_create(): - start = time.time() + start = time.perf_counter() for f in range(20000): d = creatorFunc() - end = time.time() + end = time.perf_counter() print(('%2.2f' % (end-start)), "seconds", '[20000 creations]') def test_zero(): - start = time.time() + start = time.perf_counter() for f in range(20000): x = creatorFunc().digest() - end = time.time() + end = time.perf_counter() print(('%2.2f' % (end-start)), "seconds", '[20000 "" digests]') diff --git a/Lib/threading.py b/Lib/threading.py index bb41456f..318b3301 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -568,8 +568,8 @@ class Barrier: """Implements a Barrier. Useful for synchronizing a fixed number of threads at known synchronization - points. Threads block on 'wait()' and are simultaneously once they have all - made that call. + points. Threads block on 'wait()' and are simultaneously awoken once they + have all made that call. """ @@ -578,7 +578,7 @@ class Barrier: 'action' is a callable which, when supplied, will be called by one of the threads after they have all entered the barrier and just prior to - releasing them all. If a 'timeout' is provided, it is uses as the + releasing them all. If a 'timeout' is provided, it is used as the default for all subsequent 'wait()' calls. """ @@ -1007,7 +1007,7 @@ class Thread: When the timeout argument is present and not None, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). As join() always returns None, you must call - isAlive() after join() to decide whether a timeout happened -- if the + is_alive() after join() to decide whether a timeout happened -- if the thread is still alive, the join() call timed out. When the timeout argument is not present or None, the operation will @@ -1091,7 +1091,15 @@ class Thread: self._wait_for_tstate_lock(False) return not self._is_stopped - isAlive = is_alive + def isAlive(self): + """Return whether the thread is alive. + + This method is deprecated, use is_alive() instead. + """ + import warnings + warnings.warn('isAlive() is deprecated, use is_alive() instead', + PendingDeprecationWarning, stacklevel=2) + return self.is_alive() @property def daemon(self): diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py index 06e3dfe7..ba9e3b54 100644 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -329,7 +329,12 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase): self.entry.wait_visibility() self.entry.update_idletasks() - self.assertEqual(self.entry.identify(5, 5), "textarea") + # bpo-27313: macOS Cocoa widget differs from X, allow either + if sys.platform == 'darwin': + self.assertIn(self.entry.identify(5, 5), + ("textarea", "Combobox.button") ) + else: + self.assertEqual(self.entry.identify(5, 5), "textarea") self.assertEqual(self.entry.identify(-1, -1), "") self.assertRaises(tkinter.TclError, self.entry.identify, None, 5) diff --git a/Lib/types.py b/Lib/types.py index ce4652f3..2e0513ca 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -55,7 +55,7 @@ except TypeError: GetSetDescriptorType = type(FunctionType.__code__) MemberDescriptorType = type(FunctionType.__globals__) -del sys, _f, _g, _C, _c, # Not for export +del sys, _f, _g, _C, _c, _ag # Not for export # Provide a PEP 3115 compliant mechanism for class creation diff --git a/Lib/unittest/loader.py b/Lib/unittest/loader.py index d936a96e..ba7105e1 100644 --- a/Lib/unittest/loader.py +++ b/Lib/unittest/loader.py @@ -229,7 +229,9 @@ class TestLoader(object): testFunc = getattr(testCaseClass, attrname) if not callable(testFunc): return False - fullName = '%s.%s' % (testCaseClass.__module__, testFunc.__qualname__) + fullName = f'%s.%s.%s' % ( + testCaseClass.__module__, testCaseClass.__qualname__, attrname + ) return self.testNamePatterns is None or \ any(fnmatchcase(fullName, pattern) for pattern in self.testNamePatterns) testFnNames = list(filter(shouldIncludeMethod, dir(testCaseClass))) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index f641e38d..5b8e7441 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -102,6 +102,7 @@ def _check_signature(func, mock, skipfirst, instance=False): sig.bind(*args, **kwargs) _copy_func_details(func, checksig) type(mock)._mock_check_sig = checksig + type(mock).__signature__ = sig def _copy_func_details(func, funcopy): @@ -171,11 +172,11 @@ def _set_signature(mock, original, instance=False): return mock(*args, **kwargs)""" % name exec (src, context) funcopy = context[name] - _setup_func(funcopy, mock) + _setup_func(funcopy, mock, sig) return funcopy -def _setup_func(funcopy, mock): +def _setup_func(funcopy, mock, sig): funcopy.mock = mock # can't use isinstance with mocks @@ -223,6 +224,7 @@ def _setup_func(funcopy, mock): funcopy.assert_called = assert_called funcopy.assert_not_called = assert_not_called funcopy.assert_called_once = assert_called_once + funcopy.__signature__ = sig mock._mock_delegate = funcopy @@ -318,6 +320,14 @@ class _CallList(list): def _check_and_set_parent(parent, value, name, new_name): + # function passed to create_autospec will have mock + # attribute attached to which parent must be set + if isinstance(value, FunctionTypes): + try: + value = value.mock + except AttributeError: + pass + if not _is_instance_mock(value): return False if ((value._mock_name or value._mock_new_name) or @@ -726,11 +736,10 @@ class NonCallableMock(Base): # not set on the instance itself return - if name in self.__dict__: - object.__delattr__(self, name) - obj = self._mock_children.get(name, _missing) - if obj is _deleted: + if name in self.__dict__: + super().__delattr__(name) + elif obj is _deleted: raise AttributeError(name) if obj is not _missing: del self._mock_children[name] @@ -1594,8 +1603,6 @@ class _patch_dict(object): """ def __init__(self, in_dict, values=(), clear=False, **kwargs): - if isinstance(in_dict, str): - in_dict = _importer(in_dict) self.in_dict = in_dict # support any argument supported by dict(...) constructor self.values = dict(values) @@ -1636,6 +1643,8 @@ class _patch_dict(object): def _patch_dict(self): values = self.values + if isinstance(self.in_dict, str): + self.in_dict = _importer(self.in_dict) in_dict = self.in_dict clear = self.clear @@ -2350,7 +2359,7 @@ def mock_open(mock=None, read_data=''): default) then a `MagicMock` will be created for you, with the API limited to methods or attributes available on standard file handles. - `read_data` is a string for the `read` methoddline`, and `readlines` of the + `read_data` is a string for the `read`, `readline` and `readlines` of the file handle to return. This is an empty string by default. """ def _readlines_side_effect(*args, **kwargs): diff --git a/Lib/unittest/runner.py b/Lib/unittest/runner.py index 2c5ea4ab..45e7e4c0 100644 --- a/Lib/unittest/runner.py +++ b/Lib/unittest/runner.py @@ -168,7 +168,7 @@ class TextTestRunner(object): warnings.filterwarnings('module', category=DeprecationWarning, message=r'Please use assert\w+ instead.') - startTime = time.time() + startTime = time.perf_counter() startTestRun = getattr(result, 'startTestRun', None) if startTestRun is not None: startTestRun() @@ -178,7 +178,7 @@ class TextTestRunner(object): stopTestRun = getattr(result, 'stopTestRun', None) if stopTestRun is not None: stopTestRun() - stopTime = time.time() + stopTime = time.perf_counter() timeTaken = stopTime - startTime result.printErrors() if hasattr(result, 'separator2'): diff --git a/Lib/unittest/test/test_loader.py b/Lib/unittest/test/test_loader.py index bfd72294..bc54bf05 100644 --- a/Lib/unittest/test/test_loader.py +++ b/Lib/unittest/test/test_loader.py @@ -1,3 +1,4 @@ +import functools import sys import types import warnings @@ -1575,5 +1576,20 @@ class Test_TestLoader(unittest.TestCase): self.assertIs(loader.suiteClass, unittest.TestSuite) + def test_partial_functions(self): + def noop(arg): + pass + + class Foo(unittest.TestCase): + pass + + setattr(Foo, 'test_partial', functools.partial(noop, None)) + + loader = unittest.TestLoader() + + test_names = ['test_partial'] + self.assertEqual(loader.getTestCaseNames(Foo), test_names) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/unittest/test/testmock/support.py b/Lib/unittest/test/testmock/support.py index 205431ad..73e406f0 100644 --- a/Lib/unittest/test/testmock/support.py +++ b/Lib/unittest/test/testmock/support.py @@ -1,3 +1,6 @@ +target = {'foo': 'FOO'} + + def is_instance(obj, klass): """Version of is_instance that doesn't access __class__""" return issubclass(type(obj), klass) diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py index 9388311e..745580ef 100644 --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -1,3 +1,4 @@ +import inspect import time import types import unittest @@ -901,6 +902,35 @@ class SpecSignatureTest(unittest.TestCase): self.assertFalse(hasattr(autospec, '__name__')) + def test_spec_inspect_signature(self): + + def myfunc(x, y): + pass + + mock = create_autospec(myfunc) + mock(1, 2) + mock(x=1, y=2) + + self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(myfunc)) + self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)]) + self.assertRaises(TypeError, mock, 1) + + + def test_spec_inspect_signature_annotations(self): + + def foo(a: int, b: int=10, *, c:int) -> int: + return a + b + c + + mock = create_autospec(foo) + mock(1, 2, c=3) + mock(1, c=3) + + self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(foo)) + self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)]) + self.assertRaises(TypeError, mock, 1) + self.assertRaises(TypeError, mock, 1, 2, 3, c=4) + + class TestCallList(unittest.TestCase): def test_args_list_contains_call_list(self): diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 49ecbb44..447a502b 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1739,6 +1739,33 @@ class MockTest(unittest.TestCase): self.assertRaises(AttributeError, getattr, mock, 'f') + def test_mock_does_not_raise_on_repeated_attribute_deletion(self): + # bpo-20239: Assigning and deleting twice an attribute raises. + for mock in (Mock(), MagicMock(), NonCallableMagicMock(), + NonCallableMock()): + mock.foo = 3 + self.assertTrue(hasattr(mock, 'foo')) + self.assertEqual(mock.foo, 3) + + del mock.foo + self.assertFalse(hasattr(mock, 'foo')) + + mock.foo = 4 + self.assertTrue(hasattr(mock, 'foo')) + self.assertEqual(mock.foo, 4) + + del mock.foo + self.assertFalse(hasattr(mock, 'foo')) + + + def test_mock_raises_when_deleting_nonexistent_attribute(self): + for mock in (Mock(), MagicMock(), NonCallableMagicMock(), + NonCallableMock()): + del mock.foo + with self.assertRaises(AttributeError): + del mock.foo + + def test_reset_mock_does_not_raise_on_attr_deletion(self): # bpo-31177: reset_mock should not raise AttributeError when attributes # were deleted in a mock instance @@ -1772,5 +1799,18 @@ class MockTest(unittest.TestCase): self.assertEqual(type(call.parent().parent), _Call) + def test_parent_propagation_with_create_autospec(self): + + def foo(a, b): + pass + + mock = Mock() + mock.child = create_autospec(foo) + mock.child(1, 2) + + self.assertRaises(TypeError, mock.child, 1) + self.assertEqual(mock.mock_calls, [call.child(1, 2)]) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index f0522573..c484adb6 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -664,6 +664,23 @@ class PatchTest(unittest.TestCase): test() + def test_patch_dict_decorator_resolution(self): + # bpo-35512: Ensure that patch with a string target resolves to + # the new dictionary during function call + original = support.target.copy() + + @patch.dict('unittest.test.testmock.support.target', {'bar': 'BAR'}) + def test(): + self.assertEqual(support.target, {'foo': 'BAZ', 'bar': 'BAR'}) + + try: + support.target = {'foo': 'BAZ'} + test() + self.assertEqual(support.target, {'foo': 'BAZ'}) + finally: + support.target = original + + def test_patch_descriptor(self): # would be some effort to fix this - we could special case the # builtin descriptors: classmethod, property, staticmethod diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py index 43b36a11..ec4e540d 100644 --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -126,6 +126,20 @@ class WithTest(unittest.TestCase): self.assertEqual(foo, {}) + def test_double_patch_instance_method(self): + class C: + def f(self): + pass + + c = C() + + with patch.object(c, 'f', autospec=True) as patch1: + with patch.object(c, 'f', autospec=True) as patch2: + c.f() + self.assertEqual(patch2.call_count, 1) + self.assertEqual(patch1.call_count, 0) + c.f() + self.assertEqual(patch1.call_count, 1) class TestMockOpen(unittest.TestCase): diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index f691ab74..39c5d6a8 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -391,6 +391,21 @@ def _splitnetloc(url, start=0): delim = min(delim, wdelim) # use earliest delim position return url[start:delim], url[delim:] # return (domain, rest) +def _checknetloc(netloc): + if not netloc or netloc.isascii(): + return + # looking for characters like \u2100 that expand to 'a/c' + # IDNA uses NFKC equivalence, so normalize for this check + import unicodedata + netloc2 = unicodedata.normalize('NFKC', netloc) + if netloc == netloc2: + return + _, _, netloc = netloc.rpartition('@') # anything to the left of '@' is okay + for c in '/?#@:': + if c in netloc2: + raise ValueError("netloc '" + netloc2 + "' contains invalid " + + "characters under NFKC normalization") + def urlsplit(url, scheme='', allow_fragments=True): """Parse a URL into 5 components: :///?# @@ -419,6 +434,7 @@ def urlsplit(url, scheme='', allow_fragments=True): url, fragment = url.split('#', 1) if '?' in url: url, query = url.split('?', 1) + _checknetloc(netloc) v = SplitResult('http', netloc, url, query, fragment) _parse_cache[key] = v return _coerce_result(v) @@ -442,6 +458,7 @@ def urlsplit(url, scheme='', allow_fragments=True): url, fragment = url.split('#', 1) if '?' in url: url, query = url.split('?', 1) + _checknetloc(netloc) v = SplitResult(scheme, netloc, url, query, fragment) _parse_cache[key] = v return _coerce_result(v) diff --git a/Lib/uu.py b/Lib/uu.py index 8333e864..9b1e5e60 100755 --- a/Lib/uu.py +++ b/Lib/uu.py @@ -133,10 +133,7 @@ def decode(in_file, out_file=None, mode=None, quiet=False): out_file = sys.stdout.buffer elif isinstance(out_file, str): fp = open(out_file, 'wb') - try: - os.path.chmod(out_file, mode) - except AttributeError: - pass + os.chmod(out_file, mode) out_file = fp opened_files.append(out_file) # diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index 5438b0d4..d5ab3895 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -64,11 +64,10 @@ class EnvBuilder: self.system_site_packages = False self.create_configuration(context) self.setup_python(context) - if not self.upgrade: - self.setup_scripts(context) if self.with_pip: self._setup_pip(context) if not self.upgrade: + self.setup_scripts(context) self.post_setup(context) if true_system_site_packages: # We had set it to False before, now @@ -107,10 +106,7 @@ class EnvBuilder: context.prompt = '(%s) ' % prompt create_if_needed(env_dir) env = os.environ - if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in env: - executable = os.environ['__PYVENV_LAUNCHER__'] - else: - executable = sys.executable + executable = getattr(sys, '_base_executable', sys.executable) dirname, exename = os.path.split(os.path.abspath(executable)) context.executable = executable context.python_dir = dirname @@ -176,6 +172,23 @@ class EnvBuilder: logger.warning('Unable to symlink %r to %r', src, dst) force_copy = True if force_copy: + if os.name == 'nt': + # On Windows, we rewrite symlinks to our base python.exe into + # copies of venvlauncher.exe + basename, ext = os.path.splitext(os.path.basename(src)) + if basename.endswith('_d'): + ext = '_d' + ext + basename = basename[:-2] + if sysconfig.is_python_build(True): + if basename == 'python': + basename = 'venvlauncher' + elif basename == 'pythonw': + basename = 'venvwlauncher' + scripts = os.path.dirname(src) + else: + scripts = os.path.join(os.path.dirname(__file__), "scripts", "nt") + src = os.path.join(scripts, basename + ext) + shutil.copyfile(src, dst) def setup_python(self, context): @@ -202,23 +215,31 @@ class EnvBuilder: if not os.path.islink(path): os.chmod(path, 0o755) else: - # For normal cases, the venvlauncher will be copied from - # our scripts folder. For builds, we need to copy it - # manually. - if sysconfig.is_python_build(True): - suffix = '.exe' - if context.python_exe.lower().endswith('_d.exe'): - suffix = '_d.exe' - - src = os.path.join(dirname, "venvlauncher" + suffix) - dst = os.path.join(binpath, context.python_exe) - copier(src, dst) + if self.symlinks: + # For symlinking, we need a complete copy of the root directory + # If symlinks fail, you'll get unnecessary copies of files, but + # we assume that if you've opted into symlinks on Windows then + # you know what you're doing. + suffixes = [ + f for f in os.listdir(dirname) if + os.path.normcase(os.path.splitext(f)[1]) in ('.exe', '.dll') + ] + if sysconfig.is_python_build(True): + suffixes = [ + f for f in suffixes if + os.path.normcase(f).startswith(('python', 'vcruntime')) + ] + else: + suffixes = ['python.exe', 'python_d.exe', 'pythonw.exe', + 'pythonw_d.exe'] - src = os.path.join(dirname, "venvwlauncher" + suffix) - dst = os.path.join(binpath, "pythonw" + suffix) - copier(src, dst) + for suffix in suffixes: + src = os.path.join(dirname, suffix) + if os.path.exists(src): + copier(src, os.path.join(binpath, suffix)) - # copy init.tcl over + if sysconfig.is_python_build(True): + # copy init.tcl for root, dirs, files in os.walk(context.python_dir): if 'init.tcl' in files: tcldir = os.path.basename(root) @@ -304,6 +325,9 @@ class EnvBuilder: dirs.remove(d) continue # ignore files in top level for f in files: + if (os.name == 'nt' and f.startswith('python') + and f.endswith(('.exe', '.pdb'))): + continue srcfile = os.path.join(root, f) suffix = root[plen:].split(os.sep)[2:] if not suffix: diff --git a/Lib/warnings.py b/Lib/warnings.py index ae4295e1..9064f568 100644 --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -124,7 +124,7 @@ def _formatwarnmsg(msg): if fw is not _formatwarning_orig: # warnings.formatwarning() was replaced return fw(msg.message, msg.category, - msg.filename, msg.lineno, line=msg.line) + msg.filename, msg.lineno, msg.line) return _formatwarnmsg_impl(msg) def filterwarnings(action, message="", category=Warning, module="", lineno=0, diff --git a/Lib/weakref.py b/Lib/weakref.py index 99de2eab..753f0729 100644 --- a/Lib/weakref.py +++ b/Lib/weakref.py @@ -171,10 +171,11 @@ class WeakValueDictionary(_collections_abc.MutableMapping): if self._pending_removals: self._commit_removals() new = WeakValueDictionary() - for key, wr in self.data.items(): - o = wr() - if o is not None: - new[key] = o + with _IterationGuard(self): + for key, wr in self.data.items(): + o = wr() + if o is not None: + new[key] = o return new __copy__ = copy @@ -184,10 +185,11 @@ class WeakValueDictionary(_collections_abc.MutableMapping): if self._pending_removals: self._commit_removals() new = self.__class__() - for key, wr in self.data.items(): - o = wr() - if o is not None: - new[deepcopy(key, memo)] = o + with _IterationGuard(self): + for key, wr in self.data.items(): + o = wr() + if o is not None: + new[deepcopy(key, memo)] = o return new def get(self, key, default=None): @@ -408,10 +410,11 @@ class WeakKeyDictionary(_collections_abc.MutableMapping): def copy(self): new = WeakKeyDictionary() - for key, value in self.data.items(): - o = key() - if o is not None: - new[o] = value + with _IterationGuard(self): + for key, value in self.data.items(): + o = key() + if o is not None: + new[o] = value return new __copy__ = copy @@ -419,10 +422,11 @@ class WeakKeyDictionary(_collections_abc.MutableMapping): def __deepcopy__(self, memo): from copy import deepcopy new = self.__class__() - for key, value in self.data.items(): - o = key() - if o is not None: - new[o] = deepcopy(value, memo) + with _IterationGuard(self): + for key, value in self.data.items(): + o = key() + if o is not None: + new[o] = deepcopy(value, memo) return new def get(self, key, default=None): diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 5d11bbb1..2e3a61ec 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -227,9 +227,9 @@ def library_recipes(): if internalTk(): result.extend([ dict( - name="Tcl 8.6.9", - url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl8.6.9-src.tar.gz", - checksum='aa0a121d95a0e7b73a036f26028538d4', + name="Tcl 8.6.8", + url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl8.6.8-src.tar.gz", + checksum='81656d3367af032e0ae6157eff134f89', buildDir="unix", configure_pre=[ '--enable-shared', @@ -243,9 +243,12 @@ def library_recipes(): }, ), dict( - name="Tk 8.6.9.1", - url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk8.6.9.1-src.tar.gz", - checksum='9efe3976468352dc894dae0c4e785a8e', + name="Tk 8.6.8", + url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk8.6.8-src.tar.gz", + checksum='5e0faecba458ee1386078fb228d008ba', + patches=[ + "tk868_on_10_8_10_9.patch", + ], buildDir="unix", configure_pre=[ '--enable-aqua', @@ -706,7 +709,6 @@ def extractArchive(builddir, archiveName): work for current Tcl and Tk source releases where the basename of the archive ends with "-src" but the uncompressed directory does not. For now, just special case Tcl and Tk tar.gz downloads. - Another special case: the tk8.6.9.1 tarball extracts to tk8.6.9. """ curdir = os.getcwd() try: @@ -716,8 +718,6 @@ def extractArchive(builddir, archiveName): if ((retval.startswith('tcl') or retval.startswith('tk')) and retval.endswith('-src')): retval = retval[:-4] - if retval == 'tk8.6.9.1': - retval = 'tk8.6.9' if os.path.exists(retval): shutil.rmtree(retval) fp = os.popen("tar zxf %s 2>&1"%(shellQuote(archiveName),), 'r') diff --git a/Mac/BuildScript/tk868_on_10_8_10_9.patch b/Mac/BuildScript/tk868_on_10_8_10_9.patch new file mode 100644 index 00000000..8fe10604 --- /dev/null +++ b/Mac/BuildScript/tk868_on_10_8_10_9.patch @@ -0,0 +1,18 @@ +Fix build failure with +quartz variant on OS X 10.8 and 10.9. +Even though Gestalt was deprecated in OS X 10.8, it should work fine +through OS X 10.9, and its replacement NSOperatingSystemVersion was +not introduced until OS X 10.10. + +Patch from MacPorts project and reported upstream: +https://trac.macports.org/ticket/55649 +--- tk8.6.8/macosx/tkMacOSXXStubs.c.orig 2017-12-06 09:25:08.000000000 -0600 ++++ tk8.6.8-patched/macosx/tkMacOSXXStubs.c 2018-01-06 19:34:17.000000000 -0600 +@@ -175,7 +175,7 @@ + { + int major, minor, patch; + +-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 ++#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 + Gestalt(gestaltSystemVersionMajor, (SInt32*)&major); + Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor); + Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch); diff --git a/Mac/IDLE/IDLE.app/Contents/Info.plist b/Mac/IDLE/IDLE.app/Contents/Info.plist index 826d3793..04a0a08c 100644 --- a/Mac/IDLE/IDLE.app/Contents/Info.plist +++ b/Mac/IDLE/IDLE.app/Contents/Info.plist @@ -36,7 +36,7 @@ CFBundleExecutable IDLE CFBundleGetInfoString - %version%, © 2001-2018 Python Software Foundation + %version%, © 2001-2019 Python Software Foundation CFBundleIconFile IDLE.icns CFBundleIdentifier diff --git a/Mac/PythonLauncher/Info.plist.in b/Mac/PythonLauncher/Info.plist.in index 5fa346ed..9fb4e0af 100644 --- a/Mac/PythonLauncher/Info.plist.in +++ b/Mac/PythonLauncher/Info.plist.in @@ -40,7 +40,7 @@ CFBundleExecutable Python Launcher CFBundleGetInfoString - %VERSION%, © 2001-2018 Python Software Foundation + %VERSION%, © 2001-2019 Python Software Foundation CFBundleIconFile PythonLauncher.icns CFBundleIdentifier diff --git a/Mac/Resources/app/Info.plist.in b/Mac/Resources/app/Info.plist.in index abe9ae23..b7581984 100644 --- a/Mac/Resources/app/Info.plist.in +++ b/Mac/Resources/app/Info.plist.in @@ -37,7 +37,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - %version%, (c) 2001-2018 Python Software Foundation. + %version%, (c) 2001-2019 Python Software Foundation. CFBundleName Python CFBundlePackageType diff --git a/Mac/Resources/framework/Info.plist.in b/Mac/Resources/framework/Info.plist.in index c1ea9f68..0dc2e171 100644 --- a/Mac/Resources/framework/Info.plist.in +++ b/Mac/Resources/framework/Info.plist.in @@ -17,9 +17,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - %VERSION%, (c) 2001-2018 Python Software Foundation. + %VERSION%, (c) 2001-2019 Python Software Foundation. CFBundleLongVersionString - %VERSION%, (c) 2001-2018 Python Software Foundation. + %VERSION%, (c) 2001-2019 Python Software Foundation. CFBundleSignature ???? CFBundleVersion diff --git a/Misc/ACKS b/Misc/ACKS index c35ef1c0..19359229 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -60,6 +60,7 @@ Heidi Annexstad Ramchandra Apte Éric Araujo Alexandru Ardelean +Emmanuel Arias Alicia Arlen Jeffrey Armstrong Jason Asbahr @@ -894,6 +895,7 @@ Glenn Langford Andrew Langmead Wolfgang Langner Detlef Lannert +Rémi Lapeyre Soren Larsen Amos Latteier Piers Lauder @@ -1821,3 +1823,4 @@ Jelle Zijlstra Gennadiy Zlobin Doug Zongker Peter Åstrand +Zheao Li diff --git a/Misc/NEWS b/Misc/NEWS index bce9073b..66cd4389 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,443 @@ Python News +++++++++++ +What's New in Python 3.7.3 final? +================================= + +*Release date: 2019-03-25* + +There were no new changes in version 3.7.3. + + + +What's New in Python 3.7.3 release candidate 1? +=============================================== + +*Release date: 2019-03-12* + +Security +-------- + +- bpo-36216: Changes urlsplit() to raise ValueError when the URL contains + characters that decompose under IDNA encoding (NFKC-normalization) into + characters that affect how the URL is parsed. + +- bpo-35746: [CVE-2019-5010] Fix a NULL pointer deref in ssl module. The + cert parser did not handle CRL distribution points with empty DP or URI + correctly. A malicious or buggy certificate can result into segfault. + Vulnerability (TALOS-2018-0758) reported by Colin Read and Nicolas Edet of + Cisco. + +- bpo-35121: Don't send cookies of domain A without Domain attribute to + domain B when domain A is a suffix match of domain B while using a + cookiejar with :class:`http.cookiejar.DefaultCookiePolicy` policy. Patch + by Karthikeyan Singaravelan. + +Core and Builtins +----------------- + +- bpo-35942: The error message emitted when returning invalid types from + ``__fspath__`` in interfaces that allow passing :class:`~os.PathLike` + objects has been improved and now it does explain the origin of the error. + +- bpo-35992: Fix ``__class_getitem__()`` not being called on a class with a + custom non-subscriptable metaclass. + +- bpo-35991: Fix a potential double free in Modules/_randommodule.c. + +- bpo-35961: Fix a crash in slice_richcompare(): use strong references + rather than stolen references for the two temporary internal tuples. + +- bpo-31506: Clarify the errors reported when ``object.__new__`` and + ``object.__init__`` receive more than one argument. Contributed by Sanyam + Khurana. + +- bpo-35720: Fixed a minor memory leak in pymain_parse_cmdline_impl function + in Modules/main.c + +- bpo-35623: Fix a crash when sorting very long lists. Patch by Stephan + Hohe. + +- bpo-35214: clang Memory Sanitizer build instrumentation was added to work + around false positives from posix, socket, time, test_io, and + test_faulthandler. + +- bpo-35560: Fix an assertion error in :func:`format` in debug build for + floating point formatting with "n" format, zero padding and small width. + Release build is not impacted. Patch by Karthikeyan Singaravelan. + +- bpo-35552: Format characters ``%s`` and ``%V`` in + :c:func:`PyUnicode_FromFormat` and ``%s`` in :c:func:`PyBytes_FromFormat` + no longer read memory past the limit if *precision* is specified. + +- bpo-35504: Fix segfaults and :exc:`SystemError`\ s when deleting certain + attributes. Patch by Zackery Spytz. + +- bpo-33989: Fix a possible crash in :meth:`list.sort` when sorting objects + with ``ob_type->tp_richcompare == NULL``. Patch by Zackery Spytz. + +Library +------- + +- bpo-35931: The :mod:`pdb` ``debug`` command now gracefully handles all + exceptions. + +- bpo-36251: Fix format strings used for stderrprinter and re.Match reprs. + Patch by Stephan Hohe. + +- bpo-35807: Update ensurepip to install pip 19.0.3 and setuptools 40.8.0. + +- bpo-36179: Fix two unlikely reference leaks in _hashopenssl. The leaks + only occur in out-of-memory cases. + +- bpo-35178: Ensure custom :func:`warnings.formatwarning` function can + receive `line` as positional argument. Based on patch by Tashrif Billah. + +- bpo-36106: Resolve potential name clash with libm's sinpi(). Patch by + Dmitrii Pasechnik. + +- bpo-35512: :func:`unittest.mock.patch.dict` used as a decorator with + string target resolves the target during function call instead of during + decorator construction. Patch by Karthikeyan Singaravelan. + +- bpo-36091: Clean up reference to async generator in Lib/types. Patch by + Henry Chen. + +- bpo-35899: Enum has been fixed to correctly handle empty strings and + strings with non-Latin characters (ie. 'α', 'א') without crashing. + Original patch contributed by Maxwell. Assisted by Stéphane Wirtel. + +- bpo-35918: Removed broken ``has_key`` method from + multiprocessing.managers.SyncManager.dict. Contributed by Rémi Lapeyre. + +- bpo-35960: Fix :func:`dataclasses.field` throwing away empty mapping + objects passed as metadata. + +- bpo-35847: RISC-V needed the CTYPES_PASS_BY_REF_HACK. Fixes ctypes + Structure test_pass_by_value. + +- bpo-35780: Fix lru_cache() errors arising in recursive, reentrant, or + multi-threaded code. These errors could result in orphan links and in the + cache being trapped in a state with fewer than the specified maximum + number of links. Fix handling of negative maxsize which should have been + treated as zero. Fix errors in toggling the "full" status flag. Fix + misordering of links when errors are encountered. Sync-up the C code and + pure Python code for the space saving path in functions with a single + positional argument. In this common case, the space overhead of an lru + cache entry is reduced by almost half. Fix counting of cache misses. In + error cases, the miss count was out of sync with the actual number of + times the underlying user function was called. + +- bpo-23846: :class:`asyncio.ProactorEventLoop` now catches and logs send + errors when the self-pipe is full. + +- bpo-34323: :mod:`asyncio`: Enhance ``IocpProactor.close()`` log: wait 1 + second before the first log, then log every second. Log also the number of + seconds since ``close()`` was called. + +- bpo-34294: re module, fix wrong capturing groups in rare cases. + :func:`re.search`, :func:`re.findall`, :func:`re.sub` and other functions + that scan through string looking for a match, should reset capturing + groups between two match attempts. Patch by Ma Lin. + +- bpo-35717: Fix KeyError exception raised when using enums and compile. + Patch contributed by Rémi Lapeyre. + +- bpo-35699: Fixed detection of Visual Studio Build Tools 2017 in distutils + +- bpo-32710: Fix memory leaks in asyncio ProactorEventLoop on overlapped + operation failure. + +- bpo-32710: Fix a memory leak in asyncio in the ProactorEventLoop when + ``ReadFile()`` or ``WSASend()`` overlapped operation fail immediately: + release the internal buffer. + +- bpo-35682: Fix ``asyncio.ProactorEventLoop.sendfile()``: don't attempt to + set the result of an internal future if it's already done. + +- bpo-35283: Add a pending deprecated warning for the + :meth:`threading.Thread.isAlive` method. Patch by Dong-hee Na. + +- bpo-35643: Fixed a SyntaxWarning: invalid escape sequence in + Modules/_sha3/cleanup.py. Patch by Mickaël Schoentgen. + +- bpo-35615: :mod:`weakref`: Fix a RuntimeError when copying a + WeakKeyDictionary or a WeakValueDictionary, due to some keys or values + disappearing while iterating. + +- bpo-28503: The `crypt` module now internally uses the `crypt_r()` library + function instead of `crypt()` when available. + +- bpo-35121: Don't set cookie for a request when the request path is a + prefix match of the cookie's path attribute but doesn't end with "/". + Patch by Karthikeyan Singaravelan. + +- bpo-35585: Speed-up building enums by value, e.g. http.HTTPStatus(200). + +- bpo-21478: Calls to a child function created with + :func:`unittest.mock.create_autospec` should propagate to the parent. + Patch by Karthikeyan Singaravelan. + +- bpo-35513: :class:`~unittest.runner.TextTestRunner` of + :mod:`unittest.runner` now uses :func:`time.perf_counter` rather than + :func:`time.time` to measure the execution time of a test: + :func:`time.time` can go backwards, whereas :func:`time.perf_counter` is + monotonic. + +- bpo-35502: Fixed reference leaks in + :class:`xml.etree.ElementTree.TreeBuilder` in case of unfinished building + of the tree (in particular when an error was raised during parsing XML). + +- bpo-31446: Copy command line that was passed to CreateProcessW since this + function can change the content of the input buffer. + +- bpo-20239: Allow repeated assignment deletion of + :class:`unittest.mock.Mock` attributes. Patch by Pablo Galindo. + +- bpo-17185: Set ``__signature__`` on mock for :mod:`inspect` to get + signature. Patch by Karthikeyan Singaravelan. + +- bpo-10496: :func:`~distutils.utils.check_environ` of + :mod:`distutils.utils` now catches :exc:`KeyError` on calling + :func:`pwd.getpwuid`: don't create the ``HOME`` environment variable in + this case. + +- bpo-35066: Previously, calling the strftime() method on a datetime object + with a trailing '%' in the format string would result in an exception. + However, this only occured when the datetime C module was being used; the + python implementation did not match this behavior. Datetime is now PEP-399 + compliant, and will not throw an exception on a trailing '%'. + +- bpo-24746: Avoid stripping trailing whitespace in doctest fancy diff. + Orignial patch by R. David Murray & Jairo Trad. Enhanced by Sanyam + Khurana. + +- bpo-35198: Fix C++ extension compilation on AIX + +- bpo-28441: On Cygwin and MinGW, ensure that ``sys.executable`` always + includes the full filename in the path, including the ``.exe`` suffix + (unless it is a symbolic link). + +- bpo-34572: Fix C implementation of pickle.loads to use importlib's locking + mechanisms, and thereby avoid using partially-loaded modules. Patch by Tim + Burgess. + +- bpo-33687: Fix the call to ``os.chmod()`` for ``uu.decode()`` if a mode is + given or decoded. Patch by Timo Furrer. + +- bpo-32146: Document the interaction between frozen executables and the + spawn and forkserver start methods in multiprocessing. + +Documentation +------------- + +- bpo-36083: Fix formatting of --check-hash-based-pycs options in the + manpage Synopsis. + +- bpo-34764: Improve example of iter() with 2nd sentinel argument. + +- bpo-21314: A new entry was added to the Core Language Section of the + Programming FAQ, which explaines the usage of slash(/) in the signature of + a function. Patch by Lysandros Nikolaou + +- bpo-22062: Update documentation and docstrings for pathlib. Original patch + by Mike Short. + +Tests +----- + +- bpo-36234: test_posix.PosixUidGidTests: add tests for invalid uid/gid type + (str). Initial patch written by David Malcolm. + +- bpo-29571: Fix ``test_re.test_locale_flag()``: use + ``locale.getpreferredencoding()`` rather than ``locale.getlocale()`` to + get the locale encoding. With some locales, ``locale.getlocale()`` returns + the wrong encoding. On Windows, set temporarily the ``LC_CTYPE`` locale to + the user preferred encoding to ensure that it uses the ANSI code page, to + be consistent with ``locale.getpreferredencoding()``. + +- bpo-36123: Fix race condition in test_socket. + +- bpo-27313: Avoid test_ttk_guionly ComboboxTest failure with macOS Cocoa + Tk. + +- bpo-36019: Add test.support.TEST_HTTP_URL and replace references of + http://www.example.com by this new constant. Contributed by Stéphane + Wirtel. + +- bpo-36037: Fix test_ssl for strict OpenSSL configuration like RHEL8 strict + crypto policy. Use older TLS version for minimum TLS version of the server + SSL context if needed, to test TLS version older than default minimum TLS + version. + +- bpo-35505: Make test_imap4_host_default_value independent on whether the + local IMAP server is running. + +- bpo-35917: multiprocessing: provide unit tests for SyncManager and + SharedMemoryManager classes + all the shareable types which are supposed + to be supported by them. (patch by Giampaolo Rodola) + +- bpo-35772: Fix sparse file tests of test_tarfile on ppc64 with the tmpfs + filesystem. Fix the function testing if the filesystem supports sparse + files: create a file which contains data and "holes", instead of creating + a file which contains no data. tmpfs effective block size is a page size + (tmpfs lives in the page cache). RHEL uses 64 KiB pages on aarch64, ppc64, + ppc64le, only s390x and x86_64 use 4 KiB pages, whereas the test punch + holes of 4 KiB. + +- bpo-35045: Make ssl tests less strict and also accept TLSv1 as system + default. The changes unbreaks test_min_max_version on Fedora 29. + +- bpo-31731: Fix a race condition in ``check_interrupted_write()`` of + test_io: create directly the thread with SIGALRM signal blocked, rather + than blocking the signal later from the thread. Previously, it was + possible that the thread gets the signal before the signal is blocked. + +- bpo-35424: Fix test_multiprocessing_main_handling: use + :class:`multiprocessing.Pool` with a context manager and then explicitly + join the pool. + +- bpo-35519: Rename :mod:`test.bisect` module to :mod:`test.bisect_cmd` to + avoid conflict with :mod:`bisect` module when running directly a test like + ``./python Lib/test/test_xmlrpc.py``. + +- bpo-35513: Replace :func:`time.time` with :func:`time.monotonic` in tests + to measure time delta. + +- bpo-34279: :func:`test.support.run_unittest` no longer raise + :exc:`TestDidNotRun` if the test result contains skipped tests. The + exception is now only raised if no test have been run and no test have + been skipped. + +- bpo-35412: Add testcase to ``test_future4``: check unicode literal. + +- bpo-26704: Added test demonstrating double-patching of an instance method. + Patch by Anthony Sottile. + +Build +----- + +- bpo-34691: The _contextvars module is now built into the core Python + library on Windows. + +- bpo-35683: Improved Azure Pipelines build steps and now verifying layouts + correctly + +- bpo-35642: Remove asynciomodule.c from pythoncore.vcxproj + +- bpo-35550: Fix incorrect Solaris #ifdef checks to look for __sun && __SVR4 + instead of sun when compiling. + +Windows +------- + +- bpo-24643: Fix name collisions due to ``#define timezone _timezone`` in + PC/pyconfig.h. + +- bpo-35692: ``pathlib`` no longer raises when checking file and directory + existence on drives that are not ready + +- bpo-35872: Uses the base Python executable when invoking venv in a virtual + environment + +- bpo-35873: Prevents venv paths being inherited by child processes + +- bpo-35299: Fix sysconfig detection of the source directory and distutils + handling of pyconfig.h during PGO profiling + +- bpo-32560: The ``py`` launcher now forwards its ``STARTUPINFO`` structure + to child processes. + +- bpo-35854: Fix EnvBuilder and --symlinks in venv on Windows + +- bpo-35811: Avoid propagating venv settings when launching via py.exe + +- bpo-35797: Fix default executable used by the multiprocessing module + +- bpo-29734: Fix handle leaks in os.stat on Windows. + +- bpo-35596: Use unchecked PYCs for the embeddable distro to avoid zipimport + restrictions. + +- bpo-35596: Fix vcruntime140.dll being added to embeddable distro multiple + times. + +- bpo-35402: Update Windows build to use Tcl and Tk 8.6.9 + +- bpo-33316: PyThread_release_lock always fails + +- bpo-1104: Correctly handle string length in + ``msilib.SummaryInfo.GetProperty()`` to prevent it from truncating the + last character. + +IDLE +---- + +- bpo-36176: Fix IDLE autocomplete & calltip popup colors. Prevent conflicts + with Linux dark themes (and slightly darken calltip background). + +- bpo-36152: Remove colorizer.ColorDelegator.close_when_done and the + corresponding argument of .close(). In IDLE, both have always been None + or False since 2007. + +- bpo-32129: Avoid blurry IDLE application icon on macOS with Tk 8.6. Patch + by Kevin Walzer. + +- bpo-24310: IDLE -- Document settings dialog font tab sample. + +- bpo-36096: Refactor class variables to instance variables in colorizer. + +- bpo-35833: Revise IDLE doc for control codes sent to Shell. Add a code + example block. + +- bpo-35770: IDLE macosx deletes Options => Configure IDLE. It previously + deleted Window => Zoom Height by mistake. (Zoom Height is now on the + Options menu). On Mac, the settings dialog is accessed via Preferences on + the IDLE menu. + +- bpo-35769: Change IDLE's new file name from 'Untitled' to 'untitled' + +- bpo-35689: Add docstrings and unittests for colorizer.py. + +- bpo-35660: Fix imports in idlelib.window. + +- bpo-35641: Proper format `calltip` when the function has no docstring. + +- bpo-33987: Use ttk Frame for ttk widgets. + +- bpo-34055: Fix erroneous 'smart' indents and newlines in IDLE Shell. + +- bpo-35591: Find Selection now works when selection not found. + +- bpo-35196: Speed up squeezer line counting. + +- bpo-35598: Update config_key: use PEP 8 names and ttk widgets, make some + objects global, and add tests. + +- bpo-28097: Add Previous/Next History entries to Shell menu. + +- bpo-35208: Squeezer now properly counts wrapped lines before newlines. + +- bpo-35555: Gray out Code Context menu entry when it's not applicable. + +- bpo-35521: Document the IDLE editor code context feature. Add some + internal references within the IDLE doc. + +- bpo-22703: The Code Context menu label now toggles between Show/Hide Code + Context. The Zoom Height menu now toggles between Zoom/Restore Height. + Zoom Height has moved from the Window menu to the Options menu. + +Tools/Demos +----------- + +- bpo-35132: Fix py-list and py-bt commands of python-gdb.py on gdb7. + +C API +----- + +- bpo-33817: Fixed :c:func:`_PyBytes_Resize` for empty bytes objects. + + What's New in Python 3.7.2 final? ================================= @@ -344,7 +781,10 @@ Windows macOS ----- -- bpo-35402: Update macOS installer to use Tcl/Tk 8.6.9.1. +- bpo-35402: Update macOS installer to use Tcl/Tk 8.6.9.1. [NOTE: This + change was reverted for the released python.org 3.7.2 macOS installers due + to regressions found in Tk 8.6.9.1. For now, the installers provide + Tcl/Tk 8.6.8.] - bpo-35401: Update macOS installer to use OpenSSL 1.1.0j. @@ -1008,11 +1448,11 @@ IDLE Tools/Demos ----------- -- bpo-32962: python-gdb now catchs ``UnicodeDecodeError`` exceptions when +- bpo-32962: python-gdb now catches ``UnicodeDecodeError`` exceptions when calling ``string()``. -- bpo-32962: python-gdb now catchs ValueError on read_var(): when Python has - no debug symbols for example. +- bpo-32962: python-gdb now catches ValueError on read_var(): when Python + has no debug symbols for example. C API ----- diff --git a/Misc/python.man b/Misc/python.man index 3cdf8840..8d5ad8cd 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -75,7 +75,11 @@ python \- an interpreted, interactive, object-oriented programming language .br [ .B \--check-hash-based-pycs -\'default\'|\'always\'|\'never\' +.I default +| +.I always +| +.I never ] .br [ diff --git a/Modules/_abc.c b/Modules/_abc.c index 36c1757b..1fbf3a83 100644 --- a/Modules/_abc.c +++ b/Modules/_abc.c @@ -66,7 +66,7 @@ PyDoc_STRVAR(abc_data_doc, "Internal state held by ABC machinery."); static PyTypeObject _abc_data_type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) + PyVarObject_HEAD_INIT(NULL, 0) "_abc_data", /*tp_name*/ sizeof(_abc_data), /*tp_basicsize*/ .tp_dealloc = (destructor)abc_data_dealloc, diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 5816a674..35264f58 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1110,6 +1110,10 @@ FutureObj_set_blocking(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored)) if (future_ensure_alive(fut)) { return -1; } + if (val == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } int is_true = PyObject_IsTrue(val); if (is_true < 0) { @@ -1134,6 +1138,10 @@ FutureObj_get_log_traceback(FutureObj *fut, void *Py_UNUSED(ignored)) static int FutureObj_set_log_traceback(FutureObj *fut, PyObject *val, void *Py_UNUSED(ignored)) { + if (val == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } int is_true = PyObject_IsTrue(val); if (is_true < 0) { return -1; @@ -2008,6 +2016,10 @@ TaskObj_get_log_destroy_pending(TaskObj *task, void *Py_UNUSED(ignored)) static int TaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val, void *Py_UNUSED(ignored)) { + if (val == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } int is_true = PyObject_IsTrue(val); if (is_true < 0) { return -1; diff --git a/Modules/_cryptmodule.c b/Modules/_cryptmodule.c index 58d179e6..5d03f45f 100644 --- a/Modules/_cryptmodule.c +++ b/Modules/_cryptmodule.c @@ -34,7 +34,15 @@ static PyObject * crypt_crypt_impl(PyObject *module, const char *word, const char *salt) /*[clinic end generated code: output=0512284a03d2803c input=0e8edec9c364352b]*/ { - return Py_BuildValue("s", crypt(word, salt)); + char *crypt_result; +#ifdef HAVE_CRYPT_R + struct crypt_data data; + memset(&data, 0, sizeof(data)); + crypt_result = crypt_r(word, salt, &data); +#else + crypt_result = crypt(word, salt); +#endif + return Py_BuildValue("s", crypt_result); } diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index c5fc811a..f98eabbb 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1171,6 +1171,10 @@ CharArray_set_raw(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) Py_ssize_t size; Py_buffer view; + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) < 0) return -1; size = view.len; @@ -3405,20 +3409,23 @@ PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } #endif - Py_INCREF(dll); /* for KeepRef */ - Py_DECREF(ftuple); - if (!_validate_paramflags(type, paramflags)) + if (!_validate_paramflags(type, paramflags)) { + Py_DECREF(ftuple); return NULL; + } self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds); - if (!self) + if (!self) { + Py_DECREF(ftuple); return NULL; + } Py_XINCREF(paramflags); self->paramflags = paramflags; *(void **)self->b_ptr = address; - + Py_INCREF(dll); + Py_DECREF(ftuple); if (-1 == KeepRef((CDataObject *)self, 0, dll)) { Py_DECREF((PyObject *)self); return NULL; diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index ec596b4d..e971388f 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1052,7 +1052,7 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk) #endif #if (defined(__x86_64__) && (defined(__MINGW64__) || defined(__CYGWIN__))) || \ - defined(__aarch64__) + defined(__aarch64__) || defined(__riscv) #define CTYPES_PASS_BY_REF_HACK #define POW2(x) (((x & ~(x - 1)) == x) ? x : 0) #define IS_PASS_BY_REF(x) (x > 8 || !POW2(x)) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 5afeeea4..9405b461 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1514,10 +1514,13 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, ntoappend = 1; } else if ((ch = *pin++) == '\0') { - /* There's a lone trailing %; doesn't make sense. */ - PyErr_SetString(PyExc_ValueError, "strftime format " - "ends with raw %"); - goto Done; + /* Null byte follows %, copy only '%'. + * + * Back the pin up one char so that we catch the null check + * the next time through the loop.*/ + pin--; + ptoappend = pin - 1; + ntoappend = 1; } /* A % has been seen and ch is the character after it. */ else if (ch == 'z') { @@ -1602,7 +1605,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, usednew += ntoappend; assert(usednew <= totalnew); } /* end while() */ - + if (_PyBytes_Resize(&newfmt, usednew) < 0) goto Done; { diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index ff3a240f..79f1ccd6 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2429,6 +2429,11 @@ _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, static int treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg) { + Py_VISIT(self->end_ns_event_obj); + Py_VISIT(self->start_ns_event_obj); + Py_VISIT(self->end_event_obj); + Py_VISIT(self->start_event_obj); + Py_VISIT(self->events_append); Py_VISIT(self->root); Py_VISIT(self->this); Py_VISIT(self->last); diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index ff4172d6..c6a92ed1 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -661,6 +661,26 @@ sequence is empty."); /* lru_cache object **********************************************************/ +/* There are four principal algorithmic differences from the pure python version: + + 1). The C version relies on the GIL instead of having its own reentrant lock. + + 2). The prev/next link fields use borrowed references. + + 3). For a full cache, the pure python version rotates the location of the + root entry so that it never has to move individual links and it can + limit updates to just the key and result fields. However, in the C + version, links are temporarily removed while the cache dict updates are + occurring. Afterwards, they are appended or prepended back into the + doubly-linked lists. + + 4) In the Python version, the _HashSeq class is used to prevent __hash__ + from being called more than once. In the C version, the "known hash" + variants of dictionary calls as used to the same effect. + +*/ + + /* this object is used delimit args and keywords in the cache keys */ static PyObject *kwd_mark = NULL; @@ -711,16 +731,15 @@ typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject * typedef struct lru_cache_object { lru_list_elem root; /* includes PyObject_HEAD */ - Py_ssize_t maxsize; - PyObject *maxsize_O; - PyObject *func; lru_cache_ternaryfunc wrapper; + int typed; PyObject *cache; + Py_ssize_t hits; + PyObject *func; + Py_ssize_t maxsize; + Py_ssize_t misses; PyObject *cache_info_type; - Py_ssize_t misses, hits; - int typed; PyObject *dict; - int full; } lru_cache_object; static PyTypeObject lru_cache_type; @@ -733,6 +752,15 @@ lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) /* short path, key will match args anyway, which is a tuple */ if (!typed && !kwds) { + if (PyTuple_GET_SIZE(args) == 1) { + key = PyTuple_GET_ITEM(args, 0); + if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) { + /* For common scalar keys, save space by + dropping the enclosing args tuple */ + Py_INCREF(key); + return key; + } + } Py_INCREF(args); return args; } @@ -788,10 +816,12 @@ lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) static PyObject * uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) { - PyObject *result = PyObject_Call(self->func, args, kwds); + PyObject *result; + + self->misses++; + result = PyObject_Call(self->func, args, kwds); if (!result) return NULL; - self->misses++; return result; } @@ -819,6 +849,7 @@ infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwd Py_DECREF(key); return NULL; } + self->misses++; result = PyObject_Call(self->func, args, kwds); if (!result) { Py_DECREF(key); @@ -830,15 +861,16 @@ infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwd return NULL; } Py_DECREF(key); - self->misses++; return result; } static void -lru_cache_extricate_link(lru_list_elem *link) +lru_cache_extract_link(lru_list_elem *link) { - link->prev->next = link->next; - link->next->prev = link->prev; + lru_list_elem *link_prev = link->prev; + lru_list_elem *link_next = link->next; + link_prev->next = link->next; + link_next->prev = link->prev; } static void @@ -851,11 +883,52 @@ lru_cache_append_link(lru_cache_object *self, lru_list_elem *link) link->next = root; } +static void +lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link) +{ + lru_list_elem *root = &self->root; + lru_list_elem *first = root->next; + first->prev = root->next = link; + link->prev = root; + link->next = first; +} + +/* General note on reentrancy: + + There are four dictionary calls in the bounded_lru_cache_wrapper(): + 1) The initial check for a cache match. 2) The post user-function + check for a cache match. 3) The deletion of the oldest entry. + 4) The addition of the newest entry. + + In all four calls, we have a known hash which lets use avoid a call + to __hash__(). That leaves only __eq__ as a possible source of a + reentrant call. + + The __eq__ method call is always made for a cache hit (dict access #1). + Accordingly, we have make sure not modify the cache state prior to + this call. + + The __eq__ method call is never made for the deletion (dict access #3) + because it is an identity match. + + For the other two accesses (#2 and #4), calls to __eq__ only occur + when some other entry happens to have an exactly matching hash (all + 64-bits). Though rare, this can happen, so we have to make sure to + either call it at the top of its code path before any cache + state modifications (dict access #2) or be prepared to restore + invariants at the end of the code path (dict access #4). + + Another possible source of reentrancy is a decref which can trigger + arbitrary code execution. To make the code easier to reason about, + the decrefs are deferred to the end of the each possible code path + so that we know the cache is a consistent state. + */ + static PyObject * bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) { lru_list_elem *link; - PyObject *key, *result; + PyObject *key, *result, *testresult; Py_hash_t hash; key = lru_cache_make_key(args, kwds, self->typed); @@ -867,11 +940,11 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds return NULL; } link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash); - if (link) { - lru_cache_extricate_link(link); + if (link != NULL) { + lru_cache_extract_link(link); lru_cache_append_link(self, link); - self->hits++; result = link->result; + self->hits++; Py_INCREF(result); Py_DECREF(key); return result; @@ -880,65 +953,38 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds Py_DECREF(key); return NULL; } + self->misses++; result = PyObject_Call(self->func, args, kwds); if (!result) { Py_DECREF(key); return NULL; } - if (self->full && self->root.next != &self->root) { - /* Use the oldest item to store the new key and result. */ - PyObject *oldkey, *oldresult, *popresult; - /* Extricate the oldest item. */ - link = self->root.next; - lru_cache_extricate_link(link); - /* Remove it from the cache. - The cache dict holds one reference to the link, - and the linked list holds yet one reference to it. */ - popresult = _PyDict_Pop_KnownHash(self->cache, - link->key, link->hash, - Py_None); - if (popresult == Py_None) { - /* Getting here means that this same key was added to the - cache while the lock was released. Since the link - update is already done, we need only return the - computed result and update the count of misses. */ - Py_DECREF(popresult); - Py_DECREF(link); - Py_DECREF(key); - } - else if (popresult == NULL) { - lru_cache_append_link(self, link); - Py_DECREF(key); - Py_DECREF(result); - return NULL; - } - else { - Py_DECREF(popresult); - /* Keep a reference to the old key and old result to - prevent their ref counts from going to zero during the - update. That will prevent potentially arbitrary object - clean-up code (i.e. __del__) from running while we're - still adjusting the links. */ - oldkey = link->key; - oldresult = link->result; - - link->hash = hash; - link->key = key; - link->result = result; - if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, - hash) < 0) { - Py_DECREF(link); - Py_DECREF(oldkey); - Py_DECREF(oldresult); - return NULL; - } - lru_cache_append_link(self, link); - Py_INCREF(result); /* for return */ - Py_DECREF(oldkey); - Py_DECREF(oldresult); - } - } else { - /* Put result in a new link at the front of the queue. */ + testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash); + if (testresult != NULL) { + /* Getting here means that this same key was added to the cache + during the PyObject_Call(). Since the link update is already + done, we need only return the computed result. */ + Py_DECREF(key); + return result; + } + if (PyErr_Occurred()) { + /* This is an unusual case since this same lookup + did not previously trigger an error during lookup. + Treat it the same as an error in user function + and return with the error set. */ + Py_DECREF(key); + Py_DECREF(result); + return NULL; + } + /* This is the normal case. The new key wasn't found before + user function call and it is still not there. So we + proceed normally and update the cache with the new result. */ + + assert(self->maxsize > 0); + if (PyDict_GET_SIZE(self->cache) < self->maxsize || + self->root.next == &self->root) + { + /* Cache is not full, so put the result in a new link */ link = (lru_list_elem *)PyObject_New(lru_list_elem, &lru_list_elem_type); if (link == NULL) { @@ -950,6 +996,11 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds link->hash = hash; link->key = key; link->result = result; + /* What is really needed here is a SetItem variant with a "no clobber" + option. If the __eq__ call triggers a reentrant call that adds + this same key, then this setitem call will update the cache dict + with this new link, leaving the old link as an orphan (i.e. not + having a cache dict entry that refers to it). */ if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, hash) < 0) { Py_DECREF(link); @@ -957,9 +1008,84 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds } lru_cache_append_link(self, link); Py_INCREF(result); /* for return */ - self->full = (PyDict_GET_SIZE(self->cache) >= self->maxsize); + return result; } - self->misses++; + /* Since the cache is full, we need to evict an old key and add + a new key. Rather than free the old link and allocate a new + one, we reuse the link for the new key and result and move it + to front of the cache to mark it as recently used. + + We try to assure all code paths (including errors) leave all + of the links in place. Either the link is successfully + updated and moved or it is restored to its old position. + However if an unrecoverable error is found, it doesn't + make sense to reinsert the link, so we leave it out + and the cache will no longer register as full. + */ + PyObject *oldkey, *oldresult, *popresult; + + /* Extract the oldest item. */ + assert(self->root.next != &self->root); + link = self->root.next; + lru_cache_extract_link(link); + /* Remove it from the cache. + The cache dict holds one reference to the link. + We created one other reference when the link was created. + The linked list only has borrowed references. */ + popresult = _PyDict_Pop_KnownHash(self->cache, link->key, + link->hash, Py_None); + if (popresult == Py_None) { + /* Getting here means that the user function call or another + thread has already removed the old key from the dictionary. + This link is now an orphan. Since we don't want to leave the + cache in an inconsistent state, we don't restore the link. */ + Py_DECREF(popresult); + Py_DECREF(link); + Py_DECREF(key); + return result; + } + if (popresult == NULL) { + /* An error arose while trying to remove the oldest key (the one + being evicted) from the cache. We restore the link to its + original position as the oldest link. Then we allow the + error propagate upward; treating it the same as an error + arising in the user function. */ + lru_cache_prepend_link(self, link); + Py_DECREF(key); + Py_DECREF(result); + return NULL; + } + /* Keep a reference to the old key and old result to prevent their + ref counts from going to zero during the update. That will + prevent potentially arbitrary object clean-up code (i.e. __del__) + from running while we're still adjusting the links. */ + oldkey = link->key; + oldresult = link->result; + + link->hash = hash; + link->key = key; + link->result = result; + /* Note: The link is being added to the cache dict without the + prev and next fields set to valid values. We have to wait + for successful insertion in the cache dict before adding the + link to the linked list. Otherwise, the potentially reentrant + __eq__ call could cause the then orphan link to be visited. */ + if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, + hash) < 0) { + /* Somehow the cache dict update failed. We no longer can + restore the old link. Let the error propagate upward and + leave the cache short one link. */ + Py_DECREF(popresult); + Py_DECREF(link); + Py_DECREF(oldkey); + Py_DECREF(oldresult); + return NULL; + } + lru_cache_append_link(self, link); + Py_INCREF(result); /* for return */ + Py_DECREF(popresult); + Py_DECREF(oldkey); + Py_DECREF(oldresult); return result; } @@ -995,6 +1121,9 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError); if (maxsize == -1 && PyErr_Occurred()) return NULL; + if (maxsize < 0) { + maxsize = 0; + } if (maxsize == 0) wrapper = uncached_lru_cache_wrapper; else @@ -1013,20 +1142,17 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) return NULL; } - obj->cache = cachedict; obj->root.prev = &obj->root; obj->root.next = &obj->root; - obj->maxsize = maxsize; - Py_INCREF(maxsize_O); - obj->maxsize_O = maxsize_O; + obj->wrapper = wrapper; + obj->typed = typed; + obj->cache = cachedict; Py_INCREF(func); obj->func = func; - obj->wrapper = wrapper; obj->misses = obj->hits = 0; - obj->typed = typed; + obj->maxsize = maxsize; Py_INCREF(cache_info_type); obj->cache_info_type = cache_info_type; - return (PyObject *)obj; } @@ -1060,11 +1186,10 @@ lru_cache_dealloc(lru_cache_object *obj) PyObject_GC_UnTrack(obj); list = lru_cache_unlink_list(obj); - Py_XDECREF(obj->maxsize_O); - Py_XDECREF(obj->func); Py_XDECREF(obj->cache); - Py_XDECREF(obj->dict); + Py_XDECREF(obj->func); Py_XDECREF(obj->cache_info_type); + Py_XDECREF(obj->dict); lru_cache_clear_list(list); Py_TYPE(obj)->tp_free(obj); } @@ -1088,8 +1213,13 @@ lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type) static PyObject * lru_cache_cache_info(lru_cache_object *self, PyObject *unused) { - return PyObject_CallFunction(self->cache_info_type, "nnOn", - self->hits, self->misses, self->maxsize_O, + if (self->maxsize == -1) { + return PyObject_CallFunction(self->cache_info_type, "nnOn", + self->hits, self->misses, Py_None, + PyDict_GET_SIZE(self->cache)); + } + return PyObject_CallFunction(self->cache_info_type, "nnnn", + self->hits, self->misses, self->maxsize, PyDict_GET_SIZE(self->cache)); } @@ -1098,7 +1228,6 @@ lru_cache_cache_clear(lru_cache_object *self, PyObject *unused) { lru_list_elem *list = lru_cache_unlink_list(self); self->hits = self->misses = 0; - self->full = 0; PyDict_Clear(self->cache); lru_cache_clear_list(list); Py_RETURN_NONE; @@ -1134,7 +1263,6 @@ lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) Py_VISIT(link->result); link = next; } - Py_VISIT(self->maxsize_O); Py_VISIT(self->func); Py_VISIT(self->cache); Py_VISIT(self->cache_info_type); @@ -1146,7 +1274,6 @@ static int lru_cache_tp_clear(lru_cache_object *self) { lru_list_elem *list = lru_cache_unlink_list(self); - Py_CLEAR(self->maxsize_O); Py_CLEAR(self->func); Py_CLEAR(self->cache); Py_CLEAR(self->cache_info_type); diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 31d05409..b69f16c6 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -112,17 +112,18 @@ newEVPobject(PyObject *name) return NULL; } + /* save the name for .name to return */ + Py_INCREF(name); + retval->name = name; + retval->lock = NULL; + retval->ctx = EVP_MD_CTX_new(); if (retval->ctx == NULL) { + Py_DECREF(retval); PyErr_NoMemory(); return NULL; } - /* save the name for .name to return */ - Py_INCREF(name); - retval->name = name; - retval->lock = NULL; - return retval; } @@ -181,6 +182,7 @@ EVP_copy(EVPobject *self, PyObject *unused) return NULL; if (!locked_EVP_MD_CTX_copy(newobj->ctx, self)) { + Py_DECREF(newobj); return _setException(PyExc_ValueError); } return (PyObject *)newobj; @@ -824,7 +826,7 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, if (!retval) { /* sorry, can't do much better */ PyErr_SetString(PyExc_ValueError, - "Invalid paramemter combination for n, r, p, maxmem."); + "Invalid parameter combination for n, r, p, maxmem."); return NULL; } diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 9d0d9cac..49b545c4 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -3049,6 +3049,10 @@ textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context) { Py_ssize_t n; CHECK_ATTACHED_INT(self); + if (arg == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } n = PyNumber_AsSsize_t(arg, PyExc_ValueError); if (n == -1 && PyErr_Occurred()) return -1; diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 60ef9215..15e15cdf 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -6636,13 +6636,13 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self, } } - module = PyImport_GetModule(module_name); + /* + * we don't use PyImport_GetModule here, because it can return partially- + * initialised modules, which then cause the getattribute to fail. + */ + module = PyImport_Import(module_name); if (module == NULL) { - if (PyErr_Occurred()) - return NULL; - module = PyImport_Import(module_name); - if (module == NULL) - return NULL; + return NULL; } global = getattribute(module, global_name, self->proto >= 4); Py_DECREF(module); diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 851aa977..3cf0683a 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -30,7 +30,7 @@ # define SYS_getdents64 __NR_getdents64 #endif -#if defined(sun) +#if defined(__sun) && defined(__SVR4) /* readdir64 is used to work around Solaris 9 bug 6395699. */ # define readdir readdir64 # define dirent dirent64 diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 51677f8b..1a76ba99 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -292,7 +292,6 @@ random_seed(RandomObject *self, PyObject *args) PY_LITTLE_ENDIAN, 0); /* unsigned */ if (res == -1) { - PyMem_Free(key); goto Done; } diff --git a/Modules/_sha3/cleanup.py b/Modules/_sha3/cleanup.py index 17c56b34..4f53681b 100755 --- a/Modules/_sha3/cleanup.py +++ b/Modules/_sha3/cleanup.py @@ -8,7 +8,7 @@ import os import re CPP1 = re.compile("^//(.*)") -CPP2 = re.compile("\ //(.*)") +CPP2 = re.compile(r"\ //(.*)") STATICS = ("void ", "int ", "HashReturn ", "const UINT64 ", "UINT16 ", " int prefix##") diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 351317e7..d43286a2 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1138,6 +1138,10 @@ static PyObject* pysqlite_connection_get_in_transaction(pysqlite_Connection* sel static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level, void *Py_UNUSED(ignored)) { + if (isolation_level == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } if (isolation_level == Py_None) { PyObject *res = pysqlite_connection_commit(self, NULL); if (!res) { diff --git a/Modules/_sre.c b/Modules/_sre.c index d2ea62d5..4d2bdcc2 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -347,7 +347,7 @@ _sre_unicode_tolower_impl(PyObject *module, int character) LOCAL(void) state_reset(SRE_STATE* state) { - /* FIXME: dynamic! */ + /* state->mark will be set to 0 in SRE_OP_MARK dynamically. */ /*memset(state->mark, 0, sizeof(*state->mark) * SRE_MARK_SIZE);*/ state->lastmark = -1; @@ -2319,7 +2319,7 @@ match_repr(MatchObject *self) if (group0 == NULL) return NULL; result = PyUnicode_FromFormat( - "<%s object; span=(%d, %d), match=%.50R>", + "<%s object; span=(%zd, %zd), match=%.50R>", Py_TYPE(self)->tp_name, self->mark[0], self->mark[1], group0); Py_DECREF(group0); diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 310b38bf..9baec8a9 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1516,6 +1516,10 @@ _get_crl_dp(X509 *certificate) { STACK_OF(GENERAL_NAME) *gns; dp = sk_DIST_POINT_value(dps, i); + if (dp->distpoint == NULL) { + /* Ignore empty DP value, CVE-2019-5010 */ + continue; + } gns = dp->distpoint->name.fullname; for (j=0; j < sk_GENERAL_NAME_num(gns); j++) { @@ -3626,6 +3630,10 @@ static int set_post_handshake_auth(PySSLContext *self, PyObject *arg, void *c) { int (*verify_cb)(int, X509_STORE_CTX *) = NULL; int mode = SSL_CTX_get_verify_mode(self->ctx); + if (arg == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } int pha = PyObject_IsTrue(arg); if (pha == -1) { diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 9ea5a926..036464d9 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -974,7 +974,8 @@ cleanup: _winapi.CreateProcess application_name: Py_UNICODE(accept={str, NoneType}) - command_line: Py_UNICODE(accept={str, NoneType}) + command_line: object + Can be str or None proc_attrs: object Ignored internally, can be None. thread_attrs: object @@ -993,13 +994,14 @@ process ID, and thread ID. [clinic start generated code]*/ static PyObject * -_winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name, - Py_UNICODE *command_line, PyObject *proc_attrs, +_winapi_CreateProcess_impl(PyObject *module, + const Py_UNICODE *application_name, + PyObject *command_line, PyObject *proc_attrs, PyObject *thread_attrs, BOOL inherit_handles, DWORD creation_flags, PyObject *env_mapping, - Py_UNICODE *current_directory, + const Py_UNICODE *current_directory, PyObject *startup_info) -/*[clinic end generated code: output=4652a33aff4b0ae1 input=4a43b05038d639bb]*/ +/*[clinic end generated code: output=9b2423a609230132 input=42ac293eaea03fc4]*/ { PyObject *ret = NULL; BOOL result; @@ -1007,6 +1009,7 @@ _winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name, STARTUPINFOEXW si; PyObject *environment = NULL; wchar_t *wenvironment; + wchar_t *command_line_copy = NULL; AttributeList attribute_list = {0}; ZeroMemory(&si, sizeof(si)); @@ -1041,10 +1044,23 @@ _winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name, goto cleanup; si.lpAttributeList = attribute_list.attribute_list; + if (PyUnicode_Check(command_line)) { + command_line_copy = PyUnicode_AsWideCharString(command_line, NULL); + if (command_line_copy == NULL) { + goto cleanup; + } + } + else if (command_line != Py_None) { + PyErr_Format(PyExc_TypeError, + "CreateProcess() argument 2 must be str or None, not %s", + Py_TYPE(command_line)->tp_name); + goto cleanup; + } + Py_BEGIN_ALLOW_THREADS result = CreateProcessW(application_name, - command_line, + command_line_copy, NULL, NULL, inherit_handles, @@ -1068,6 +1084,7 @@ _winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name, pi.dwThreadId); cleanup: + PyMem_Free(command_line_copy); Py_XDECREF(environment); freeattributelist(&attribute_list); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 7b4a4a3a..ee7ae546 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1712,9 +1712,9 @@ some other type. [clinic start generated code]*/ static PyObject * -array_array_fromunicode_impl(arrayobject *self, Py_UNICODE *ustr, +array_array_fromunicode_impl(arrayobject *self, const Py_UNICODE *ustr, Py_ssize_clean_t ustr_length) -/*[clinic end generated code: output=ebb72fc16975e06d input=150f00566ffbca6e]*/ +/*[clinic end generated code: output=cf2f662908e2befc input=150f00566ffbca6e]*/ { char typecode; diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index 4d0aaf3a..5c91ada1 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -133,6 +133,10 @@ codecctx_errors_set(MultibyteStatefulCodecContext *self, PyObject *value, PyObject *cb; const char *str; + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "errors must be a string"); return -1; diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h index c66522eb..f4d88423 100644 --- a/Modules/clinic/_winapi.c.h +++ b/Modules/clinic/_winapi.c.h @@ -286,6 +286,8 @@ PyDoc_STRVAR(_winapi_CreateProcess__doc__, "\n" "Create a new process and its primary thread.\n" "\n" +" command_line\n" +" Can be str or None\n" " proc_attrs\n" " Ignored internally, can be None.\n" " thread_attrs\n" @@ -298,28 +300,29 @@ PyDoc_STRVAR(_winapi_CreateProcess__doc__, {"CreateProcess", (PyCFunction)_winapi_CreateProcess, METH_FASTCALL, _winapi_CreateProcess__doc__}, static PyObject * -_winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name, - Py_UNICODE *command_line, PyObject *proc_attrs, +_winapi_CreateProcess_impl(PyObject *module, + const Py_UNICODE *application_name, + PyObject *command_line, PyObject *proc_attrs, PyObject *thread_attrs, BOOL inherit_handles, DWORD creation_flags, PyObject *env_mapping, - Py_UNICODE *current_directory, + const Py_UNICODE *current_directory, PyObject *startup_info); static PyObject * _winapi_CreateProcess(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - Py_UNICODE *application_name; - Py_UNICODE *command_line; + const Py_UNICODE *application_name; + PyObject *command_line; PyObject *proc_attrs; PyObject *thread_attrs; BOOL inherit_handles; DWORD creation_flags; PyObject *env_mapping; - Py_UNICODE *current_directory; + const Py_UNICODE *current_directory; PyObject *startup_info; - if (!_PyArg_ParseStack(args, nargs, "ZZOOikOZO:CreateProcess", + if (!_PyArg_ParseStack(args, nargs, "ZOOOikOZO:CreateProcess", &application_name, &command_line, &proc_attrs, &thread_attrs, &inherit_handles, &creation_flags, &env_mapping, ¤t_directory, &startup_info)) { goto exit; } @@ -941,4 +944,4 @@ _winapi_GetFileType(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P exit: return return_value; } -/*[clinic end generated code: output=baaf3d379b91be0a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=896d06ce2290aa86 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index b03a5079..c85d0c62 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -376,14 +376,14 @@ PyDoc_STRVAR(array_array_fromunicode__doc__, {"fromunicode", (PyCFunction)array_array_fromunicode, METH_O, array_array_fromunicode__doc__}, static PyObject * -array_array_fromunicode_impl(arrayobject *self, Py_UNICODE *ustr, +array_array_fromunicode_impl(arrayobject *self, const Py_UNICODE *ustr, Py_ssize_clean_t ustr_length); static PyObject * array_array_fromunicode(arrayobject *self, PyObject *arg) { PyObject *return_value = NULL; - Py_UNICODE *ustr; + const Py_UNICODE *ustr; Py_ssize_clean_t ustr_length; if (!PyArg_Parse(arg, "u#:fromunicode", &ustr, &ustr_length)) { @@ -505,4 +505,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=1289bde2a095a712 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2d0fb1937dea02c2 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 3230cd70..caa1cacd 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1264,7 +1264,7 @@ PyDoc_STRVAR(os_replace__doc__, " descriptor open to a directory, and the respective path string (src or dst)\n" " should be relative; the path will then be relative to that directory.\n" "src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError.\""); +" If they are unavailable, using them will raise a NotImplementedError."); #define OS_REPLACE_METHODDEF \ {"replace", (PyCFunction)os_replace, METH_FASTCALL|METH_KEYWORDS, os_replace__doc__}, @@ -1350,7 +1350,7 @@ PyDoc_STRVAR(os_system__doc__, {"system", (PyCFunction)os_system, METH_FASTCALL|METH_KEYWORDS, os_system__doc__}, static long -os_system_impl(PyObject *module, Py_UNICODE *command); +os_system_impl(PyObject *module, const Py_UNICODE *command); static PyObject * os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1358,7 +1358,7 @@ os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k PyObject *return_value = NULL; static const char * const _keywords[] = {"command", NULL}; static _PyArg_Parser _parser = {"u:system", _keywords, 0}; - Py_UNICODE *command; + const Py_UNICODE *command; long _return_value; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, @@ -5201,7 +5201,8 @@ PyDoc_STRVAR(os_startfile__doc__, {"startfile", (PyCFunction)os_startfile, METH_FASTCALL|METH_KEYWORDS, os_startfile__doc__}, static PyObject * -os_startfile_impl(PyObject *module, path_t *filepath, Py_UNICODE *operation); +os_startfile_impl(PyObject *module, path_t *filepath, + const Py_UNICODE *operation); static PyObject * os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -5210,7 +5211,7 @@ os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject static const char * const _keywords[] = {"filepath", "operation", NULL}; static _PyArg_Parser _parser = {"O&|u:startfile", _keywords, 0}; path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0); - Py_UNICODE *operation = NULL; + const Py_UNICODE *operation = NULL; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, path_converter, &filepath, &operation)) { @@ -6537,4 +6538,4 @@ exit: #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=c6ca6ad4afa64454 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=32c935671ee020d5 input=a9049054013a1b77]*/ diff --git a/Modules/getpath.c b/Modules/getpath.c index e6a3e8e7..bfb33316 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -296,6 +296,41 @@ absolutize(wchar_t *path) } +#if defined(__CYGWIN__) || defined(__MINGW32__) +/* add_exe_suffix requires that progpath be allocated at least + MAXPATHLEN + 1 bytes. +*/ + +#ifndef EXE_SUFFIX +#define EXE_SUFFIX L".exe" +#endif + +static void +add_exe_suffix(wchar_t *progpath) +{ + /* Check for already have an executable suffix */ + size_t n = wcslen(progpath); + size_t s = wcslen(EXE_SUFFIX); + if (wcsncasecmp(EXE_SUFFIX, progpath+n-s, s) != 0) { + if (n + s > MAXPATHLEN) { + Py_FatalError("progpath overflow in getpath.c's add_exe_suffix()"); + } + /* Save original path for revert */ + wchar_t orig[MAXPATHLEN+1]; + wcsncpy(orig, progpath, MAXPATHLEN); + + wcsncpy(progpath+n, EXE_SUFFIX, s); + progpath[n+s] = '\0'; + + if (!isxfile(progpath)) { + /* Path that added suffix is invalid */ + wcsncpy(progpath, orig, MAXPATHLEN); + } + } +} +#endif + + /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN bytes long. */ @@ -605,6 +640,16 @@ calculate_program_full_path(const _PyCoreConfig *core_config, if (program_full_path[0] != SEP && program_full_path[0] != '\0') { absolutize(program_full_path); } +#if defined(__CYGWIN__) || defined(__MINGW32__) + /* For these platforms it is necessary to ensure that the .exe suffix + * is appended to the filename, otherwise there is potential for + * sys.executable to return the name of a directory under the same + * path (bpo-28441). + */ + if (program_full_path[0] != '\0') { + add_exe_suffix(program_full_path); + } +#endif config->program_full_path = _PyMem_RawWcsdup(program_full_path); if (config->program_full_path == NULL) { diff --git a/Modules/main.c b/Modules/main.c index af2c191b..a7453811 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -2165,6 +2165,7 @@ pymain_read_conf(_PyMain *pymain, _PyCoreConfig *config, _PyCmdline *cmdline) goto done; } pymain_clear_cmdline(pymain, cmdline); + pymain_clear_pymain(pymain); memset(cmdline, 0, sizeof(*cmdline)); cmdline_get_global_config(cmdline); diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 5d9fe5aa..9eaeff11 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -77,7 +77,7 @@ static const double sqrtpi = 1.772453850905516027298167483341145182798; #endif /* !defined(HAVE_ERF) || !defined(HAVE_ERFC) */ static double -sinpi(double x) +m_sinpi(double x) { double y, r; int n; @@ -305,7 +305,7 @@ m_tgamma(double x) integer. */ if (absx > 200.0) { if (x < 0.0) { - return 0.0/sinpi(x); + return 0.0/m_sinpi(x); } else { errno = ERANGE; @@ -329,7 +329,7 @@ m_tgamma(double x) } z = z * lanczos_g / y; if (x < 0.0) { - r = -pi / sinpi(absx) / absx * exp(y) / lanczos_sum(absx); + r = -pi / m_sinpi(absx) / absx * exp(y) / lanczos_sum(absx); r -= z * r; if (absx < 140.0) { r /= pow(y, absx - 0.5); @@ -400,7 +400,7 @@ m_lgamma(double x) r += (absx - 0.5) * (log(absx + lanczos_g - 0.5) - 1); if (x < 0.0) /* Use reflection formula to get value for negative x. */ - r = logpi - log(fabs(sinpi(absx))) - log(absx) - r; + r = logpi - log(fabs(m_sinpi(absx))) - log(absx) - r; if (Py_IS_INFINITY(r)) errno = ERANGE; return r; diff --git a/Modules/overlapped.c b/Modules/overlapped.c index ae7cddad..7798856b 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -561,6 +561,28 @@ Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)self; } + +/* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release + buffers while overlapped are still running, to prevent a crash. */ +static int +Overlapped_clear(OverlappedObject *self) +{ + switch (self->type) { + case TYPE_READ: + case TYPE_ACCEPT: + Py_CLEAR(self->allocated_buffer); + break; + case TYPE_WRITE: + case TYPE_READINTO: + if (self->user_buffer.obj) { + PyBuffer_Release(&self->user_buffer); + } + break; + } + self->type = TYPE_NOT_STARTED; + return 0; +} + static void Overlapped_dealloc(OverlappedObject *self) { @@ -594,20 +616,11 @@ Overlapped_dealloc(OverlappedObject *self) } } - if (self->overlapped.hEvent != NULL) + if (self->overlapped.hEvent != NULL) { CloseHandle(self->overlapped.hEvent); - - switch (self->type) { - case TYPE_READ: - case TYPE_ACCEPT: - Py_CLEAR(self->allocated_buffer); - break; - case TYPE_WRITE: - case TYPE_READINTO: - if (self->user_buffer.obj) - PyBuffer_Release(&self->user_buffer); - break; } + + Overlapped_clear(self); PyObject_Del(self); SetLastError(olderr); } @@ -723,7 +736,7 @@ do_ReadFile(OverlappedObject *self, HANDLE handle, case ERROR_IO_PENDING: Py_RETURN_NONE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -826,7 +839,7 @@ do_WSARecv(OverlappedObject *self, HANDLE handle, case ERROR_IO_PENDING: Py_RETURN_NONE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -954,7 +967,7 @@ Overlapped_WriteFile(OverlappedObject *self, PyObject *args) case ERROR_IO_PENDING: Py_RETURN_NONE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -1011,7 +1024,7 @@ Overlapped_WSASend(OverlappedObject *self, PyObject *args) case ERROR_IO_PENDING: Py_RETURN_NONE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -1061,7 +1074,7 @@ Overlapped_AcceptEx(OverlappedObject *self, PyObject *args) case ERROR_IO_PENDING: Py_RETURN_NONE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -1153,7 +1166,7 @@ Overlapped_ConnectEx(OverlappedObject *self, PyObject *args) case ERROR_IO_PENDING: Py_RETURN_NONE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -1192,7 +1205,7 @@ Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args) case ERROR_IO_PENDING: Py_RETURN_NONE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -1247,7 +1260,7 @@ Overlapped_TransmitFile(OverlappedObject *self, PyObject *args) case ERROR_IO_PENDING: Py_RETURN_NONE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -1288,7 +1301,7 @@ Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args) case ERROR_IO_PENDING: Py_RETURN_FALSE; default: - self->type = TYPE_NOT_STARTED; + Overlapped_clear(self); return SetFromWindowsErr(err); } } @@ -1338,6 +1351,25 @@ Overlapped_getpending(OverlappedObject *self) self->type != TYPE_NOT_STARTED); } +static int +Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) +{ + switch (self->type) { + case TYPE_READ: + case TYPE_ACCEPT: + Py_VISIT(self->allocated_buffer); + break; + case TYPE_WRITE: + case TYPE_READINTO: + if (self->user_buffer.obj) { + Py_VISIT(&self->user_buffer.obj); + } + break; + } + return 0; +} + + static PyMethodDef Overlapped_methods[] = { {"getresult", (PyCFunction) Overlapped_getresult, METH_VARARGS, Overlapped_getresult_doc}, @@ -1408,7 +1440,7 @@ PyTypeObject OverlappedType = { /* tp_as_buffer */ 0, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_doc */ "OVERLAPPED structure wrapper", - /* tp_traverse */ 0, + /* tp_traverse */ (traverseproc)Overlapped_traverse, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 5403660b..e7a1f987 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -393,6 +393,10 @@ static int win32_can_symlink = 0; #define HAVE_STRUCT_STAT_ST_FSTYPE 1 #endif +#ifdef _Py_MEMORY_SANITIZER +# include +#endif + #ifdef HAVE_FORK static void run_at_forkers(PyObject *lst, int reverse) @@ -975,28 +979,35 @@ path_converter(PyObject *o, void *p) if (!is_index && !is_buffer && !is_unicode && !is_bytes) { /* Inline PyOS_FSPath() for better error messages. */ _Py_IDENTIFIER(__fspath__); - PyObject *func = NULL; + PyObject *func, *res; func = _PyObject_LookupSpecial(o, &PyId___fspath__); if (NULL == func) { goto error_format; } - /* still owns a reference to the original object */ - Py_DECREF(o); - o = _PyObject_CallNoArg(func); + res = _PyObject_CallNoArg(func); Py_DECREF(func); - if (NULL == o) { + if (NULL == res) { goto error_exit; } - else if (PyUnicode_Check(o)) { + else if (PyUnicode_Check(res)) { is_unicode = 1; } - else if (PyBytes_Check(o)) { + else if (PyBytes_Check(res)) { is_bytes = 1; } else { - goto error_format; + PyErr_Format(PyExc_TypeError, + "expected %.200s.__fspath__() to return str or bytes, " + "not %.200s", Py_TYPE(o)->tp_name, + Py_TYPE(res)->tp_name); + Py_DECREF(res); + goto error_exit; } + + /* still owns a reference to the original object */ + Py_DECREF(o); + o = res; } if (is_unicode) { @@ -1612,11 +1623,6 @@ get_target_path(HANDLE hdl, wchar_t **target_path) return FALSE; } - if(!CloseHandle(hdl)) { - PyMem_RawFree(buf); - return FALSE; - } - buf[result_length] = 0; *target_path = buf; @@ -1674,9 +1680,10 @@ win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, return -1; } if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (!win32_get_reparse_tag(hFile, &reparse_tag)) + if (!win32_get_reparse_tag(hFile, &reparse_tag)) { + CloseHandle(hFile); return -1; - + } /* Close the outer open file handle now that we're about to reopen it with different flags. */ if (!CloseHandle(hFile)) @@ -1693,8 +1700,14 @@ win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, if (hFile2 == INVALID_HANDLE_VALUE) return -1; - if (!get_target_path(hFile2, &target_path)) + if (!get_target_path(hFile2, &target_path)) { + CloseHandle(hFile2); + return -1; + } + + if (!CloseHandle(hFile2)) { return -1; + } code = win32_xstat_impl(target_path, result, FALSE); PyMem_RawFree(target_path); @@ -4116,13 +4129,13 @@ If either src_dir_fd or dst_dir_fd is not None, it should be a file descriptor open to a directory, and the respective path string (src or dst) should be relative; the path will then be relative to that directory. src_dir_fd and dst_dir_fd, may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError." + If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) -/*[clinic end generated code: output=1968c02e7857422b input=25515dfb107c8421]*/ +/*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/ { return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); } @@ -4181,8 +4194,8 @@ Execute the command in a subshell. [clinic start generated code]*/ static long -os_system_impl(PyObject *module, Py_UNICODE *command) -/*[clinic end generated code: output=96c4dffee36dfb48 input=303f5ce97df606b0]*/ +os_system_impl(PyObject *module, const Py_UNICODE *command) +/*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/ { long result; Py_BEGIN_ALLOW_THREADS @@ -5689,6 +5702,9 @@ os_sched_rr_get_interval_impl(PyObject *module, pid_t pid) posix_error(); return -1.0; } +#ifdef _Py_MEMORY_SANITIZER + __msan_unpoison(&interval, sizeof(interval)); +#endif return (double)interval.tv_sec + 1e-9*interval.tv_nsec; } #endif /* HAVE_SCHED_RR_GET_INTERVAL */ @@ -5926,7 +5942,7 @@ os_openpty_impl(PyObject *module) #endif #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) PyOS_sighandler_t sig_saved; -#ifdef sun +#if defined(__sun) && defined(__SVR4) extern char *ptsname(int fildes); #endif #endif @@ -6155,6 +6171,12 @@ posix_getgrouplist(PyObject *self, PyObject *args) return posix_error(); } +#ifdef _Py_MEMORY_SANITIZER + /* Clang memory sanitizer libc intercepts don't know getgrouplist. */ + __msan_unpoison(&ngroups, sizeof(ngroups)); + __msan_unpoison(groups, ngroups*sizeof(*groups)); +#endif + list = PyList_New(ngroups); if (list == NULL) { PyMem_Del(groups); @@ -10792,8 +10814,9 @@ the underlying Win32 ShellExecute function doesn't work if it is. [clinic start generated code]*/ static PyObject * -os_startfile_impl(PyObject *module, path_t *filepath, Py_UNICODE *operation) -/*[clinic end generated code: output=912ceba79acfa1c9 input=63950bf2986380d0]*/ +os_startfile_impl(PyObject *module, path_t *filepath, + const Py_UNICODE *operation) +/*[clinic end generated code: output=66dc311c94d50797 input=63950bf2986380d0]*/ { HINSTANCE rc; diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index e6d3f8be..988471e1 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -100,6 +100,10 @@ Local naming conventions: #include "Python.h" #include "structmember.h" +#ifdef _Py_MEMORY_SANITIZER +# include +#endif + /* Socket object documentation */ PyDoc_STRVAR(sock_doc, "socket(family=AF_INET, type=SOCK_STREAM, proto=0) -> socket object\n\ @@ -261,7 +265,7 @@ http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getaddrinfo.c.diff?r1=1.82& #endif /* Solaris fails to define this variable at all. */ -#if defined(sun) && !defined(INET_ADDRSTRLEN) +#if (defined(__sun) && defined(__SVR4)) && !defined(INET_ADDRSTRLEN) #define INET_ADDRSTRLEN 16 #endif @@ -6463,7 +6467,23 @@ socket_if_nameindex(PyObject *self, PyObject *arg) return NULL; } +#ifdef _Py_MEMORY_SANITIZER + __msan_unpoison(ni, sizeof(ni)); + __msan_unpoison(&ni[0], sizeof(ni[0])); +#endif for (i = 0; ni[i].if_index != 0 && i < INT_MAX; i++) { +#ifdef _Py_MEMORY_SANITIZER + /* This one isn't the end sentinel, the next one must exist. */ + __msan_unpoison(&ni[i+1], sizeof(ni[0])); + /* Otherwise Py_BuildValue internals are flagged by MSan when + they access the not-msan-tracked if_name string data. */ + { + char *to_sanitize = ni[i].if_name; + do { + __msan_unpoison(to_sanitize, 1); + } while (*to_sanitize++ != '\0'); + } +#endif PyObject *ni_tuple = Py_BuildValue("IO&", ni[i].if_index, PyUnicode_DecodeFSDefault, ni[i].if_name); diff --git a/Modules/sre_lib.h b/Modules/sre_lib.h index 44948e21..437ab43f 100644 --- a/Modules/sre_lib.h +++ b/Modules/sre_lib.h @@ -1363,6 +1363,10 @@ exit: return ret; /* should never get here */ } +/* need to reset capturing groups between two SRE(match) callings in loops */ +#define RESET_CAPTURE_GROUP() \ + do { state->lastmark = state->lastindex = -1; } while (0) + LOCAL(Py_ssize_t) SRE(search)(SRE_STATE* state, SRE_CODE* pattern) { @@ -1440,6 +1444,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) if (status != 0) return status; ++ptr; + RESET_CAPTURE_GROUP(); } return 0; } @@ -1487,6 +1492,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) /* close but no cigar -- try again */ if (++ptr >= end) return 0; + RESET_CAPTURE_GROUP(); } i = overlap[i]; } while (i != 0); @@ -1510,6 +1516,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) if (status != 0) break; ptr++; + RESET_CAPTURE_GROUP(); } } else { /* general case */ @@ -1520,6 +1527,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) state->must_advance = 0; while (status == 0 && ptr < end) { ptr++; + RESET_CAPTURE_GROUP(); TRACE(("|%p|%p|SEARCH\n", pattern, ptr)); state->start = state->ptr = ptr; status = SRE(match)(state, pattern, 0); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 13a174a4..ae7de5b2 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -34,6 +34,20 @@ #endif /* MS_WINDOWS */ #endif /* !__WATCOMC__ || __QNX__ */ +#ifdef _Py_MEMORY_SANITIZER +# include +#endif + +#ifdef _MSC_VER +#define _Py_timezone _timezone +#define _Py_daylight _daylight +#define _Py_tzname _tzname +#else +#define _Py_timezone timezone +#define _Py_daylight daylight +#define _Py_tzname tzname +#endif + #define SEC_TO_NS (1000 * 1000 * 1000) /* Forward declarations */ @@ -331,6 +345,9 @@ time_pthread_getcpuclockid(PyObject *self, PyObject *args) PyErr_SetFromErrno(PyExc_OSError); return NULL; } +#ifdef _Py_MEMORY_SANITIZER + __msan_unpoison(&clk_id, sizeof(clk_id)); +#endif return PyLong_FromLong(clk_id); } @@ -718,7 +735,7 @@ time_strftime(PyObject *self, PyObject *args) return NULL; } -#if defined(_MSC_VER) || defined(sun) || defined(_AIX) +#if defined(_MSC_VER) || (defined(__sun) && defined(__SVR4)) || defined(_AIX) if (buf.tm_year + 1900 < 1 || 9999 < buf.tm_year + 1900) { PyErr_SetString(PyExc_ValueError, "strftime() requires year in [1; 9999]"); @@ -764,7 +781,7 @@ time_strftime(PyObject *self, PyObject *args) return NULL; } } -#elif (defined(_AIX) || defined(sun)) && defined(HAVE_WCSFTIME) +#elif (defined(_AIX) || (defined(__sun) && defined(__SVR4))) && defined(HAVE_WCSFTIME) for (outbuf = wcschr(fmt, '%'); outbuf != NULL; outbuf = wcschr(outbuf+2, '%')) @@ -1547,18 +1564,18 @@ init_timezone(PyObject *m) #if defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__) PyObject *otz0, *otz1; tzset(); - PyModule_AddIntConstant(m, "timezone", timezone); + PyModule_AddIntConstant(m, "timezone", _Py_timezone); #ifdef HAVE_ALTZONE PyModule_AddIntConstant(m, "altzone", altzone); #else - PyModule_AddIntConstant(m, "altzone", timezone-3600); + PyModule_AddIntConstant(m, "altzone", _Py_timezone-3600); #endif - PyModule_AddIntConstant(m, "daylight", daylight); - otz0 = PyUnicode_DecodeLocale(tzname[0], "surrogateescape"); + PyModule_AddIntConstant(m, "daylight", _Py_daylight); + otz0 = PyUnicode_DecodeLocale(_Py_tzname[0], "surrogateescape"); if (otz0 == NULL) { return -1; } - otz1 = PyUnicode_DecodeLocale(tzname[1], "surrogateescape"); + otz1 = PyUnicode_DecodeLocale(_Py_tzname[1], "surrogateescape"); if (otz1 == NULL) { Py_DECREF(otz0); return -1; diff --git a/Objects/abstract.c b/Objects/abstract.c index 2d48a112..9416df43 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -143,6 +143,7 @@ PyObject * PyObject_GetItem(PyObject *o, PyObject *key) { PyMappingMethods *m; + PySequenceMethods *ms; if (o == NULL || key == NULL) { return null_error(); @@ -155,7 +156,8 @@ PyObject_GetItem(PyObject *o, PyObject *key) return item; } - if (o->ob_type->tp_as_sequence) { + ms = o->ob_type->tp_as_sequence; + if (ms && ms->sq_item) { if (PyIndex_Check(key)) { Py_ssize_t key_value; key_value = PyNumber_AsSsize_t(key, PyExc_IndexError); @@ -163,9 +165,10 @@ PyObject_GetItem(PyObject *o, PyObject *key) return NULL; return PySequence_GetItem(o, key_value); } - else if (o->ob_type->tp_as_sequence->sq_item) + else { return type_error("sequence index must " "be integer, not '%.200s'", key); + } } if (PyType_Check(o)) { diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 711faba6..172c7f38 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -311,9 +311,15 @@ PyBytes_FromFormatV(const char *format, va_list vargs) Py_ssize_t i; p = va_arg(vargs, const char*); - i = strlen(p); - if (prec > 0 && i > prec) - i = prec; + if (prec <= 0) { + i = strlen(p); + } + else { + i = 0; + while (i < prec && p[i]) { + i++; + } + } s = _PyBytesWriter_WriteBytes(&writer, s, p, i); if (s == NULL) goto error; @@ -2990,9 +2996,22 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) /* return early if newsize equals to v->ob_size */ return 0; } + if (Py_SIZE(v) == 0) { + if (newsize == 0) { + return 0; + } + *pv = _PyBytes_FromSize(newsize, 0); + Py_DECREF(v); + return (*pv == NULL) ? -1 : 0; + } if (Py_REFCNT(v) != 1) { goto error; } + if (newsize == 0) { + *pv = _PyBytes_FromSize(0, 0); + Py_DECREF(v); + return (*pv == NULL) ? -1 : 0; + } /* XXX UNREF/NEWREF interface should be more symmetrical */ _Py_DEC_REFTOTAL; _Py_ForgetReference(v); diff --git a/Objects/fileobject.c b/Objects/fileobject.c index ed4e12ba..d886e96e 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -407,7 +407,7 @@ stdprinter_fileno(PyStdPrinter_Object *self) static PyObject * stdprinter_repr(PyStdPrinter_Object *self) { - return PyUnicode_FromFormat("", + return PyUnicode_FromFormat("", self->fd, self); } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 4ef10d0e..4362615c 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -90,6 +90,10 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore int blockstack_top = 0; /* (ditto) */ unsigned char setup_op = 0; /* (ditto) */ + if (p_new_lineno == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); + return -1; + } /* f_lineno must be an integer. */ if (!PyLong_CheckExact(p_new_lineno)) { PyErr_SetString(PyExc_ValueError, diff --git a/Objects/listobject.c b/Objects/listobject.c index c8ffeff0..7dc68a73 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2232,7 +2232,6 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) int ints_are_bounded = 1; /* Prove that assumption by checking every key. */ - int i; for (i=0; i < saved_ob_size; i++) { if (keys_are_in_tuples && @@ -2280,6 +2279,9 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) else if ((ms.key_richcompare = key_type->tp_richcompare) != NULL) { ms.key_compare = unsafe_object_compare; } + else { + ms.key_compare = safe_object_compare; + } } else { ms.key_compare = safe_object_compare; diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index 59f084d1..4d5212f6 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -564,14 +564,11 @@ static PyMethodDef slice_methods[] = { static PyObject * slice_richcompare(PyObject *v, PyObject *w, int op) { - PyObject *t1; - PyObject *t2; - PyObject *res; - if (!PySlice_Check(v) || !PySlice_Check(w)) Py_RETURN_NOTIMPLEMENTED; if (v == w) { + PyObject *res; /* XXX Do we really need this shortcut? There's a unit test for it, but is that fair? */ switch (op) { @@ -588,34 +585,27 @@ slice_richcompare(PyObject *v, PyObject *w, int op) return res; } - t1 = PyTuple_New(3); - if (t1 == NULL) + + PyObject *t1 = PyTuple_Pack(3, + ((PySliceObject *)v)->start, + ((PySliceObject *)v)->stop, + ((PySliceObject *)v)->step); + if (t1 == NULL) { return NULL; - t2 = PyTuple_New(3); + } + + PyObject *t2 = PyTuple_Pack(3, + ((PySliceObject *)w)->start, + ((PySliceObject *)w)->stop, + ((PySliceObject *)w)->step); if (t2 == NULL) { Py_DECREF(t1); return NULL; } - PyTuple_SET_ITEM(t1, 0, ((PySliceObject *)v)->start); - PyTuple_SET_ITEM(t1, 1, ((PySliceObject *)v)->stop); - PyTuple_SET_ITEM(t1, 2, ((PySliceObject *)v)->step); - PyTuple_SET_ITEM(t2, 0, ((PySliceObject *)w)->start); - PyTuple_SET_ITEM(t2, 1, ((PySliceObject *)w)->stop); - PyTuple_SET_ITEM(t2, 2, ((PySliceObject *)w)->step); - - res = PyObject_RichCompare(t1, t2, op); - - PyTuple_SET_ITEM(t1, 0, NULL); - PyTuple_SET_ITEM(t1, 1, NULL); - PyTuple_SET_ITEM(t1, 2, NULL); - PyTuple_SET_ITEM(t2, 0, NULL); - PyTuple_SET_ITEM(t2, 1, NULL); - PyTuple_SET_ITEM(t2, 2, NULL); - + PyObject *res = PyObject_RichCompare(t1, t2, op); Py_DECREF(t1); Py_DECREF(t2); - return res; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 46821057..c578d6e9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3654,11 +3654,13 @@ object_init(PyObject *self, PyObject *args, PyObject *kwds) PyTypeObject *type = Py_TYPE(self); if (excess_args(args, kwds)) { if (type->tp_init != object_init) { - PyErr_SetString(PyExc_TypeError, "object.__init__() takes no arguments"); + PyErr_SetString(PyExc_TypeError, + "object.__init__() takes exactly one argument (the instance to initialize)"); return -1; } if (type->tp_new == object_new) { - PyErr_Format(PyExc_TypeError, "%.200s().__init__() takes no arguments", + PyErr_Format(PyExc_TypeError, + "%.200s.__init__() takes exactly one argument (the instance to initialize)", type->tp_name); return -1; } @@ -3671,7 +3673,8 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { if (excess_args(args, kwds)) { if (type->tp_new != object_new) { - PyErr_SetString(PyExc_TypeError, "object.__new__() takes no arguments"); + PyErr_SetString(PyExc_TypeError, + "object.__new__() takes exactly one argument (the type to instantiate)"); return NULL; } if (type->tp_init == object_init) { diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index d46ab2a1..b67ffac4 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -2579,9 +2579,15 @@ unicode_fromformat_write_cstr(_PyUnicodeWriter *writer, const char *str, PyObject *unicode; int res; - length = strlen(str); - if (precision != -1) - length = Py_MIN(length, precision); + if (precision == -1) { + length = strlen(str); + } + else { + length = 0; + while (length < precision && str[length]) { + length++; + } + } unicode = PyUnicode_DecodeUTF8Stateful(str, length, "replace", NULL); if (unicode == NULL) return -1; @@ -9356,6 +9362,7 @@ _PyUnicode_InsertThousandsGrouping( PyObject *thousands_sep, Py_UCS4 *maxchar) { + min_width = Py_MAX(0, min_width); if (writer) { assert(digits != NULL); assert(maxchar == NULL); @@ -9366,7 +9373,6 @@ _PyUnicode_InsertThousandsGrouping( } assert(0 <= d_pos); assert(0 <= n_digits); - assert(0 <= min_width); assert(grouping != NULL); if (digits != NULL) { diff --git a/PC/_msi.c b/PC/_msi.c index 024b2d3c..ae30acbc 100644 --- a/PC/_msi.c +++ b/PC/_msi.c @@ -555,7 +555,7 @@ summary_getproperty(msiobj* si, PyObject *args) FILETIME fval; char sbuf[1000]; char *sval = sbuf; - DWORD ssize = sizeof(sval); + DWORD ssize = sizeof(sbuf); if (!PyArg_ParseTuple(args, "i:GetProperty", &field)) return NULL; @@ -563,6 +563,7 @@ summary_getproperty(msiobj* si, PyObject *args) status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival, &fval, sval, &ssize); if (status == ERROR_MORE_DATA) { + ssize++; sval = malloc(ssize); if (sval == NULL) { return PyErr_NoMemory(); @@ -572,21 +573,29 @@ summary_getproperty(msiobj* si, PyObject *args) } switch(type) { - case VT_I2: case VT_I4: - return PyLong_FromLong(ival); + case VT_I2: + case VT_I4: + result = PyLong_FromLong(ival); + break; case VT_FILETIME: PyErr_SetString(PyExc_NotImplementedError, "FILETIME result"); - return NULL; + result = NULL; + break; case VT_LPSTR: result = PyBytes_FromStringAndSize(sval, ssize); - if (sval != sbuf) - free(sval); - return result; + break; case VT_EMPTY: - Py_RETURN_NONE; + Py_INCREF(Py_None); + result = Py_None; + break; + default: + PyErr_Format(PyExc_NotImplementedError, "result of type %d", type); + result = NULL; + break; } - PyErr_Format(PyExc_NotImplementedError, "result of type %d", type); - return NULL; + if (sval != sbuf) + free(sval); + return result; } static PyObject* @@ -907,7 +916,7 @@ msidb_getsummaryinformation(msiobj *db, PyObject *args) return msierror(status); oresult = PyObject_NEW(struct msiobj, &summary_Type); - if (!result) { + if (!oresult) { MsiCloseHandle(result); return NULL; } diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h index 69781a96..6a5f6138 100644 --- a/PC/clinic/winreg.c.h +++ b/PC/clinic/winreg.c.h @@ -137,14 +137,14 @@ PyDoc_STRVAR(winreg_ConnectRegistry__doc__, {"ConnectRegistry", (PyCFunction)winreg_ConnectRegistry, METH_FASTCALL, winreg_ConnectRegistry__doc__}, static HKEY -winreg_ConnectRegistry_impl(PyObject *module, Py_UNICODE *computer_name, - HKEY key); +winreg_ConnectRegistry_impl(PyObject *module, + const Py_UNICODE *computer_name, HKEY key); static PyObject * winreg_ConnectRegistry(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - Py_UNICODE *computer_name; + const Py_UNICODE *computer_name; HKEY key; HKEY _return_value; @@ -185,14 +185,14 @@ PyDoc_STRVAR(winreg_CreateKey__doc__, {"CreateKey", (PyCFunction)winreg_CreateKey, METH_FASTCALL, winreg_CreateKey__doc__}, static HKEY -winreg_CreateKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key); +winreg_CreateKey_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key); static PyObject * winreg_CreateKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *sub_key; + const Py_UNICODE *sub_key; HKEY _return_value; if (!_PyArg_ParseStack(args, nargs, "O&Z:CreateKey", @@ -238,8 +238,9 @@ PyDoc_STRVAR(winreg_CreateKeyEx__doc__, {"CreateKeyEx", (PyCFunction)winreg_CreateKeyEx, METH_FASTCALL|METH_KEYWORDS, winreg_CreateKeyEx__doc__}, static HKEY -winreg_CreateKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, - int reserved, REGSAM access); +winreg_CreateKeyEx_impl(PyObject *module, HKEY key, + const Py_UNICODE *sub_key, int reserved, + REGSAM access); static PyObject * winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -248,7 +249,7 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; static _PyArg_Parser _parser = {"O&Z|ii:CreateKeyEx", _keywords, 0}; HKEY key; - Py_UNICODE *sub_key; + const Py_UNICODE *sub_key; int reserved = 0; REGSAM access = KEY_WRITE; HKEY _return_value; @@ -289,14 +290,14 @@ PyDoc_STRVAR(winreg_DeleteKey__doc__, {"DeleteKey", (PyCFunction)winreg_DeleteKey, METH_FASTCALL, winreg_DeleteKey__doc__}, static PyObject * -winreg_DeleteKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key); +winreg_DeleteKey_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key); static PyObject * winreg_DeleteKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *sub_key; + const Py_UNICODE *sub_key; if (!_PyArg_ParseStack(args, nargs, "O&u:DeleteKey", clinic_HKEY_converter, &key, &sub_key)) { @@ -337,8 +338,9 @@ PyDoc_STRVAR(winreg_DeleteKeyEx__doc__, {"DeleteKeyEx", (PyCFunction)winreg_DeleteKeyEx, METH_FASTCALL|METH_KEYWORDS, winreg_DeleteKeyEx__doc__}, static PyObject * -winreg_DeleteKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, - REGSAM access, int reserved); +winreg_DeleteKeyEx_impl(PyObject *module, HKEY key, + const Py_UNICODE *sub_key, REGSAM access, + int reserved); static PyObject * winreg_DeleteKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -347,7 +349,7 @@ winreg_DeleteKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py static const char * const _keywords[] = {"key", "sub_key", "access", "reserved", NULL}; static _PyArg_Parser _parser = {"O&u|ii:DeleteKeyEx", _keywords, 0}; HKEY key; - Py_UNICODE *sub_key; + const Py_UNICODE *sub_key; REGSAM access = KEY_WOW64_64KEY; int reserved = 0; @@ -376,14 +378,14 @@ PyDoc_STRVAR(winreg_DeleteValue__doc__, {"DeleteValue", (PyCFunction)winreg_DeleteValue, METH_FASTCALL, winreg_DeleteValue__doc__}, static PyObject * -winreg_DeleteValue_impl(PyObject *module, HKEY key, Py_UNICODE *value); +winreg_DeleteValue_impl(PyObject *module, HKEY key, const Py_UNICODE *value); static PyObject * winreg_DeleteValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *value; + const Py_UNICODE *value; if (!_PyArg_ParseStack(args, nargs, "O&Z:DeleteValue", clinic_HKEY_converter, &key, &value)) { @@ -490,13 +492,14 @@ PyDoc_STRVAR(winreg_ExpandEnvironmentStrings__doc__, {"ExpandEnvironmentStrings", (PyCFunction)winreg_ExpandEnvironmentStrings, METH_O, winreg_ExpandEnvironmentStrings__doc__}, static PyObject * -winreg_ExpandEnvironmentStrings_impl(PyObject *module, Py_UNICODE *string); +winreg_ExpandEnvironmentStrings_impl(PyObject *module, + const Py_UNICODE *string); static PyObject * winreg_ExpandEnvironmentStrings(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - Py_UNICODE *string; + const Py_UNICODE *string; if (!PyArg_Parse(arg, "u:ExpandEnvironmentStrings", &string)) { goto exit; @@ -579,16 +582,16 @@ PyDoc_STRVAR(winreg_LoadKey__doc__, {"LoadKey", (PyCFunction)winreg_LoadKey, METH_FASTCALL, winreg_LoadKey__doc__}, static PyObject * -winreg_LoadKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, - Py_UNICODE *file_name); +winreg_LoadKey_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, + const Py_UNICODE *file_name); static PyObject * winreg_LoadKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *sub_key; - Py_UNICODE *file_name; + const Py_UNICODE *sub_key; + const Py_UNICODE *file_name; if (!_PyArg_ParseStack(args, nargs, "O&uu:LoadKey", clinic_HKEY_converter, &key, &sub_key, &file_name)) { @@ -623,7 +626,7 @@ PyDoc_STRVAR(winreg_OpenKey__doc__, {"OpenKey", (PyCFunction)winreg_OpenKey, METH_FASTCALL|METH_KEYWORDS, winreg_OpenKey__doc__}, static HKEY -winreg_OpenKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, +winreg_OpenKey_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, int reserved, REGSAM access); static PyObject * @@ -633,7 +636,7 @@ winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; static _PyArg_Parser _parser = {"O&Z|ii:OpenKey", _keywords, 0}; HKEY key; - Py_UNICODE *sub_key; + const Py_UNICODE *sub_key; int reserved = 0; REGSAM access = KEY_READ; HKEY _return_value; @@ -675,7 +678,7 @@ PyDoc_STRVAR(winreg_OpenKeyEx__doc__, {"OpenKeyEx", (PyCFunction)winreg_OpenKeyEx, METH_FASTCALL|METH_KEYWORDS, winreg_OpenKeyEx__doc__}, static HKEY -winreg_OpenKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, +winreg_OpenKeyEx_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, int reserved, REGSAM access); static PyObject * @@ -685,7 +688,7 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; static _PyArg_Parser _parser = {"O&Z|ii:OpenKeyEx", _keywords, 0}; HKEY key; - Py_UNICODE *sub_key; + const Py_UNICODE *sub_key; int reserved = 0; REGSAM access = KEY_READ; HKEY _return_value; @@ -764,14 +767,14 @@ PyDoc_STRVAR(winreg_QueryValue__doc__, {"QueryValue", (PyCFunction)winreg_QueryValue, METH_FASTCALL, winreg_QueryValue__doc__}, static PyObject * -winreg_QueryValue_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key); +winreg_QueryValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key); static PyObject * winreg_QueryValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *sub_key; + const Py_UNICODE *sub_key; if (!_PyArg_ParseStack(args, nargs, "O&Z:QueryValue", clinic_HKEY_converter, &key, &sub_key)) { @@ -803,14 +806,14 @@ PyDoc_STRVAR(winreg_QueryValueEx__doc__, {"QueryValueEx", (PyCFunction)winreg_QueryValueEx, METH_FASTCALL, winreg_QueryValueEx__doc__}, static PyObject * -winreg_QueryValueEx_impl(PyObject *module, HKEY key, Py_UNICODE *name); +winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name); static PyObject * winreg_QueryValueEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *name; + const Py_UNICODE *name; if (!_PyArg_ParseStack(args, nargs, "O&Z:QueryValueEx", clinic_HKEY_converter, &key, &name)) { @@ -847,14 +850,14 @@ PyDoc_STRVAR(winreg_SaveKey__doc__, {"SaveKey", (PyCFunction)winreg_SaveKey, METH_FASTCALL, winreg_SaveKey__doc__}, static PyObject * -winreg_SaveKey_impl(PyObject *module, HKEY key, Py_UNICODE *file_name); +winreg_SaveKey_impl(PyObject *module, HKEY key, const Py_UNICODE *file_name); static PyObject * winreg_SaveKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *file_name; + const Py_UNICODE *file_name; if (!_PyArg_ParseStack(args, nargs, "O&u:SaveKey", clinic_HKEY_converter, &key, &file_name)) { @@ -896,8 +899,8 @@ PyDoc_STRVAR(winreg_SetValue__doc__, {"SetValue", (PyCFunction)winreg_SetValue, METH_FASTCALL, winreg_SetValue__doc__}, static PyObject * -winreg_SetValue_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, - DWORD type, Py_UNICODE *value, +winreg_SetValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, + DWORD type, const Py_UNICODE *value, Py_ssize_clean_t value_length); static PyObject * @@ -905,9 +908,9 @@ winreg_SetValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *sub_key; + const Py_UNICODE *sub_key; DWORD type; - Py_UNICODE *value; + const Py_UNICODE *value; Py_ssize_clean_t value_length; if (!_PyArg_ParseStack(args, nargs, "O&Zku#:SetValue", @@ -967,15 +970,16 @@ PyDoc_STRVAR(winreg_SetValueEx__doc__, {"SetValueEx", (PyCFunction)winreg_SetValueEx, METH_FASTCALL, winreg_SetValueEx__doc__}, static PyObject * -winreg_SetValueEx_impl(PyObject *module, HKEY key, Py_UNICODE *value_name, - PyObject *reserved, DWORD type, PyObject *value); +winreg_SetValueEx_impl(PyObject *module, HKEY key, + const Py_UNICODE *value_name, PyObject *reserved, + DWORD type, PyObject *value); static PyObject * winreg_SetValueEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HKEY key; - Py_UNICODE *value_name; + const Py_UNICODE *value_name; PyObject *reserved; DWORD type; PyObject *value; @@ -1091,4 +1095,4 @@ winreg_QueryReflectionKey(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=d1c8e2678015dd7d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=60c92ffc7438f8cf input=a9049054013a1b77]*/ diff --git a/PC/config.c b/PC/config.c index 2037b3db..c4922ccd 100644 --- a/PC/config.c +++ b/PC/config.c @@ -72,6 +72,8 @@ extern PyObject* PyInit__string(void); extern PyObject* PyInit__stat(void); extern PyObject* PyInit__opcode(void); +extern PyObject* PyInit__contextvars(void); + /* tools/freeze/makeconfig.py marker for additional "extern" */ /* -- ADDMODULE MARKER 1 -- */ @@ -164,6 +166,8 @@ struct _inittab _PyImport_Inittab[] = { {"_stat", PyInit__stat}, {"_opcode", PyInit__opcode}, + {"_contextvars", PyInit__contextvars}, + /* Sentinel */ {0, 0} }; diff --git a/PC/launcher.c b/PC/launcher.c index 4c620dab..a4e67811 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -666,7 +666,7 @@ run_child(wchar_t * cmdline) if (!ok) error(RC_CREATE_PROCESS, L"Job information setting failed"); memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); + GetStartupInfoW(&si); ok = safe_duplicate_handle(GetStdHandle(STD_INPUT_HANDLE), &si.hStdInput); if (!ok) error(RC_NO_STD_HANDLES, L"stdin duplication failed"); @@ -1707,6 +1707,17 @@ process(int argc, wchar_t ** argv) command = skip_me(GetCommandLineW()); debug(L"Called with command line: %ls\n", command); +#if !defined(VENV_REDIRECT) + /* bpo-35811: The __PYVENV_LAUNCHER__ variable is used to + * override sys.executable and locate the original prefix path. + * However, if it is silently inherited by a non-venv Python + * process, that process will believe it is running in the venv + * still. This is the only place where *we* can clear it (that is, + * when py.exe is being used to launch Python), so we do. + */ + SetEnvironmentVariableW(L"__PYVENV_LAUNCHER__", NULL); +#endif + #if defined(SCRIPT_WRAPPER) /* The launcher is being used in "script wrapper" mode. * There should therefore be a Python script named -script.py in diff --git a/PC/layout/main.py b/PC/layout/main.py index 217b2b09..910085c0 100644 --- a/PC/layout/main.py +++ b/PC/layout/main.py @@ -46,7 +46,7 @@ TCLTK_FILES_ONLY = FileNameSet("turtle.py") VENV_DIRS_ONLY = FileNameSet("venv", "ensurepip") -EXCLUDE_FROM_PYDS = FileStemSet("python*", "pyshellext") +EXCLUDE_FROM_PYDS = FileStemSet("python*", "pyshellext", "vcruntime*") EXCLUDE_FROM_LIB = FileNameSet("*.pyc", "__pycache__", "*.pickle") EXCLUDE_FROM_PACKAGED_LIB = FileNameSet("readme.txt") EXCLUDE_FROM_COMPILE = FileNameSet("badsyntax_*", "bad_*") @@ -156,6 +156,8 @@ def get_layout(ns): for dest, src in rglob(ns.build, "vcruntime*.dll"): yield dest, src + yield "LICENSE.txt", ns.source / "LICENSE" + for dest, src in rglob(ns.build, ("*.pyd", "*.dll")): if src.stem.endswith("_d") != bool(ns.debug) and src not in REQUIRED_DLLS: continue @@ -240,12 +242,18 @@ def get_layout(ns): yield "DLLs/{}".format(ns.include_cat.name), ns.include_cat -def _compile_one_py(src, dest, name, optimize): +def _compile_one_py(src, dest, name, optimize, checked=True): import py_compile if dest is not None: dest = str(dest) + mode = ( + py_compile.PycInvalidationMode.CHECKED_HASH + if checked + else py_compile.PycInvalidationMode.UNCHECKED_HASH + ) + try: return Path( py_compile.compile( @@ -254,7 +262,7 @@ def _compile_one_py(src, dest, name, optimize): str(name), doraise=True, optimize=optimize, - invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH, + invalidation_mode=mode, ) ) except py_compile.PyCompileError: @@ -262,16 +270,16 @@ def _compile_one_py(src, dest, name, optimize): return None -def _py_temp_compile(src, ns, dest_dir=None): +def _py_temp_compile(src, ns, dest_dir=None, checked=True): if not ns.precompile or src not in PY_FILES or src.parent in DATA_DIRS: return None dest = (dest_dir or ns.temp) / (src.stem + ".py") - return _compile_one_py(src, dest.with_suffix(".pyc"), dest, optimize=2) + return _compile_one_py(src, dest.with_suffix(".pyc"), dest, optimize=2, checked=checked) -def _write_to_zip(zf, dest, src, ns): - pyc = _py_temp_compile(src, ns) +def _write_to_zip(zf, dest, src, ns, checked=True): + pyc = _py_temp_compile(src, ns, checked=checked) if pyc: try: zf.write(str(pyc), dest.with_suffix(".pyc")) @@ -321,7 +329,7 @@ def generate_source_files(ns): ns.temp.mkdir(parents=True, exist_ok=True) with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf: for dest, src in get_lib_layout(ns): - _write_to_zip(zf, dest, src, ns) + _write_to_zip(zf, dest, src, ns, checked=False) if ns.include_underpth: log_info("Generating {} in {}", PYTHON_PTH_NAME, ns.temp) diff --git a/PC/pyconfig.h b/PC/pyconfig.h index d2a3f5dd..46fc84e9 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -192,18 +192,6 @@ typedef int pid_t; #define Py_IS_FINITE(X) _finite(X) #define copysign _copysign -/* VS 2010 and above already defines hypot as _hypot */ -#if _MSC_VER < 1600 -#define hypot _hypot -#endif - -/* VS 2015 defines these names with a leading underscore */ -#if _MSC_VER >= 1900 -#define timezone _timezone -#define daylight _daylight -#define tzname _tzname -#endif - /* Side by Side assemblies supported in VS 2005 and VS 2008 but not 2010*/ #if _MSC_VER >= 1400 && _MSC_VER < 1600 #define HAVE_SXS 1 @@ -231,7 +219,6 @@ typedef int pid_t; #endif #define COMPILER "[gcc]" -#define hypot _hypot #define PY_LONG_LONG long long #define PY_LLONG_MIN LLONG_MIN #define PY_LLONG_MAX LLONG_MAX diff --git a/PC/winreg.c b/PC/winreg.c index 6f310664..e3801b25 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -826,9 +826,9 @@ If the function fails, an OSError exception is raised. [clinic start generated code]*/ static HKEY -winreg_ConnectRegistry_impl(PyObject *module, Py_UNICODE *computer_name, - HKEY key) -/*[clinic end generated code: output=5ab79d02aa3167b4 input=5f98a891a347e68e]*/ +winreg_ConnectRegistry_impl(PyObject *module, + const Py_UNICODE *computer_name, HKEY key) +/*[clinic end generated code: output=cd4f70fb9ec901fb input=5f98a891a347e68e]*/ { HKEY retKey; long rc; @@ -863,8 +863,8 @@ If the function fails, an OSError exception is raised. [clinic start generated code]*/ static HKEY -winreg_CreateKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key) -/*[clinic end generated code: output=9c81d4095527c927 input=3cdd1622488acea2]*/ +winreg_CreateKey_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key) +/*[clinic end generated code: output=2af13910d56eae26 input=3cdd1622488acea2]*/ { HKEY retKey; long rc; @@ -902,9 +902,10 @@ If the function fails, an OSError exception is raised. [clinic start generated code]*/ static HKEY -winreg_CreateKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, - int reserved, REGSAM access) -/*[clinic end generated code: output=b9fce6dc5c4e39b1 input=42c2b03f98406b66]*/ +winreg_CreateKeyEx_impl(PyObject *module, HKEY key, + const Py_UNICODE *sub_key, int reserved, + REGSAM access) +/*[clinic end generated code: output=643a70ad6a361a97 input=42c2b03f98406b66]*/ { HKEY retKey; long rc; @@ -937,8 +938,8 @@ is removed. If the function fails, an OSError exception is raised. [clinic start generated code]*/ static PyObject * -winreg_DeleteKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key) -/*[clinic end generated code: output=7734b1e431991ae4 input=b31d225b935e4211]*/ +winreg_DeleteKey_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key) +/*[clinic end generated code: output=d2652a84f70e0862 input=b31d225b935e4211]*/ { long rc; rc = RegDeleteKeyW(key, sub_key ); @@ -972,9 +973,10 @@ On unsupported Windows versions, NotImplementedError is raised. [clinic start generated code]*/ static PyObject * -winreg_DeleteKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, - REGSAM access, int reserved) -/*[clinic end generated code: output=01378d86ad3eb936 input=711d9d89e7ecbed7]*/ +winreg_DeleteKeyEx_impl(PyObject *module, HKEY key, + const Py_UNICODE *sub_key, REGSAM access, + int reserved) +/*[clinic end generated code: output=52a1c8b374ebc003 input=711d9d89e7ecbed7]*/ { HMODULE hMod; typedef LONG (WINAPI *RDKEFunc)(HKEY, const wchar_t*, REGSAM, int); @@ -1014,8 +1016,8 @@ Removes a named value from a registry key. [clinic start generated code]*/ static PyObject * -winreg_DeleteValue_impl(PyObject *module, HKEY key, Py_UNICODE *value) -/*[clinic end generated code: output=67e7e9a514f84951 input=a78d3407a4197b21]*/ +winreg_DeleteValue_impl(PyObject *module, HKEY key, const Py_UNICODE *value) +/*[clinic end generated code: output=56fa9d21f3a54371 input=a78d3407a4197b21]*/ { long rc; Py_BEGIN_ALLOW_THREADS @@ -1182,8 +1184,9 @@ Expand environment vars. [clinic start generated code]*/ static PyObject * -winreg_ExpandEnvironmentStrings_impl(PyObject *module, Py_UNICODE *string) -/*[clinic end generated code: output=cba46ac293a8af1a input=b2a9714d2b751aa6]*/ +winreg_ExpandEnvironmentStrings_impl(PyObject *module, + const Py_UNICODE *string) +/*[clinic end generated code: output=8fa4e959747a7312 input=b2a9714d2b751aa6]*/ { wchar_t *retValue = NULL; DWORD retValueSize; @@ -1275,9 +1278,9 @@ tree. [clinic start generated code]*/ static PyObject * -winreg_LoadKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, - Py_UNICODE *file_name) -/*[clinic end generated code: output=87344005c5905cde input=e3b5b45ade311582]*/ +winreg_LoadKey_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, + const Py_UNICODE *file_name) +/*[clinic end generated code: output=65f89f2548cb27c7 input=e3b5b45ade311582]*/ { long rc; @@ -1309,9 +1312,9 @@ If the function fails, an OSError exception is raised. [clinic start generated code]*/ static HKEY -winreg_OpenKey_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, +winreg_OpenKey_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, int reserved, REGSAM access) -/*[clinic end generated code: output=a905f1b947f3ce85 input=098505ac36a9ae28]*/ +/*[clinic end generated code: output=8849bff2c30104ad input=098505ac36a9ae28]*/ { HKEY retKey; long rc; @@ -1336,9 +1339,9 @@ If the function fails, an OSError exception is raised. [clinic start generated code]*/ static HKEY -winreg_OpenKeyEx_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, +winreg_OpenKeyEx_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, int reserved, REGSAM access) -/*[clinic end generated code: output=226042593b37e940 input=c6c4972af8622959]*/ +/*[clinic end generated code: output=81bc2bd684bc77ae input=c6c4972af8622959]*/ { return winreg_OpenKey_impl(module, key, sub_key, reserved, access); } @@ -1406,8 +1409,8 @@ completeness. [clinic start generated code]*/ static PyObject * -winreg_QueryValue_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key) -/*[clinic end generated code: output=2bb8d1e02c10d0b6 input=41cafbbf423b21d6]*/ +winreg_QueryValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key) +/*[clinic end generated code: output=c655810ae50c63a9 input=41cafbbf423b21d6]*/ { long rc; PyObject *retStr; @@ -1473,8 +1476,8 @@ The return value is a tuple of the value and the type_id. [clinic start generated code]*/ static PyObject * -winreg_QueryValueEx_impl(PyObject *module, HKEY key, Py_UNICODE *name) -/*[clinic end generated code: output=5b4fa3e33d6d3e8f input=cf366cada4836891]*/ +winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) +/*[clinic end generated code: output=f1b85b1c3d887ec7 input=cf366cada4836891]*/ { long rc; BYTE *retBuf, *tmp; @@ -1546,8 +1549,8 @@ to the API. [clinic start generated code]*/ static PyObject * -winreg_SaveKey_impl(PyObject *module, HKEY key, Py_UNICODE *file_name) -/*[clinic end generated code: output=1dda1502bd4c30d8 input=da735241f91ac7a2]*/ +winreg_SaveKey_impl(PyObject *module, HKEY key, const Py_UNICODE *file_name) +/*[clinic end generated code: output=ca94b835c88f112b input=da735241f91ac7a2]*/ { LPSECURITY_ATTRIBUTES pSA = NULL; @@ -1592,10 +1595,10 @@ KEY_SET_VALUE access. [clinic start generated code]*/ static PyObject * -winreg_SetValue_impl(PyObject *module, HKEY key, Py_UNICODE *sub_key, - DWORD type, Py_UNICODE *value, +winreg_SetValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, + DWORD type, const Py_UNICODE *value, Py_ssize_clean_t value_length) -/*[clinic end generated code: output=1e31931174820631 input=2cd2adab79339c53]*/ +/*[clinic end generated code: output=686bedb1cbb4367b input=2cd2adab79339c53]*/ { long rc; @@ -1658,9 +1661,10 @@ the configuration registry to help the registry perform efficiently. [clinic start generated code]*/ static PyObject * -winreg_SetValueEx_impl(PyObject *module, HKEY key, Py_UNICODE *value_name, - PyObject *reserved, DWORD type, PyObject *value) -/*[clinic end generated code: output=c88c8426b6c00ec7 input=900a9e3990bfb196]*/ +winreg_SetValueEx_impl(PyObject *module, HKEY key, + const Py_UNICODE *value_name, PyObject *reserved, + DWORD type, PyObject *value) +/*[clinic end generated code: output=811b769a66ae11b7 input=900a9e3990bfb196]*/ { BYTE *data; DWORD len; diff --git a/PCbuild/_contextvars.vcxproj b/PCbuild/_contextvars.vcxproj deleted file mode 100644 index cf266f39..00000000 --- a/PCbuild/_contextvars.vcxproj +++ /dev/null @@ -1,77 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - PGInstrument - Win32 - - - PGInstrument - x64 - - - PGUpdate - Win32 - - - PGUpdate - x64 - - - Release - Win32 - - - Release - x64 - - - - {B8BF1D81-09DC-42D4-B406-4F868B33A89E} - _contextvars - Win32Proj - - - - - DynamicLibrary - NotSet - - - - .pyd - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - - - - - - - - - - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - - - - - - diff --git a/PCbuild/_contextvars.vcxproj.filters b/PCbuild/_contextvars.vcxproj.filters deleted file mode 100644 index 06200c34..00000000 --- a/PCbuild/_contextvars.vcxproj.filters +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - {7CBD8910-233D-4E9A-9164-9BA66C1F0E6D} - - - - - Source Files - - - diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat index df69a195..7f90fca2 100644 --- a/PCbuild/find_python.bat +++ b/PCbuild/find_python.bat @@ -24,7 +24,7 @@ :begin_search @set PYTHON= -@set _Py_EXTERNALS_DIR=%EXTERNAL_DIR% +@set _Py_EXTERNALS_DIR=%EXTERNALS_DIR% @if "%_Py_EXTERNALS_DIR%"=="" (set _Py_EXTERNALS_DIR=%~dp0\..\externals) @rem If we have Python in externals, use that one diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index dfbc924d..ddeb9626 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -51,8 +51,8 @@ set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.0j set libraries=%libraries% sqlite-3.21.0.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.8.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.8.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 set libraries=%libraries% xz-5.2.2 set libraries=%libraries% zlib-1.2.11 @@ -73,7 +73,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.0j -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.8.0 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/openssl.props b/PCbuild/openssl.props index 001dc45d..4b8d5df8 100644 --- a/PCbuild/openssl.props +++ b/PCbuild/openssl.props @@ -23,6 +23,6 @@ - + \ No newline at end of file diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj index 19d8d2f7..b13abb7d 100644 --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -50,7 +50,7 @@ - + diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index 2b36835b..eaeb8b0d 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -185,10 +185,11 @@ public override bool Execute() { $(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Kits\Installed Roots@KitsRoot)\bin\x86 $(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A@InstallationFolder)\Bin\ <_SignCommand Condition="Exists($(SdkBinPath)) and '$(SigningCertificate)' != '' and $(SupportSigning)">"$(SdkBinPath)\signtool.exe" sign /q /a /n "$(SigningCertificate)" /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d "Python $(PythonVersion)" + <_SignCommand Condition="Exists($(SdkBinPath)) and '$(SigningCertificateSha1)' != '' and $(SupportSigning)">"$(SdkBinPath)\signtool.exe" sign /q /a /sha1 "$(SigningCertificateSha1)" /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d "Python $(PythonVersion)" <_MakeCatCommand Condition="Exists($(SdkBinPath))">"$(SdkBinPath)\makecat.exe" - - + + diff --git a/PCbuild/python.props b/PCbuild/python.props index 3e60cddf..66533b69 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -76,7 +76,7 @@ matter which WinSDK version we use. --> <_RegistryVersion>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion) - <_RegistryVersion Condition="$(_RegistryVersion) == ''">$(Registry:HKEY_LOCAL_MACHINE\WOW6432Node\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion) + <_RegistryVersion Condition="$(_RegistryVersion) == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion) <_RegistryVersion Condition="$(_RegistryVersion) != '' and !$(_RegistryVersion.EndsWith('.0'))">$(_RegistryVersion).0 diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index a10a5219..e9947473 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -229,7 +229,6 @@ - diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 34ce5930..a0978e0f 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -1016,9 +1016,6 @@ PC - - Modules - Modules diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 6e0ec0e0..7dc31c39 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -4,7 +4,7 @@ 8 6 - 8 + 9 0 $(TclMajorVersion) $(TclMinorVersion) diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index e2afba2b..58b0802f 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -116,7 +116,7 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise) flags = blocking ? 0 : GRND_NONBLOCK; dest = buffer; while (0 < size) { -#ifdef sun +#if defined(__sun) && defined(__SVR4) /* Issue #26735: On Solaris, getrandom() is limited to returning up to 1024 bytes. Call it multiple times if more bytes are requested. */ @@ -266,7 +266,7 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise) } return 1; } -#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */ +#endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */ static struct { diff --git a/Python/getcopyright.c b/Python/getcopyright.c index 51772ece..27a1731f 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -4,7 +4,7 @@ static const char cprt[] = "\ -Copyright (c) 2001-2018 Python Software Foundation.\n\ +Copyright (c) 2001-2019 Python Software Foundation.\n\ All Rights Reserved.\n\ \n\ Copyright (c) 2000 BeOpen.com.\n\ diff --git a/Python/import.c b/Python/import.c index 5f5d135c..ccdd5993 100644 --- a/Python/import.c +++ b/Python/import.c @@ -743,7 +743,6 @@ _PyImport_FindExtensionObjectEx(PyObject *name, PyObject *filename, } if (_PyState_AddModule(mod, def) < 0) { PyMapping_DelItem(modules, name); - Py_DECREF(mod); return NULL; } if (Py_VerboseFlag) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index efe5b29e..cdc2edf0 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -134,11 +134,14 @@ sys_breakpointhook(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb modulepath = PyUnicode_FromString("builtins"); attrname = envar; } - else { + else if (last_dot != envar) { /* Split on the last dot; */ modulepath = PyUnicode_FromStringAndSize(envar, last_dot - envar); attrname = last_dot + 1; } + else { + goto warn; + } if (modulepath == NULL) { PyMem_RawFree(envar); return NULL; @@ -156,21 +159,29 @@ sys_breakpointhook(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb Py_DECREF(fromlist); if (module == NULL) { - goto error; + if (PyErr_ExceptionMatches(PyExc_ImportError)) { + goto warn; + } + PyMem_RawFree(envar); + return NULL; } PyObject *hook = PyObject_GetAttrString(module, attrname); Py_DECREF(module); if (hook == NULL) { - goto error; + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + goto warn; + } + PyMem_RawFree(envar); + return NULL; } PyMem_RawFree(envar); PyObject *retval = _PyObject_FastCallKeywords(hook, args, nargs, keywords); Py_DECREF(hook); return retval; - error: + warn: /* If any of the imports went wrong, then warn and ignore. */ PyErr_Clear(); int status = PyErr_WarnFormat( diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 61fa8619..56295d0e 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -104,8 +104,9 @@ LeaveNonRecursiveMutex(PNRMUTEX mutex) if (PyMUTEX_LOCK(&mutex->cs)) return FALSE; mutex->locked = 0; - result = PyCOND_SIGNAL(&mutex->cv); - result &= PyMUTEX_UNLOCK(&mutex->cs); + /* condvar APIs return 0 on success. We need to return TRUE on success. */ + result = !PyCOND_SIGNAL(&mutex->cv); + PyMUTEX_UNLOCK(&mutex->cs); return result; } diff --git a/README.rst b/README.rst index 43ded3e4..96d05f93 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.7.2 +This is Python version 3.7.3 ============================ .. image:: https://travis-ci.org/python/cpython.svg?branch=master @@ -18,8 +18,8 @@ This is Python version 3.7.2 :target: https://codecov.io/gh/python/cpython Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -2012, 2013, 2014, 2015, 2016, 2017, 2018 Python Software Foundation. All rights -reserved. +2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Python Software Foundation. All +rights reserved. See the end of this file for further copyright and license information. @@ -60,7 +60,7 @@ On Unix, Linux, BSD, macOS, and Cygwin:: make test sudo make install -This will install Python as python3. +This will install Python as ``python3``. You can pass many options to the configure script; run ``./configure --help`` to find out more. On macOS and Cygwin, the executable is called ``python.exe``; @@ -247,8 +247,8 @@ Copyright and License Information --------------------------------- Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -2012, 2013, 2014, 2015, 2016, 2017, 2018 Python Software Foundation. All rights -reserved. +2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Python Software Foundation. All +rights reserved. Copyright (c) 2000 BeOpen.com. All rights reserved. diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index b704b5a6..0ba8caba 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2824,7 +2824,7 @@ class unicode_converter(CConverter): @add_legacy_c_converter('Z', accept={str, NoneType}) @add_legacy_c_converter('Z#', accept={str, NoneType}, zeroes=True) class Py_UNICODE_converter(CConverter): - type = 'Py_UNICODE *' + type = 'const Py_UNICODE *' default_type = (str, Null, NoneType) format_unit = 'u' diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index bfaa9403..d744cab7 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -1178,7 +1178,7 @@ class PyUnicodeObjectPtr(PyObjectPtr): def proxyval(self, visited): global _is_pep393 if _is_pep393 is None: - fields = gdb.lookup_type('PyUnicodeObject').target().fields() + fields = gdb.lookup_type('PyUnicodeObject').fields() _is_pep393 = 'data' in [f.name for f in fields] if _is_pep393: # Python 3.3 and newer diff --git a/Tools/msi/dev/dev.wixproj b/Tools/msi/dev/dev.wixproj index bc3a19ce..4a56cec3 100644 --- a/Tools/msi/dev/dev.wixproj +++ b/Tools/msi/dev/dev.wixproj @@ -21,7 +21,8 @@ - + $(PySourcePath) !(bindpath.src) $(PySourcePath) diff --git a/Tools/msi/lib/lib_files.wxs b/Tools/msi/lib/lib_files.wxs index 4bd0c57e..a9952bda 100644 --- a/Tools/msi/lib/lib_files.wxs +++ b/Tools/msi/lib/lib_files.wxs @@ -1,6 +1,6 @@  - + diff --git a/Tools/msi/sdktools.psm1 b/Tools/msi/sdktools.psm1 index 81a74d36..61edb341 100644 --- a/Tools/msi/sdktools.psm1 +++ b/Tools/msi/sdktools.psm1 @@ -21,6 +21,9 @@ function Sign-File { $description = "Python"; } } + if (-not $certsha1) { + $certsha1 = $env:SigningCertificateSha1; + } if (-not $certname) { $certname = $env:SigningCertificate; } @@ -32,7 +35,7 @@ function Sign-File { if ($certsha1) { SignTool sign /sha1 $certsha1 /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a } elseif ($certname) { - SignTool sign /n $certname /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a + SignTool sign /a /n $certname /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a } elseif ($certfile) { SignTool sign /f $certfile /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a } else { diff --git a/Tools/nuget/python.nuspec b/Tools/nuget/python.nuspec index d5f3e632..8f98e808 100644 --- a/Tools/nuget/python.nuspec +++ b/Tools/nuget/python.nuspec @@ -5,9 +5,8 @@ Python 0.0.0.0 Python Software Foundation - https://docs.python.org/3/license.html + tools\LICENSE.txt https://www.python.org/ - false Installs 64-bit Python for use in build scenarios. https://www.python.org/static/favicon.ico python diff --git a/Tools/nuget/pythondaily.nuspec b/Tools/nuget/pythondaily.nuspec index ee3343bb..5cf55806 100644 --- a/Tools/nuget/pythondaily.nuspec +++ b/Tools/nuget/pythondaily.nuspec @@ -3,11 +3,10 @@ pythondaily Python (Daily build) - 0.0.0.0 Python Software Foundation - https://docs.python.org/3/license.html + 0.0.0.0 + tools\LICENSE.txt https://www.python.org/ - false Installs an unsigned, untested build of Python for test purposes only. https://www.python.org/static/favicon.ico python diff --git a/Tools/nuget/pythondaily.symbols.nuspec b/Tools/nuget/pythondaily.symbols.nuspec index b89717a1..608e15c5 100644 --- a/Tools/nuget/pythondaily.symbols.nuspec +++ b/Tools/nuget/pythondaily.symbols.nuspec @@ -5,9 +5,7 @@ Python (Daily build) 0.0.0.0 Python Software Foundation - https://docs.python.org/3/license.html https://www.python.org/ - false Contains symbols for the daily build of Python. https://www.python.org/static/favicon.ico python diff --git a/Tools/nuget/pythonx86.nuspec b/Tools/nuget/pythonx86.nuspec index ebfcd6c9..27ef67e7 100644 --- a/Tools/nuget/pythonx86.nuspec +++ b/Tools/nuget/pythonx86.nuspec @@ -5,9 +5,8 @@ Python (32-bit) Python Software Foundation 0.0.0.0 - https://docs.python.org/3/license.html + tools\LICENSE.txt https://www.python.org/ - false Installs 32-bit Python for use in build scenarios. https://www.python.org/static/favicon.ico python diff --git a/aclocal.m4 b/aclocal.m4 index 32828c24..85a0dbba 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15.1 -*- Autoconf -*- +# generated automatically by aclocal 1.16.1 -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -13,7 +13,7 @@ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -dnl serial 11 (pkg-config-0.29) +dnl serial 11 (pkg-config-0.29.1) dnl dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson @@ -55,7 +55,7 @@ dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], -[m4_define([PKG_MACROS_VERSION], [0.29]) +[m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ diff --git a/configure b/configure index 5e5f974b..18047ced 100755 --- a/configure +++ b/configure @@ -784,6 +784,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -897,6 +898,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1149,6 +1151,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1286,7 +1297,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1439,6 +1450,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -12727,6 +12739,150 @@ fi done +# We search for both crypt and crypt_r as one or the other may be defined +# This gets us our -lcrypt in LIBS when required on the target platform. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt" >&5 +$as_echo_n "checking for library containing crypt... " >&6; } +if ${ac_cv_search_crypt+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char crypt (); +int +main () +{ +return crypt (); + ; + return 0; +} +_ACEOF +for ac_lib in '' crypt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_crypt=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_crypt+:} false; then : + break +fi +done +if ${ac_cv_search_crypt+:} false; then : + +else + ac_cv_search_crypt=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt" >&5 +$as_echo "$ac_cv_search_crypt" >&6; } +ac_res=$ac_cv_search_crypt +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt_r" >&5 +$as_echo_n "checking for library containing crypt_r... " >&6; } +if ${ac_cv_search_crypt_r+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char crypt_r (); +int +main () +{ +return crypt_r (); + ; + return 0; +} +_ACEOF +for ac_lib in '' crypt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_crypt_r=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_crypt_r+:} false; then : + break +fi +done +if ${ac_cv_search_crypt_r+:} false; then : + +else + ac_cv_search_crypt_r=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt_r" >&5 +$as_echo "$ac_cv_search_crypt_r" >&6; } +ac_res=$ac_cv_search_crypt_r +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +ac_fn_c_check_func "$LINENO" "crypt_r" "ac_cv_func_crypt_r" +if test "x$ac_cv_func_crypt_r" = xyes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define _GNU_SOURCE /* Required for crypt_r()'s prototype in glibc. */ +#include + +int +main () +{ + +struct crypt_data d; +char *r = crypt_r("", "", &d); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + + for ac_func in clock_gettime do : ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" @@ -15598,6 +15754,8 @@ else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#include +#include int main() { int val1 = nice(1); diff --git a/configure.ac b/configure.ac index a7de901e..ad0f4d42 100644 --- a/configure.ac +++ b/configure.ac @@ -3875,6 +3875,23 @@ AC_CHECK_FUNCS(gettimeofday, ]) ) +# We search for both crypt and crypt_r as one or the other may be defined +# This gets us our -lcrypt in LIBS when required on the target platform. +AC_SEARCH_LIBS(crypt, crypt) +AC_SEARCH_LIBS(crypt_r, crypt) + +AC_CHECK_FUNC(crypt_r, + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#define _GNU_SOURCE /* Required for crypt_r()'s prototype in glibc. */ +#include +]], [[ +struct crypt_data d; +char *r = crypt_r("", "", &d); +]])], + [AC_DEFINE(HAVE_CRYPT_R, 1, [Define if you have the crypt_r() function.])], + []) +) + AC_CHECK_FUNCS(clock_gettime, [], [ AC_CHECK_LIB(rt, clock_gettime, [ LIBS="$LIBS -lrt" @@ -4873,6 +4890,8 @@ LIBS=$LIBS_no_readline AC_MSG_CHECKING(for broken nice()) AC_CACHE_VAL(ac_cv_broken_nice, [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include int main() { int val1 = nice(1); diff --git a/pyconfig.h.in b/pyconfig.h.in index a82e82cc..4032fa51 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -143,6 +143,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CRYPT_H +/* Define if you have the crypt_r() function. */ +#undef HAVE_CRYPT_R + /* Define to 1 if you have the `ctermid' function. */ #undef HAVE_CTERMID