manylinux: false
coverage: false
+resources:
+ containers:
+ - container: manylinux1
+ image: pyca/cryptography-manylinux1:x86_64
+
jobs:
- job: Prebuild
displayName: Pre-build checks
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
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
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
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
+++ /dev/null
-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'))
--- /dev/null
+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
+++ /dev/null
-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
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
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" \
-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'
- 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
+variables:
+ manylinux: false
+ coverage: false
+
+resources:
+ containers:
+ - container: manylinux1
+ image: pyca/cryptography-manylinux1:x86_64
+
jobs:
- job: Prebuild
displayName: Pre-build checks
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
+++ /dev/null
-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()
--- /dev/null
+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()
steps:
- checkout: self
- clean: true
+ clean: false
fetchDepth: 5
- powershell: |
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)
If you find a bug in this documentation or would like to propose an improvement,
please submit a bug report on the :ref:`tracker <using-the-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).
.. _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/
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)
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)
.. 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)
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)
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
.. 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
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)
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)
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.
.. 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)
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)
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)
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`.
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
.. 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.
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
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.
# 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:
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::
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:
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::
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::
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::
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:
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:
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:
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:
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:
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::
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:::
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:::
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:::
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:
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:
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:
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:
PyImport_ImportFrozenModule:int:::
PyImport_ImportFrozenModule:const char*:::
+PyImport_ImportFrozenModuleObject:int:::
+PyImport_ImportFrozenModuleObject:PyObject*::+1:
+
PyImport_ImportModule:PyObject*::+1:
PyImport_ImportModule:const char*:name::
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::
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:
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:::
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::
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::
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:::
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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::
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::
PyRun_StringFlags:PyObject*:locals:0:
PyRun_StringFlags:PyCompilerFlags*:flags::
+PySeqIter_Check:int:::
+PySeqIter_Check::op::
+
PySeqIter_New:PyObject*::+1:
PySeqIter_New:PyObject*:seq::
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:
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:
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:
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:
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::
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:
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::
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::
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::
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::
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::
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::
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::
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:
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:
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:
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:
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:
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:
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
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::
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
Where in the world is www.python.org located?
---------------------------------------------
-The Python project's infrastructure is located all over the world.
-`www.python.org <https://www.python.org>`_ is graciously hosted by `Rackspace
-<https://www.rackspace.com>`_, with CDN caching provided by `Fastly
-<https://www.fastly.com>`_. `Upfront Systems
-<http://www.upfrontsoftware.co.za>`_ hosts `bugs.python.org
-<https://bugs.python.org>`_. Many other Python services like `the Wiki
-<https://wiki.python.org>`_ are hosted by `Oregon State
-University Open Source Lab <https://osuosl.org>`_.
+The Python project's infrastructure is located all over the world and is managed
+by the Python Infrastructure Team. Details `here <http://infra.psf.io>`__.
Why is it called 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
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 "<stdin>", line 1, in <module>
+ 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
===================
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?
------------------------------------------------------------------------------
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
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
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::
# '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')
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)
# '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')
# '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')
.. 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``.
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
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
: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 <https://en.wikipedia.org/wiki/Unicode#History>`_
-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
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.
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
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
difficult reading. `A chronology <http://www.unicode.org/history/>`_ 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 <https://www.youtube.com/watch?v=MijmeoH9LT4>`
+(9 minutes 36 seconds).
+
To help understand the standard, Jukka Korpela has written `an introductory
guide <http://jkorpela.fi/unicode/guide.html>`_ to reading the
Unicode character tables.
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.
# '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: <encoding name> -*-
-
Side note: Python 3 also supports using Unicode characters in identifiers::
répertoire = "/tmp/records.log"
>>> 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
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::
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
---------------------------
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
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
.. 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
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
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.
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.
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
<asyncio-pass-keywords>` 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.
.. 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<asyncio-streams>`.
+ Raised by the :ref:`asyncio stream APIs<asyncio-streams>`.
- This exception is a subclass of :exc:`EOFError`.
+ This exception is a subclass of :exc:`EOFError`.
.. attribute:: expected
.. 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.
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.
See the :ref:`concurrency and multithreading <asyncio-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
*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)
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
: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::
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
.. 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::
: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
+ <https://medium.com/@krishankantsinghal/my-first-blog-on-medium-583159139237>`_).
+
+* 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
: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::
'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
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
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::
... '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``
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
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.
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, \
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
-:mod:`contextlib` --- Utilities for :keyword:`with`\ -statement contexts
-========================================================================
+:mod:`!contextlib` --- Utilities for :keyword:`!with`\ -statement contexts
+==========================================================================
.. module:: contextlib
:synopsis: Utilities for with-statement contexts.
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.
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.
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
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
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 <variable 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.
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
>>> 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
+<https://www.bytereef.org/mpdecimal/doc/libmpdec/index.html>`_ library for
+arbitrary precision correctly-rounded decimal floating point arithmetic.
+``libmpdec`` uses `Karatsuba multiplication
+<https://en.wikipedia.org/wiki/Karatsuba_algorithm>`_
+for medium-sized numbers and the `Number Theoretic Transform
+<https://en.wikipedia.org/wiki/Discrete_Fourier_transform_(general)#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
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
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:
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)
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 <faq-positional-only-arguments>`.
+
This function is added to the built-in namespace by the :mod:`site` module.
.. versionchanged:: 3.4
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)
``'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'``).
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 <open-newline-parameter>` parameter for further details.
+
.. note::
Python doesn't depend on the underlying operating system's notion of text
.. 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:
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
b'<!doctype html>\n<!--[if"...
...
>>> # Example of an invalid request
+ >>> conn = http.client.HTTPSConnection("docs.python.org")
>>> conn.request("GET", "/parrot.spam")
>>> r2 = conn.getresponse()
>>> print(r2.status, r2.reason)
``413`` ``REQUEST_ENTITY_TOO_LARGE`` HTTP/1.1 :rfc:`7231`, Section 6.5.11
``414`` ``REQUEST_URI_TOO_LONG`` HTTP/1.1 :rfc:`7231`, Section 6.5.12
``415`` ``UNSUPPORTED_MEDIA_TYPE`` HTTP/1.1 :rfc:`7231`, Section 6.5.13
-``416`` ``REQUEST_RANGE_NOT_SATISFIABLE`` HTTP/1.1 Range Requests :rfc:`7233`, Section 4.4
+``416`` ``REQUESTED_RANGE_NOT_SATISFIABLE`` HTTP/1.1 Range Requests :rfc:`7233`, Section 4.4
``417`` ``EXPECTATION_FAILED`` HTTP/1.1 :rfc:`7231`, Section 6.5.14
``421`` ``MISDIRECTED_REQUEST`` HTTP/2 :rfc:`7540`, Section 9.1.2
``422`` ``UNPROCESSABLE_ENTITY`` WebDAV :rfc:`4918`, Section 11.2
Show Completions
Open a scrollable list allowing selection of keywords and attributes. See
- Completions in the Tips sections below.
+ :ref:`Completions <completions>` in the Editing and navigation section below.
Expand Word
Expand a prefix you have typed to match a full word in the same window;
Show call tip
After an unclosed parenthesis for a function, open a small window with
- function parameter hints.
+ function parameter hints. See :ref:`Calltips <calltips>` in the
+ Editing and navigation section below.
Show surrounding parens
Highlight the surrounding parenthesis.
+.. _format-menu:
+
Format menu (Editor window only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Restart Shell
Restart the shell to clean the environment.
+Previous History
+ Cycle through earlier commands in history which match the current entry.
+
+Next History
+ Cycle through later commands in history which match the current entry.
+
Interrupt Execution
Stop a running program.
Configure IDLE
Open a configuration dialog and change preferences for the following:
fonts, indentation, keybindings, text color themes, startup windows and
- size, additional help sources, and extensions (see below). On macOS,
- open the configuration dialog by selecting Preferences in the application
- menu. To use a new built-in color theme (IDLE Dark) with older IDLEs,
- save it as a new custom theme.
+ size, additional help sources, and extensions. On macOS, open the
+ configuration dialog by selecting Preferences in the application
+ menu. For more, see
+ :ref:`Setting preferences <preferences>` under Help and preferences.
- Non-default user settings are saved in a .idlerc directory in the user's
- home directory. Problems caused by bad user configuration files are solved
- by editing or deleting one or more of the files in .idlerc.
+Zoom/Restore Height
+ Toggles the window between normal size and maximum height. The initial size
+ defaults to 40 lines by 80 chars unless changed on the General tab of the
+ Configure IDLE dialog.
-Code Context (toggle)(Editor Window only)
+Show/Hide Code Context (Editor Window only)
Open a pane at the top of the edit window which shows the block context
- of the code which has scrolled above the top of the window. Clicking a
- line in this pane exposes that line at the top of the editor.
+ of the code which has scrolled above the top of the window. See
+ :ref:`Code Context <code-context>` in the Editing and Navigation section below.
Window menu (Shell and Editor)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Zoom Height
- Toggles the window between normal size and maximum height. The initial size
- defaults to 40 lines by 80 chars unless changed on the General tab of the
- Configure IDLE dialog.
-
-The rest of this menu lists the names of all open windows; select one to bring
-it to the foreground (deiconifying it if necessary).
+Lists the names of all open windows; select one to bring it to the foreground
+(deiconifying it if necessary).
Help menu (Shell and Editor)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run the turtledemo module with example Python code and turtle drawings.
Additional help sources may be added here with the Configure IDLE dialog under
-the General tab. See the "Help sources" subsection below for more
-on Help menu choices.
+the General tab. See the :ref:`Help sources <help-sources>` subsection below
+for more on Help menu choices.
.. index::
single: Cut
the code above and the prompt below down to a 'Squeezed text' label.
+.. _editing-and-navigation:
+
Editing and navigation
----------------------
Shell window one tab), number depends on Indent width. Currently, tabs
are restricted to four spaces due to Tcl/Tk limitations.
-See also the indent/dedent region commands in the edit menu.
+See also the indent/dedent region commands on the
+:ref:`Format menu <format-menu>`.
+
+
+.. _completions:
Completions
^^^^^^^^^^^
If you don't like the ACW popping up unbidden, simply make the delay
longer or disable the extension.
+.. _calltips:
+
Calltips
^^^^^^^^
might want to run a file after writing the import statements at the top,
or immediately run an existing file before editing.
+.. _code-context:
+
+Code Context
+^^^^^^^^^^^^
+
+Within an editor window containing Python code, code context can be toggled
+in order to show or hide a pane at the top of the window. When shown, this
+pane freezes the opening lines for block code, such as those beginning with
+``class``, ``def``, or ``if`` keywords, that would have otherwise scrolled
+out of view. The size of the pane will be expanded and contracted as needed
+to show the all current levels of context, up to the maximum number of
+lines defined in the Configure IDLE dialog (which defaults to 15). If there
+are no current context lines and the feature is toggled on, a single blank
+line will display. Clicking on a line in the context pane will move that
+line to the top of the editor.
+
+The text and background colors for the context pane can be configured under
+the Highlights tab in the Configure IDLE dialog.
+
Python Shell window
^^^^^^^^^^^^^^^^^^^
A Windows console, for instance, keeps a user-settable 1 to 9999 lines,
with 300 the default.
-Text widgets display a subset of Unicode, the Basic Multilingual Plane (BMP).
-Which characters get a proper glyph instead of a replacement box depends on
-the operating system and installed fonts. Newline characters cause following
-text to appear on a new line, but other control characters are either
-replaced with a box or deleted. However, ``repr()``, which is used for
-interactive echo of expression values, replaces control characters,
-some BMP codepoints, and all non-BMP characters with escape codes
-before they are output.
+A Tk Text widget, and hence IDLE's Shell, displays characters (codepoints)
+in the the BMP (Basic Multilingual Plane) subset of Unicode.
+Which characters are displayed with a proper glyph and which with a
+replacement box depends on the operating system and installed fonts.
+Tab characters cause the following text to begin after
+the next tab stop. (They occur every 8 'characters').
+Newline characters cause following text to appear on a new line.
+Other control characters are ignored or displayed as a space, box, or
+something else, depending on the operating system and font.
+(Moving the text cursor through such output with arrow keys may exhibit
+some surprising spacing behavior.)
+
+.. code-block:: none
+
+ >>> s = 'a\tb\a<\x02><\r>\bc\nd'
+ >>> len(s)
+ 14
+ >>> s # Display repr(s)
+ 'a\tb\x07<\x02><\r>\x08c\nd'
+ >>> print(s, end='') # Display s as is.
+ # Result varies by OS and font. Try it.
+
+The ``repr`` function is used for interactive echo of expression
+values. It returns an altered version of the input string in which
+control codes, some BMP codepoints, and all non-BMP codepoints are
+replaced with escape codes. As demonstrated above, it allows one to
+identify the characters in a string, regardless of how they are displayed.
Normal and error output are generally kept separate (on separate lines)
from code input and each other. They each get different highlight colors.
Help and preferences
--------------------
+.. _help-sources:
+
Help sources
^^^^^^^^^^^^
Selected URLs can be added or removed from the help menu at any time using the
General tab of the Configure IDLE dialog .
+.. _preferences:
+
Setting preferences
^^^^^^^^^^^^^^^^^^^
The font preferences, highlighting, keys, and general preferences can be
-changed via Configure IDLE on the Option menu. Keys can be user defined;
-IDLE ships with four built-in key sets. In addition, a user can create a
-custom key set in the Configure IDLE dialog under the keys tab.
+changed via Configure IDLE on the Option menu.
+Non-default user settings are saved in a .idlerc directory in the user's
+home directory. Problems caused by bad user configuration files are solved
+by editing or deleting one or more of the files in .idlerc.
+
+On the Font tab, see the text sample for the effect of font face and size
+on multiple characters in multiple languages. Edit the sample to add
+other characters of personal interest. Use the sample to select
+monospaced fonts. If particular characters have problems in Shell or an
+editor, add them to the top of the sample and try changing first size
+and then font.
+
+On the Highlights and Keys tab, select a built-in or custom color theme
+and key set. To use a newer built-in color theme or key set with older
+IDLEs, save it as a new custom theme or key set and it well be accessible
+to older IDLEs.
IDLE on macOS
^^^^^^^^^^^^^
The :class:`IMAP4` class supports the :keyword:`with` statement. When used
like this, the IMAP4 ``LOGOUT`` command is issued automatically when the
- :keyword:`with` statement exits. E.g.::
+ :keyword:`!with` statement exits. E.g.::
>>> from imaplib import IMAP4
>>> with IMAP4("domain.org") as M:
If a module imports objects from another module using :keyword:`from` ...
:keyword:`import` ..., calling :func:`reload` for the other module does not
redefine the objects imported from it --- one way around this is to re-execute
- the :keyword:`from` statement, another is to use :keyword:`import` and qualified
+ the :keyword:`!from` statement, another is to use :keyword:`!import` and qualified
names (*module*.*name*) instead.
If a module instantiates instances of a class, reloading the module that defines
-:mod:`importlib` --- The implementation of :keyword:`import`
-============================================================
+:mod:`!importlib` --- The implementation of :keyword:`!import`
+==============================================================
.. module:: importlib
:synopsis: The implementation of the import machinery.
The purpose of the :mod:`importlib` package is two-fold. One is to provide the
implementation of the :keyword:`import` statement (and thus, by extension, the
:func:`__import__` function) in Python source code. This provides an
-implementation of :keyword:`import` which is portable to any Python
+implementation of :keyword:`!import` which is portable to any Python
interpreter. This also provides an implementation which is easier to
comprehend than one implemented in a programming language other than Python.
If a module imports objects from another module using :keyword:`from` ...
:keyword:`import` ..., calling :func:`reload` for the other module does not
redefine the objects imported from it --- one way around this is to
- re-execute the :keyword:`from` statement, another is to use :keyword:`import`
+ re-execute the :keyword:`!from` statement, another is to use :keyword:`!import`
and qualified names (*module.name*) instead.
If a module instantiates instances of a class, reloading the module that
if spec is not None:
break
else:
- raise ImportError(f'No module named {absolute_name!r}')
+ msg = f'No module named {absolute_name!r}'
+ raise ModuleNotFoundError(msg, name=absolute_name)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules[absolute_name] = module
Raises :exc:`ValueError` if no signature can be provided, and
:exc:`TypeError` if that type of object is not supported.
+ A slash(/) in the signature of a function denotes that the parameters prior
+ to it are positional-only. For more info, see
+ :ref:`the FAQ entry on positional-only parameters <faq-positional-only-arguments>`.
+
.. versionadded:: 3.5
``follow_wrapped`` parameter. Pass ``False`` to get a signature of
``callable`` specifically (``callable.__wrapped__`` will not be used to
:class:`IOBase` is also a context manager and therefore supports the
:keyword:`with` statement. In this example, *file* is closed after the
- :keyword:`with` statement's suite is finished---even if an exception occurs::
+ :keyword:`!with` statement's suite is finished---even if an exception occurs::
with open('spam.txt', 'w') as file:
file.write('Spam and eggs!')
(on most systems, additional bytes are zero-filled). The new file size
is returned.
- .. versionchanged:: 3.5
- Windows will now zero-fill files when extending.
+ .. versionchanged:: 3.5
+ Windows will now zero-fill files when extending.
.. method:: writable()
enabled. The default is ``True`` because this
enables old behaviour in a
backward-compatible way. This behaviour is to
- disable any existing loggers unless they or
- their ancestors are explicitly named in the
- logging configuration.
+ disable any existing non-root loggers unless
+ they or their ancestors are explicitly named
+ in the logging configuration.
.. versionchanged:: 3.4
An instance of a subclass of :class:`~configparser.RawConfigParser` is
If the specified value is ``True``, the configuration is processed
as described in the section on :ref:`logging-config-dict-incremental`.
-* *disable_existing_loggers* - whether any existing loggers are to be
- disabled. This setting mirrors the parameter of the same name in
+* *disable_existing_loggers* - whether any existing non-root loggers are
+ to be disabled. This setting mirrors the parameter of the same name in
:func:`fileConfig`. If absent, this parameter defaults to ``True``.
This value is ignored if *incremental* is ``True``.
use :func:`get_context` to avoid interfering with the choice of the
library user.
+.. warning::
+
+ The ``'spawn'`` and ``'forkserver'`` start methods cannot currently
+ be used with "frozen" executables (i.e., binaries produced by
+ packages like **PyInstaller** and **cx_Freeze**) on Unix.
+ The ``'fork'`` start method does work.
+
Exchanging objects between processes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Connect a local manager object to a remote manager process::
>>> from multiprocessing.managers import BaseManager
- >>> m = BaseManager(address=('127.0.0.1', 5000), authkey=b'abc')
+ >>> m = BaseManager(address=('127.0.0.1', 50000), authkey=b'abc')
>>> m.connect()
.. method:: shutdown()
the process pool as separate tasks. The (approximate) size of these
chunks can be specified by setting *chunksize* to a positive integer.
+ Note that it may cause high memory usage for very long iterables. Consider
+ using :meth:`imap` or :meth:`imap_unordered` with explicit *chunksize*
+ option for better efficiency.
+
.. method:: map_async(func, iterable[, chunksize[, callback[, error_callback]]])
A variant of the :meth:`.map` method which returns a result object.
.. method:: imap(func, iterable[, chunksize])
- A lazier version of :meth:`map`.
+ A lazier version of :meth:`.map`.
The *chunksize* argument is the same as the one used by the :meth:`.map`
method. For very long iterables using a large value for *chunksize* can
.. versionadded:: 3.2
-.. method:: NNTP.starttls(ssl_context=None)
+.. method:: NNTP.starttls(context=None)
Send a ``STARTTLS`` command. This will enable encryption on the NNTP
- connection. The *ssl_context* argument is optional and should be a
+ connection. The *context* argument is optional and should be a
:class:`ssl.SSLContext` object. Please read :ref:`ssl-security` for best
practices.
Return ``True`` if pathname *path* is a :dfn:`mount point`: a point in a
file system where a different file system has been mounted. On POSIX, the
- function checks whether *path*'s parent, :file:`path/..`, is on a different
- device than *path*, or whether :file:`path/..` and *path* point to the same
+ function checks whether *path*'s parent, :file:`{path}/..`, is on a different
+ device than *path*, or whether :file:`{path}/..` and *path* point to the same
i-node on the same device --- this should detect mount points for all Unix
- and POSIX variants. On Windows, a drive letter root and a share UNC are
+ and POSIX variants. It is not able to reliably detect bind mounts on the
+ same filesystem. On Windows, a drive letter root and a share UNC are
always mount points, and for any other path ``GetVolumePathName`` is called
to see if it is different from the input path.
which have the same form as the parent. An important aspect of this structure
which should be noted is that keywords used to identify the parent node type,
such as the keyword :keyword:`if` in an :const:`if_stmt`, are included in the
-node tree without any special treatment. For example, the :keyword:`if` keyword
+node tree without any special treatment. For example, the :keyword:`!if` keyword
is represented by the tuple ``(1, 'if')``, where ``1`` is the numeric value
associated with all :const:`NAME` tokens, including variable and function names
defined by the user. In an alternate form returned when line number information
-<?xml version="1.0" standalone="yes"?>
-
-<svg version="1.1" viewBox="0.0 0.0 538.0 496.0" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="p.0"><path d="m0 0l538.0 0l0 496.0l-538.0 0l0 -496.0z" clip-rule="nonzero"></path></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l538.916 0l0 496.08398l-538.916 0z" fill-rule="nonzero"></path><path fill="#ffffff" d="m176.0 24.0l187.43307 0l0 80.53543l-187.43307 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m176.0 24.0l187.43307 0l0 80.53543l-187.43307 0z" fill-rule="nonzero"></path><path fill="#000000" d="m235.18527 66.877716l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm13.9296875 -2.234375l0 5.484375q0.515625 0 0.75 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.515625 0l0 -0.375q-0.6875 0.3125 -1.3125 0.46875q-0.625 0.171875 -1.1875 0.171875q-0.796875 0 -1.375 -0.328125q-0.578125 -0.34375 -0.90625 -0.9375q-0.25 -0.421875 -0.25 -1.046875l0 -3.453125l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.875 0l0 4.765625q0 0.5 0.234375 0.75q0.25 0.234375 0.765625 0.234375q0.484375 0 1.03125 -0.1875q0.5625 -0.203125 1.390625 -0.703125l0 -3.265625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm5.8671875 0l0 1.0q1.015625 -0.734375 1.59375 -0.96875q0.578125 -0.25 1.09375 -0.25q0.78125 0 1.515625 0.578125q0.5 0.390625 0.5 0.796875q0 0.34375 -0.25 0.59375q-0.234375 0.234375 -0.5625 0.234375q-0.296875 0 -0.625 -0.296875q-0.328125 -0.296875 -0.59375 -0.296875q-0.328125 0 -1.0 0.421875q-0.671875 0.421875 -1.671875 1.265625l0 2.40625l2.28125 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-4.828125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.953125 0l0 -3.890625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm13.9609375 4.359375l-6.578125 0q0.25 0.625 0.890625 1.015625q0.640625 0.375 1.71875 0.375q0.890625 0 2.375 -0.390625q0.609375 -0.15625 0.84375 -0.15625q0.3125 0 0.53125 0.234375q0.21875 0.21875 0.21875 0.5625q0 0.3125 -0.234375 0.53125q-0.3125 0.296875 -1.53125 0.5625q-1.203125 0.265625 -2.3125 0.265625q-1.921875 0 -3.078125 -1.09375q-1.15625 -1.09375 -1.15625 -2.671875q0 -1.6875 1.25 -2.75q1.25 -1.0625 2.875 -1.0625q0.96875 0 1.78125 0.34375q0.828125 0.34375 1.21875 0.75q0.5625 0.578125 0.9375 1.421875q0.25 0.59375 0.25 1.375l0 0.6875zm-1.78125 -1.609375q-0.359375 -0.6875 -0.953125 -1.015625q-0.59375 -0.34375 -1.421875 -0.34375q-0.8125 0 -1.40625 0.34375q-0.59375 0.328125 -0.96875 1.015625l4.75 0zm6.4296875 1.09375l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.921875l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"></path><path fill="#ffffff" d="m16.0 144.0l187.43306 0l0 80.53543l-187.43306 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m16.0 144.0l187.43306 0l0 80.53543l-187.43306 0z" fill-rule="nonzero"></path><path fill="#000000" d="m51.181374 186.87772l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm13.9296875 -2.234375l0 5.484375q0.515625 0 0.75 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.515625 0l0 -0.375q-0.6875 0.3125 -1.3125 0.46875q-0.625 0.171875 -1.1875 0.171875q-0.796875 0 -1.375 -0.328125q-0.578125 -0.34375 -0.90625 -0.9375q-0.25 -0.421875 -0.25 -1.046875l0 -3.453125l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.875 0l0 4.765625q0 0.5 0.234375 0.75q0.25 0.234375 0.765625 0.234375q0.484375 0 1.03125 -0.1875q0.5625 -0.203125 1.390625 -0.703125l0 -3.265625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm5.8671875 0l0 1.0q1.015625 -0.734375 1.59375 -0.96875q0.578125 -0.25 1.09375 -0.25q0.78125 0 1.515625 0.578125q0.5 0.390625 0.5 0.796875q0 0.34375 -0.25 0.59375q-0.234375 0.234375 -0.5625 0.234375q-0.296875 0 -0.625 -0.296875q-0.328125 -0.296875 -0.59375 -0.296875q-0.328125 0 -1.0 0.421875q-0.671875 0.421875 -1.671875 1.265625l0 2.40625l2.28125 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-4.828125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.953125 0l0 -3.890625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm13.9609375 4.359375l-6.578125 0q0.25 0.625 0.890625 1.015625q0.640625 0.375 1.71875 0.375q0.890625 0 2.375 -0.390625q0.609375 -0.15625 0.84375 -0.15625q0.3125 0 0.53125 0.234375q0.21875 0.21875 0.21875 0.5625q0 0.3125 -0.234375 0.53125q-0.3125 0.296875 -1.53125 0.5625q-1.203125 0.265625 -2.3125 0.265625q-1.921875 0 -3.078125 -1.09375q-1.15625 -1.09375 -1.15625 -2.671875q0 -1.6875 1.25 -2.75q1.25 -1.0625 2.875 -1.0625q0.96875 0 1.78125 0.34375q0.828125 0.34375 1.21875 0.75q0.5625 0.578125 0.9375 1.421875q0.25 0.59375 0.25 1.375l0 0.6875zm-1.78125 -1.609375q-0.359375 -0.6875 -0.953125 -1.015625q-0.59375 -0.34375 -1.421875 -0.34375q-0.8125 0 -1.40625 0.34375q-0.59375 0.328125 -0.96875 1.015625l4.75 0zm6.4296875 1.09375l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm14.6953125 1.4375q0 0.921875 -0.515625 1.796875q-0.515625 0.859375 -1.53125 1.375q-1.0 0.515625 -2.109375 0.515625q-1.09375 0 -2.09375 -0.5q-1.0 -0.515625 -1.53125 -1.375q-0.515625 -0.875 -0.515625 -1.828125q0 -0.953125 0.53125 -1.875q0.53125 -0.9375 1.53125 -1.46875q1.0 -0.53125 2.078125 -0.53125q1.09375 0 2.109375 0.546875q1.015625 0.546875 1.53125 1.46875q0.515625 0.90625 0.515625 1.875zm-1.609375 0.015625q0 -0.78125 -0.546875 -1.421875q-0.765625 -0.875 -2.0 -0.875q-1.078125 0 -1.8125 0.703125q-0.71875 0.6875 -0.71875 1.59375q0 0.75 0.734375 1.40625q0.734375 0.65625 1.796875 0.65625q1.078125 0 1.8125 -0.65625q0.734375 -0.65625 0.734375 -1.40625zm8.7734375 -1.8125q-0.390625 -0.25 -0.828125 -0.359375q-0.421875 -0.125 -0.890625 -0.125q-0.921875 0 -1.46875 0.296875q-0.25 0.140625 -0.25 0.296875q0 0.171875 0.328125 0.34375q0.25 0.125 1.125 0.25q1.59375 0.21875 2.21875 0.4375q0.8125 0.28125 1.25 0.859375q0.453125 0.5625 0.453125 1.203125q0 0.859375 -0.75 1.4375q-1.09375 0.84375 -2.828125 0.84375q-0.6875 0 -1.28125 -0.125q-0.59375 -0.125 -1.078125 -0.359375q-0.125 0.09375 -0.265625 0.15625q-0.125 0.046875 -0.265625 0.046875q-0.375 0 -0.59375 -0.234375q-0.21875 -0.25 -0.21875 -0.828125l0 -0.546875q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.296875 0 0.484375 0.15625q0.203125 0.15625 0.3125 0.546875q0.359375 0.3125 0.875 0.484375q0.515625 0.15625 1.1875 0.15625q1.109375 0 1.71875 -0.34375q0.28125 -0.171875 0.28125 -0.359375q0 -0.3125 -0.40625 -0.515625q-0.421875 -0.203125 -1.71875 -0.34375q-1.921875 -0.203125 -2.578125 -0.78125q-0.640625 -0.578125 -0.640625 -1.40625q0 -0.859375 0.71875 -1.4375q0.984375 -0.78125 2.578125 -0.78125q0.5625 0 1.0625 0.109375q0.515625 0.109375 0.984375 0.328125q0.15625 -0.109375 0.28125 -0.15625q0.125 -0.0625 0.234375 -0.0625q0.328125 0 0.546875 0.25q0.21875 0.234375 0.21875 0.8125l0 0.390625q0 0.53125 -0.125 0.71875q-0.25 0.359375 -0.671875 0.359375q-0.296875 0 -0.515625 -0.171875q-0.21875 -0.1875 -0.28125 -0.484375zm8.4453125 -4.921875l0 1.703125l-1.90625 0l0 -1.703125l1.90625 0zm0.21875 3.046875l0 5.484375l1.921875 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-5.4375 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.921875 0l0 -3.890625l-1.296875 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.890625 0zm10.007805 3.40625l2.4375 2.078125q0.4375 0.03125 0.65625 0.25q0.21875 0.21875 0.21875 0.5625q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.8125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.28125 0.171875 -0.5q0.1875 -0.21875 0.484375 -0.296875l-1.1875 -1.03125l-1.2187424 1.03125q0.35936737 0.09375 0.5156174 0.296875q0.171875 0.1875 0.171875 0.5q0 0.359375 -0.25 0.59375q-0.23436737 0.21875 -0.8124924 0.21875l-1.8125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.328125 0.21875 -0.546875q0.21875 -0.21875 0.65625 -0.25l2.375 -2.09375l-2.109375 -1.796875q-0.40625 -0.03125 -0.625 -0.25q-0.21875 -0.21875 -0.21875 -0.546875q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.5 0q0.578125 0 0.8124924 0.21875q0.25 0.21875 0.25 0.5625q0 0.46875 -0.43749237 0.75l0.9687424 0.8125l0.953125 -0.828125q-0.421875 -0.296875 -0.421875 -0.703125q0 -0.375 0.234375 -0.59375q0.25 -0.21875 0.828125 -0.21875l1.484375 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.328125 -0.21875 0.546875q-0.21875 0.21875 -0.640625 0.25l-2.109375 1.8125zm7.4765625 0.4375l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.921875l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"></path><path fill="#ffffff" d="m336.0 143.46457l187.43304 0l0 80.53543l-187.43304 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m336.0 143.46457l187.43304 0l0 80.53543l-187.43304 0z" fill-rule="nonzero"></path><path fill="#000000" d="m361.5798 186.34229l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm13.9296875 -2.234375l0 5.484375q0.515625 0 0.75 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.515625 0l0 -0.375q-0.6875 0.3125 -1.3125 0.46875q-0.625 0.171875 -1.1875 0.171875q-0.796875 0 -1.375 -0.328125q-0.578125 -0.34375 -0.90625 -0.9375q-0.25 -0.421875 -0.25 -1.046875l0 -3.453125l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.875 0l0 4.765625q0 0.5 0.234375 0.75q0.25 0.234375 0.765625 0.234375q0.484375 0 1.03125 -0.1875q0.5625 -0.203125 1.390625 -0.703125l0 -3.265625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm5.8671875 0l0 1.0q1.015625 -0.734375 1.59375 -0.96875q0.578125 -0.25 1.09375 -0.25q0.78125 0 1.515625 0.578125q0.5 0.390625 0.5 0.796875q0 0.34375 -0.25 0.59375q-0.234375 0.234375 -0.5625 0.234375q-0.296875 0 -0.625 -0.296875q-0.328125 -0.296875 -0.59375 -0.296875q-0.328125 0 -1.0 0.421875q-0.671875 0.421875 -1.671875 1.265625l0 2.40625l2.28125 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-4.828125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.953125 0l0 -3.890625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm13.9609375 4.359375l-6.578125 0q0.25 0.625 0.890625 1.015625q0.640625 0.375 1.71875 0.375q0.890625 0 2.375 -0.390625q0.609375 -0.15625 0.84375 -0.15625q0.3125 0 0.53125 0.234375q0.21875 0.21875 0.21875 0.5625q0 0.3125 -0.234375 0.53125q-0.3125 0.296875 -1.53125 0.5625q-1.203125 0.265625 -2.3125 0.265625q-1.921875 0 -3.078125 -1.09375q-1.15625 -1.09375 -1.15625 -2.671875q0 -1.6875 1.25 -2.75q1.25 -1.0625 2.875 -1.0625q0.96875 0 1.78125 0.34375q0.828125 0.34375 1.21875 0.75q0.5625 0.578125 0.9375 1.421875q0.25 0.59375 0.25 1.375l0 0.6875zm-1.78125 -1.609375q-0.359375 -0.6875 -0.953125 -1.015625q-0.59375 -0.34375 -1.421875 -0.34375q-0.8125 0 -1.40625 0.34375q-0.59375 0.328125 -0.96875 1.015625l4.75 0zm7.3671875 -0.203125l-1.484375 4.546875l-1.796875 0l-0.953125 -7.875q-0.375 -0.046875 -0.5625 -0.25q-0.1875 -0.203125 -0.1875 -0.53125q0 -0.375 0.25 -0.59375q0.25 -0.234375 0.828125 -0.234375l2.125 0.015625q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-0.828125 0l0.53125 4.484375l1.25 -3.734375l1.671875 0l1.25 3.734375l0.53125 -4.484375l-0.84375 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.21875 -0.234375 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.234375 0.828125 -0.234375l2.125 0.015625q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.296875 -0.203125 0.515625q-0.1875 0.21875 -0.5625 0.28125l-0.921875 7.875l-1.765625 0l-1.53125 -4.546875zm10.1640625 -5.59375l0 1.703125l-1.90625 0l0 -1.703125l1.90625 0zm0.21875 3.046875l0 5.484375l1.921875 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-5.4375 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.921875 0l0 -3.890625l-1.296875 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.890625 0zm7.1953125 0l0 0.53125q0.4375 -0.375 0.953125 -0.5625q0.53125 -0.1875 1.15625 -0.1875q1.421875 0 2.25 0.890625q0.65625 0.703125 0.65625 1.84375l0 2.96875q0.5 0 0.734375 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.453125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.34375 0.234375 -0.5625q0.25 -0.234375 0.75 -0.234375l0 -3.015625q0 -0.53125 -0.28125 -0.765625q-0.359375 -0.3125 -1.09375 -0.3125q-0.5625 0 -0.984375 0.21875q-0.40625 0.203125 -1.046875 0.90625l0 2.96875q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -3.890625q-0.5 0 -0.75 -0.21875q-0.234375 -0.234375 -0.234375 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.53125 0zm14.8984375 -3.046875l0 8.53125l0.265625 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.875 0l0 -0.390625q-0.546875 0.3125 -1.140625 0.484375q-0.59375 0.171875 -1.234375 0.171875q-1.8125 0 -2.921875 -1.046875q-1.09375 -1.046875 -1.09375 -2.609375q0 -1.625 1.15625 -2.765625q1.15625 -1.15625 2.828125 -1.15625q0.625 0 1.21875 0.203125q0.609375 0.1875 1.1875 0.5625l0 -1.984375l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l1.875 0zm-1.609375 6.796875q0 -0.984375 -0.703125 -1.671875q-0.6875 -0.6875 -1.6875 -0.6875q-1.0 0 -1.703125 0.6875q-0.6875 0.6875 -0.6875 1.65625q0 0.875 0.625 1.453125q0.625 0.5625 1.765625 0.5625q1.125 0 1.75 -0.5625q0.640625 -0.578125 0.640625 -1.4375zm11.6953125 -0.078125q0 0.921875 -0.515625 1.796875q-0.515625 0.859375 -1.53125 1.375q-1.0 0.515625 -2.109375 0.515625q-1.09375 0 -2.09375 -0.5q-1.0 -0.515625 -1.53125 -1.375q-0.515625 -0.875 -0.515625 -1.828125q0 -0.953125 0.53125 -1.875q0.53125 -0.9375 1.53125 -1.46875q1.0 -0.53125 2.078125 -0.53125q1.09375 0 2.109375 0.546875q1.015625 0.546875 1.53125 1.46875q0.515625 0.90625 0.515625 1.875zm-1.609375 0.015625q0 -0.78125 -0.546875 -1.421875q-0.765625 -0.875 -2.0 -0.875q-1.078125 0 -1.8125 0.703125q-0.71875 0.6875 -0.71875 1.59375q0 0.75 0.734375 1.40625q0.734375 0.65625 1.796875 0.65625q1.078125 0 1.8125 -0.65625q0.734375 -0.65625 0.734375 -1.40625zm7.0546875 0.453125l-1.109375 2.953125l-1.5 0l-1.34375 -5.5q-0.4375 -0.015625 -0.671875 -0.234375q-0.21875 -0.234375 -0.21875 -0.5625q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.484375 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.28125 0.609375q-0.21875 0.1875 -0.828125 0.1875l0.609375 2.546875l0.984375 -2.609375l1.421875 0l1.0 2.609375l0.625 -2.546875q-0.59375 0 -0.78125 -0.109375q-0.375 -0.25 -0.375 -0.6875q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.5 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.328125 -0.21875 0.546875q-0.21875 0.21875 -0.640625 0.25l-1.3125 5.5l-1.484375 0l-1.171875 -2.953125zm11.3203125 -2.265625q-0.390625 -0.25 -0.828125 -0.359375q-0.421875 -0.125 -0.890625 -0.125q-0.921875 0 -1.46875 0.296875q-0.25 0.140625 -0.25 0.296875q0 0.171875 0.328125 0.34375q0.25 0.125 1.125 0.25q1.59375 0.21875 2.21875 0.4375q0.8125 0.28125 1.25 0.859375q0.453125 0.5625 0.453125 1.203125q0 0.859375 -0.75 1.4375q-1.09375 0.84375 -2.828125 0.84375q-0.6875 0 -1.28125 -0.125q-0.59375 -0.125 -1.078125 -0.359375q-0.125 0.09375 -0.265625 0.15625q-0.125 0.046875 -0.265625 0.046875q-0.375 0 -0.59375 -0.234375q-0.21875 -0.25 -0.21875 -0.828125l0 -0.546875q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.296875 0 0.484375 0.15625q0.203125 0.15625 0.3125 0.546875q0.359375 0.3125 0.875 0.484375q0.515625 0.15625 1.1875 0.15625q1.109375 0 1.71875 -0.34375q0.28125 -0.171875 0.28125 -0.359375q0 -0.3125 -0.40625 -0.515625q-0.421875 -0.203125 -1.71875 -0.34375q-1.921875 -0.203125 -2.578125 -0.78125q-0.640625 -0.578125 -0.640625 -1.40625q0 -0.859375 0.71875 -1.4375q0.984375 -0.78125 2.578125 -0.78125q0.5625 0 1.0625 0.109375q0.515625 0.109375 0.984375 0.328125q0.15625 -0.109375 0.28125 -0.15625q0.125 -0.0625 0.234375 -0.0625q0.328125 0 0.546875 0.25q0.21875 0.234375 0.21875 0.8125l0 0.390625q0 0.53125 -0.125 0.71875q-0.25 0.359375 -0.671875 0.359375q-0.296875 0 -0.515625 -0.171875q-0.21875 -0.1875 -0.28125 -0.484375zm6.9453125 1.96875l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.921875l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"></path><path fill="#ffffff" d="m176.0 271.46457l187.43307 0l0 80.53543l-187.43307 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m176.0 271.46457l187.43307 0l0 80.53543l-187.43307 0z" fill-rule="nonzero"></path><path fill="#000000" d="m254.3884 314.3423l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.921875l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"></path><path fill="#ffffff" d="m16.0 400.0l187.43306 0l0 80.53543l-187.43306 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m16.0 400.0l187.43306 0l0 80.53543l-187.43306 0z" fill-rule="nonzero"></path><path fill="#000000" d="m70.3845 442.87772l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm14.6953125 1.4375q0 0.921875 -0.515625 1.796875q-0.515625 0.859375 -1.53125 1.375q-1.0 0.515625 -2.109375 0.515625q-1.09375 0 -2.09375 -0.5q-1.0 -0.515625 -1.53125 -1.375q-0.515625 -0.875 -0.515625 -1.828125q0 -0.953125 0.53125 -1.875q0.53125 -0.9375 1.53125 -1.46875q1.0 -0.53125 2.078125 -0.53125q1.09375 0 2.109375 0.546875q1.015625 0.546875 1.53125 1.46875q0.515625 0.90625 0.515625 1.875zm-1.609375 0.015625q0 -0.78125 -0.546875 -1.421875q-0.765625 -0.875 -2.0 -0.875q-1.078125 0 -1.8125 0.703125q-0.71875 0.6875 -0.71875 1.59375q0 0.75 0.734375 1.40625q0.734375 0.65625 1.796875 0.65625q1.078125 0 1.8125 -0.65625q0.734375 -0.65625 0.734375 -1.40625zm8.7734375 -1.8125q-0.390625 -0.25 -0.828125 -0.359375q-0.421875 -0.125 -0.890625 -0.125q-0.921875 0 -1.46875 0.296875q-0.25 0.140625 -0.25 0.296875q0 0.171875 0.328125 0.34375q0.25 0.125 1.125 0.25q1.59375 0.21875 2.21875 0.4375q0.8125 0.28125 1.25 0.859375q0.453125 0.5625 0.453125 1.203125q0 0.859375 -0.75 1.4375q-1.09375 0.84375 -2.828125 0.84375q-0.6875 0 -1.28125 -0.125q-0.59375 -0.125 -1.078125 -0.359375q-0.125 0.09375 -0.265625 0.15625q-0.125 0.046875 -0.265625 0.046875q-0.375 0 -0.59375 -0.234375q-0.21875 -0.25 -0.21875 -0.828125l0 -0.546875q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.296875 0 0.484375 0.15625q0.203125 0.15625 0.3125 0.546875q0.359375 0.3125 0.875 0.484375q0.515625 0.15625 1.1875 0.15625q1.109375 0 1.71875 -0.34375q0.28125 -0.171875 0.28125 -0.359375q0 -0.3125 -0.40625 -0.515625q-0.421875 -0.203125 -1.71875 -0.34375q-1.921875 -0.203125 -2.578125 -0.78125q-0.640625 -0.578125 -0.640625 -1.40625q0 -0.859375 0.71875 -1.4375q0.984375 -0.78125 2.578125 -0.78125q0.5625 0 1.0625 0.109375q0.515625 0.109375 0.984375 0.328125q0.15625 -0.109375 0.28125 -0.15625q0.125 -0.0625 0.234375 -0.0625q0.328125 0 0.546875 0.25q0.21875 0.234375 0.21875 0.8125l0 0.390625q0 0.53125 -0.125 0.71875q-0.25 0.359375 -0.671875 0.359375q-0.296875 0 -0.515625 -0.171875q-0.21875 -0.1875 -0.28125 -0.484375zm8.4453125 -4.921875l0 1.703125l-1.90625 0l0 -1.703125l1.90625 0zm0.21875 3.046875l0 5.484375l1.921875 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-5.4375 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.921875 0l0 -3.890625l-1.296875 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.890625 0zm10.0078125 3.40625l2.4375 2.078125q0.4375 0.03125 0.65625 0.25q0.21875 0.21875 0.21875 0.5625q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.8125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.28125 0.171875 -0.5q0.1875 -0.21875 0.484375 -0.296875l-1.1875 -1.03125l-1.21875 1.03125q0.359375 0.09375 0.515625 0.296875q0.171875 0.1875 0.171875 0.5q0 0.359375 -0.25 0.59375q-0.234375 0.21875 -0.8125 0.21875l-1.8125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.328125 0.21875 -0.546875q0.21875 -0.21875 0.65625 -0.25l2.375 -2.09375l-2.109375 -1.796875q-0.40625 -0.03125 -0.625 -0.25q-0.21875 -0.21875 -0.21875 -0.546875q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.5 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.5625q0 0.46875 -0.4375 0.75l0.96875 0.8125l0.953125 -0.828125q-0.421875 -0.296875 -0.421875 -0.703125q0 -0.375 0.234375 -0.59375q0.25 -0.21875 0.828125 -0.21875l1.484375 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.328125 -0.21875 0.546875q-0.21875 0.21875 -0.640625 0.25l-2.109375 1.8125zm7.4765625 0.4375l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.976555 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3124924 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.8437424 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.8437424 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.6249924 -0.109375 1.1249924 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.9687424 0 -1.6718674 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.5781174 0 1.2968674 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.921875l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"></path><path fill="#ffffff" d="m336.0 400.0l187.43304 0l0 80.53543l-187.43304 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m336.0 400.0l187.43304 0l0 80.53543l-187.43304 0z" fill-rule="nonzero"></path><path fill="#000000" d="m381.72043 441.58084l-1.484375 4.546875l-1.796875 0l-0.953125 -7.875q-0.375 -0.046875 -0.5625 -0.25q-0.1875 -0.203125 -0.1875 -0.53125q0 -0.375 0.25 -0.59375q0.25 -0.234375 0.828125 -0.234375l2.125 0.015625q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-0.828125 0l0.53125 4.484375l1.25 -3.734375l1.671875 0l1.25 3.734375l0.53125 -4.484375l-0.84375 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.21875 -0.234375 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.234375 0.828125 -0.234375l2.125 0.015625q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.296875 -0.203125 0.515625q-0.1875 0.21875 -0.5625 0.28125l-0.921875 7.875l-1.765625 0l-1.53125 -4.546875zm10.1640625 -5.59375l0 1.703125l-1.90625 0l0 -1.703125l1.90625 0zm0.21875 3.046875l0 5.484375l1.921875 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-5.4375 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.921875 0l0 -3.890625l-1.296875 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.890625 0zm7.1953125 0l0 0.53125q0.4375 -0.375 0.953125 -0.5625q0.53125 -0.1875 1.15625 -0.1875q1.421875 0 2.25 0.890625q0.65625 0.703125 0.65625 1.84375l0 2.96875q0.5 0 0.734375 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.453125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.34375 0.234375 -0.5625q0.25 -0.234375 0.75 -0.234375l0 -3.015625q0 -0.53125 -0.28125 -0.765625q-0.359375 -0.3125 -1.09375 -0.3125q-0.5625 0 -0.984375 0.21875q-0.40625 0.203125 -1.046875 0.90625l0 2.96875q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -3.890625q-0.5 0 -0.75 -0.21875q-0.234375 -0.234375 -0.234375 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.53125 0zm14.8984375 -3.046875l0 8.53125l0.265625 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.875 0l0 -0.390625q-0.546875 0.3125 -1.140625 0.484375q-0.59375 0.171875 -1.234375 0.171875q-1.8125 0 -2.921875 -1.046875q-1.09375 -1.046875 -1.09375 -2.609375q0 -1.625 1.15625 -2.765625q1.15625 -1.15625 2.828125 -1.15625q0.625 0 1.21875 0.203125q0.609375 0.1875 1.1875 0.5625l0 -1.984375l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l1.875 0zm-1.609375 6.796875q0 -0.984375 -0.703125 -1.671875q-0.6875 -0.6875 -1.6875 -0.6875q-1.0 0 -1.703125 0.6875q-0.6875 0.6875 -0.6875 1.65625q0 0.875 0.625 1.453125q0.625 0.5625 1.765625 0.5625q1.125 0 1.75 -0.5625q0.640625 -0.578125 0.640625 -1.4375zm11.6953125 -0.078125q0 0.921875 -0.515625 1.796875q-0.515625 0.859375 -1.53125 1.375q-1.0 0.515625 -2.109375 0.515625q-1.09375 0 -2.09375 -0.5q-1.0 -0.515625 -1.53125 -1.375q-0.515625 -0.875 -0.515625 -1.828125q0 -0.953125 0.53125 -1.875q0.53125 -0.9375 1.53125 -1.46875q1.0 -0.53125 2.078125 -0.53125q1.09375 0 2.109375 0.546875q1.015625 0.546875 1.53125 1.46875q0.515625 0.90625 0.515625 1.875zm-1.609375 0.015625q0 -0.78125 -0.546875 -1.421875q-0.765625 -0.875 -2.0 -0.875q-1.078125 0 -1.8125 0.703125q-0.71875 0.6875 -0.71875 1.59375q0 0.75 0.734375 1.40625q0.734375 0.65625 1.796875 0.65625q1.078125 0 1.8125 -0.65625q0.734375 -0.65625 0.734375 -1.40625zm7.0546875 0.453125l-1.109375 2.953125l-1.5 0l-1.34375 -5.5q-0.4375 -0.015625 -0.671875 -0.234375q-0.21875 -0.234375 -0.21875 -0.5625q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.484375 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.28125 0.609375q-0.21875 0.1875 -0.828125 0.1875l0.609375 2.546875l0.984375 -2.609375l1.421875 0l1.0 2.609375l0.625 -2.546875q-0.59375 0 -0.78125 -0.109375q-0.375 -0.25 -0.375 -0.6875q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.5 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.328125 -0.21875 0.546875q-0.21875 0.21875 -0.640625 0.25l-1.3125 5.5l-1.484375 0l-1.171875 -2.953125zm11.3203125 -2.265625q-0.390625 -0.25 -0.828125 -0.359375q-0.421875 -0.125 -0.890625 -0.125q-0.921875 0 -1.46875 0.296875q-0.25 0.140625 -0.25 0.296875q0 0.171875 0.328125 0.34375q0.25 0.125 1.125 0.25q1.59375 0.21875 2.21875 0.4375q0.8125 0.28125 1.25 0.859375q0.453125 0.5625 0.453125 1.203125q0 0.859375 -0.75 1.4375q-1.09375 0.84375 -2.828125 0.84375q-0.6875 0 -1.28125 -0.125q-0.59375 -0.125 -1.078125 -0.359375q-0.125 0.09375 -0.265625 0.15625q-0.125 0.046875 -0.265625 0.046875q-0.375 0 -0.59375 -0.234375q-0.21875 -0.25 -0.21875 -0.828125l0 -0.546875q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.296875 0 0.484375 0.15625q0.203125 0.15625 0.3125 0.546875q0.359375 0.3125 0.875 0.484375q0.515625 0.15625 1.1875 0.15625q1.109375 0 1.71875 -0.34375q0.28125 -0.171875 0.28125 -0.359375q0 -0.3125 -0.40625 -0.515625q-0.421875 -0.203125 -1.71875 -0.34375q-1.921875 -0.203125 -2.578125 -0.78125q-0.640625 -0.578125 -0.640625 -1.40625q0 -0.859375 0.71875 -1.4375q0.984375 -0.78125 2.578125 -0.78125q0.5625 0 1.0625 0.109375q0.515625 0.109375 0.984375 0.328125q0.15625 -0.109375 0.28125 -0.15625q0.125 -0.0625 0.234375 -0.0625q0.328125 0 0.546875 0.25q0.21875 0.234375 0.21875 0.8125l0 0.390625q0 0.53125 -0.125 0.71875q-0.25 0.359375 -0.671875 0.359375q-0.296875 0 -0.515625 -0.171875q-0.21875 -0.1875 -0.28125 -0.484375zm6.9453125 1.96875l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.921875l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m96.0 144.0l0 -80.0l80.0 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="butt" d="m96.0 144.0l0 -80.0l68.0 0" fill-rule="evenodd"></path><path stroke="#000000" stroke-width="2.0" stroke-linecap="butt" d="m164.0 67.30347l9.076202 -3.3034668l-9.076202 -3.303463z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m431.5013 143.08398l0 -78.99999l-68.0 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="butt" d="m431.5013 143.08398l0 -78.99999l-56.0 0" fill-rule="evenodd"></path><path stroke="#000000" stroke-width="2.0" stroke-linecap="butt" d="m375.5013 60.780525l-9.076202 3.3034668l9.076202 3.3034592z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m269.71652 104.53543l0 166.92914" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="butt" d="m269.71652 116.53543l0 154.92914" fill-rule="evenodd"></path><path stroke="#000000" stroke-width="2.0" stroke-linecap="butt" d="m273.02 116.53543l-3.3034668 -9.076195l-3.3034668 9.076195z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m65.0 223.08398l-1.0078735 176.91339" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="butt" d="m64.93163 235.08379l-0.93950653 164.91359" fill-rule="evenodd"></path><path stroke="#000000" stroke-width="2.0" stroke-linecap="butt" d="m68.23505 235.10262l-3.2517014 -9.094864l-3.3551178 9.05722z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m471.0 224.38058l-1.0078735 176.91336" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="butt" d="m470.93164 236.38037l-0.93951416 164.9136" fill-rule="evenodd"></path><path stroke="#000000" stroke-width="2.0" stroke-linecap="butt" d="m474.23505 236.3992l-3.251709 -9.094864l-3.3551025 9.05722z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m128.50131 400.00266l0 -86.168l47.496002 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="butt" d="m128.50131 400.00266l0 -86.168l35.496002 0" fill-rule="evenodd"></path><path stroke="#000000" stroke-width="2.0" stroke-linecap="butt" d="m163.99731 317.13812l9.076202 -3.3034668l-9.076202 -3.3034668z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m414.71902 400.00266l0 -86.168l-51.216003 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="butt" d="m414.71902 400.00266l0 -86.168l-39.216003 0" fill-rule="evenodd"></path><path stroke="#000000" stroke-width="2.0" stroke-linecap="butt" d="m375.50302 310.5312l-9.076172 3.3034668l9.076172 3.3034668z" fill-rule="evenodd"></path></g></svg>
-
+<svg version="1.1" viewBox="0.0 0.0 539.005249343832 319.40944881889766" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="p.0"><path d="m0 0l539.00525 0l0 319.40945l-539.00525 0l0 -319.40945z" clip-rule="nonzero"/></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l539.00525 0l0 319.40945l-539.00525 0z" fill-rule="evenodd"/><path fill="#ffffff" d="m203.43307 37.929134l113.98425 0l0 61.165356l-113.98425 0z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m203.43307 37.929134l113.98425 0l0 61.165356l-113.98425 0z" fill-rule="evenodd"/><path fill="#000000" d="m225.89395 71.12181l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm13.9296875 -2.234375l0 5.484375q0.515625 0 0.75 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.515625 0l0 -0.375q-0.6875 0.3125 -1.3125 0.46875q-0.625 0.171875 -1.1875 0.171875q-0.796875 0 -1.375 -0.328125q-0.578125 -0.34375 -0.90625 -0.9375q-0.25 -0.421875 -0.25 -1.046875l0 -3.453125l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.875 0l0 4.765625q0 0.5 0.234375 0.75q0.25 0.234375 0.765625 0.234375q0.484375 0 1.03125 -0.1875q0.5625 -0.203125 1.390625 -0.703125l0 -3.265625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm5.8671875 0l0 1.0q1.015625 -0.734375 1.59375 -0.96875q0.578125 -0.25 1.09375 -0.25q0.78125 0 1.515625 0.578125q0.5 0.390625 0.5 0.796875q0 0.34375 -0.25 0.59375q-0.234375 0.234375 -0.5625 0.234375q-0.296875 0 -0.625 -0.296875q-0.328125 -0.296875 -0.59375 -0.296875q-0.328125 0 -1.0 0.421875q-0.671875 0.421875 -1.671875 1.265625l0 2.40625l2.28125 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-4.828125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.953125 0l0 -3.890625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm13.9609375 4.359375l-6.578125 0q0.25 0.625 0.890625 1.015625q0.640625 0.375 1.71875 0.375q0.890625 0 2.375 -0.390625q0.609375 -0.15625 0.84375 -0.15625q0.3125 0 0.53125 0.234375q0.21875 0.21875 0.21875 0.5625q0 0.3125 -0.234375 0.53125q-0.3125 0.296875 -1.53125 0.5625q-1.203125 0.265625 -2.3125 0.265625q-1.921875 0 -3.078125 -1.09375q-1.15625 -1.09375 -1.15625 -2.671875q0 -1.6875 1.25 -2.75q1.25 -1.0625 2.875 -1.0625q0.96875 0 1.78125 0.34375q0.828125 0.34375 1.21875 0.75q0.5625 0.578125 0.9375 1.421875q0.25 0.59375 0.25 1.375l0 0.6875zm-1.78125 -1.609375q-0.359375 -0.6875 -0.953125 -1.015625q-0.59375 -0.34375 -1.421875 -0.34375q-0.8125 0 -1.40625 0.34375q-0.59375 0.328125 -0.96875 1.015625l4.75 0zm6.4296875 1.09375l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.921875l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m26.64567 99.10499l158.20471 0l0 61.16535l-158.20471 0z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m26.64567 99.10499l158.20471 0l0 61.16535l-158.20471 0z" fill-rule="evenodd"/><path fill="#000000" d="m47.212875 132.29767l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.2656326l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.1562576q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.42188263 -1.421875 -0.42188263l-1.84375 0l0 3.0156326zm13.9296875 -2.234375l0 5.484375q0.515625 0 0.75 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.515625 0l0 -0.375q-0.6875 0.3125 -1.3125 0.46875q-0.625 0.171875 -1.1875 0.171875q-0.796875 0 -1.375 -0.328125q-0.578125 -0.34375 -0.90625 -0.9375q-0.25 -0.421875 -0.25 -1.046875l0 -3.453125l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.875 0l0 4.765625q0 0.5 0.234375 0.75q0.25 0.234375 0.765625 0.234375q0.484375 0 1.03125 -0.1875q0.5625 -0.203125 1.390625 -0.703125l0 -3.265625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm5.8671875 0l0 1.0q1.015625 -0.734375 1.59375 -0.96875q0.578125 -0.25 1.09375 -0.25q0.78125 0 1.515625 0.578125q0.5 0.390625 0.5 0.796875q0 0.34375 -0.25 0.59375q-0.234375 0.234375 -0.5625 0.234375q-0.296875 0 -0.625 -0.296875q-0.328125 -0.296875 -0.59375 -0.296875q-0.328125 0 -1.0 0.421875q-0.671875 0.421875 -1.671875 1.265625l0 2.40625l2.28125 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-4.828125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.953125 0l0 -3.890625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm13.9609375 4.359375l-6.578125 0q0.25 0.625 0.890625 1.015625q0.640625 0.375 1.71875 0.375q0.890625 0 2.375 -0.390625q0.609375 -0.15625 0.84375 -0.15625q0.3125 0 0.53125 0.234375q0.21875 0.21875 0.21875 0.5625q0 0.3125 -0.234375 0.53125q-0.3125 0.296875 -1.53125 0.5625q-1.203125 0.265625 -2.3125 0.265625q-1.921875 0 -3.078125 -1.09375q-1.15625 -1.09375 -1.15625 -2.671875q0 -1.6875 1.25 -2.75q1.25 -1.0625 2.875 -1.0625q0.96875 0 1.78125 0.34375q0.828125 0.34375 1.21875 0.75q0.5625 0.578125 0.9375 1.421875q0.25 0.59375 0.25 1.375l0 0.6875zm-1.78125 -1.609375q-0.359375 -0.6875 -0.953125 -1.015625q-0.59375 -0.34375 -1.421875 -0.34375q-0.8125 0 -1.40625 0.34375q-0.59375 0.328125 -0.96875 1.015625l4.75 0zm6.4296875 1.09375l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.2656326l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.1562576q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.42188263 -1.421875 -0.42188263l-1.84375 0l0 3.0156326zm14.6953125 1.4375q0 0.921875 -0.515625 1.796875q-0.515625 0.859375 -1.53125 1.375q-1.0 0.515625 -2.109375 0.515625q-1.09375 0 -2.09375 -0.5q-1.0 -0.515625 -1.53125 -1.375q-0.515625 -0.875 -0.515625 -1.828125q0 -0.953125 0.53125 -1.875q0.53125 -0.9375 1.53125 -1.46875q1.0 -0.53125 2.078125 -0.53125q1.09375 0 2.109375 0.546875q1.015625 0.546875 1.53125 1.46875q0.515625 0.90625 0.515625 1.875zm-1.609375 0.015625q0 -0.78125 -0.546875 -1.421875q-0.765625 -0.875 -2.0 -0.875q-1.078125 0 -1.8125 0.703125q-0.71875 0.6875 -0.71875 1.59375q0 0.75 0.734375 1.40625q0.734375 0.65625 1.796875 0.65625q1.078125 0 1.8125 -0.65625q0.734375 -0.65625 0.734375 -1.40625zm8.7734375 -1.8125q-0.390625 -0.25 -0.828125 -0.359375q-0.421875 -0.125 -0.890625 -0.125q-0.921875 0 -1.46875 0.296875q-0.25 0.140625 -0.25 0.296875q0 0.171875 0.328125 0.34375q0.25 0.125 1.125 0.25q1.59375 0.21875 2.21875 0.4375q0.8125 0.28125 1.25 0.859375q0.453125 0.5625 0.453125 1.203125q0 0.859375 -0.75 1.4375q-1.09375 0.84375 -2.828125 0.84375q-0.6875 0 -1.28125 -0.125q-0.59375 -0.125 -1.078125 -0.359375q-0.125 0.09375 -0.265625 0.15625q-0.125 0.046875 -0.265625 0.046875q-0.375 0 -0.59375 -0.234375q-0.21875 -0.25 -0.21875 -0.828125l0 -0.546875q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.296875 0 0.484375 0.15625q0.203125 0.15625 0.3125 0.546875q0.359375 0.3125 0.875 0.484375q0.515625 0.15625 1.1875 0.15625q1.109375 0 1.71875 -0.34375q0.28125 -0.171875 0.28125 -0.359375q0 -0.3125 -0.40625 -0.515625q-0.421875 -0.203125 -1.71875 -0.34375q-1.921875 -0.203125 -2.578125 -0.78125q-0.640625 -0.578125 -0.640625 -1.40625q0 -0.859375 0.71875 -1.4375q0.984375 -0.78125 2.578125 -0.78125q0.5625 0 1.0625 0.109375q0.515625 0.109375 0.984375 0.328125q0.15625 -0.109375 0.28125 -0.15625q0.125 -0.0625 0.234375 -0.0625q0.328125 0 0.546875 0.25q0.21875 0.234375 0.21875 0.8125l0 0.390625q0 0.53125 -0.125 0.71875q-0.25 0.359375 -0.671875 0.359375q-0.296875 0 -0.515625 -0.171875q-0.21875 -0.1875 -0.28125 -0.484375zm8.4453125 -4.9218826l0 1.703125l-1.90625 0l0 -1.703125l1.90625 0zm0.21875 3.0468826l0 5.484375l1.921875 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-5.4375 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.921875 0l0 -3.890625l-1.296875 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.890625 0zm10.0078125 3.40625l2.4375 2.078125q0.4375 0.03125 0.65625 0.25q0.21875 0.21875 0.21875 0.5625q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.8125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.28125 0.171875 -0.5q0.1875 -0.21875 0.484375 -0.296875l-1.1875 -1.03125l-1.21875 1.03125q0.359375 0.09375 0.515625 0.296875q0.171875 0.1875 0.171875 0.5q0 0.359375 -0.25 0.59375q-0.234375 0.21875 -0.8125 0.21875l-1.8125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.328125 0.21875 -0.546875q0.21875 -0.21875 0.65625 -0.25l2.375 -2.09375l-2.109375 -1.796875q-0.40625 -0.03125 -0.625 -0.25q-0.21875 -0.21875 -0.21875 -0.546875q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.5 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.5625q0 0.46875 -0.4375 0.75l0.96875 0.8125l0.953125 -0.828125q-0.421875 -0.296875 -0.421875 -0.703125q0 -0.375 0.234375 -0.59375q0.25 -0.21875 0.828125 -0.21875l1.484375 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.328125 -0.21875 0.546875q-0.21875 0.21875 -0.640625 0.25l-2.109375 1.8125zm7.4765625 0.4375l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.2656326l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.1562576q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.42188263 -1.421875 -0.42188263l-1.84375 0l0 3.0156326zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.4531326q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.4531326l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.6406326l0 3.4218826q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.9218826l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m336.0 99.10499l174.04724 0l0 61.16535l-174.04724 0z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m336.0 99.10499l174.04724 0l0 61.16535l-174.04724 0z" fill-rule="evenodd"/><path fill="#000000" d="m354.8869 132.29767l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.2656326l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.1562576q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.42188263 -1.421875 -0.42188263l-1.84375 0l0 3.0156326zm13.9296875 -2.234375l0 5.484375q0.515625 0 0.75 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.515625 0l0 -0.375q-0.6875 0.3125 -1.3125 0.46875q-0.625 0.171875 -1.1875 0.171875q-0.796875 0 -1.375 -0.328125q-0.578125 -0.34375 -0.90625 -0.9375q-0.25 -0.421875 -0.25 -1.046875l0 -3.453125l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.875 0l0 4.765625q0 0.5 0.234375 0.75q0.25 0.234375 0.765625 0.234375q0.484375 0 1.03125 -0.1875q0.5625 -0.203125 1.390625 -0.703125l0 -3.265625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm5.8671875 0l0 1.0q1.015625 -0.734375 1.59375 -0.96875q0.578125 -0.25 1.09375 -0.25q0.78125 0 1.515625 0.578125q0.5 0.390625 0.5 0.796875q0 0.34375 -0.25 0.59375q-0.234375 0.234375 -0.5625 0.234375q-0.296875 0 -0.625 -0.296875q-0.328125 -0.296875 -0.59375 -0.296875q-0.328125 0 -1.0 0.421875q-0.671875 0.421875 -1.671875 1.265625l0 2.40625l2.28125 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-4.828125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.953125 0l0 -3.890625l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.171875 0zm13.9609375 4.359375l-6.578125 0q0.25 0.625 0.890625 1.015625q0.640625 0.375 1.71875 0.375q0.890625 0 2.375 -0.390625q0.609375 -0.15625 0.84375 -0.15625q0.3125 0 0.53125 0.234375q0.21875 0.21875 0.21875 0.5625q0 0.3125 -0.234375 0.53125q-0.3125 0.296875 -1.53125 0.5625q-1.203125 0.265625 -2.3125 0.265625q-1.921875 0 -3.078125 -1.09375q-1.15625 -1.09375 -1.15625 -2.671875q0 -1.6875 1.25 -2.75q1.25 -1.0625 2.875 -1.0625q0.96875 0 1.78125 0.34375q0.828125 0.34375 1.21875 0.75q0.5625 0.578125 0.9375 1.421875q0.25 0.59375 0.25 1.375l0 0.6875zm-1.78125 -1.609375q-0.359375 -0.6875 -0.953125 -1.015625q-0.59375 -0.34375 -1.421875 -0.34375q-0.8125 0 -1.40625 0.34375q-0.59375 0.328125 -0.96875 1.015625l4.75 0zm7.3671875 -0.203125l-1.484375 4.546875l-1.796875 0l-0.953125 -7.8750076q-0.375 -0.046875 -0.5625 -0.25q-0.1875 -0.203125 -0.1875 -0.53125q0 -0.375 0.25 -0.59375q0.25 -0.234375 0.828125 -0.234375l2.125 0.015625q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-0.828125 0l0.53125 4.4843826l1.25 -3.734375l1.671875 0l1.25 3.734375l0.53125 -4.4843826l-0.84375 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.21875 -0.234375 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.234375 0.828125 -0.234375l2.125 0.015625q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.296875 -0.203125 0.515625q-0.1875 0.21875 -0.5625 0.28125l-0.921875 7.8750076l-1.765625 0l-1.53125 -4.546875zm10.1640625 -5.5937576l0 1.703125l-1.90625 0l0 -1.703125l1.90625 0zm0.21875 3.0468826l0 5.484375l1.921875 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-5.4375 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.921875 0l0 -3.890625l-1.296875 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.890625 0zm7.1953125 0l0 0.53125q0.4375 -0.375 0.953125 -0.5625q0.53125 -0.1875 1.15625 -0.1875q1.421875 0 2.25 0.890625q0.65625 0.703125 0.65625 1.84375l0 2.96875q0.5 0 0.734375 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.453125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.34375 0.234375 -0.5625q0.25 -0.234375 0.75 -0.234375l0 -3.015625q0 -0.53125 -0.28125 -0.765625q-0.359375 -0.3125 -1.09375 -0.3125q-0.5625 0 -0.984375 0.21875q-0.40625 0.203125 -1.046875 0.90625l0 2.96875q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -3.890625q-0.5 0 -0.75 -0.21875q-0.234375 -0.234375 -0.234375 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.53125 0zm14.8984375 -3.0468826l0 8.531258l0.265625 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.875 0l0 -0.390625q-0.546875 0.3125 -1.140625 0.484375q-0.59375 0.171875 -1.234375 0.171875q-1.8125 0 -2.921875 -1.046875q-1.09375 -1.046875 -1.09375 -2.609375q0 -1.625 1.15625 -2.765625q1.15625 -1.15625 2.828125 -1.15625q0.625 0 1.21875 0.203125q0.609375 0.1875 1.1875 0.5625l0 -1.9843826l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l1.875 0zm-1.609375 6.7968826q0 -0.984375 -0.703125 -1.671875q-0.6875 -0.6875 -1.6875 -0.6875q-1.0 0 -1.703125 0.6875q-0.6875 0.6875 -0.6875 1.65625q0 0.875 0.625 1.453125q0.625 0.5625 1.765625 0.5625q1.125 0 1.75 -0.5625q0.640625 -0.578125 0.640625 -1.4375zm11.6953125 -0.078125q0 0.921875 -0.515625 1.796875q-0.515625 0.859375 -1.53125 1.375q-1.0 0.515625 -2.109375 0.515625q-1.09375 0 -2.09375 -0.5q-1.0 -0.515625 -1.53125 -1.375q-0.515625 -0.875 -0.515625 -1.828125q0 -0.953125 0.53125 -1.875q0.53125 -0.9375 1.53125 -1.46875q1.0 -0.53125 2.078125 -0.53125q1.09375 0 2.109375 0.546875q1.015625 0.546875 1.53125 1.46875q0.515625 0.90625 0.515625 1.875zm-1.609375 0.015625q0 -0.78125 -0.546875 -1.421875q-0.765625 -0.875 -2.0 -0.875q-1.078125 0 -1.8125 0.703125q-0.71875 0.6875 -0.71875 1.59375q0 0.75 0.734375 1.40625q0.734375 0.65625 1.796875 0.65625q1.078125 0 1.8125 -0.65625q0.734375 -0.65625 0.734375 -1.40625zm7.0546875 0.453125l-1.109375 2.953125l-1.5 0l-1.34375 -5.5q-0.4375 -0.015625 -0.671875 -0.234375q-0.21875 -0.234375 -0.21875 -0.5625q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.484375 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.28125 0.609375q-0.21875 0.1875 -0.828125 0.1875l0.609375 2.546875l0.984375 -2.609375l1.421875 0l1.0 2.609375l0.625 -2.546875q-0.59375 0 -0.78125 -0.109375q-0.375 -0.25 -0.375 -0.6875q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.5 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.328125 -0.21875 0.546875q-0.21875 0.21875 -0.640625 0.25l-1.3125 5.5l-1.484375 0l-1.171875 -2.953125zm11.3203125 -2.265625q-0.390625 -0.25 -0.828125 -0.359375q-0.421875 -0.125 -0.890625 -0.125q-0.921875 0 -1.46875 0.296875q-0.25 0.140625 -0.25 0.296875q0 0.171875 0.328125 0.34375q0.25 0.125 1.125 0.25q1.59375 0.21875 2.21875 0.4375q0.8125 0.28125 1.25 0.859375q0.453125 0.5625 0.453125 1.203125q0 0.859375 -0.75 1.4375q-1.09375 0.84375 -2.828125 0.84375q-0.6875 0 -1.28125 -0.125q-0.59375 -0.125 -1.078125 -0.359375q-0.125 0.09375 -0.265625 0.15625q-0.125 0.046875 -0.265625 0.046875q-0.375 0 -0.59375 -0.234375q-0.21875 -0.25 -0.21875 -0.828125l0 -0.546875q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.296875 0 0.484375 0.15625q0.203125 0.15625 0.3125 0.546875q0.359375 0.3125 0.875 0.484375q0.515625 0.15625 1.1875 0.15625q1.109375 0 1.71875 -0.34375q0.28125 -0.171875 0.28125 -0.359375q0 -0.3125 -0.40625 -0.515625q-0.421875 -0.203125 -1.71875 -0.34375q-1.921875 -0.203125 -2.578125 -0.78125q-0.640625 -0.578125 -0.640625 -1.40625q0 -0.859375 0.71875 -1.4375q0.984375 -0.78125 2.578125 -0.78125q0.5625 0 1.0625 0.109375q0.515625 0.109375 0.984375 0.328125q0.15625 -0.109375 0.28125 -0.15625q0.125 -0.0625 0.234375 -0.0625q0.328125 0 0.546875 0.25q0.21875 0.234375 0.21875 0.8125l0 0.390625q0 0.53125 -0.125 0.71875q-0.25 0.359375 -0.671875 0.359375q-0.296875 0 -0.515625 -0.171875q-0.21875 -0.1875 -0.28125 -0.484375zm6.9453125 1.96875l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.2656326l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.1562576q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.42188263 -1.421875 -0.42188263l-1.84375 0l0 3.0156326zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.4531326q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.4531326l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.6406326l0 3.4218826q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.9218826l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m203.43307 160.27034l113.98425 0l0 61.16536l-113.98425 0z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m203.43307 160.27034l113.98425 0l0 61.16536l-113.98425 0z" fill-rule="evenodd"/><path fill="#000000" d="m245.09708 193.46301l0 1.640625l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.265625l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.859375l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.515625q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.296875l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.875q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.234375 0.203125 0.375q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.625l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.515625 0.21875 0.671875q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.203125 0.625 -0.203125q0.3125 0 0.53125 0.234375q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.59375l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.890625q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 3.0q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.921875l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m26.64567 221.4357l158.20471 0l0 61.165344l-158.20471 0z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m26.64567 221.4357l158.20471 0l0 61.165344l-158.20471 0z" fill-rule="evenodd"/><path fill="#000000" d="m66.416 254.62837l0 1.6406097l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.2656097l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm14.6953125 1.4375q0 0.921875 -0.515625 1.7968597q-0.515625 0.859375 -1.53125 1.375q-1.0 0.515625 -2.109375 0.515625q-1.09375 0 -2.09375 -0.5q-1.0 -0.515625 -1.53125 -1.375q-0.515625 -0.87498474 -0.515625 -1.8281097q0 -0.953125 0.53125 -1.875q0.53125 -0.9375 1.53125 -1.46875q1.0 -0.53125 2.078125 -0.53125q1.09375 0 2.109375 0.546875q1.015625 0.546875 1.53125 1.46875q0.515625 0.90625 0.515625 1.875zm-1.609375 0.015625q0 -0.78125 -0.546875 -1.421875q-0.765625 -0.875 -2.0 -0.875q-1.078125 0 -1.8125 0.703125q-0.71875 0.6875 -0.71875 1.59375q0 0.75 0.734375 1.40625q0.734375 0.65623474 1.796875 0.65623474q1.078125 0 1.8125 -0.65623474q0.734375 -0.65625 0.734375 -1.40625zm8.7734375 -1.8125q-0.390625 -0.25 -0.828125 -0.359375q-0.421875 -0.125 -0.890625 -0.125q-0.921875 0 -1.46875 0.296875q-0.25 0.140625 -0.25 0.296875q0 0.171875 0.328125 0.34375q0.25 0.125 1.125 0.25q1.59375 0.21875 2.21875 0.4375q0.8125 0.28125 1.25 0.859375q0.453125 0.5625 0.453125 1.203125q0 0.85935974 -0.75 1.4374847q-1.09375 0.84375 -2.828125 0.84375q-0.6875 0 -1.28125 -0.125q-0.59375 -0.125 -1.078125 -0.359375q-0.125 0.09375 -0.265625 0.15625q-0.125 0.046875 -0.265625 0.046875q-0.375 0 -0.59375 -0.234375q-0.21875 -0.25 -0.21875 -0.828125l0 -0.546875q0 -0.57810974 0.21875 -0.81248474q0.21875 -0.25 0.578125 -0.25q0.296875 0 0.484375 0.15625q0.203125 0.15625 0.3125 0.546875q0.359375 0.31248474 0.875 0.48435974q0.515625 0.15625 1.1875 0.15625q1.109375 0 1.71875 -0.34375q0.28125 -0.171875 0.28125 -0.35935974q0 -0.3125 -0.40625 -0.515625q-0.421875 -0.203125 -1.71875 -0.34375q-1.921875 -0.203125 -2.578125 -0.78125q-0.640625 -0.578125 -0.640625 -1.40625q0 -0.859375 0.71875 -1.4375q0.984375 -0.78125 2.578125 -0.78125q0.5625 0 1.0625 0.109375q0.515625 0.109375 0.984375 0.328125q0.15625 -0.109375 0.28125 -0.15625q0.125 -0.0625 0.234375 -0.0625q0.328125 0 0.546875 0.25q0.21875 0.234375 0.21875 0.8125l0 0.390625q0 0.53125 -0.125 0.71875q-0.25 0.359375 -0.671875 0.359375q-0.296875 0 -0.515625 -0.171875q-0.21875 -0.1875 -0.28125 -0.484375zm8.4453125 -4.921875l0 1.703125l-1.90625 0l0 -1.703125l1.90625 0zm0.21875 3.046875l0 5.4843597l1.921875 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-5.4375 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.921875 0l0 -3.8906097l-1.296875 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.890625 0zm10.0078125 3.40625l2.4375 2.0781097q0.4375 0.03125 0.65625 0.25q0.21875 0.21875 0.21875 0.5625q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.8125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.28125 0.171875 -0.5q0.1875 -0.21875 0.484375 -0.296875l-1.1875 -1.0312347l-1.21875 1.0312347q0.359375 0.09375 0.515625 0.296875q0.171875 0.1875 0.171875 0.5q0 0.359375 -0.25 0.59375q-0.234375 0.21875 -0.8125 0.21875l-1.8125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.328125 0.21875 -0.546875q0.21875 -0.21875 0.65625 -0.25l2.375 -2.0937347l-2.109375 -1.796875q-0.40625 -0.03125 -0.625 -0.25q-0.21875 -0.21875 -0.21875 -0.546875q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.5 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.5625q0 0.46875 -0.4375 0.75l0.96875 0.8125l0.953125 -0.828125q-0.421875 -0.296875 -0.421875 -0.703125q0 -0.375 0.234375 -0.59375q0.25 -0.21875 0.828125 -0.21875l1.484375 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.328125 -0.21875 0.546875q-0.21875 0.21875 -0.640625 0.25l-2.109375 1.8125zm7.4765625 0.4375l0 1.6406097l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.2656097l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.8593597l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.5156097q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.2968597l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.8749847q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.23435974 0.203125 0.37498474q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.62498474l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.51560974 0.21875 0.67185974q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.20310974 0.625 -0.20310974q0.3125 0 0.53125 0.23435974q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.5937347l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 2.9999847q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.8906097q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 2.9999847q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.9218597l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m336.0 221.4357l174.04724 0l0 61.165344l-174.04724 0z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m336.0 221.4357l174.04724 0l0 61.165344l-174.04724 0z" fill-rule="evenodd"/><path fill="#000000" d="m375.02753 253.3315l-1.484375 4.5468597l-1.796875 0l-0.953125 -7.8749847q-0.375 -0.046875 -0.5625 -0.25q-0.1875 -0.203125 -0.1875 -0.53125q0 -0.375 0.25 -0.59375q0.25 -0.234375 0.828125 -0.234375l2.125 0.015625q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-0.828125 0l0.53125 4.484375l1.25 -3.734375l1.671875 0l1.25 3.734375l0.53125 -4.484375l-0.84375 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.21875 -0.234375 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.234375 0.828125 -0.234375l2.125 0.015625q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.296875 -0.203125 0.515625q-0.1875 0.21875 -0.5625 0.28125l-0.921875 7.8749847l-1.765625 0l-1.53125 -4.5468597zm10.1640625 -5.59375l0 1.703125l-1.90625 0l0 -1.703125l1.90625 0zm0.21875 3.046875l0 5.4843597l1.921875 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-5.4375 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.921875 0l0 -3.8906097l-1.296875 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l2.890625 0zm7.1953125 0l0 0.53125q0.4375 -0.375 0.953125 -0.5625q0.53125 -0.1875 1.15625 -0.1875q1.421875 0 2.25 0.890625q0.65625 0.703125 0.65625 1.84375l0 2.9687347q0.5 0 0.734375 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.453125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.34375 0.234375 -0.5625q0.25 -0.234375 0.75 -0.234375l0 -3.0156097q0 -0.53125 -0.28125 -0.765625q-0.359375 -0.3125 -1.09375 -0.3125q-0.5625 0 -0.984375 0.21875q-0.40625 0.203125 -1.046875 0.90625l0 2.9687347q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -3.8906097q-0.5 0 -0.75 -0.21875q-0.234375 -0.234375 -0.234375 -0.578125q0 -0.359375 0.234375 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.53125 0zm14.8984375 -3.046875l0 8.531235l0.265625 0q0.578125 0 0.828125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.25 0.21875 -0.828125 0.21875l-1.875 0l0 -0.390625q-0.546875 0.3125 -1.140625 0.484375q-0.59375 0.171875 -1.234375 0.171875q-1.8125 0 -2.921875 -1.046875q-1.09375 -1.046875 -1.09375 -2.6093597q0 -1.625 1.15625 -2.765625q1.15625 -1.15625 2.828125 -1.15625q0.625 0 1.21875 0.203125q0.609375 0.1875 1.1875 0.5625l0 -1.984375l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l1.875 0zm-1.609375 6.796875q0 -0.984375 -0.703125 -1.671875q-0.6875 -0.6875 -1.6875 -0.6875q-1.0 0 -1.703125 0.6875q-0.6875 0.6875 -0.6875 1.65625q0 0.875 0.625 1.453125q0.625 0.56248474 1.765625 0.56248474q1.125 0 1.75 -0.56248474q0.640625 -0.578125 0.640625 -1.4375zm11.6953125 -0.078125q0 0.921875 -0.515625 1.7968597q-0.515625 0.859375 -1.53125 1.375q-1.0 0.515625 -2.109375 0.515625q-1.09375 0 -2.09375 -0.5q-1.0 -0.515625 -1.53125 -1.375q-0.515625 -0.87498474 -0.515625 -1.8281097q0 -0.953125 0.53125 -1.875q0.53125 -0.9375 1.53125 -1.46875q1.0 -0.53125 2.078125 -0.53125q1.09375 0 2.109375 0.546875q1.015625 0.546875 1.53125 1.46875q0.515625 0.90625 0.515625 1.875zm-1.609375 0.015625q0 -0.78125 -0.546875 -1.421875q-0.765625 -0.875 -2.0 -0.875q-1.078125 0 -1.8125 0.703125q-0.71875 0.6875 -0.71875 1.59375q0 0.75 0.734375 1.40625q0.734375 0.65623474 1.796875 0.65623474q1.078125 0 1.8125 -0.65623474q0.734375 -0.65625 0.734375 -1.40625zm7.0546875 0.453125l-1.109375 2.9531097l-1.5 0l-1.34375 -5.4999847q-0.4375 -0.015625 -0.671875 -0.234375q-0.21875 -0.234375 -0.21875 -0.5625q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.484375 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.28125 0.609375q-0.21875 0.1875 -0.828125 0.1875l0.609375 2.546875l0.984375 -2.609375l1.421875 0l1.0 2.609375l0.625 -2.546875q-0.59375 0 -0.78125 -0.109375q-0.375 -0.25 -0.375 -0.6875q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l1.5 0q0.578125 0 0.828125 0.21875q0.25 0.21875 0.25 0.578125q0 0.328125 -0.21875 0.546875q-0.21875 0.21875 -0.640625 0.25l-1.3125 5.4999847l-1.484375 0l-1.171875 -2.9531097zm11.3203125 -2.265625q-0.390625 -0.25 -0.828125 -0.359375q-0.421875 -0.125 -0.890625 -0.125q-0.921875 0 -1.46875 0.296875q-0.25 0.140625 -0.25 0.296875q0 0.171875 0.328125 0.34375q0.25 0.125 1.125 0.25q1.59375 0.21875 2.21875 0.4375q0.8125 0.28125 1.25 0.859375q0.453125 0.5625 0.453125 1.203125q0 0.85935974 -0.75 1.4374847q-1.09375 0.84375 -2.828125 0.84375q-0.6875 0 -1.28125 -0.125q-0.59375 -0.125 -1.078125 -0.359375q-0.125 0.09375 -0.265625 0.15625q-0.125 0.046875 -0.265625 0.046875q-0.375 0 -0.59375 -0.234375q-0.21875 -0.25 -0.21875 -0.828125l0 -0.546875q0 -0.57810974 0.21875 -0.81248474q0.21875 -0.25 0.578125 -0.25q0.296875 0 0.484375 0.15625q0.203125 0.15625 0.3125 0.546875q0.359375 0.31248474 0.875 0.48435974q0.515625 0.15625 1.1875 0.15625q1.109375 0 1.71875 -0.34375q0.28125 -0.171875 0.28125 -0.35935974q0 -0.3125 -0.40625 -0.515625q-0.421875 -0.203125 -1.71875 -0.34375q-1.921875 -0.203125 -2.578125 -0.78125q-0.640625 -0.578125 -0.640625 -1.40625q0 -0.859375 0.71875 -1.4375q0.984375 -0.78125 2.578125 -0.78125q0.5625 0 1.0625 0.109375q0.515625 0.109375 0.984375 0.328125q0.15625 -0.109375 0.28125 -0.15625q0.125 -0.0625 0.234375 -0.0625q0.328125 0 0.546875 0.25q0.21875 0.234375 0.21875 0.8125l0 0.390625q0 0.53125 -0.125 0.71875q-0.25 0.359375 -0.671875 0.359375q-0.296875 0 -0.515625 -0.171875q-0.21875 -0.1875 -0.28125 -0.484375zm6.9453125 1.96875l0 1.6406097l1.625 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-3.46875 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l0.25 0l0 -6.2656097l-0.25 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.234375 0.828125 -0.234375l3.6875 0.015625q1.625 0 2.5625 0.890625q0.953125 0.875 0.953125 2.15625q0 0.703125 -0.3125 1.328125q-0.25 0.46875 -0.8125 0.921875q-0.5625 0.453125 -1.15625 0.6875q-0.59375 0.234375 -1.5625 0.234375l-1.515625 0zm0 -1.609375l1.484375 0q1.046875 0 1.65625 -0.46875q0.625 -0.46875 0.625 -1.140625q0 -0.5625 -0.5 -0.984375q-0.5 -0.421875 -1.421875 -0.421875l-1.84375 0l0 3.015625zm11.9765625 4.8593597l0 -0.375q-0.609375 0.3125 -1.34375 0.46875q-0.71875 0.171875 -1.3125 0.171875q-1.28125 0 -2.09375 -0.6875q-0.796875 -0.6875 -0.796875 -1.5156097q0 -1.0 1.015625 -1.859375q1.03125 -0.875 2.84375 -0.875q0.734375 0 1.6875 0.15625l0 -0.375q0 -0.359375 -0.3125 -0.578125q-0.3125 -0.234375 -1.171875 -0.234375q-0.71875 0 -1.84375 0.28125q-0.421875 0.09375 -0.65625 0.09375q-0.328125 0 -0.546875 -0.21875q-0.21875 -0.234375 -0.21875 -0.59375q0 -0.203125 0.078125 -0.34375q0.078125 -0.15625 0.21875 -0.25q0.140625 -0.09375 0.578125 -0.21875q0.59375 -0.15625 1.203125 -0.25q0.625 -0.109375 1.125 -0.109375q1.5 0 2.3125 0.65625q0.828125 0.640625 0.828125 1.75l0 3.2968597l0.28125 0q0.578125 0 0.8125 0.234375q0.25 0.21875 0.25 0.578125q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.875 0zm0 -2.8749847q-0.96875 -0.1875 -1.78125 -0.1875q-0.96875 0 -1.671875 0.484375q-0.4375 0.296875 -0.4375 0.609375q0 0.23435974 0.203125 0.37498474q0.390625 0.25 1.078125 0.25q0.578125 0 1.296875 -0.21875q0.734375 -0.234375 1.3125 -0.62498474l0 -0.6875zm7.7578125 -2.625l0 3.21875q0 0.51560974 0.21875 0.67185974q0.328125 0.265625 1.171875 0.265625q1.21875 0 2.265625 -0.53125q0.390625 -0.20310974 0.625 -0.20310974q0.3125 0 0.53125 0.23435974q0.234375 0.234375 0.234375 0.578125q0 0.3125 -0.25 0.53125q-0.375 0.375 -1.515625 0.6875q-1.125 0.3125 -1.890625 0.3125q-1.5 0 -2.25 -0.640625q-0.734375 -0.65625 -0.734375 -1.5937347l0 -3.53125l-0.578125 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.21875 -0.25 -0.578125q0 -0.359375 0.25 -0.578125q0.25 -0.21875 0.828125 -0.21875l0.578125 0l0 -1.453125q0 -0.578125 0.21875 -0.8125q0.21875 -0.25 0.578125 -0.25q0.359375 0 0.578125 0.25q0.21875 0.234375 0.21875 0.8125l0 1.453125l2.96875 0q0.578125 0 0.8125 0.21875q0.25 0.21875 0.25 0.578125q0 0.359375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-2.96875 0zm8.3515625 -4.640625l0 3.421875q0.5 -0.296875 1.0 -0.4375q0.515625 -0.15625 1.046875 -0.15625q0.828125 0 1.46875 0.28125q0.65625 0.28125 1.078125 0.890625q0.421875 0.609375 0.421875 1.53125l0 2.9999847q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.5625 0 -0.8125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.4375 0.375 -0.671875q0.203125 -0.125 0.796875 -0.125l0 -2.8906097q0 -0.625 -0.28125 -0.875q-0.359375 -0.328125 -1.078125 -0.328125q-0.53125 0 -0.953125 0.203125q-0.40625 0.203125 -1.09375 0.890625l0 2.9999847q0.609375 0 0.796875 0.125q0.375 0.234375 0.375 0.6875q0 0.34375 -0.25 0.578125q-0.234375 0.21875 -0.8125 0.21875l-1.828125 0q-0.578125 0 -0.828125 -0.21875q-0.234375 -0.234375 -0.234375 -0.59375q0 -0.4375 0.375 -0.671875q0.1875 -0.125 0.796875 -0.125l0 -6.9218597l-0.265625 0q-0.578125 0 -0.828125 -0.21875q-0.25 -0.234375 -0.25 -0.59375q0 -0.34375 0.25 -0.5625q0.25 -0.234375 0.828125 -0.234375l1.875 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m105.74803 99.10499l97.70079 -30.58268" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m105.74803 99.10499l91.97476 -28.79029" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m198.21622 71.891l3.8374481 -2.9319763l-4.824295 -0.22064209z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m423.02362 99.10499l-105.60629 -30.58268" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m423.02362 99.10499l-99.84308 -28.913704" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m323.63998 68.60474l-4.818451 0.32421875l3.8995361 2.848877z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m105.74803 221.4357l0 -61.16536" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m105.74803 221.4357l0 -55.16536" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m107.399765 166.27034l-1.6517334 -4.538101l-1.6517334 4.538101z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m423.02362 221.4357l0 -61.16536" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m423.02362 221.4357l0 -55.16536" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m424.67535 166.27034l-1.6517334 -4.538101l-1.6517334 4.538101z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m260.4252 160.27034l0 -61.16535" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m260.4252 160.27034l0 -55.16535" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m262.07693 105.10499l-1.6517334 -4.538101l-1.6517334 4.538101z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m105.74803 221.4357l97.70079 -30.582687" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m105.74803 221.4357l91.97476 -28.790298" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m198.21622 194.22171l3.8374481 -2.9319763l-4.824295 -0.22064209z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m423.02362 221.4357l-105.60629 -30.582687" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m423.02362 221.4357l-99.84308 -28.913696" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m323.63998 190.93544l-4.818451 0.32421875l3.8995361 2.848877z" fill-rule="evenodd"/></g></svg>
\ No newline at end of file
.. method:: Path.glob(pattern)
- Glob the given *pattern* in the directory represented by this path,
+ Glob the given relative *pattern* in the directory represented by this path,
yielding all matching files (of any kind)::
>>> sorted(Path('.').glob('*.py'))
.. method:: Path.rglob(pattern)
- This is like calling :meth:`Path.glob` with "``**``" added in front of the
- given *pattern*::
+ This is like calling :func:`Path.glob` with "``**/``" added in front of the
+ given relative *pattern*::
>>> sorted(Path().rglob("*.py"))
[PosixPath('build/lib/pathlib.py'),
the code following this statement, and continue running without the debugger
using the :pdbcmd:`continue` command.
+.. versionadded:: 3.7
+ The built-in :func:`breakpoint()`, when called with defaults, can be used
+ instead of ``import pdb; pdb.set_trace()``.
+
The typical usage to inspect a crashed program is::
>>> import pdb
.. [#] Don't confuse this with the :mod:`marshal` module
.. [#] This is why :keyword:`lambda` functions cannot be pickled: all
- :keyword:`lambda` functions share the same name: ``<lambda>``.
+ :keyword:`!lambda` functions share the same name: ``<lambda>``.
.. [#] The exception raised will likely be an :exc:`ImportError` or an
:exc:`AttributeError` but it could be something else.
with the :class:`float` values returned by :func:`random` (that includes
integers, floats, and fractions but excludes decimals).
+ For a given seed, the :func:`choices` function with equal weighting
+ typically produces a different sequence than repeated calls to
+ :func:`choice`. The algorithm used by :func:`choices` uses floating
+ point arithmetic for internal consistency and speed. The algorithm used
+ by :func:`choice` defaults to integer arithmetic with repeated selections
+ to avoid small biases from round-off error.
+
.. versionadded:: 3.6
>>> # Estimate the probability of getting 5 or more heads from 7 spins
>>> # of a biased coin that settles on heads 60% of the time.
- >>> trial = lambda: choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5
+ >>> def trial():
+ ... return choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5
+ ...
>>> sum(trial() for i in range(10000)) / 10000
0.4169
>>> # Probability of the median of 5 samples being in middle two quartiles
- >>> trial = lambda : 2500 <= sorted(choices(range(10000), k=5))[2] < 7500
+ >>> def trial():
+ ... return 2500 <= sorted(choices(range(10000), k=5))[2] < 7500
+ ...
>>> sum(trial() for i in range(10000)) / 10000
0.7958
``(?#...)``
A comment; the contents of the parentheses are simply ignored.
+.. index:: single: (?=; in regular expressions
+
``(?=...)``
Matches if ``...`` matches next, but doesn't consume any of the string. This is
called a :dfn:`lookahead assertion`. For example, ``Isaac (?=Asimov)`` will match
only inside character classes.)
``'\u'`` and ``'\U'`` escape sequences are only recognized in Unicode
-patterns. In bytes patterns they are errors.
+patterns. In bytes patterns they are errors. Unknown escapes of ASCII
+letters are reserved for future use and treated as errors.
Octal escapes are included in a limited form. If the first digit is a 0, or if
there are three octal digits, it is considered an octal escape. Otherwise, it is
*string* is returned unchanged. *repl* can be a string or a function; if it is
a string, any backslash escapes in it are processed. That is, ``\n`` is
converted to a single newline character, ``\r`` is converted to a carriage return, and
- so forth. Unknown escapes such as ``\&`` are left alone. Backreferences, such
+ so forth. Unknown escapes of ASCII letters are reserved for future use and
+ treated as errors. Other unknown escapes such as ``\&`` are left alone.
+ Backreferences, such
as ``\6``, are replaced with the substring matched by group 6 in the pattern.
For example::
| :const:`EPOLLMSG` | Ignored. |
+-------------------------+-----------------------------------------------+
+ .. versionadded:: 3.6
+ :const:`EPOLLEXCLUSIVE` was added. It's only supported by Linux Kernel 4.5
+ or later.
.. method:: epoll.close()
The :class:`SMTP` class supports the :keyword:`with` statement. When used
like this, the SMTP ``QUIT`` command is issued automatically when the
- :keyword:`with` statement exits. E.g.::
+ :keyword:`!with` statement exits. E.g.::
>>> from smtplib import SMTP
>>> with SMTP("domain.org") as smtp:
:meth:`~BaseServer.handle_request` or
:meth:`~BaseServer.serve_forever` method of the server object to
process one or many requests. Finally, call :meth:`~BaseServer.server_close`
-to close the socket (unless you used a :keyword:`with` statement).
+to close the socket (unless you used a :keyword:`!with` statement).
When inheriting from :class:`ThreadingMixIn` for threaded connection behavior,
you should explicitly declare how you want your threads to behave on an abrupt
If any precondition isn't met (e.g. not TLS 1.3, PHA not enabled), an
:exc:`SSLError` is raised.
- .. versionadded:: 3.7.1
-
.. note::
Only available with OpenSSL 1.1.1 and TLS 1.3 enabled. Without TLS 1.3
support, the method raises :exc:`NotImplementedError`.
+ .. versionadded:: 3.7.1
+
.. method:: SSLSocket.version()
Return the actual SSL protocol version negotiated by the connection
This attribute is not available unless the ssl module is compiled
with OpenSSL 1.1.0g or newer.
+ .. versionadded:: 3.7
+
.. attribute:: SSLContext.minimum_version
Like :attr:`SSLContext.maximum_version` except it is the lowest
This attribute is not available unless the ssl module is compiled
with OpenSSL 1.1.0g or newer.
+ .. versionadded:: 3.7
+
.. attribute:: SSLContext.options
An integer representing the set of SSL options enabled on this context.
:meth:`SSLSocket.verify_client_post_handshake` is called and some I/O is
performed.
- .. versionadded:: 3.7.1
-
.. note::
Only available with OpenSSL 1.1.1 and TLS 1.3 enabled. Without TLS 1.3
support, the property value is None and can't be modified
+ .. versionadded:: 3.7.1
+
.. attribute:: SSLContext.protocol
The protocol version chosen when constructing the context. This attribute
subject common name in the absence of a subject alternative name
extension (default: true).
- .. versionadded:: 3.7
-
.. note::
Only writeable with OpenSSL 1.1.0 or higher.
+ .. versionadded:: 3.7
+
.. attribute:: SSLContext.verify_flags
The flags for certificate verification operations. You can set flags like
.. _boolean:
-Boolean Operations --- :keyword:`and`, :keyword:`or`, :keyword:`not`
-====================================================================
+Boolean Operations --- :keyword:`!and`, :keyword:`!or`, :keyword:`!not`
+=======================================================================
.. index:: pair: Boolean; operations
.. method:: copy()
- Return a new set with a shallow copy of *s*.
+ Return a shallow copy of the set.
Note, the non-operator versions of :meth:`union`, :meth:`intersection`,
Return a shallow copy of the dictionary.
- .. classmethod:: fromkeys(seq[, value])
+ .. classmethod:: fromkeys(iterable[, value])
- Create a new dictionary with keys from *seq* and values set to *value*.
+ Create a new dictionary with keys from *iterable* and values set to *value*.
:meth:`fromkeys` is a class method that returns a new dictionary. *value*
defaults to ``None``.
Enter the runtime context and return either this object or another object
related to the runtime context. The value returned by this method is bound to
- the identifier in the :keyword:`as` clause of :keyword:`with` statements using
+ the identifier in the :keyword:`!as` clause of :keyword:`with` statements using
this context manager.
An example of a context manager that returns itself is a :term:`file object`.
decimal context to a copy of the original decimal context and then return the
copy. This allows changes to be made to the current decimal context in the body
of the :keyword:`with` statement without affecting code outside the
- :keyword:`with` statement.
+ :keyword:`!with` statement.
.. method:: contextmanager.__exit__(exc_type, exc_val, exc_tb)
Returning a true value from this method will cause the :keyword:`with` statement
to suppress the exception and continue execution with the statement immediately
- following the :keyword:`with` statement. Otherwise the exception continues
+ following the :keyword:`!with` statement. Otherwise the exception continues
propagating after this method has finished executing. Exceptions that occur
during execution of this method will replace any exception that occurred in the
- body of the :keyword:`with` statement.
+ body of the :keyword:`!with` statement.
The exception passed in should never be reraised explicitly - instead, this
method should return a false value to indicate that the method completed
^^^^^^^^^^
Exceptions raised in the child process, before the new program has started to
-execute, will be re-raised in the parent. Additionally, the exception object
-will have one extra attribute called :attr:`child_traceback`, which is a string
-containing traceback information from the child's point of view.
+execute, will be re-raised in the parent.
The most common exception raised is :exc:`OSError`. This occurs, for example,
when trying to execute a non-existent file. Applications should prepare for
.. data:: CREATE_NO_WINDOW
A :class:`Popen` ``creationflags`` parameter to specify that a new process
- will not create a window
+ will not create a window.
.. versionadded:: 3.7
* :class:`Popen` raises an exception if the execution fails.
-* the *capturestderr* argument is replaced with the *stderr* argument.
+* The *capturestderr* argument is replaced with the *stderr* argument.
* ``stdin=PIPE`` and ``stdout=PIPE`` must be specified.
returned by the :func:`open` function. Their parameters are chosen as
follows:
- * The character encoding is platform-dependent. Under Windows, if the stream
- is interactive (that is, if its :meth:`isatty` method returns ``True``), the
- console codepage is used, otherwise the ANSI code page. Under other
- platforms, the locale encoding is used (see :meth:`locale.getpreferredencoding`).
-
- Under all platforms though, you can override this value by setting the
- :envvar:`PYTHONIOENCODING` environment variable before starting Python.
+ * The character encoding is platform-dependent. Non-Windows
+ platforms use the locale encoding (see
+ :meth:`locale.getpreferredencoding()`).
+
+ On Windows, UTF-8 is used for the console device. Non-character
+ devices such as disk files and pipes use the system locale
+ encoding (i.e. the ANSI codepage). Non-console character
+ devices such as NUL (i.e. where isatty() returns True) use the
+ value of the console input and output codepages at startup,
+ respectively for stdin and stdout/stderr. This defaults to the
+ system locale encoding if the process is not initially attached
+ to a console.
+
+ The special behaviour of the console can be overridden
+ by setting the environment variable PYTHONLEGACYWINDOWSSTDIO
+ before starting Python. In that case, the console codepages are
+ used as for any other character device.
+
+ Under all platforms, you can override the character encoding by
+ setting the :envvar:`PYTHONIOENCODING` environment variable before
+ starting Python or by using the new :option:`-X` ``utf8`` command
+ line option and :envvar:`PYTHONUTF8` environment variable. However,
+ for the Windows console, this only applies when
+ :envvar:`PYTHONLEGACYWINDOWSSTDIO` is also set.
* When interactive, ``stdout`` and ``stderr`` streams are line-buffered.
Otherwise, they are block-buffered like regular text files. You can
an empty string for other reasons. See the individual descriptions below.
A :class:`Telnet` object is a context manager and can be used in a
- :keyword:`with` statement. When the :keyword:`with` block ends, the
+ :keyword:`with` statement. When the :keyword:`!with` block ends, the
:meth:`close` method is called::
>>> from telnetlib import Telnet
The directory name can be retrieved from the :attr:`name` attribute of the
returned object. When the returned object is used as a context manager, the
- :attr:`name` will be assigned to the target of the :keyword:`as` clause in
+ :attr:`name` will be assigned to the target of the :keyword:`!as` clause in
the :keyword:`with` statement, if there is one.
The directory can be explicitly cleaned up by calling the
Check for presence of docstrings.
+.. data:: TEST_HTTP_URL
+
+ Define the URL of a dedicated HTTP server for the network tests.
+
The :mod:`test.support` module defines the following functions:
.. _with-locks:
-Using locks, conditions, and semaphores in the :keyword:`with` statement
-------------------------------------------------------------------------
+Using locks, conditions, and semaphores in the :keyword:`!with` statement
+-------------------------------------------------------------------------
All of the objects provided by this module that have :meth:`acquire` and
:meth:`release` methods can be used as context managers for a :keyword:`with`
The reference point of the returned value is undefined, so that only the
difference between the results of consecutive calls is valid.
- On Windows versions older than Vista, :func:`monotonic` detects
- :c:func:`GetTickCount` integer overflow (32 bits, roll-over after 49.7 days).
- It increases an internal epoch (reference time) by 2\ :sup:`32` each time
- that an overflow is detected. The epoch is stored in the process-local state
- and so the value of :func:`monotonic` may be different in two Python
- processes running for more than 49 days. On more recent versions of Windows
- and on other operating systems, :func:`monotonic` is system-wide.
-
.. versionadded:: 3.3
.. versionchanged:: 3.5
- The function is now always available.
+ The function is now always available and always system-wide.
.. function:: monotonic_ns() -> int
Similar to :data:`CLOCK_MONOTONIC`, but provides access to a raw
hardware-based time that is not subject to NTP adjustments.
- Availability: Linux 2.6.28 or later.
+ .. availability:: Linux 2.6.28 and newer, macOS 10.12 and newer.
.. versionadded:: 3.3
Thread-specific CPU-time clock.
- Availability: Unix.
+ .. availability:: Unix.
.. versionadded:: 3.3
By default, :meth:`.timeit` temporarily turns off :term:`garbage
collection` during the timing. The advantage of this approach is that
- it makes independent timings more comparable. This disadvantage is
+ it makes independent timings more comparable. The disadvantage is
that GC may be an important component of the performance of the
function being measured. If so, GC can be re-enabled as the first
statement in the *setup* string. For example::
>>> t.timeit()
0.3955516149999312
>>> t.repeat()
- [0.40193588800002544, 0.3960157959998014, 0.39594301399984033]
+ [0.40183617287970225, 0.37027556854118704, 0.38344867356679524, 0.3712595970846668, 0.37866875250654886]
The following examples show how to time expressions that contain multiple lines.
root = tix.Tk()
root.tk.eval('package require Tix')
-If this fails, you have a Tk installation problem which must be resolved before
-proceeding. Use the environment variable :envvar:`TIX_LIBRARY` to point to the
-installed Tix library directory, and make sure you have the dynamic
-object library (:file:`tix8183.dll` or :file:`libtix8183.so`) in the same
-directory that contains your Tk dynamic object library (:file:`tk8183.dll` or
-:file:`libtk8183.so`). The directory with the dynamic object library should also
-have a file called :file:`pkgIndex.tcl` (case sensitive), which contains the
-line::
-
- package ifneeded Tix 8.1 [list load "[file join $dir tix8183.dll]" Tix]
-
Tix Widgets
-----------
--------------
-This module defines utility function to assist in dynamic creation of
+This module defines utility functions to assist in dynamic creation of
new types.
It also defines names for some object types that are used by the standard
Type aliases are useful for simplifying complex type signatures. For example::
- from typing import Dict, Tuple, List
+ from typing import Dict, Tuple, Sequence
ConnectionOptions = Dict[str, str]
Address = Tuple[str, int]
Server = Tuple[Address, ConnectionOptions]
- def broadcast_message(message: str, servers: List[Server]) -> None:
+ def broadcast_message(message: str, servers: Sequence[Server]) -> None:
...
# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
message: str,
- servers: List[Tuple[Tuple[str, int], Dict[str, str]]]) -> None:
+ servers: Sequence[Tuple[Tuple[str, int], Dict[str, str]]]) -> None:
...
Note that ``None`` as a type hint is a special case and is replaced by
.. class:: Mapping(Sized, Collection[KT], Generic[VT_co])
A generic version of :class:`collections.abc.Mapping`.
+ This type can be used as follows::
+
+ def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:
+ return word_list[word]
.. class:: MutableMapping(Mapping[KT, VT])
Generic version of :class:`list`.
Useful for annotating return types. To annotate arguments it is preferred
- to use abstract collection types such as :class:`Mapping`, :class:`Sequence`,
- or :class:`AbstractSet`.
+ to use an abstract collection type such as :class:`Sequence` or
+ :class:`Iterable`.
This type may be used as follows::
.. class:: Set(set, MutableSet[T])
A generic version of :class:`builtins.set <set>`.
+ Useful for annotating return types. To annotate arguments it is preferred
+ to use an abstract collection type such as :class:`AbstractSet`.
.. class:: FrozenSet(frozenset, AbstractSet[T_co])
.. class:: Dict(dict, MutableMapping[KT, VT])
A generic version of :class:`dict`.
- The usage of this type is as follows::
+ Useful for annotating return types. To annotate arguments it is preferred
+ to use an abstract collection type such as :class:`Mapping`.
- def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
- return word_list[word]
+ This type can be used as follows::
+
+ def count_words(text: str) -> Dict[str, int]:
+ ...
.. class:: DefaultDict(collections.defaultdict, MutableMapping[KT, VT])
def stop() -> NoReturn:
raise RuntimeError('no way')
- .. versionadded:: 3.6.5
+ .. versionadded:: 3.5.4
.. data:: Union
Instead of ``autospec=True`` you can pass ``autospec=some_object`` to use an
arbitrary object as the spec instead of the one being replaced.
- By default :func:`patch` will fail to replace attributes that don't exist. If
- you pass in ``create=True``, and the attribute doesn't exist, patch will
- create the attribute for you when the patched function is called, and
- delete it again afterwards. This is useful for writing tests against
- attributes that your production code creates at runtime. It is off by
- default because it can be dangerous. With it switched on you can write
- passing tests against APIs that don't actually exist!
+ By default :func:`patch` will fail to replace attributes that don't exist.
+ If you pass in ``create=True``, and the attribute doesn't exist, patch will
+ create the attribute for you when the patched function is called, and delete
+ it again after the patched function has exited. This is useful for writing
+ tests against attributes that your production code creates at runtime. It is
+ off by default because it can be dangerous. With it switched on you can
+ write passing tests against APIs that don't actually exist!
.. note::
...
KeyError
+By default, attempting to patch a function in a module (or a method or an
+attribute in a class) that does not exist will fail with :exc:`AttributeError`::
+
+ >>> @patch('sys.non_existing_attribute', 42)
+ ... def test():
+ ... assert sys.non_existing_attribute == 42
+ ...
+ >>> test()
+ Traceback (most recent call last):
+ ...
+ AttributeError: <module 'sys' (built-in)> does not have the attribute 'non_existing'
+
+but adding ``create=True`` in the call to :func:`patch` will make the previous example
+work as expected::
+
+ >>> @patch('sys.non_existing_attribute', 42, create=True)
+ ... def test(mock_stdout):
+ ... assert sys.non_existing_attribute == 42
+ ...
+ >>> test()
+
patch.object
~~~~~~~~~~~~
.. method:: run(test)
- This method is the main public interface to the `TextTestRunner`. This
+ This method is the main public interface to the ``TextTestRunner``. This
method takes a :class:`TestSuite` or :class:`TestCase` instance. A
:class:`TestResult` is created by calling
:func:`_makeResult` and the test(s) are run and the
Unmatched square brackets in the :attr:`netloc` attribute will raise a
:exc:`ValueError`.
+ Characters in the :attr:`netloc` attribute that decompose under NFKC
+ normalization (as used by the IDNA encoding) into any of ``/``, ``?``,
+ ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is
+ decomposed before parsing, no error will be raised.
+
.. versionchanged:: 3.2
Added IPv6 URL parsing capabilities.
Out-of-range port numbers now raise :exc:`ValueError`, instead of
returning :const:`None`.
+ .. versionchanged:: 3.7.3
+ Characters that affect netloc parsing under NFKC normalization will
+ now raise :exc:`ValueError`.
+
.. function:: parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None)
Unmatched square brackets in the :attr:`netloc` attribute will raise a
:exc:`ValueError`.
+ Characters in the :attr:`netloc` attribute that decompose under NFKC
+ normalization (as used by the IDNA encoding) into any of ``/``, ``?``,
+ ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is
+ decomposed before parsing, no error will be raised.
+
.. versionchanged:: 3.6
Out-of-range port numbers now raise :exc:`ValueError`, instead of
returning :const:`None`.
+ .. versionchanged:: 3.7.3
+ Characters that affect netloc parsing under NFKC normalization will
+ now raise :exc:`ValueError`.
+
.. function:: urlunsplit(parts)
any existing target directory, before creating the environment.
* ``symlinks`` -- a Boolean value indicating whether to attempt to symlink the
- Python binary (and any necessary DLLs or other binaries,
- e.g. ``pythonw.exe``), rather than copying.
+ Python binary rather than copying.
* ``upgrade`` -- a Boolean value which, if true, will upgrade an existing
environment with the running Python - for use when that Python has been
.. method:: setup_python(context)
- Creates a copy of the Python executable in the environment on POSIX
- systems. If a specific executable ``python3.x`` was used, symlinks to
- ``python`` and ``python3`` will be created pointing to that executable,
- unless files with those names already exist.
+ Creates a copy or symlink to the Python executable in the environment.
+ On POSIX systems, if a specific executable ``python3.x`` was used,
+ symlinks to ``python`` and ``python3`` will be created pointing to that
+ executable, unless files with those names already exist.
.. method:: setup_scripts(context)
Installs activation scripts appropriate to the platform into the virtual
- environment. On Windows, also installs the ``python[w].exe`` scripts.
+ environment.
.. method:: post_setup(context)
.. versionchanged:: 3.7.2
Windows now uses redirector scripts for ``python[w].exe`` instead of
- copying the actual binaries, and so :meth:`setup_python` does nothing
- unless running from a build in the source tree.
+ copying the actual binaries. In 3.7.2 only :meth:`setup_python` does
+ nothing unless running from a build in the source tree.
+
+ .. versionchanged:: 3.7.3
+ Windows copies the redirector scripts as part of :meth:`setup_python`
+ instead of :meth:`setup_scripts`. This was not the case in 3.7.2.
+ When using symlinks, the original executables will be linked.
In addition, :class:`EnvBuilder` provides this utility method that can be
called from :meth:`setup_scripts` or :meth:`post_setup` in subclasses to
the file object.
The :func:`.open` function may be used in a :keyword:`with` statement. When
- the :keyword:`with` block completes, the :meth:`Wave_read.close()
+ the :keyword:`!with` block completes, the :meth:`Wave_read.close()
<wave.Wave_read.close>` or :meth:`Wave_write.close()
<wave.Wave_write.close()>` method is called.
You can avoid calling this method explicitly by using the :keyword:`with`
statement. The following code will automatically unlink *dom* when the
- :keyword:`with` block is exited::
+ :keyword:`!with` block is exited::
with xml.dom.minidom.parse(datasource) as dom:
... # Work with dom.
*elem* is an element tree or an individual element.
-.. function:: fromstring(text)
+.. function:: fromstring(text, parser=None)
Parses an XML section from a string constant. Same as :func:`XML`. *text*
- is a string containing XML data. Returns an :class:`Element` instance.
+ is a string containing XML data. *parser* is an optional parser instance.
+ If not given, the standard :class:`XMLParser` parser is used.
+ Returns an :class:`Element` instance.
.. function:: fromstringlist(sequence, parser=None)
ZipFile is also a context manager and therefore supports the
:keyword:`with` statement. In the example, *myzip* is closed after the
- :keyword:`with` statement's suite is finished---even if an exception occurs::
+ :keyword:`!with` statement's suite is finished---even if an exception occurs::
with ZipFile('spam.zip', 'w') as myzip:
myzip.write('eggs.txt')
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python |release| alone or in any derivative
version, provided, however, that PSF's License Agreement and PSF's notice of
- copyright, i.e., "Copyright © 2001-2018 Python Software Foundation; All Rights
+ copyright, i.e., "Copyright © 2001-2019 Python Software Foundation; All Rights
Reserved" are retained in Python |release| alone or in any derivative version
prepared by Licensee.
\r
rem Search for HHC in likely places\r
set HTMLHELP=\r
-where hhc /q && set HTMLHELP=hhc && goto :skiphhcsearch\r
+where hhc /q && set "HTMLHELP=hhc" && goto :skiphhcsearch\r
where /R ..\externals hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"\r
if not exist "%HTMLHELP%" where /R "%ProgramFiles(x86)%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"\r
if not exist "%HTMLHELP%" where /R "%ProgramFiles%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"\r
.. _elif:
.. _else:
-The :keyword:`if` statement
-===========================
+The :keyword:`!if` statement
+============================
.. index::
- statement: if
+ ! statement: if
keyword: elif
keyword: else
single: : (colon); compound statement
.. _while:
-The :keyword:`while` statement
-==============================
+The :keyword:`!while` statement
+===============================
.. index::
- statement: while
+ ! statement: while
keyword: else
pair: loop; statement
- keyword: else
single: : (colon); compound statement
The :keyword:`while` statement is used for repeated execution as long as an
This repeatedly tests the expression and, if it is true, executes the first
suite; if the expression is false (which may be the first time it is tested) the
-suite of the :keyword:`else` clause, if present, is executed and the loop
+suite of the :keyword:`!else` clause, if present, is executed and the loop
terminates.
.. index::
statement: continue
A :keyword:`break` statement executed in the first suite terminates the loop
-without executing the :keyword:`else` clause's suite. A :keyword:`continue`
+without executing the :keyword:`!else` clause's suite. A :keyword:`continue`
statement executed in the first suite skips the rest of the suite and goes back
to testing the expression.
.. _for:
-The :keyword:`for` statement
-============================
+The :keyword:`!for` statement
+=============================
.. index::
- statement: for
+ ! statement: for
keyword: in
keyword: else
pair: target; list
pair: loop; statement
- keyword: in
- keyword: else
- pair: target; list
object: sequence
single: : (colon); compound statement
standard rules for assignments (see :ref:`assignment`), and then the suite is
executed. When the items are exhausted (which is immediately when the sequence
is empty or an iterator raises a :exc:`StopIteration` exception), the suite in
-the :keyword:`else` clause, if present, is executed, and the loop terminates.
+the :keyword:`!else` clause, if present, is executed, and the loop terminates.
.. index::
statement: break
statement: continue
A :keyword:`break` statement executed in the first suite terminates the loop
-without executing the :keyword:`else` clause's suite. A :keyword:`continue`
+without executing the :keyword:`!else` clause's suite. A :keyword:`continue`
statement executed in the first suite skips the rest of the suite and continues
-with the next item, or with the :keyword:`else` clause if there is no next
+with the next item, or with the :keyword:`!else` clause if there is no next
item.
The for-loop makes assignments to the variables(s) in the target list.
.. _except:
.. _finally:
-The :keyword:`try` statement
-============================
+The :keyword:`!try` statement
+=============================
.. index::
- statement: try
+ ! statement: try
keyword: except
keyword: finally
keyword: else
The :keyword:`except` clause(s) specify one or more exception handlers. When no
exception occurs in the :keyword:`try` clause, no exception handler is executed.
-When an exception occurs in the :keyword:`try` suite, a search for an exception
+When an exception occurs in the :keyword:`!try` suite, a search for an exception
handler is started. This search inspects the except clauses in turn until one
is found that matches the exception. An expression-less except clause, if
present, must be last; it matches any exception. For an except clause with an
.. index:: single: as; except clause
When a matching except clause is found, the exception is assigned to the target
-specified after the :keyword:`as` keyword in that except clause, if present, and
+specified after the :keyword:`!as` keyword in that except clause, if present, and
the except clause's suite is executed. All except clauses must have an
executable block. When the end of this block is reached, execution continues
normally after the entire try statement. (This means that if two nested
statement: break
statement: continue
-The optional :keyword:`else` clause is executed if the control flow leaves the
+The optional :keyword:`!else` clause is executed if the control flow leaves the
:keyword:`try` suite, no exception was raised, and no :keyword:`return`,
:keyword:`continue`, or :keyword:`break` statement was executed. Exceptions in
-the :keyword:`else` clause are not handled by the preceding :keyword:`except`
+the :keyword:`!else` clause are not handled by the preceding :keyword:`except`
clauses.
.. index:: keyword: finally
If :keyword:`finally` is present, it specifies a 'cleanup' handler. The
:keyword:`try` clause is executed, including any :keyword:`except` and
-:keyword:`else` clauses. If an exception occurs in any of the clauses and is
-not handled, the exception is temporarily saved. The :keyword:`finally` clause
+:keyword:`!else` clauses. If an exception occurs in any of the clauses and is
+not handled, the exception is temporarily saved. The :keyword:`!finally` clause
is executed. If there is a saved exception it is re-raised at the end of the
-:keyword:`finally` clause. If the :keyword:`finally` clause raises another
+:keyword:`!finally` clause. If the :keyword:`!finally` clause raises another
exception, the saved exception is set as the context of the new exception.
-If the :keyword:`finally` clause executes a :keyword:`return` or :keyword:`break`
+If the :keyword:`!finally` clause executes a :keyword:`return` or :keyword:`break`
statement, the saved exception is discarded::
>>> def f():
statement: continue
When a :keyword:`return`, :keyword:`break` or :keyword:`continue` statement is
-executed in the :keyword:`try` suite of a :keyword:`try`...\ :keyword:`finally`
+executed in the :keyword:`try` suite of a :keyword:`!try`...\ :keyword:`!finally`
statement, the :keyword:`finally` clause is also executed 'on the way out.' A
-:keyword:`continue` statement is illegal in the :keyword:`finally` clause. (The
+:keyword:`continue` statement is illegal in the :keyword:`!finally` clause. (The
reason is a problem with the current implementation --- this restriction may be
lifted in the future).
The return value of a function is determined by the last :keyword:`return`
statement executed. Since the :keyword:`finally` clause always executes, a
-:keyword:`return` statement executed in the :keyword:`finally` clause will
+:keyword:`!return` statement executed in the :keyword:`!finally` clause will
always be the last one executed::
>>> def foo():
.. _with:
.. _as:
-The :keyword:`with` statement
-=============================
+The :keyword:`!with` statement
+==============================
.. index::
- statement: with
+ ! statement: with
keyword: as
single: as; with statement
single: , (comma); with statement
single: ->; function annotations
single: : (colon); function annotations
-Parameters may have annotations of the form "``: expression``" following the
-parameter name. Any parameter may have an annotation even those of the form
+Parameters may have an :term:`annotation <function annotation>` of the form "``: expression``"
+following the parameter name. Any parameter may have an annotation, even those of the form
``*identifier`` or ``**identifier``. Functions may have "return" annotation of
the form "``-> expression``" after the parameter list. These annotations can be
any valid Python expression. The presence of annotations does not change the
section :ref:`lambda`. Note that the lambda expression is merely a shorthand for a
simplified function definition; a function defined in a ":keyword:`def`"
statement can be passed around or assigned to another name just like a function
-defined by a lambda expression. The ":keyword:`def`" form is actually more powerful
+defined by a lambda expression. The ":keyword:`!def`" form is actually more powerful
since it allows the execution of multiple statements and annotations.
**Programmer's note:** Functions are first-class objects. A "``def``" statement
.. index:: statement: async for
.. _`async for`:
-The :keyword:`async for` statement
-----------------------------------
+The :keyword:`!async for` statement
+-----------------------------------
.. productionlist::
async_for_stmt: "async" `for_stmt`
.. index:: statement: async with
.. _`async with`:
-The :keyword:`async with` statement
------------------------------------
+The :keyword:`!async with` statement
+------------------------------------
.. productionlist::
async_with_stmt: "async" `with_stmt`
called, always returns an iterator object which can be used to execute the
body of the function: calling the iterator's :meth:`iterator.__next__`
method will cause the function to execute until it provides a value
- using the :keyword:`yield` statement. When the function executes a
+ using the :keyword:`!yield` statement. When the function executes a
:keyword:`return` statement or falls off the end, a :exc:`StopIteration`
exception is raised and the iterator will have reached the end of the set of
values to be returned.
Modules are a basic organizational unit of Python code, and are created by
the :ref:`import system <importsystem>` as invoked either by the
- :keyword:`import` statement (see :keyword:`import`), or by calling
+ :keyword:`import` statement, or by calling
functions such as :func:`importlib.import_module` and built-in
:func:`__import__`. A module object has a namespace implemented by a
dictionary object (this is the dictionary referenced by the ``__globals__``
(unless explicitly declared in *__slots__* or available in a parent.)
The space saved over using *__dict__* can be significant.
+Attribute lookup speed can be significantly improved as well.
.. data:: object.__slots__
established when executing a :keyword:`with` statement. The context manager
handles the entry into, and the exit from, the desired runtime context for the
execution of the block of code. Context managers are normally invoked using the
-:keyword:`with` statement (described in section :ref:`with`), but can also be
+:keyword:`!with` statement (described in section :ref:`with`), but can also be
used by directly invoking their methods.
.. index::
Enter the runtime context related to this object. The :keyword:`with` statement
will bind this method's return value to the target(s) specified in the
- :keyword:`as` clause of the statement, if any.
+ :keyword:`!as` clause of the statement, if any.
.. method:: object.__exit__(self, exc_type, exc_value, traceback)
:keyword:`import` statements, class and function definitions (these bind the
class or function name in the defining block), and targets that are identifiers
if occurring in an assignment, :keyword:`for` loop header, or after
-:keyword:`as` in a :keyword:`with` statement or :keyword:`except` clause.
-The :keyword:`import` statement
+:keyword:`!as` in a :keyword:`with` statement or :keyword:`except` clause.
+The :keyword:`!import` statement
of the form ``from ... import *`` binds all names defined in the imported
module, except those beginning with an underscore. This form may only be used
at the module level.
global namespace, i.e. the namespace of the module containing the code block,
and the builtins namespace, the namespace of the module :mod:`builtins`. The
global namespace is searched first. If the name is not found there, the
-builtins namespace is searched. The :keyword:`global` statement must precede
+builtins namespace is searched. The :keyword:`!global` statement must precede
all uses of the name.
The :keyword:`global` statement has the same scope as a name binding operation
comp_if: "if" `expression_nocond` [`comp_iter`]
The comprehension consists of a single expression followed by at least one
-:keyword:`for` clause and zero or more :keyword:`for` or :keyword:`if` clauses.
+:keyword:`!for` clause and zero or more :keyword:`!for` or :keyword:`!if` clauses.
In this case, the elements of the new container are those that would be produced
-by considering each of the :keyword:`for` or :keyword:`if` clauses a block,
+by considering each of the :keyword:`!for` or :keyword:`!if` clauses a block,
nesting from left to right, and evaluating the expression to produce an element
each time the innermost block is reached.
-However, aside from the iterable expression in the leftmost :keyword:`for` clause,
+However, aside from the iterable expression in the leftmost :keyword:`!for` clause,
the comprehension is executed in a separate implicitly nested scope. This ensures
that names assigned to in the target list don't "leak" into the enclosing scope.
-The iterable expression in the leftmost :keyword:`for` clause is evaluated
+The iterable expression in the leftmost :keyword:`!for` clause is evaluated
directly in the enclosing scope and then passed as an argument to the implictly
-nested scope. Subsequent :keyword:`for` clauses and any filter condition in the
-leftmost :keyword:`for` clause cannot be evaluated in the enclosing scope as
+nested scope. Subsequent :keyword:`!for` clauses and any filter condition in the
+leftmost :keyword:`!for` clause cannot be evaluated in the enclosing scope as
they may depend on the values obtained from the leftmost iterable. For example:
``[x*y for x in range(10) for y in range(x, x+10)]``.
.. index::
single: await; in comprehensions
-Since Python 3.6, in an :keyword:`async def` function, an :keyword:`async for`
+Since Python 3.6, in an :keyword:`async def` function, an :keyword:`!async for`
clause may be used to iterate over a :term:`asynchronous iterator`.
-A comprehension in an :keyword:`async def` function may consist of either a
-:keyword:`for` or :keyword:`async for` clause following the leading
-expression, may contain additional :keyword:`for` or :keyword:`async for`
+A comprehension in an :keyword:`!async def` function may consist of either a
+:keyword:`!for` or :keyword:`!async for` clause following the leading
+expression, may contain additional :keyword:`!for` or :keyword:`!async for`
clauses, and may also use :keyword:`await` expressions.
-If a comprehension contains either :keyword:`async for` clauses
-or :keyword:`await` expressions it is called an
+If a comprehension contains either :keyword:`!async for` clauses
+or :keyword:`!await` expressions it is called an
:dfn:`asynchronous comprehension`. An asynchronous comprehension may
suspend the execution of the coroutine function in which it appears.
See also :pep:`530`.
Variables used in the generator expression are evaluated lazily when the
:meth:`~generator.__next__` method is called for the generator object (in the same
fashion as normal generators). However, the iterable expression in the
-leftmost :keyword:`for` clause is immediately evaluated, so that an error
+leftmost :keyword:`!for` clause is immediately evaluated, so that an error
produced by it will be emitted at the point where the generator expression
is defined, rather than at the point where the first value is retrieved.
-Subsequent :keyword:`for` clauses and any filter condition in the leftmost
-:keyword:`for` clause cannot be evaluated in the enclosing scope as they may
+Subsequent :keyword:`!for` clauses and any filter condition in the leftmost
+:keyword:`!for` clause cannot be evaluated in the enclosing scope as they may
depend on the values obtained from the leftmost iterable. For example:
``(x*y for x in range(10) for y in range(x, x+10))``.
:exc:`DeprecationWarning` when compiled, in Python 3.8+ they will emit
:exc:`SyntaxError`).
-If a generator expression contains either :keyword:`async for`
+If a generator expression contains either :keyword:`!async for`
clauses or :keyword:`await` expressions it is called an
:dfn:`asynchronous generator expression`. An asynchronous generator
expression returns a new asynchronous generator object,
In an asynchronous generator function, yield expressions are allowed anywhere
in a :keyword:`try` construct. However, if an asynchronous generator is not
resumed before it is finalized (by reaching a zero reference count or by
-being garbage collected), then a yield expression within a :keyword:`try`
+being garbage collected), then a yield expression within a :keyword:`!try`
construct could result in a failure to execute pending :keyword:`finally`
clauses. In this case, it is the responsibility of the event loop or
scheduler running the asynchronous generator to call the asynchronous
generator-iterator's :meth:`~agen.aclose` method and run the resulting
-coroutine object, thus allowing any pending :keyword:`finally` clauses
+coroutine object, thus allowing any pending :keyword:`!finally` clauses
to execute.
To take care of finalization, an event loop should define
The operators :keyword:`in` and :keyword:`not in` test for membership. ``x in
s`` evaluates to ``True`` if *x* is a member of *s*, and ``False`` otherwise.
``x not in s`` returns the negation of ``x in s``. All built-in sequences and
-set types support this as well as dictionary, for which :keyword:`in` tests
+set types support this as well as dictionary, for which :keyword:`!in` tests
whether the dictionary has a given key. For container types such as list, tuple,
set, frozenset, dict, or collections.deque, the expression ``x in y`` is equivalent
to ``any(x is e or x == e for e in y)``.
(for example, ``not 'foo'`` produces ``False`` rather than ``''``.)
+.. _if_expr:
+
Conditional expressions
=======================
+===============================================+=====================================+
| :keyword:`lambda` | Lambda expression |
+-----------------------------------------------+-------------------------------------+
-| :keyword:`if` -- :keyword:`else` | Conditional expression |
+| :keyword:`if <if_expr>` -- :keyword:`!else` | Conditional expression |
+-----------------------------------------------+-------------------------------------+
| :keyword:`or` | Boolean OR |
+-----------------------------------------------+-------------------------------------+
The :keyword:`import` statement combines two operations; it searches for the
named module, then it binds the results of that search to a name in the local
-scope. The search operation of the :keyword:`import` statement is defined as
+scope. The search operation of the :keyword:`!import` statement is defined as
a call to the :func:`__import__` function, with the appropriate arguments.
The return value of :func:`__import__` is used to perform the name
-binding operation of the :keyword:`import` statement. See the
-:keyword:`import` statement for the exact details of that name binding
+binding operation of the :keyword:`!import` statement. See the
+:keyword:`!import` statement for the exact details of that name binding
operation.
A direct call to :func:`__import__` performs only the module search and, if
single: statement; assignment, annotated
single: : (colon); annotated variable
-Annotation assignment is the combination, in a single statement,
-of a variable or attribute annotation and an optional assignment statement:
+:term:`Annotation <variable annotation>` assignment is the combination, in a single
+statement, of a variable or attribute annotation and an optional assignment statement:
.. productionlist::
annotated_assignment_stmt: `augtarget` ":" `expression` ["=" `expression`]
.. _assert:
-The :keyword:`assert` statement
-===============================
+The :keyword:`!assert` statement
+================================
.. index::
- statement: assert
+ ! statement: assert
pair: debugging; assertions
single: , (comma); expression list
.. _pass:
-The :keyword:`pass` statement
-=============================
+The :keyword:`!pass` statement
+==============================
.. index::
statement: pass
.. _del:
-The :keyword:`del` statement
-============================
+The :keyword:`!del` statement
+=============================
.. index::
- statement: del
+ ! statement: del
pair: deletion; target
triple: deletion; target; list
.. _return:
-The :keyword:`return` statement
-===============================
+The :keyword:`!return` statement
+================================
.. index::
- statement: return
+ ! statement: return
pair: function; definition
pair: class; definition
.. index:: keyword: finally
When :keyword:`return` passes control out of a :keyword:`try` statement with a
-:keyword:`finally` clause, that :keyword:`finally` clause is executed before
+:keyword:`finally` clause, that :keyword:`!finally` clause is executed before
really leaving the function.
In a generator function, the :keyword:`return` statement indicates that the
In an asynchronous generator function, an empty :keyword:`return` statement
indicates that the asynchronous generator is done and will cause
-:exc:`StopAsyncIteration` to be raised. A non-empty :keyword:`return`
+:exc:`StopAsyncIteration` to be raised. A non-empty :keyword:`!return`
statement is a syntax error in an asynchronous generator function.
.. _yield:
-The :keyword:`yield` statement
-==============================
+The :keyword:`!yield` statement
+===============================
.. index::
statement: yield
.. _raise:
-The :keyword:`raise` statement
-==============================
+The :keyword:`!raise` statement
+===============================
.. index::
- statement: raise
+ ! statement: raise
single: exception
pair: raising; exception
single: __traceback__ (exception attribute)
.. _break:
-The :keyword:`break` statement
-==============================
+The :keyword:`!break` statement
+===============================
.. index::
- statement: break
+ ! statement: break
statement: for
statement: while
pair: loop; statement
.. index:: keyword: else
pair: loop control; target
-It terminates the nearest enclosing loop, skipping the optional :keyword:`else`
+It terminates the nearest enclosing loop, skipping the optional :keyword:`!else`
clause if the loop has one.
If a :keyword:`for` loop is terminated by :keyword:`break`, the loop control
.. index:: keyword: finally
When :keyword:`break` passes control out of a :keyword:`try` statement with a
-:keyword:`finally` clause, that :keyword:`finally` clause is executed before
+:keyword:`finally` clause, that :keyword:`!finally` clause is executed before
really leaving the loop.
.. _continue:
-The :keyword:`continue` statement
-=================================
+The :keyword:`!continue` statement
+==================================
.. index::
- statement: continue
+ ! statement: continue
statement: for
statement: while
pair: loop; statement
cycle of the nearest enclosing loop.
When :keyword:`continue` passes control out of a :keyword:`try` statement with a
-:keyword:`finally` clause, that :keyword:`finally` clause is executed before
+:keyword:`finally` clause, that :keyword:`!finally` clause is executed before
really starting the next loop cycle.
.. _import:
.. _from:
-The :keyword:`import` statement
-===============================
+The :keyword:`!import` statement
+================================
.. index::
- statement: import
+ ! statement: import
single: module; importing
pair: name; binding
keyword: from
.. index:: single: as; import statement
-* If the module name is followed by :keyword:`as`, then the name
- following :keyword:`as` is bound directly to the imported module.
+* If the module name is followed by :keyword:`!as`, then the name
+ following :keyword:`!as` is bound directly to the imported module.
* If no other name is specified, and the module being imported is a top
level module, the module's name is bound in the local namespace as a
reference to the imported module
check the imported module again for that attribute
#. if the attribute is not found, :exc:`ImportError` is raised.
#. otherwise, a reference to that value is stored in the local namespace,
- using the name in the :keyword:`as` clause if it is present,
+ using the name in the :keyword:`!as` clause if it is present,
otherwise using the attribute name
Examples::
.. _global:
-The :keyword:`global` statement
-===============================
+The :keyword:`!global` statement
+================================
.. index::
- statement: global
+ ! statement: global
triple: global; name; binding
single: , (comma); identifier list
The :keyword:`global` statement is a declaration which holds for the entire
current code block. It means that the listed identifiers are to be interpreted
as globals. It would be impossible to assign to a global variable without
-:keyword:`global`, although free variables may refer to globals without being
+:keyword:`!global`, although free variables may refer to globals without being
declared global.
Names listed in a :keyword:`global` statement must not be used in the same code
-block textually preceding that :keyword:`global` statement.
+block textually preceding that :keyword:`!global` statement.
Names listed in a :keyword:`global` statement must not be defined as formal
parameters or in a :keyword:`for` loop control target, :keyword:`class`
builtin: compile
**Programmer's note:** :keyword:`global` is a directive to the parser. It
-applies only to code parsed at the same time as the :keyword:`global` statement.
-In particular, a :keyword:`global` statement contained in a string or code
+applies only to code parsed at the same time as the :keyword:`!global` statement.
+In particular, a :keyword:`!global` statement contained in a string or code
object supplied to the built-in :func:`exec` function does not affect the code
block *containing* the function call, and code contained in such a string is
-unaffected by :keyword:`global` statements in the code containing the function
+unaffected by :keyword:`!global` statements in the code containing the function
call. The same applies to the :func:`eval` and :func:`compile` functions.
.. _nonlocal:
-The :keyword:`nonlocal` statement
-=================================
+The :keyword:`!nonlocal` statement
+==================================
.. index:: statement: nonlocal
single: , (comma); identifier list
entry = self.get(name)
if not entry:
continue
- elif entry.result_type not in ("PyObject*", "PyVarObject*"):
+ elif not entry.result_type.endswith("Object*"):
continue
if entry.result_refs is None:
rc = 'Return value: Always NULL.'
<ul>
<li><a href="https://docs.python.org/3.8/">{% trans %}Python 3.8 (in development){% endtrans %}</a></li>
<li><a href="https://docs.python.org/3.7/">{% trans %}Python 3.7 (stable){% endtrans %}</a></li>
- <li><a href="https://docs.python.org/3.6/">{% trans %}Python 3.6 (stable){% endtrans %}</a></li>
+ <li><a href="https://docs.python.org/3.6/">{% trans %}Python 3.6 (security-fixes){% endtrans %}</a></li>
<li><a href="https://docs.python.org/3.5/">{% trans %}Python 3.5 (security-fixes){% endtrans %}</a></li>
<li><a href="https://docs.python.org/2.7/">{% trans %}Python 2.7 (stable){% endtrans %}</a></li>
<li><a href="https://www.python.org/doc/versions/">{% trans %}All versions{% endtrans %}</a></li>
object that defines the method :meth:`~iterator.__next__` which accesses
elements in the container one at a time. When there are no more elements,
:meth:`~iterator.__next__` raises a :exc:`StopIteration` exception which tells the
-:keyword:`for` loop to terminate. You can call the :meth:`~iterator.__next__` method
+:keyword:`!for` loop to terminate. You can call the :meth:`~iterator.__next__` method
using the :func:`next` built-in function; this example shows how it all works::
>>> s = 'abc'
.. _tut-if:
-:keyword:`if` Statements
-========================
+:keyword:`!if` Statements
+=========================
Perhaps the most well-known statement type is the :keyword:`if` statement. For
example::
More
There can be zero or more :keyword:`elif` parts, and the :keyword:`else` part is
-optional. The keyword ':keyword:`elif`' is short for 'else if', and is useful
-to avoid excessive indentation. An :keyword:`if` ... :keyword:`elif` ...
-:keyword:`elif` ... sequence is a substitute for the ``switch`` or
+optional. The keyword ':keyword:`!elif`' is short for 'else if', and is useful
+to avoid excessive indentation. An :keyword:`!if` ... :keyword:`!elif` ...
+:keyword:`!elif` ... sequence is a substitute for the ``switch`` or
``case`` statements found in other languages.
.. _tut-for:
-:keyword:`for` Statements
-=========================
+:keyword:`!for` Statements
+==========================
.. index::
statement: for
The :keyword:`for` statement in Python differs a bit from what you may be used
to in C or Pascal. Rather than always iterating over an arithmetic progression
of numbers (like in Pascal), or giving the user the ability to define both the
-iteration step and halting condition (as C), Python's :keyword:`for` statement
+iteration step and halting condition (as C), Python's :keyword:`!for` statement
iterates over the items of any sequence (a list or a string), in the order that
they appear in the sequence. For example (no pun intended):
.. _tut-break:
-:keyword:`break` and :keyword:`continue` Statements, and :keyword:`else` Clauses on Loops
-=========================================================================================
+:keyword:`!break` and :keyword:`!continue` Statements, and :keyword:`!else` Clauses on Loops
+============================================================================================
The :keyword:`break` statement, like in C, breaks out of the innermost enclosing
:keyword:`for` or :keyword:`while` loop.
-Loop statements may have an ``else`` clause; it is executed when the loop
+Loop statements may have an :keyword:`!else` clause; it is executed when the loop
terminates through exhaustion of the list (with :keyword:`for`) or when the
condition becomes false (with :keyword:`while`), but not when the loop is
terminated by a :keyword:`break` statement. This is exemplified by the
When used with a loop, the ``else`` clause has more in common with the
``else`` clause of a :keyword:`try` statement than it does that of
-:keyword:`if` statements: a :keyword:`try` statement's ``else`` clause runs
+:keyword:`if` statements: a :keyword:`!try` statement's ``else`` clause runs
when no exception occurs, and a loop's ``else`` clause runs when no ``break``
-occurs. For more on the :keyword:`try` statement and exceptions, see
+occurs. For more on the :keyword:`!try` statement and exceptions, see
:ref:`tut-handling`.
The :keyword:`continue` statement, also borrowed from C, continues with the next
.. _tut-pass:
-:keyword:`pass` Statements
-==========================
+:keyword:`!pass` Statements
+===========================
The :keyword:`pass` statement does nothing. It can be used when a statement is
required syntactically but the program requires no action. For example::
Another place :keyword:`pass` can be used is as a place-holder for a function or
conditional body when you are working on new code, allowing you to keep thinking
-at a more abstract level. The :keyword:`pass` is silently ignored::
+at a more abstract level. The :keyword:`!pass` is silently ignored::
>>> def initlog(*args):
... pass # Remember to implement this!
This example, as usual, demonstrates some new Python features:
* The :keyword:`return` statement returns with a value from a function.
- :keyword:`return` without an expression argument returns ``None``. Falling off
+ :keyword:`!return` without an expression argument returns ``None``. Falling off
the end of a function also returns ``None``.
* The statement ``result.append(a)`` calls a *method* of the list object
information about the types used by user-defined functions (see :pep:`3107` and
:pep:`484` for more information).
-Annotations are stored in the :attr:`__annotations__` attribute of the function
-as a dictionary and have no effect on any other part of the function. Parameter
-annotations are defined by a colon after the parameter name, followed by an
-expression evaluating to the value of the annotation. Return annotations are
+:term:`Annotations <function annotation>` are stored in the :attr:`__annotations__`
+attribute of the function as a dictionary and have no effect on any other part of the
+function. Parameter annotations are defined by a colon after the parameter name, followed
+by an expression evaluating to the value of the annotation. Return annotations are
defined by a literal ``->``, followed by an expression, between the parameter
list and the colon denoting the end of the :keyword:`def` statement. The
following example has a positional argument, a keyword argument, and the return
which is more concise and readable.
A list comprehension consists of brackets containing an expression followed
-by a :keyword:`for` clause, then zero or more :keyword:`for` or :keyword:`if`
+by a :keyword:`!for` clause, then zero or more :keyword:`!for` or :keyword:`!if`
clauses. The result will be a new list resulting from evaluating the expression
-in the context of the :keyword:`for` and :keyword:`if` clauses which follow it.
+in the context of the :keyword:`!for` and :keyword:`!if` clauses which follow it.
For example, this listcomp combines the elements of two lists if they are not
equal::
.. _tut-del:
-The :keyword:`del` statement
-============================
+The :keyword:`!del` statement
+=============================
There is a way to remove an item from a list given its index instead of its
value: the :keyword:`del` statement. This differs from the :meth:`pop` method
-which returns a value. The :keyword:`del` statement can also be used to remove
+which returns a value. The :keyword:`!del` statement can also be used to remove
slices from a list or clear the entire list (which we did earlier by assignment
of an empty list to the slice). For example::
A :keyword:`try` statement may have more than one except clause, to specify
handlers for different exceptions. At most one handler will be executed.
Handlers only handle exceptions that occur in the corresponding try clause, not
-in other handlers of the same :keyword:`try` statement. An except clause may
+in other handlers of the same :keyword:`!try` statement. An except clause may
name multiple exceptions as a parenthesized tuple, for example::
... except (RuntimeError, TypeError, NameError):
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
-The use of the :keyword:`else` clause is better than adding additional code to
+The use of the :keyword:`!else` clause is better than adding additional code to
the :keyword:`try` clause because it avoids accidentally catching an exception
-that wasn't raised by the code being protected by the :keyword:`try` ...
-:keyword:`except` statement.
+that wasn't raised by the code being protected by the :keyword:`!try` ...
+:keyword:`!except` statement.
When an exception occurs, it may have an associated value, also known as the
exception's *argument*. The presence and type of the argument depend on the
A *finally clause* is always executed before leaving the :keyword:`try`
statement, whether an exception has occurred or not. When an exception has
-occurred in the :keyword:`try` clause and has not been handled by an
-:keyword:`except` clause (or it has occurred in an :keyword:`except` or
-:keyword:`else` clause), it is re-raised after the :keyword:`finally` clause has
-been executed. The :keyword:`finally` clause is also executed "on the way out"
-when any other clause of the :keyword:`try` statement is left via a
+occurred in the :keyword:`!try` clause and has not been handled by an
+:keyword:`except` clause (or it has occurred in an :keyword:`!except` or
+:keyword:`!else` clause), it is re-raised after the :keyword:`finally` clause has
+been executed. The :keyword:`!finally` clause is also executed "on the way out"
+when any other clause of the :keyword:`!try` statement is left via a
:keyword:`break`, :keyword:`continue` or :keyword:`return` statement. A more
complicated example::
As you can see, the :keyword:`finally` clause is executed in any event. The
:exc:`TypeError` raised by dividing two strings is not handled by the
-:keyword:`except` clause and therefore re-raised after the :keyword:`finally`
+:keyword:`except` clause and therefore re-raised after the :keyword:`!finally`
clause has been executed.
In real world applications, the :keyword:`finally` clause is useful for
It is good practice to use the :keyword:`with` keyword when dealing
with file objects. The advantage is that the file is properly closed
after its suite finishes, even if an exception is raised at some
-point. Using :keyword:`with` is also much shorter than writing
+point. Using :keyword:`!with` is also much shorter than writing
equivalent :keyword:`try`\ -\ :keyword:`finally` blocks::
>>> with open('workfile') as f:
frowned upon, since it often causes poorly readable code. However, it is okay to
use it to save typing in interactive sessions.
-If the module name is followed by :keyword:`as`, then the name
-following :keyword:`as` is bound directly to the imported module.
+If the module name is followed by :keyword:`!as`, then the name
+following :keyword:`!as` is bound directly to the imported module.
::
directories that don't exist already) and places a ``pyvenv.cfg`` file in it
with a ``home`` key pointing to the Python installation from which the command
was run. It also creates a ``bin`` (or ``Scripts`` on Windows) subdirectory
-containing a copy of the ``python`` binary (or binaries, in the case of
-Windows). It also creates an (initially empty) ``lib/pythonX.Y/site-packages``
-subdirectory (on Windows, this is ``Lib\site-packages``). If an existing
+containing a copy/symlink of the Python binary/binaries (as appropriate for the
+platform or arguments used at environment creation time). It also creates an
+(initially empty) ``lib/pythonX.Y/site-packages`` subdirectory
+(on Windows, this is ``Lib\site-packages``). If an existing
directory is specified, it will be re-used.
.. deprecated:: 3.6
The command, if run with ``-h``, will show the available options::
usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
- [--upgrade] [--without-pip]
+ [--upgrade] [--without-pip] [--prompt PROMPT]
ENV_DIR [ENV_DIR ...]
Creates virtual Python environments in one or more target directories.
of Python, assuming Python has been upgraded in-place.
--without-pip Skips installing or upgrading pip in the virtual
environment (pip is bootstrapped by default)
+ --prompt PROMPT Provides an alternative prompt prefix for this
+ environment.
Once an environment has been created, you may wish to activate it, e.g. by
sourcing an activate script in its bin directory.
In earlier versions, if the target directory already existed, an error was
raised, unless the ``--clear`` or ``--upgrade`` option was provided.
+.. note::
+ While symlinks are supported on Windows, they are not recommended. Of
+ particular note is that double-clicking ``python.exe`` in File Explorer
+ will resolve the symlink eagerly and ignore the virtual environment.
+
The created ``pyvenv.cfg`` file also includes the
``include-system-site-packages`` key, set to ``true`` if ``venv`` is
run with the ``--system-site-packages`` option, ``false`` otherwise.
L)
Because of Python's scoping rules, a default argument is used so that the
-anonymous function created by the :keyword:`lambda` statement knows what
+anonymous function created by the :keyword:`lambda` expression knows what
substring is being searched for. List comprehensions make this cleaner::
sublist = [ s for s in L if string.find(s, S) != -1 ]
for exprN in sequenceN
if condition ]
-The :keyword:`for`...\ :keyword:`in` clauses contain the sequences to be
+The :keyword:`!for`...\ :keyword:`!in` clauses contain the sequences to be
iterated over. The sequences do not have to be the same length, because they
are *not* iterated over in parallel, but from left to right; this is explained
more clearly in the following paragraphs. The elements of the generated list
-will be the successive values of *expression*. The final :keyword:`if` clause
+will be the successive values of *expression*. The final :keyword:`!if` clause
is optional; if present, *expression* is only evaluated and added to the result
if *condition* is true.
# the expression to the
# resulting list.
-This means that when there are multiple :keyword:`for`...\ :keyword:`in`
+This means that when there are multiple :keyword:`!for`...\ :keyword:`!in`
clauses, the resulting list will be equal to the product of the lengths of all
the sequences. If you have two lists of length 3, the output list is 9 elements
long::
trying every index of the sequence until either *obj* is found or an
:exc:`IndexError` is encountered. Moshe Zadka contributed a patch which adds a
:meth:`__contains__` magic method for providing a custom implementation for
-:keyword:`in`. Additionally, new built-in objects written in C can define what
-:keyword:`in` means for them via a new slot in the sequence protocol.
+:keyword:`!in`. Additionally, new built-in objects written in C can define what
+:keyword:`!in` means for them via a new slot in the sequence protocol.
Earlier versions of Python used a recursive algorithm for deleting objects.
Deeply nested data structures could cause the interpreter to fill up the C stack
the binding of the name ``g`` isn't in either its local namespace or in the
module-level namespace. This isn't much of a problem in practice (how often do
you recursively define interior functions like this?), but this also made using
-the :keyword:`lambda` statement clumsier, and this was a problem in practice.
+the :keyword:`lambda` expression clumsier, and this was a problem in practice.
In code which uses :keyword:`lambda` you can often find local variables being
copied by passing them as the default values of arguments. ::
While it looks like a normal :keyword:`import` statement, it's not; there are
strict rules on where such a future statement can be put. They can only be at
the top of a module, and must precede any Python code or regular
-:keyword:`import` statements. This is because such statements can affect how
+:keyword:`!import` statements. This is because such statements can affect how
the Python bytecode compiler parses code and generates bytecode, so they must
precede any statement that will result in bytecodes being produced.
This means that :keyword:`class` statements that don't have any base classes are
always classic classes in Python 2.2. (Actually you can also change this by
setting a module-level variable named :attr:`__metaclass__` --- see :pep:`253`
-for the details --- but it's easier to just subclass :keyword:`object`.)
+for the details --- but it's easier to just subclass :class:`object`.)
The type objects for the built-in types are available as built-ins, named using
a clever trick. Python has always had built-in functions named :func:`int`,
yield i
A new keyword, :keyword:`yield`, was introduced for generators. Any function
-containing a :keyword:`yield` statement is a generator function; this is
+containing a :keyword:`!yield` statement is a generator function; this is
detected by Python's bytecode compiler which compiles the function specially as
a result. Because a new keyword was introduced, generators must be explicitly
enabled in a module by including a ``from __future__ import generators``
returns a generator object that supports the iterator protocol. On executing
the :keyword:`yield` statement, the generator outputs the value of ``i``,
similar to a :keyword:`return` statement. The big difference between
-:keyword:`yield` and a :keyword:`return` statement is that on reaching a
-:keyword:`yield` the generator's state of execution is suspended and local
+:keyword:`!yield` and a :keyword:`!return` statement is that on reaching a
+:keyword:`!yield` the generator's state of execution is suspended and local
variables are preserved. On the next call to the generator's ``next()`` method,
-the function will resume executing immediately after the :keyword:`yield`
-statement. (For complicated reasons, the :keyword:`yield` statement isn't
-allowed inside the :keyword:`try` block of a
+the function will resume executing immediately after the :keyword:`!yield`
+statement. (For complicated reasons, the :keyword:`!yield` statement isn't
+allowed inside the :keyword:`!try` block of a
:keyword:`try`...\ :keyword:`finally` statement; read :pep:`255` for a full
-explanation of the interaction between :keyword:`yield` and exceptions.)
+explanation of the interaction between :keyword:`!yield` and exceptions.)
Here's a sample usage of the :func:`generate_ints` generator::
Inside a generator function, the :keyword:`return` statement can only be used
without a value, and signals the end of the procession of values; afterwards the
-generator cannot return any further values. :keyword:`return` with a value, such
+generator cannot return any further values. :keyword:`!return` with a value, such
as ``return 5``, is a syntax error inside a generator function. The end of the
generator's results can also be indicated by raising :exc:`StopIteration`
manually, or by just letting the flow of execution fall off the bottom of the
the binding of the name ``g`` isn't in either its local namespace or in the
module-level namespace. This isn't much of a problem in practice (how often do
you recursively define interior functions like this?), but this also made using
-the :keyword:`lambda` statement clumsier, and this was a problem in practice.
-In code which uses :keyword:`lambda` you can often find local variables being
+the :keyword:`lambda` expression clumsier, and this was a problem in practice.
+In code which uses :keyword:`!lambda` you can often find local variables being
copied by passing them as the default values of arguments. ::
def find(self, name):
yield i
A new keyword, :keyword:`yield`, was introduced for generators. Any function
-containing a :keyword:`yield` statement is a generator function; this is
+containing a :keyword:`!yield` statement is a generator function; this is
detected by Python's bytecode compiler which compiles the function specially as
a result.
returns a generator object that supports the iterator protocol. On executing
the :keyword:`yield` statement, the generator outputs the value of ``i``,
similar to a :keyword:`return` statement. The big difference between
-:keyword:`yield` and a :keyword:`return` statement is that on reaching a
-:keyword:`yield` the generator's state of execution is suspended and local
+:keyword:`!yield` and a :keyword:`!return` statement is that on reaching a
+:keyword:`!yield` the generator's state of execution is suspended and local
variables are preserved. On the next call to the generator's ``.next()``
method, the function will resume executing immediately after the
-:keyword:`yield` statement. (For complicated reasons, the :keyword:`yield`
+:keyword:`!yield` statement. (For complicated reasons, the :keyword:`!yield`
statement isn't allowed inside the :keyword:`try` block of a
-:keyword:`try`...\ :keyword:`finally` statement; read :pep:`255` for a full
-explanation of the interaction between :keyword:`yield` and exceptions.)
+:keyword:`!try`...\ :keyword:`!finally` statement; read :pep:`255` for a full
+explanation of the interaction between :keyword:`!yield` and exceptions.)
Here's a sample usage of the :func:`generate_ints` generator::
Inside a generator function, the :keyword:`return` statement can only be used
without a value, and signals the end of the procession of values; afterwards the
-generator cannot return any further values. :keyword:`return` with a value, such
+generator cannot return any further values. :keyword:`!return` with a value, such
as ``return 5``, is a syntax error inside a generator function. The end of the
generator's results can also be indicated by raising :exc:`StopIteration`
manually, or by just letting the flow of execution fall off the bottom of the
Booleans, and would require that the expression in an :keyword:`if` statement
always evaluate to a Boolean result. Python is not this strict and never will
be, as :pep:`285` explicitly says. This means you can still use any expression
-in an :keyword:`if` statement, even ones that evaluate to a list or tuple or
+in an :keyword:`!if` statement, even ones that evaluate to a list or tuple or
some random object. The Boolean type is a subclass of the :class:`int` class so
that arithmetic using a Boolean still works. ::
Until Python 2.5, the :keyword:`try` statement came in two flavours. You could
use a :keyword:`finally` block to ensure that code is always executed, or one or
more :keyword:`except` blocks to catch specific exceptions. You couldn't
-combine both :keyword:`except` blocks and a :keyword:`finally` block, because
+combine both :keyword:`!except` blocks and a :keyword:`!finally` block, because
generating the right bytecode for the combined version was complicated and it
wasn't clear what the semantics of the combined statement should be.
from 0 up to 9. On encountering the :keyword:`yield` statement, the iterator
returns the provided value and suspends the function's execution, preserving the
local variables. Execution resumes on the following call to the iterator's
-:meth:`next` method, picking up after the :keyword:`yield` statement.
+:meth:`next` method, picking up after the :keyword:`!yield` statement.
In Python 2.3, :keyword:`yield` was a statement; it didn't return any value. In
-2.5, :keyword:`yield` is now an expression, returning a value that can be
+2.5, :keyword:`!yield` is now an expression, returning a value that can be
assigned to a variable or otherwise operated on::
val = (yield i)
Values are sent into a generator by calling its ``send(value)`` method. The
generator's code is then resumed and the :keyword:`yield` expression returns the
specified *value*. If the regular :meth:`next` method is called, the
-:keyword:`yield` returns :const:`None`.
+:keyword:`!yield` returns :const:`None`.
Here's the previous example, modified to allow changing the value of the
internal counter. ::
------------------------
Under the hood, the ':keyword:`with`' statement is fairly complicated. Most
-people will only use ':keyword:`with`' in company with existing objects and
+people will only use ':keyword:`!with`' in company with existing objects and
don't need to know these details, so you can skip the rest of this section if
you like. Authors of new objects will need to understand the details of the
underlying implementation and should keep reading.
exactly one value. The code up to the :keyword:`yield` will be executed as the
:meth:`__enter__` method, and the value yielded will be the method's return
value that will get bound to the variable in the ':keyword:`with`' statement's
-:keyword:`as` clause, if any. The code after the :keyword:`yield` will be
+:keyword:`!as` clause, if any. The code after the :keyword:`yield` will be
executed in the :meth:`__exit__` method. Any exception raised in the block will
-be raised by the :keyword:`yield` statement.
+be raised by the :keyword:`!yield` statement.
Our database example from the previous section could be written using this
decorator as::
The :mod:`contextlib` module also has a ``nested(mgr1, mgr2, ...)`` function
that combines a number of context managers so you don't need to write nested
-':keyword:`with`' statements. In this example, the single ':keyword:`with`'
+':keyword:`with`' statements. In this example, the single ':keyword:`!with`'
statement both starts a database transaction and acquires a thread lock::
lock = threading.Lock()
The previous version, Python 2.5, added the ':keyword:`with`'
statement as an optional feature, to be enabled by a ``from __future__
import with_statement`` directive. In 2.6 the statement no longer needs to
-be specially enabled; this means that :keyword:`with` is now always a
+be specially enabled; this means that :keyword:`!with` is now always a
keyword. The rest of this section is a copy of the corresponding
section from the "What's New in Python 2.5" document; if you're
-familiar with the ':keyword:`with`' statement
+familiar with the ':keyword:`!with`' statement
from Python 2.5, you can skip this section.
The ':keyword:`with`' statement clarifies code that previously would use
------------------------
Under the hood, the ':keyword:`with`' statement is fairly complicated. Most
-people will only use ':keyword:`with`' in company with existing objects and
+people will only use ':keyword:`!with`' in company with existing objects and
don't need to know these details, so you can skip the rest of this section if
you like. Authors of new objects will need to understand the details of the
underlying implementation and should keep reading.
exactly one value. The code up to the :keyword:`yield` will be executed as the
:meth:`__enter__` method, and the value yielded will be the method's return
value that will get bound to the variable in the ':keyword:`with`' statement's
-:keyword:`as` clause, if any. The code after the :keyword:`yield` will be
+:keyword:`!as` clause, if any. The code after the :keyword:`!yield` will be
executed in the :meth:`__exit__` method. Any exception raised in the block will
-be raised by the :keyword:`yield` statement.
+be raised by the :keyword:`!yield` statement.
Using this decorator, our database example from the previous section
could be written as::
The :mod:`contextlib` module also has a ``nested(mgr1, mgr2, ...)`` function
that combines a number of context managers so you don't need to write nested
-':keyword:`with`' statements. In this example, the single ':keyword:`with`'
+':keyword:`with`' statements. In this example, the single ':keyword:`!with`'
statement both starts a database transaction and acquires a thread lock::
lock = threading.Lock()
* An obscure change: when you use the :func:`locals` function inside a
:keyword:`class` statement, the resulting dictionary no longer returns free
variables. (Free variables, in this case, are variables referenced in the
- :keyword:`class` statement that aren't attributes of the class.)
+ :keyword:`!class` statement that aren't attributes of the class.)
.. ======================================================================
* The :keyword:`with` statement can now use multiple context managers
in one statement. Context managers are processed from left to right
- and each one is treated as beginning a new :keyword:`with` statement.
+ and each one is treated as beginning a new :keyword:`!with` statement.
This means that::
with A() as a, B() as b:
* The :keyword:`import` statement will no longer try an absolute import
if a relative import (e.g. ``from .os import sep``) fails. This
- fixes a bug, but could possibly break certain :keyword:`import`
+ fixes a bug, but could possibly break certain :keyword:`!import`
statements that were only working by accident. (Fixed by Meador Inge;
:issue:`7902`.)
* Deprecated function: :func:`contextlib.nested`, which allows
handling more than one context manager with a single :keyword:`with`
- statement, has been deprecated, because the :keyword:`with` statement
+ statement, has been deprecated, because the :keyword:`!with` statement
now supports multiple context managers.
* The :mod:`cookielib` module now ignores cookies that have an invalid
* :pep:`3104`: :keyword:`nonlocal` statement. Using ``nonlocal x``
you can now assign directly to a variable in an outer (but
- non-global) scope. :keyword:`nonlocal` is a new reserved word.
+ non-global) scope. :keyword:`!nonlocal` is a new reserved word.
* :pep:`3132`: Extended Iterable Unpacking. You can now write things
like ``a, b, *rest = some_sequence``. And even ``*rest, a =
* :pep:`3109` and :pep:`3134`: new :keyword:`raise` statement syntax:
:samp:`raise [{expr} [from {expr}]]`. See below.
-* :keyword:`as` and :keyword:`with` are now reserved words. (Since
+* :keyword:`!as` and :keyword:`with` are now reserved words. (Since
2.6, actually.)
* ``True``, ``False``, and ``None`` are reserved words. (2.6 partially enforced
the restrictions on ``None`` already.)
* Change from :keyword:`except` *exc*, *var* to
- :keyword:`except` *exc* :keyword:`as` *var*. See :pep:`3110`.
+ :keyword:`!except` *exc* :keyword:`!as` *var*. See :pep:`3110`.
* :pep:`3115`: New Metaclass Syntax. Instead of::
* :ref:`pep-3105`. This is now a standard feature and no longer needs
to be imported from :mod:`__future__`. More details were given above.
-* :ref:`pep-3110`. The :keyword:`except` *exc* :keyword:`as` *var*
- syntax is now standard and :keyword:`except` *exc*, *var* is no
- longer supported. (Of course, the :keyword:`as` *var* part is still
+* :ref:`pep-3110`. The :keyword:`except` *exc* :keyword:`!as` *var*
+ syntax is now standard and :keyword:`!except` *exc*, *var* is no
+ longer supported. (Of course, the :keyword:`!as` *var* part is still
optional.)
* :ref:`pep-3112`. The ``b"..."`` string literal notation (and its
------
:class:`~shelve.Shelf` instances may now be used in :keyword:`with` statements,
-and will be automatically closed at the end of the :keyword:`with` block.
+and will be automatically closed at the end of the :keyword:`!with` block.
(Contributed by Filip Gruszczyński in :issue:`13896`.)
a :exc:`DeprecationWarning` in Python 3.6 and a :exc:`RuntimeError` in
Python 3.8.
+* With the introduction of :exc:`ModuleNotFoundError`, import system consumers
+ may start expecting import system replacements to raise that more specific
+ exception when appropriate, rather than the less-specific :exc:`ImportError`.
+ To provide future compatibility with such consumers, implementors of
+ alternative import systems that completely replace :func:`__import__` will
+ need to update their implementations to raise the new subclass when a module
+ can't be found at all. Implementors of compliant plugins to the default
+ import system shouldn't need to make any changes, as the default import
+ system will raise the new subclass when appropriate.
+
+
Changes in the C API
--------------------
Yield expressions (both ``yield`` and ``yield from`` clauses) are now deprecated
in comprehensions and generator expressions (aside from the iterable expression
-in the leftmost :keyword:`for` clause). This ensures that comprehensions
+in the leftmost :keyword:`!for` clause). This ensures that comprehensions
always immediately return a container of the appropriate type (rather than
potentially returning a :term:`generator iterator` object), while generator
expressions won't attempt to interleave their implicit output with the output
#include <unistd.h>
#endif
#ifdef HAVE_CRYPT_H
+#if defined(HAVE_CRYPT_R) && !defined(_GNU_SOURCE)
+/* Required for glibc to expose the crypt_r() function prototype. */
+# define _GNU_SOURCE
+# define _Py_GNU_SOURCE_FOR_CRYPT
+#endif
#include <crypt.h>
+#ifdef _Py_GNU_SOURCE_FOR_CRYPT
+/* Don't leak the _GNU_SOURCE define to other headers. */
+# undef _GNU_SOURCE
+# undef _Py_GNU_SOURCE_FOR_CRYPT
+#endif
#endif
/* For size_t? */
/*--start constants--*/
#define PY_MAJOR_VERSION 3
#define PY_MINOR_VERSION 7
-#define PY_MICRO_VERSION 2
+#define PY_MICRO_VERSION 3
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL
#define PY_RELEASE_SERIAL 0
/* Version as a string */
-#define PY_VERSION "3.7.2"
+#define PY_VERSION "3.7.3"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "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" are retained in Python alone or in any derivative version
+2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Python Software Foundation;
+All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
self._force_close(exc)
def _force_close(self, exc):
- if self._empty_waiter is not None:
+ if self._empty_waiter is not None and not self._empty_waiter.done():
if exc is None:
self._empty_waiter.set_result(None)
else:
f.add_done_callback(self._loop_self_reading)
def _write_to_self(self):
- self._csock.send(b'\0')
+ try:
+ self._csock.send(b'\0')
+ except OSError:
+ if self._debug:
+ logger.debug("Fail to write a null byte into the "
+ "self-pipe socket",
+ exc_info=True)
def _start_serving(self, protocol_factory, sock,
sslcontext=None, server=None, backlog=100,
import msvcrt
import socket
import struct
+import time
import weakref
from . import events
self._unregistered = []
self._stopped_serving = weakref.WeakSet()
+ def _check_closed(self):
+ if self._iocp is None:
+ raise RuntimeError('IocpProactor is closed')
+
def __repr__(self):
- return ('<%s overlapped#=%s result#=%s>'
- % (self.__class__.__name__, len(self._cache),
- len(self._results)))
+ info = ['overlapped#=%s' % len(self._cache),
+ 'result#=%s' % len(self._results)]
+ if self._iocp is None:
+ info.append('closed')
+ return '<%s %s>' % (self.__class__.__name__, " ".join(info))
def set_loop(self, loop):
self._loop = loop
return fut
def _wait_for_handle(self, handle, timeout, _is_cancel):
+ self._check_closed()
+
if timeout is None:
ms = _winapi.INFINITE
else:
# that succeed immediately.
def _register(self, ov, obj, callback):
+ self._check_closed()
+
# Return a future which will be set with the result of the
# operation when it completes. The future's value is actually
# the value returned by callback().
already be signalled (pending in the proactor event queue). It is also
safe if the event is never signalled (because it was cancelled).
"""
+ self._check_closed()
self._unregistered.append(ov)
def _get_accept_socket(self, family):
self._stopped_serving.add(obj)
def close(self):
+ if self._iocp is None:
+ # already closed
+ return
+
# Cancel remaining registered operations.
for address, (fut, ov, obj, callback) in list(self._cache.items()):
if fut.cancelled():
context['source_traceback'] = fut._source_traceback
self._loop.call_exception_handler(context)
+ # Wait until all cancelled overlapped complete: don't exit with running
+ # overlapped to prevent a crash. Display progress every second if the
+ # loop is still running.
+ msg_update = 1.0
+ start_time = time.monotonic()
+ next_msg = start_time + msg_update
while self._cache:
- if not self._poll(1):
- logger.debug('taking long time to close proactor')
+ if next_msg <= time.monotonic():
+ logger.debug('%r is running after closing for %.1f seconds',
+ self, time.monotonic() - start_time)
+ next_msg = time.monotonic() + msg_update
+
+ # handle a few events, or timeout
+ self._poll(msg_update)
self._results = []
- if self._iocp is not None:
- _winapi.CloseHandle(self._iocp)
- self._iocp = None
+
+ _winapi.CloseHandle(self._iocp)
+ self._iocp = None
def __del__(self):
self.close()
## print BUF.from_param(c_char_p("python"))
## print BUF.from_param(BUF(*"pyth"))
+ def test_del_segfault(self):
+ BUF = c_char * 4
+ buf = BUF()
+ with self.assertRaises(AttributeError):
+ del buf.raw
+
+
@need_symbol('c_wchar')
class WStringArrayTestCase(unittest.TestCase):
def test(self):
self.hash = hash
self.compare = compare
self.metadata = (_EMPTY_METADATA
- if metadata is None or len(metadata) == 0 else
+ if metadata is None else
types.MappingProxyType(metadata))
self._field_type = None
"-prerelease",
"-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
"-property", "installationPath",
+ "-products", "*",
], encoding="mbcs", errors="strict").strip()
except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):
return None, None
# Put the Python "system" include dir at the end, so that
# any local include dirs take precedence.
- self.include_dirs.append(py_include)
+ self.include_dirs.extend(py_include.split(os.path.pathsep))
if plat_py_include != py_include:
- self.include_dirs.append(plat_py_include)
+ self.include_dirs.extend(
+ plat_py_include.split(os.path.pathsep))
self.ensure_string_list('libraries')
self.ensure_string_list('link_objects')
project_base = os.path.abspath(os.environ["_PYTHON_PROJECT_BASE"])
else:
project_base = os.path.dirname(os.path.abspath(sys.executable))
-if (os.name == 'nt' and
- project_base.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
- project_base = os.path.dirname(os.path.dirname(project_base))
+
# python_build: (Boolean) if true, we're either building Python or
# building an extension with an un-installed Python, so we use
if os.path.isfile(os.path.join(d, "Modules", fn)):
return True
return False
+
_sys_home = getattr(sys, '_home', None)
-if (_sys_home and os.name == 'nt' and
- _sys_home.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
- _sys_home = os.path.dirname(os.path.dirname(_sys_home))
+
+if os.name == 'nt':
+ def _fix_pcbuild(d):
+ if d and os.path.normcase(d).startswith(
+ os.path.normcase(os.path.join(PREFIX, "PCbuild"))):
+ return PREFIX
+ return d
+ project_base = _fix_pcbuild(project_base)
+ _sys_home = _fix_pcbuild(_sys_home)
+
def _python_build():
if _sys_home:
return _is_python_source_dir(_sys_home)
return _is_python_source_dir(project_base)
+
python_build = _python_build()
+
# Calculate the build qualifier flags if they are defined. Adding the flags
# to the include and lib directories only makes sense for an installation, not
# an in-source build.
python_dir = 'python' + get_python_version() + build_flags
return os.path.join(prefix, "include", python_dir)
elif os.name == "nt":
+ if python_build:
+ # Include both the include and PC dir to ensure we can find
+ # pyconfig.h
+ return (os.path.join(prefix, "include") + os.path.pathsep +
+ os.path.join(prefix, "PC"))
return os.path.join(prefix, "include")
else:
raise DistutilsPlatformError(
cmd.finalize_options()
py_include = sysconfig.get_python_inc()
- self.assertIn(py_include, cmd.include_dirs)
+ for p in py_include.split(os.path.pathsep):
+ self.assertIn(p, cmd.include_dirs)
plat_py_include = sysconfig.get_python_inc(plat_specific=1)
- self.assertIn(plat_py_include, cmd.include_dirs)
+ for p in plat_py_include.split(os.path.pathsep):
+ self.assertIn(p, cmd.include_dirs)
# make sure cmd.libraries is turned into a list
# if it's a string
import unittest
from copy import copy
from test.support import run_unittest
+from unittest import mock
from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError
from distutils.util import (get_platform, convert_path, change_root,
def test_check_environ(self):
util._environ_checked = 0
- if 'HOME' in os.environ:
- del os.environ['HOME']
+ os.environ.pop('HOME', None)
- # posix without HOME
- if os.name == 'posix': # this test won't run on windows
- check_environ()
- import pwd
- self.assertEqual(os.environ['HOME'], pwd.getpwuid(os.getuid())[5])
- else:
- check_environ()
+ check_environ()
self.assertEqual(os.environ['PLAT'], get_platform())
self.assertEqual(util._environ_checked, 1)
+ @unittest.skipUnless(os.name == 'posix', 'specific to posix')
+ def test_check_environ_getpwuid(self):
+ util._environ_checked = 0
+ os.environ.pop('HOME', None)
+
+ import pwd
+
+ # only set pw_dir field, other fields are not used
+ result = pwd.struct_passwd((None, None, None, None, None,
+ '/home/distutils', None))
+ with mock.patch.object(pwd, 'getpwuid', return_value=result):
+ check_environ()
+ self.assertEqual(os.environ['HOME'], '/home/distutils')
+
+ util._environ_checked = 0
+ os.environ.pop('HOME', None)
+
+ # bpo-10496: Catch pwd.getpwuid() error
+ with mock.patch.object(pwd, 'getpwuid', side_effect=KeyError):
+ check_environ()
+ self.assertNotIn('HOME', os.environ)
+
def test_split_quoted(self):
self.assertEqual(split_quoted('""one"" "two" \'three\' \\four'),
['one', 'two', 'three', 'four'])
i = 1
while '=' in linker[i]:
i += 1
- linker[i] = self.compiler_cxx[i]
+
+ if os.path.basename(linker[i]) == 'ld_so_aix':
+ # AIX platforms prefix the compiler with the ld_so_aix
+ # script, so we need to adjust our linker index
+ offset = 1
+ else:
+ offset = 0
+
+ linker[i+offset] = self.compiler_cxx[i]
if sys.platform == 'darwin':
linker = _osx_support.compiler_fixup(linker, ld_args)
return
if os.name == 'posix' and 'HOME' not in os.environ:
- import pwd
- os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
+ try:
+ import pwd
+ os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
+ except (ImportError, KeyError):
+ # bpo-10496: if the current user identifier doesn't exist in the
+ # password database, do nothing
+ pass
if 'PLAT' not in os.environ:
os.environ['PLAT'] = get_platform()
kind = 'ndiff with -expected +actual'
else:
assert 0, 'Bad diff option'
- # Remove trailing whitespace on diff output.
- diff = [line.rstrip() + '\n' for line in diff]
return 'Differences (%s):\n' % kind + _indent(''.join(diff))
# If we're not using diff, then simply list the expected
__all__ = ["version", "bootstrap"]
-_SETUPTOOLS_VERSION = "40.6.2"
+_SETUPTOOLS_VERSION = "40.8.0"
-_PIP_VERSION = "18.1"
+_PIP_VERSION = "19.0.3"
_PROJECTS = [
("setuptools", _SETUPTOOLS_VERSION),
def _is_dunder(name):
"""Returns True if a __dunder__ name, False otherwise."""
- return (name[:2] == name[-2:] == '__' and
- name[2:3] != '_' and
- name[-3:-2] != '_' and
- len(name) > 4)
+ return (len(name) > 4 and
+ name[:2] == name[-2:] == '__' and
+ name[2] != '_' and
+ name[-3] != '_')
def _is_sunder(name):
"""Returns True if a _sunder_ name, False otherwise."""
- return (name[0] == name[-1] == '_' and
+ return (len(name) > 2 and
+ name[0] == name[-1] == '_' and
name[1:2] != '_' and
- name[-2:-1] != '_' and
- len(name) > 2)
+ name[-2:-1] != '_')
+
def _make_class_unpicklable(cls):
"""Make the given class un-picklable."""
_order_ = classdict.pop('_order_', None)
# check for illegal enum names (any others?)
- invalid_names = set(enum_members) & {'mro', }
+ invalid_names = set(enum_members) & {'mro', ''}
if invalid_names:
raise ValueError('Invalid enum member name: {0}'.format(
','.join(invalid_names)))
if module is None:
try:
module = sys._getframe(2).f_globals['__name__']
- except (AttributeError, ValueError) as exc:
+ except (AttributeError, ValueError, KeyError) as exc:
pass
if module is None:
_make_class_unpicklable(enum_class)
# by-value search for a matching enum member
# see if it's in the reverse mapping (for hashable values)
try:
- if value in cls._value2member_map_:
- return cls._value2member_map_[value]
+ return cls._value2member_map_[value]
+ except KeyError:
+ # Not found, no need to do long O(n) search
+ pass
except TypeError:
# not there, now do long search -- O(n) behavior
for member in cls._member_map_.values():
def _make_key(args, kwds, typed,
kwd_mark = (object(),),
- fasttypes = {int, str, frozenset, type(None)},
+ fasttypes = {int, str},
tuple=tuple, type=type, len=len):
"""Make a cache key from optionally typed positional and keyword arguments
# Early detection of an erroneous call to @lru_cache without any arguments
# resulting in the inner function being passed to maxsize instead of an
- # integer or None.
- if maxsize is not None and not isinstance(maxsize, int):
+ # integer or None. Negative maxsize is treated as 0.
+ if isinstance(maxsize, int):
+ if maxsize < 0:
+ maxsize = 0
+ elif maxsize is not None:
raise TypeError('Expected maxsize to be an integer or None')
def decorating_function(user_function):
if maxsize == 0:
def wrapper(*args, **kwds):
- # No caching -- just a statistics update after a successful call
+ # No caching -- just a statistics update
nonlocal misses
- result = user_function(*args, **kwds)
misses += 1
+ result = user_function(*args, **kwds)
return result
elif maxsize is None:
if result is not sentinel:
hits += 1
return result
+ misses += 1
result = user_function(*args, **kwds)
cache[key] = result
- misses += 1
return result
else:
link[NEXT] = root
hits += 1
return result
+ misses += 1
result = user_function(*args, **kwds)
with lock:
if key in cache:
# Use the cache_len bound method instead of the len() function
# which could potentially be wrapped in an lru_cache itself.
full = (cache_len() >= maxsize)
- misses += 1
return result
def cache_info():
req_path = request_path(request)
if ((cookie.version > 0 or
(cookie.version == 0 and self.strict_ns_set_path)) and
- not req_path.startswith(cookie.path)):
+ not self.path_return_ok(cookie.path, request)):
_debug(" path attribute %s is not a prefix of request "
"path %s", cookie.path, req_path)
return False
req_host, erhn = eff_request_host(request)
domain = cookie.domain
+ if domain and not domain.startswith("."):
+ dotdomain = "." + domain
+ else:
+ dotdomain = domain
+
# strict check of non-domain cookies: Mozilla does this, MSIE5 doesn't
if (cookie.version == 0 and
(self.strict_ns_domain & self.DomainStrictNonDomain) and
_debug(" effective request-host name %s does not domain-match "
"RFC 2965 cookie domain %s", erhn, domain)
return False
- if cookie.version == 0 and not ("."+erhn).endswith(domain):
+ if cookie.version == 0 and not ("."+erhn).endswith(dotdomain):
_debug(" request-host %s does not match Netscape cookie domain "
"%s", req_host, domain)
return False
req_host = "."+req_host
if not erhn.startswith("."):
erhn = "."+erhn
- if not (req_host.endswith(domain) or erhn.endswith(domain)):
+ if domain and not domain.startswith("."):
+ dotdomain = "." + domain
+ else:
+ dotdomain = domain
+ if not (req_host.endswith(dotdomain) or erhn.endswith(dotdomain)):
#_debug(" request domain %s does not match cookie domain %s",
# req_host, domain)
return False
def path_return_ok(self, path, request):
_debug("- checking cookie path=%s", path)
req_path = request_path(request)
- if not req_path.startswith(path):
- _debug(" %s does not path-match %s", req_path, path)
- return False
- return True
+ pathlen = len(path)
+ if req_path == path:
+ return True
+ elif (req_path.startswith(path) and
+ (path.endswith("/") or req_path[pathlen:pathlen+1] == "/")):
+ return True
+ _debug(" %s does not path-match %s", req_path, path)
+ return False
def vals_sorted_by_key(adict):
keys = sorted(adict.keys())
-What's New in IDLE 3.7.2
-Released on 2018-07-31?
+What's New in IDLE 3.7.3
+Released on 2019-??-??
======================================
+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-36096: Make colorizer state variables instance-only.
+
+bpo-24310: Document settings dialog font tab sample.
+
+bpo-35689: Add docstrings and tests for 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 new file name from 'Untitled' to 'untitled'.
+
+bpo-35660: Fix imports in window module.
+
+bpo-35641: Properly format calltip for function without docstring.
+
+bpo-33987: Use ttk Frame for ttk widgets.
+
+bpo-34055: Fix erroneous 'smart' indents and newlines in IDLE Shell.
+
+bpo-28097: Add Previous/Next History entries to Shell menu.
+
+bpo-35591: Find Selection now works when selection not found.
+
+bpo-35598: Update config_key: use PEP 8 names and ttk widgets,
+make some objects global, and add tests.
+
+bpo-35196: Speed up squeezer line counting.
+
+bpo-35208: Squeezer now counts wrapped lines before newlines.
+
+bpo-35555: Gray out Code Context menu entry when it's not applicable.
+
+bpo-22703: Improve the Code Context and Zoom Height menu labels.
+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.
+
+bpo-35521: Document the editor code context feature.
+Add some internal references within the IDLE doc.
+
+
+What's New in IDLE 3.7.2
+Released on 2018-12-21?
+======================================
+
bpo-34864: When starting IDLE on MacOS, warn if the system setting
"Prefer tabs when opening documents" is "Always". As previous
documented for this issue, running IDLE with this setting causes
import platform
from tkinter import *
-from tkinter.ttk import Scrollbar
+from tkinter.ttk import Frame, Scrollbar
from idlelib.autocomplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES
from idlelib.multicall import MC_SHIFT
pass
self.scrollbar = scrollbar = Scrollbar(acw, orient=VERTICAL)
self.listbox = listbox = Listbox(acw, yscrollcommand=scrollbar.set,
- exportselection=False, bg="white")
+ exportselection=False)
for item in self.completions:
listbox.insert(END, item)
self.origselforeground = listbox.cget("selectforeground")
if len(line) > _MAX_COLS:
line = line[: _MAX_COLS - 3] + '...'
lines.append(line)
- argspec = '\n'.join(lines)
+ argspec = '\n'.join(lines)
if not argspec:
argspec = _default_callable_argspec
return argspec
def showcontents(self):
"""Create the call-tip widget."""
self.label = Label(self.tipwindow, text=self.text, justify=LEFT,
- background="#ffffe0", relief=SOLID, borderwidth=1,
+ background="#ffffd0", foreground="black",
+ relief=SOLID, borderwidth=1,
font=self.anchor_widget['font'])
self.label.pack()
# thus ensuring that it will appear directly above text_frame.
self.context.pack(side=TOP, fill=X, expand=False,
before=self.editwin.text_frame)
+ menu_status = 'Hide'
else:
self.context.destroy()
self.context = None
+ menu_status = 'Show'
+ self.editwin.update_menu_label(menu='options', index='* Code Context',
+ label=f'{menu_status} Code Context')
return "break"
def get_context(self, new_topvisible, stopline=1, stopindent=0):
class ColorDelegator(Delegator):
+ """Delegator for syntax highlighting (text coloring).
+
+ Instance variables:
+ delegate: Delegator below this one in the stack, meaning the
+ one this one delegates to.
+
+ Used to track state:
+ after_id: Identifier for scheduled after event, which is a
+ timer for colorizing the text.
+ allow_colorizing: Boolean toggle for applying colorizing.
+ colorizing: Boolean flag when colorizing is in process.
+ stop_colorizing: Boolean flag to end an active colorizing
+ process.
+ """
def __init__(self):
Delegator.__init__(self)
+ self.init_state()
self.prog = prog
self.idprog = idprog
self.LoadTagDefs()
+ def init_state(self):
+ "Initialize variables that track colorizing state."
+ self.after_id = None
+ self.allow_colorizing = True
+ self.stop_colorizing = False
+ self.colorizing = False
+
def setdelegate(self, delegate):
+ """Set the delegate for this instance.
+
+ A delegate is an instance of a Delegator class and each
+ delegate points to the next delegator in the stack. This
+ allows multiple delegators to be chained together for a
+ widget. The bottom delegate for a colorizer is a Text
+ widget.
+
+ If there is a delegate, also start the colorizing process.
+ """
if self.delegate is not None:
self.unbind("<<toggle-auto-coloring>>")
Delegator.setdelegate(self, delegate)
self.bind("<<toggle-auto-coloring>>", self.toggle_colorize_event)
self.notify_range("1.0", "end")
else:
- # No delegate - stop any colorizing
+ # No delegate - stop any colorizing.
self.stop_colorizing = True
self.allow_colorizing = False
def config_colors(self):
+ "Configure text widget tags with colors from tagdefs."
for tag, cnf in self.tagdefs.items():
- if cnf:
- self.tag_configure(tag, **cnf)
+ self.tag_configure(tag, **cnf)
self.tag_raise('sel')
def LoadTagDefs(self):
+ "Create dictionary of tag names to text colors."
theme = idleConf.CurrentTheme()
self.tagdefs = {
"COMMENT": idleConf.GetHighlight(theme, "comment"),
if DEBUG: print('tagdefs',self.tagdefs)
def insert(self, index, chars, tags=None):
+ "Insert chars into widget at index and mark for colorizing."
index = self.index(index)
self.delegate.insert(index, chars, tags)
self.notify_range(index, index + "+%dc" % len(chars))
def delete(self, index1, index2=None):
+ "Delete chars between indexes and mark for colorizing."
index1 = self.index(index1)
self.delegate.delete(index1, index2)
self.notify_range(index1)
- after_id = None
- allow_colorizing = True
- colorizing = False
-
def notify_range(self, index1, index2=None):
+ "Mark text changes for processing and restart colorizing, if active."
self.tag_add("TODO", index1, index2)
if self.after_id:
if DEBUG: print("colorizing already scheduled")
if self.allow_colorizing:
if DEBUG: print("schedule colorizing")
self.after_id = self.after(1, self.recolorize)
+ return
- close_when_done = None # Window to be closed when done colorizing
-
- def close(self, close_when_done=None):
+ def close(self):
if self.after_id:
after_id = self.after_id
self.after_id = None
self.after_cancel(after_id)
self.allow_colorizing = False
self.stop_colorizing = True
- if close_when_done:
- if not self.colorizing:
- close_when_done.destroy()
- else:
- self.close_when_done = close_when_done
- def toggle_colorize_event(self, event):
+ def toggle_colorize_event(self, event=None):
+ """Toggle colorizing on and off.
+
+ When toggling off, if colorizing is scheduled or is in
+ process, it will be cancelled and/or stopped.
+
+ When toggling on, colorizing will be scheduled.
+ """
if self.after_id:
after_id = self.after_id
self.after_id = None
return "break"
def recolorize(self):
+ """Timer event (every 1ms) to colorize text.
+
+ Colorizing is only attempted when the text widget exists,
+ when colorizing is toggled on, and when the colorizing
+ process is not already running.
+
+ After colorizing is complete, some cleanup is done to
+ make sure that all the text has been colorized.
+ """
self.after_id = None
if not self.delegate:
if DEBUG: print("no delegate")
if self.allow_colorizing and self.tag_nextrange("TODO", "1.0"):
if DEBUG: print("reschedule colorizing")
self.after_id = self.after(1, self.recolorize)
- if self.close_when_done:
- top = self.close_when_done
- self.close_when_done = None
- top.destroy()
def recolorize_main(self):
+ "Evaluate text and apply colorizing tags."
next = "1.0"
while True:
item = self.tag_nextrange("TODO", next)
return
def removecolors(self):
+ "Remove all colorizing tags."
for tag in self.tagdefs:
self.tag_remove(tag, "1.0", "end")
"'x', '''x''', \"x\", \"\"\"x\"\"\"\n"
"r'x', u'x', R'x', U'x', f'x', F'x'\n"
"fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n"
- "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x'.rB'x',Rb'x',RB'x'\n"
+ "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'\n"
"# Invalid combinations of legal characters should be half colored.\n"
"ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n"
)
"""
Dialog for building Tkinter accelerator key bindings
"""
-from tkinter import *
-from tkinter.ttk import Scrollbar
+from tkinter import Toplevel, Listbox, Text, StringVar, TclError
+from tkinter.ttk import Frame, Button, Checkbutton, Entry, Label, Scrollbar
from tkinter import messagebox
import string
import sys
+FUNCTION_KEYS = ('F1', 'F2' ,'F3' ,'F4' ,'F5' ,'F6',
+ 'F7', 'F8' ,'F9' ,'F10' ,'F11' ,'F12')
+ALPHANUM_KEYS = tuple(string.ascii_lowercase + string.digits)
+PUNCTUATION_KEYS = tuple('~!@#%^&*()_-+={}[]|;:,.<>/?')
+WHITESPACE_KEYS = ('Tab', 'Space', 'Return')
+EDIT_KEYS = ('BackSpace', 'Delete', 'Insert')
+MOVE_KEYS = ('Home', 'End', 'Page Up', 'Page Down', 'Left Arrow',
+ 'Right Arrow', 'Up Arrow', 'Down Arrow')
+AVAILABLE_KEYS = (ALPHANUM_KEYS + PUNCTUATION_KEYS + FUNCTION_KEYS +
+ WHITESPACE_KEYS + EDIT_KEYS + MOVE_KEYS)
+
+
+def translate_key(key, modifiers):
+ "Translate from keycap symbol to the Tkinter keysym."
+ mapping = {'Space':'space',
+ '~':'asciitilde', '!':'exclam', '@':'at', '#':'numbersign',
+ '%':'percent', '^':'asciicircum', '&':'ampersand',
+ '*':'asterisk', '(':'parenleft', ')':'parenright',
+ '_':'underscore', '-':'minus', '+':'plus', '=':'equal',
+ '{':'braceleft', '}':'braceright',
+ '[':'bracketleft', ']':'bracketright', '|':'bar',
+ ';':'semicolon', ':':'colon', ',':'comma', '.':'period',
+ '<':'less', '>':'greater', '/':'slash', '?':'question',
+ 'Page Up':'Prior', 'Page Down':'Next',
+ 'Left Arrow':'Left', 'Right Arrow':'Right',
+ 'Up Arrow':'Up', 'Down Arrow': 'Down', 'Tab':'Tab'}
+ key = mapping.get(key, key)
+ if 'Shift' in modifiers and key in string.ascii_lowercase:
+ key = key.upper()
+ return f'Key-{key}'
+
+
class GetKeysDialog(Toplevel):
# Dialog title for invalid key sequence
keyerror_title = 'Key Sequence Error'
- def __init__(self, parent, title, action, currentKeySequences,
+ def __init__(self, parent, title, action, current_key_sequences,
*, _htest=False, _utest=False):
"""
+ parent - parent of this dialog
+ title - string which is the title of the popup dialog
action - string, the name of the virtual event these keys will be
mapped to
- currentKeys - list, a list of all key sequence lists currently mapped
- to virtual events, for overlap checking
- _utest - bool, do not wait when running unittest
+ current_key_sequences - list, a list of all key sequence lists
+ currently mapped to virtual events, for overlap checking
_htest - bool, change box location when running htest
+ _utest - bool, do not wait when running unittest
"""
Toplevel.__init__(self, parent)
- self.withdraw() #hide while setting geometry
+ self.withdraw() # Hide while setting geometry.
self.configure(borderwidth=5)
- self.resizable(height=FALSE, width=FALSE)
+ self.resizable(height=False, width=False)
self.title(title)
self.transient(parent)
self.grab_set()
- self.protocol("WM_DELETE_WINDOW", self.Cancel)
+ self.protocol("WM_DELETE_WINDOW", self.cancel)
self.parent = parent
- self.action=action
- self.currentKeySequences = currentKeySequences
+ self.action = action
+ self.current_key_sequences = current_key_sequences
self.result = ''
- self.keyString = StringVar(self)
- self.keyString.set('')
- self.SetModifiersForPlatform() # set self.modifiers, self.modifier_label
+ self.key_string = StringVar(self)
+ self.key_string.set('')
+ # Set self.modifiers, self.modifier_label.
+ self.set_modifiers_for_platform()
self.modifier_vars = []
for modifier in self.modifiers:
variable = StringVar(self)
variable.set('')
self.modifier_vars.append(variable)
self.advanced = False
- self.CreateWidgets()
- self.LoadFinalKeyList()
+ self.create_widgets()
self.update_idletasks()
self.geometry(
"+%d+%d" % (
parent.winfo_rooty() +
((parent.winfo_height()/2 - self.winfo_reqheight()/2)
if not _htest else 150)
- ) ) #centre dialog over parent (or below htest box)
+ ) ) # Center dialog over parent (or below htest box).
if not _utest:
- self.deiconify() #geometry set, unhide
+ self.deiconify() # Geometry set, unhide.
self.wait_window()
def showerror(self, *args, **kwargs):
# Make testing easier. Replace in #30751.
messagebox.showerror(*args, **kwargs)
- def CreateWidgets(self):
- frameMain = Frame(self,borderwidth=2,relief=SUNKEN)
- frameMain.pack(side=TOP,expand=TRUE,fill=BOTH)
- frameButtons=Frame(self)
- frameButtons.pack(side=BOTTOM,fill=X)
- self.buttonOK = Button(frameButtons,text='OK',
- width=8,command=self.OK)
- self.buttonOK.grid(row=0,column=0,padx=5,pady=5)
- self.buttonCancel = Button(frameButtons,text='Cancel',
- width=8,command=self.Cancel)
- self.buttonCancel.grid(row=0,column=1,padx=5,pady=5)
- self.frameKeySeqBasic = Frame(frameMain)
- self.frameKeySeqAdvanced = Frame(frameMain)
- self.frameControlsBasic = Frame(frameMain)
- self.frameHelpAdvanced = Frame(frameMain)
- self.frameKeySeqAdvanced.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5)
- self.frameKeySeqBasic.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5)
- self.frameKeySeqBasic.lift()
- self.frameHelpAdvanced.grid(row=1,column=0,sticky=NSEW,padx=5)
- self.frameControlsBasic.grid(row=1,column=0,sticky=NSEW,padx=5)
- self.frameControlsBasic.lift()
- self.buttonLevel = Button(frameMain,command=self.ToggleLevel,
- text='Advanced Key Binding Entry >>')
- self.buttonLevel.grid(row=2,column=0,stick=EW,padx=5,pady=5)
- labelTitleBasic = Label(self.frameKeySeqBasic,
- text="New keys for '"+self.action+"' :")
- labelTitleBasic.pack(anchor=W)
- labelKeysBasic = Label(self.frameKeySeqBasic,justify=LEFT,
- textvariable=self.keyString,relief=GROOVE,borderwidth=2)
- labelKeysBasic.pack(ipadx=5,ipady=5,fill=X)
+ def create_widgets(self):
+ self.frame = frame = Frame(self, borderwidth=2, relief='sunken')
+ frame.pack(side='top', expand=True, fill='both')
+
+ frame_buttons = Frame(self)
+ frame_buttons.pack(side='bottom', fill='x')
+
+ self.button_ok = Button(frame_buttons, text='OK',
+ width=8, command=self.ok)
+ self.button_ok.grid(row=0, column=0, padx=5, pady=5)
+ self.button_cancel = Button(frame_buttons, text='Cancel',
+ width=8, command=self.cancel)
+ self.button_cancel.grid(row=0, column=1, padx=5, pady=5)
+
+ # Basic entry key sequence.
+ self.frame_keyseq_basic = Frame(frame, name='keyseq_basic')
+ self.frame_keyseq_basic.grid(row=0, column=0, sticky='nsew',
+ padx=5, pady=5)
+ basic_title = Label(self.frame_keyseq_basic,
+ text=f"New keys for '{self.action}' :")
+ basic_title.pack(anchor='w')
+
+ basic_keys = Label(self.frame_keyseq_basic, justify='left',
+ textvariable=self.key_string, relief='groove',
+ borderwidth=2)
+ basic_keys.pack(ipadx=5, ipady=5, fill='x')
+
+ # Basic entry controls.
+ self.frame_controls_basic = Frame(frame)
+ self.frame_controls_basic.grid(row=1, column=0, sticky='nsew', padx=5)
+
+ # Basic entry modifiers.
self.modifier_checkbuttons = {}
column = 0
for modifier, variable in zip(self.modifiers, self.modifier_vars):
label = self.modifier_label.get(modifier, modifier)
- check=Checkbutton(self.frameControlsBasic,
- command=self.BuildKeyString,
- text=label,variable=variable,onvalue=modifier,offvalue='')
- check.grid(row=0,column=column,padx=2,sticky=W)
+ check = Checkbutton(self.frame_controls_basic,
+ command=self.build_key_string, text=label,
+ variable=variable, onvalue=modifier, offvalue='')
+ check.grid(row=0, column=column, padx=2, sticky='w')
self.modifier_checkbuttons[modifier] = check
column += 1
- labelFnAdvice=Label(self.frameControlsBasic,justify=LEFT,
- text=\
- "Select the desired modifier keys\n"+
- "above, and the final key from the\n"+
- "list on the right.\n\n" +
- "Use upper case Symbols when using\n" +
- "the Shift modifier. (Letters will be\n" +
- "converted automatically.)")
- labelFnAdvice.grid(row=1,column=0,columnspan=4,padx=2,sticky=W)
- self.listKeysFinal=Listbox(self.frameControlsBasic,width=15,height=10,
- selectmode=SINGLE)
- self.listKeysFinal.bind('<ButtonRelease-1>',self.FinalKeySelected)
- self.listKeysFinal.grid(row=0,column=4,rowspan=4,sticky=NS)
- scrollKeysFinal=Scrollbar(self.frameControlsBasic,orient=VERTICAL,
- command=self.listKeysFinal.yview)
- self.listKeysFinal.config(yscrollcommand=scrollKeysFinal.set)
- scrollKeysFinal.grid(row=0,column=5,rowspan=4,sticky=NS)
- self.buttonClear=Button(self.frameControlsBasic,
- text='Clear Keys',command=self.ClearKeySeq)
- self.buttonClear.grid(row=2,column=0,columnspan=4)
- labelTitleAdvanced = Label(self.frameKeySeqAdvanced,justify=LEFT,
- text="Enter new binding(s) for '"+self.action+"' :\n"+
- "(These bindings will not be checked for validity!)")
- labelTitleAdvanced.pack(anchor=W)
- self.entryKeysAdvanced=Entry(self.frameKeySeqAdvanced,
- textvariable=self.keyString)
- self.entryKeysAdvanced.pack(fill=X)
- labelHelpAdvanced=Label(self.frameHelpAdvanced,justify=LEFT,
+
+ # Basic entry help text.
+ help_basic = Label(self.frame_controls_basic, justify='left',
+ text="Select the desired modifier keys\n"+
+ "above, and the final key from the\n"+
+ "list on the right.\n\n" +
+ "Use upper case Symbols when using\n" +
+ "the Shift modifier. (Letters will be\n" +
+ "converted automatically.)")
+ help_basic.grid(row=1, column=0, columnspan=4, padx=2, sticky='w')
+
+ # Basic entry key list.
+ self.list_keys_final = Listbox(self.frame_controls_basic, width=15,
+ height=10, selectmode='single')
+ self.list_keys_final.insert('end', *AVAILABLE_KEYS)
+ self.list_keys_final.bind('<ButtonRelease-1>', self.final_key_selected)
+ self.list_keys_final.grid(row=0, column=4, rowspan=4, sticky='ns')
+ scroll_keys_final = Scrollbar(self.frame_controls_basic,
+ orient='vertical',
+ command=self.list_keys_final.yview)
+ self.list_keys_final.config(yscrollcommand=scroll_keys_final.set)
+ scroll_keys_final.grid(row=0, column=5, rowspan=4, sticky='ns')
+ self.button_clear = Button(self.frame_controls_basic,
+ text='Clear Keys',
+ command=self.clear_key_seq)
+ self.button_clear.grid(row=2, column=0, columnspan=4)
+
+ # Advanced entry key sequence.
+ self.frame_keyseq_advanced = Frame(frame, name='keyseq_advanced')
+ self.frame_keyseq_advanced.grid(row=0, column=0, sticky='nsew',
+ padx=5, pady=5)
+ advanced_title = Label(self.frame_keyseq_advanced, justify='left',
+ text=f"Enter new binding(s) for '{self.action}' :\n" +
+ "(These bindings will not be checked for validity!)")
+ advanced_title.pack(anchor='w')
+ self.advanced_keys = Entry(self.frame_keyseq_advanced,
+ textvariable=self.key_string)
+ self.advanced_keys.pack(fill='x')
+
+ # Advanced entry help text.
+ self.frame_help_advanced = Frame(frame)
+ self.frame_help_advanced.grid(row=1, column=0, sticky='nsew', padx=5)
+ help_advanced = Label(self.frame_help_advanced, justify='left',
text="Key bindings are specified using Tkinter keysyms as\n"+
"in these samples: <Control-f>, <Shift-F2>, <F12>,\n"
"<Control-space>, <Meta-less>, <Control-Alt-Shift-X>.\n"
"is the 'do-nothing' keybinding.\n\n" +
"Multiple separate bindings for one action should be\n"+
"separated by a space, eg., <Alt-v> <Meta-v>." )
- labelHelpAdvanced.grid(row=0,column=0,sticky=NSEW)
+ help_advanced.grid(row=0, column=0, sticky='nsew')
+
+ # Switch between basic and advanced.
+ self.button_level = Button(frame, command=self.toggle_level,
+ text='<< Basic Key Binding Entry')
+ self.button_level.grid(row=2, column=0, stick='ew', padx=5, pady=5)
+ self.toggle_level()
- def SetModifiersForPlatform(self):
+ def set_modifiers_for_platform(self):
"""Determine list of names of key modifiers for this platform.
The names are used to build Tk bindings -- it doesn't matter if the
- keyboard has these keys, it matters if Tk understands them. The
+ keyboard has these keys; it matters if Tk understands them. The
order is also important: key binding equality depends on it, so
config-keys.def must use the same ordering.
"""
self.modifiers = ['Shift', 'Control', 'Option', 'Command']
else:
self.modifiers = ['Control', 'Alt', 'Shift']
- self.modifier_label = {'Control': 'Ctrl'} # short name
-
- def ToggleLevel(self):
- if self.buttonLevel.cget('text')[:8]=='Advanced':
- self.ClearKeySeq()
- self.buttonLevel.config(text='<< Basic Key Binding Entry')
- self.frameKeySeqAdvanced.lift()
- self.frameHelpAdvanced.lift()
- self.entryKeysAdvanced.focus_set()
+ self.modifier_label = {'Control': 'Ctrl'} # Short name.
+
+ def toggle_level(self):
+ "Toggle between basic and advanced keys."
+ if self.button_level.cget('text').startswith('Advanced'):
+ self.clear_key_seq()
+ self.button_level.config(text='<< Basic Key Binding Entry')
+ self.frame_keyseq_advanced.lift()
+ self.frame_help_advanced.lift()
+ self.advanced_keys.focus_set()
self.advanced = True
else:
- self.ClearKeySeq()
- self.buttonLevel.config(text='Advanced Key Binding Entry >>')
- self.frameKeySeqBasic.lift()
- self.frameControlsBasic.lift()
+ self.clear_key_seq()
+ self.button_level.config(text='Advanced Key Binding Entry >>')
+ self.frame_keyseq_basic.lift()
+ self.frame_controls_basic.lift()
self.advanced = False
- def FinalKeySelected(self,event):
- self.BuildKeyString()
+ def final_key_selected(self, event=None):
+ "Handler for clicking on key in basic settings list."
+ self.build_key_string()
- def BuildKeyString(self):
- keyList = modifiers = self.GetModifiers()
- finalKey = self.listKeysFinal.get(ANCHOR)
- if finalKey:
- finalKey = self.TranslateKey(finalKey, modifiers)
- keyList.append(finalKey)
- self.keyString.set('<' + '-'.join(keyList) + '>')
+ def build_key_string(self):
+ "Create formatted string of modifiers plus the key."
+ keylist = modifiers = self.get_modifiers()
+ final_key = self.list_keys_final.get('anchor')
+ if final_key:
+ final_key = translate_key(final_key, modifiers)
+ keylist.append(final_key)
+ self.key_string.set(f"<{'-'.join(keylist)}>")
- def GetModifiers(self):
- modList = [variable.get() for variable in self.modifier_vars]
- return [mod for mod in modList if mod]
+ def get_modifiers(self):
+ "Return ordered list of modifiers that have been selected."
+ mod_list = [variable.get() for variable in self.modifier_vars]
+ return [mod for mod in mod_list if mod]
- def ClearKeySeq(self):
- self.listKeysFinal.select_clear(0,END)
- self.listKeysFinal.yview(MOVETO, '0.0')
+ def clear_key_seq(self):
+ "Clear modifiers and keys selection."
+ self.list_keys_final.select_clear(0, 'end')
+ self.list_keys_final.yview('moveto', '0.0')
for variable in self.modifier_vars:
variable.set('')
- self.keyString.set('')
-
- def LoadFinalKeyList(self):
- #these tuples are also available for use in validity checks
- self.functionKeys=('F1','F2','F3','F4','F5','F6','F7','F8','F9',
- 'F10','F11','F12')
- self.alphanumKeys=tuple(string.ascii_lowercase+string.digits)
- self.punctuationKeys=tuple('~!@#%^&*()_-+={}[]|;:,.<>/?')
- self.whitespaceKeys=('Tab','Space','Return')
- self.editKeys=('BackSpace','Delete','Insert')
- self.moveKeys=('Home','End','Page Up','Page Down','Left Arrow',
- 'Right Arrow','Up Arrow','Down Arrow')
- #make a tuple of most of the useful common 'final' keys
- keys=(self.alphanumKeys+self.punctuationKeys+self.functionKeys+
- self.whitespaceKeys+self.editKeys+self.moveKeys)
- self.listKeysFinal.insert(END, *keys)
-
- def TranslateKey(self, key, modifiers):
- "Translate from keycap symbol to the Tkinter keysym"
- translateDict = {'Space':'space',
- '~':'asciitilde','!':'exclam','@':'at','#':'numbersign',
- '%':'percent','^':'asciicircum','&':'ampersand','*':'asterisk',
- '(':'parenleft',')':'parenright','_':'underscore','-':'minus',
- '+':'plus','=':'equal','{':'braceleft','}':'braceright',
- '[':'bracketleft',']':'bracketright','|':'bar',';':'semicolon',
- ':':'colon',',':'comma','.':'period','<':'less','>':'greater',
- '/':'slash','?':'question','Page Up':'Prior','Page Down':'Next',
- 'Left Arrow':'Left','Right Arrow':'Right','Up Arrow':'Up',
- 'Down Arrow': 'Down', 'Tab':'Tab'}
- if key in translateDict:
- key = translateDict[key]
- if 'Shift' in modifiers and key in string.ascii_lowercase:
- key = key.upper()
- key = 'Key-' + key
- return key
-
- def OK(self, event=None):
- keys = self.keyString.get().strip()
+ self.key_string.set('')
+
+ def ok(self, event=None):
+ keys = self.key_string.get().strip()
if not keys:
self.showerror(title=self.keyerror_title, parent=self,
message="No key specified.")
return
- if (self.advanced or self.KeysOK(keys)) and self.bind_ok(keys):
+ if (self.advanced or self.keys_ok(keys)) and self.bind_ok(keys):
self.result = keys
self.grab_release()
self.destroy()
- def Cancel(self, event=None):
- self.result=''
+ def cancel(self, event=None):
+ self.result = ''
self.grab_release()
self.destroy()
- def KeysOK(self, keys):
- '''Validity check on user's 'basic' keybinding selection.
+ def keys_ok(self, keys):
+ """Validity check on user's 'basic' keybinding selection.
Doesn't check the string produced by the advanced dialog because
'modifiers' isn't set.
-
- '''
- finalKey = self.listKeysFinal.get(ANCHOR)
- modifiers = self.GetModifiers()
- keysOK = False
+ """
+ final_key = self.list_keys_final.get('anchor')
+ modifiers = self.get_modifiers()
title = self.keyerror_title
- key_sequences = [key for keylist in self.currentKeySequences
+ key_sequences = [key for keylist in self.current_key_sequences
for key in keylist]
if not keys.endswith('>'):
self.showerror(title, parent=self,
message='Missing the final Key')
elif (not modifiers
- and finalKey not in self.functionKeys + self.moveKeys):
+ and final_key not in FUNCTION_KEYS + MOVE_KEYS):
self.showerror(title=title, parent=self,
message='No modifier key(s) specified.')
elif (modifiers == ['Shift']) \
- and (finalKey not in
- self.functionKeys + self.moveKeys + ('Tab', 'Space')):
+ and (final_key not in
+ FUNCTION_KEYS + MOVE_KEYS + ('Tab', 'Space')):
msg = 'The shift modifier by itself may not be used with'\
' this key symbol.'
self.showerror(title=title, parent=self, message=msg)
msg = 'This key combination is already in use.'
self.showerror(title=title, parent=self, message=msg)
else:
- keysOK = True
- return keysOK
+ return True
+ return False
def bind_ok(self, keys):
"Return True if Tcl accepts the new keys else show message."
-
try:
binding = self.bind(keys, lambda: None)
except TclError as err:
TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE,
NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW,
HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END)
-from tkinter.ttk import (Button, Checkbutton, Entry, Frame, Label, LabelFrame,
+from tkinter.ttk import (Frame, LabelFrame, Button, Checkbutton, Entry, Label,
OptionMenu, Notebook, Radiobutton, Scrollbar, Style)
import tkinter.colorchooser as tkColorChooser
import tkinter.font as tkFont
import os
from tkinter import *
-from tkinter.ttk import Scrollbar
+from tkinter.ttk import Frame, Scrollbar
from idlelib import macosx
from idlelib.scrolledlist import ScrolledList
text.bind("<<zoom-height>>", self.ZoomHeight(self).zoom_height_event)
text.bind("<<toggle-code-context>>",
self.CodeContext(self).toggle_code_context_event)
- squeezer = self.Squeezer(self)
- text.bind("<<squeeze-current-text>>",
- squeezer.squeeze_current_text_event)
def _filename_to_unicode(self, filename):
"""Return filename as BMP unicode so diplayable in Tk."""
menu.delete(self.wmenu_end+1, end)
window.add_windows_to_menu(menu)
+ def update_menu_label(self, menu, index, label):
+ "Update label for menu item at index."
+ menuitem = self.menudict[menu]
+ menuitem.entryconfig(index, label=label)
+
+ def update_menu_state(self, menu, index, state):
+ "Update state for menu item at index."
+ menuitem = self.menudict[menu]
+ menuitem.entryconfig(index, state=state)
+
def handle_yview(self, event, *args):
"Handle scrollbar."
if event == 'moveto':
elif long:
title = long
else:
- title = "Untitled"
+ title = "untitled"
icon = short or long or title
if not self.get_saved():
title = "*%s*" % title
if filename:
filename = os.path.basename(filename)
else:
- filename = "Untitled"
+ filename = "untitled"
# return unicode string to display non-ASCII chars correctly
return self._filename_to_unicode(filename)
self.io = None
self.undo = None
if self.color:
- self.color.close(False)
+ self.color.close()
self.color = None
self.text = None
self.tkinter_vars = None
import sys
from tkinter import StringVar, BooleanVar
-from tkinter.ttk import Checkbutton
+from tkinter.ttk import Checkbutton # Frame imported in ...Base
from idlelib.searchbase import SearchDialogBase
from idlelib import searchengine
def _grep_dialog(parent): # htest #
from tkinter import Toplevel, Text, SEL, END
- from tkinter.ttk import Button
+ from tkinter.ttk import Frame, Button
from idlelib.pyshell import PyShellFileList
+
top = Toplevel(parent)
top.title("Test GrepDialog")
x, y = map(int, parent.geometry().split('+')[1:])
top.geometry(f"+{x}+{y + 175}")
flist = PyShellFileList(top)
- text = Text(top, height=5)
+ frame = Frame(top)
+ frame.pack()
+ text = Text(frame, height=5)
text.pack()
def show_grep_dialog():
grep(text, flist=flist)
text.tag_remove(SEL, "1.0", END)
- button = Button(top, text="Show GrepDialog", command=show_grep_dialog)
+ button = Button(frame, text="Show GrepDialog", command=show_grep_dialog)
button.pack()
if __name__ == "__main__":
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>IDLE — Python 3.8.0a0 documentation</title>
+ <title>IDLE — Python 3.8.0a1 documentation</title>
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript" src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
- title="Search within Python 3.8.0a0 documentation"
+ title="Search within Python 3.8.0a1 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<li>
- <a href="../index.html">3.8.0a0 Documentation</a> »
+ <a href="../index.html">3.8.0a1 Documentation</a> »
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
<dd>Move cursor to the line number requested and make that line visible.</dd>
<dt>Show Completions</dt>
<dd>Open a scrollable list allowing selection of keywords and attributes. See
-Completions in the Tips sections below.</dd>
+<a class="reference internal" href="#completions"><span class="std std-ref">Completions</span></a> in the Editing and navigation section below.</dd>
<dt>Expand Word</dt>
<dd>Expand a prefix you have typed to match a full word in the same window;
repeat to get a different expansion.</dd>
<dt>Show call tip</dt>
<dd>After an unclosed parenthesis for a function, open a small window with
-function parameter hints.</dd>
+function parameter hints. See <a class="reference internal" href="#calltips"><span class="std std-ref">Calltips</span></a> in the
+Editing and navigation section below.</dd>
<dt>Show surrounding parens</dt>
<dd>Highlight the surrounding parenthesis.</dd>
</dl>
</div>
<div class="section" id="format-menu-editor-window-only">
-<h3>Format menu (Editor window only)<a class="headerlink" href="#format-menu-editor-window-only" title="Permalink to this headline">¶</a></h3>
+<span id="format-menu"></span><h3>Format menu (Editor window only)<a class="headerlink" href="#format-menu-editor-window-only" title="Permalink to this headline">¶</a></h3>
<dl class="docutils">
<dt>Indent Region</dt>
<dd>Shift selected lines right by the indent width (default 4 spaces).</dd>
<dd>Scroll the shell window to the last Shell restart.</dd>
<dt>Restart Shell</dt>
<dd>Restart the shell to clean the environment.</dd>
+<dt>Previous History</dt>
+<dd>Cycle through earlier commands in history which match the current entry.</dd>
+<dt>Next History</dt>
+<dd>Cycle through later commands in history which match the current entry.</dd>
<dt>Interrupt Execution</dt>
<dd>Stop a running program.</dd>
</dl>
<h3>Options menu (Shell and Editor)<a class="headerlink" href="#options-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
<dl class="docutils">
<dt>Configure IDLE</dt>
-<dd><p class="first">Open a configuration dialog and change preferences for the following:
+<dd>Open a configuration dialog and change preferences for the following:
fonts, indentation, keybindings, text color themes, startup windows and
-size, additional help sources, and extensions (see below). On macOS,
-open the configuration dialog by selecting Preferences in the application
-menu. To use a new built-in color theme (IDLE Dark) with older IDLEs,
-save it as a new custom theme.</p>
-<p class="last">Non-default user settings are saved in a .idlerc directory in the user’s
-home directory. Problems caused by bad user configuration files are solved
-by editing or deleting one or more of the files in .idlerc.</p>
-</dd>
-<dt>Code Context (toggle)(Editor Window only)</dt>
+size, additional help sources, and extensions. On macOS, open the
+configuration dialog by selecting Preferences in the application
+menu. For more, see
+<a class="reference internal" href="#preferences"><span class="std std-ref">Setting preferences</span></a> under Help and preferences.</dd>
+<dt>Zoom/Restore Height</dt>
+<dd>Toggles the window between normal size and maximum height. The initial size
+defaults to 40 lines by 80 chars unless changed on the General tab of the
+Configure IDLE dialog.</dd>
+<dt>Show/Hide Code Context (Editor Window only)</dt>
<dd>Open a pane at the top of the edit window which shows the block context
-of the code which has scrolled above the top of the window. Clicking a
-line in this pane exposes that line at the top of the editor.</dd>
+of the code which has scrolled above the top of the window. See
+<a class="reference internal" href="#code-context"><span class="std std-ref">Code Context</span></a> in the Editing and Navigation section below.</dd>
</dl>
</div>
<div class="section" id="window-menu-shell-and-editor">
<h3>Window menu (Shell and Editor)<a class="headerlink" href="#window-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils">
-<dt>Zoom Height</dt>
-<dd>Toggles the window between normal size and maximum height. The initial size
-defaults to 40 lines by 80 chars unless changed on the General tab of the
-Configure IDLE dialog.</dd>
-</dl>
-<p>The rest of this menu lists the names of all open windows; select one to bring
-it to the foreground (deiconifying it if necessary).</p>
+<p>Lists the names of all open windows; select one to bring it to the foreground
+(deiconifying it if necessary).</p>
</div>
<div class="section" id="help-menu-shell-and-editor">
<h3>Help menu (Shell and Editor)<a class="headerlink" href="#help-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
<dd>Run the turtledemo module with example Python code and turtle drawings.</dd>
</dl>
<p>Additional help sources may be added here with the Configure IDLE dialog under
-the General tab. See the “Help sources” subsection below for more
-on Help menu choices.</p>
+the General tab. See the <a class="reference internal" href="#help-sources"><span class="std std-ref">Help sources</span></a> subsection below
+for more on Help menu choices.</p>
</div>
<div class="section" id="context-menus">
<span id="index-4"></span><h3>Context Menus<a class="headerlink" href="#context-menus" title="Permalink to this headline">¶</a></h3>
</div>
</div>
<div class="section" id="editing-and-navigation">
-<h2>Editing and navigation<a class="headerlink" href="#editing-and-navigation" title="Permalink to this headline">¶</a></h2>
+<span id="id2"></span><h2>Editing and navigation<a class="headerlink" href="#editing-and-navigation" title="Permalink to this headline">¶</a></h2>
<div class="section" id="editor-windows">
<h3>Editor windows<a class="headerlink" href="#editor-windows" title="Permalink to this headline">¶</a></h3>
<p>IDLE may open editor windows when it starts, depending on settings
to 4 spaces if they are there. <kbd class="kbd docutils literal notranslate">Tab</kbd> inserts spaces (in the Python
Shell window one tab), number depends on Indent width. Currently, tabs
are restricted to four spaces due to Tcl/Tk limitations.</p>
-<p>See also the indent/dedent region commands in the edit menu.</p>
+<p>See also the indent/dedent region commands on the
+<a class="reference internal" href="#format-menu"><span class="std std-ref">Format menu</span></a>.</p>
</div>
<div class="section" id="completions">
-<h3>Completions<a class="headerlink" href="#completions" title="Permalink to this headline">¶</a></h3>
+<span id="id3"></span><h3>Completions<a class="headerlink" href="#completions" title="Permalink to this headline">¶</a></h3>
<p>Completions are supplied for functions, classes, and attributes of classes,
both built-in and user-defined. Completions are also provided for
filenames.</p>
longer or disable the extension.</p>
</div>
<div class="section" id="calltips">
-<h3>Calltips<a class="headerlink" href="#calltips" title="Permalink to this headline">¶</a></h3>
+<span id="id4"></span><h3>Calltips<a class="headerlink" href="#calltips" title="Permalink to this headline">¶</a></h3>
<p>A calltip is shown when one types <kbd class="kbd docutils literal notranslate">(</kbd> after the name of an <em>accessible</em>
function. A name expression may include dots and subscripts. A calltip
remains until it is clicked, the cursor is moved out of the argument area,
might want to run a file after writing the import statements at the top,
or immediately run an existing file before editing.</p>
</div>
+<div class="section" id="code-context">
+<span id="id5"></span><h3>Code Context<a class="headerlink" href="#code-context" title="Permalink to this headline">¶</a></h3>
+<p>Within an editor window containing Python code, code context can be toggled
+in order to show or hide a pane at the top of the window. When shown, this
+pane freezes the opening lines for block code, such as those beginning with
+<code class="docutils literal notranslate"><span class="pre">class</span></code>, <code class="docutils literal notranslate"><span class="pre">def</span></code>, or <code class="docutils literal notranslate"><span class="pre">if</span></code> keywords, that would have otherwise scrolled
+out of view. The size of the pane will be expanded and contracted as needed
+to show the all current levels of context, up to the maximum number of
+lines defined in the Configure IDLE dialog (which defaults to 15). If there
+are no current context lines and the feature is toggled on, a single blank
+line will display. Clicking on a line in the context pane will move that
+line to the top of the editor.</p>
+<p>The text and background colors for the context pane can be configured under
+the Highlights tab in the Configure IDLE dialog.</p>
+</div>
<div class="section" id="python-shell-window">
<h3>Python Shell window<a class="headerlink" href="#python-shell-window" title="Permalink to this headline">¶</a></h3>
<p>With IDLE’s Shell, one enters, edits, and recalls complete statements.
In contrast, some system text windows only keep the last n lines of output.
A Windows console, for instance, keeps a user-settable 1 to 9999 lines,
with 300 the default.</p>
-<p>Text widgets display a subset of Unicode, the Basic Multilingual Plane (BMP).
-Which characters get a proper glyph instead of a replacement box depends on
-the operating system and installed fonts. Newline characters cause following
-text to appear on a new line, but other control characters are either
-replaced with a box or deleted. However, <code class="docutils literal notranslate"><span class="pre">repr()</span></code>, which is used for
-interactive echo of expression values, replaces control characters,
-some BMP codepoints, and all non-BMP characters with escape codes
-before they are output.</p>
+<p>A Tk Text widget, and hence IDLE’s Shell, displays characters (codepoints)
+in the the BMP (Basic Multilingual Plane) subset of Unicode.
+Which characters are displayed with a proper glyph and which with a
+replacement box depends on the operating system and installed fonts.
+Tab characters cause the following text to begin after
+the next tab stop. (They occur every 8 ‘characters’).
+Newline characters cause following text to appear on a new line.
+Other control characters are ignored or displayed as a space, box, or
+something else, depending on the operating system and font.
+(Moving the text cursor through such output with arrow keys may exhibit
+some surprising spacing behavior.)</p>
+<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>>>> s = 'a\tb\a<\x02><\r>\bc\nd'
+>>> len(s)
+14
+>>> s # Display repr(s)
+'a\tb\x07<\x02><\r>\x08c\nd'
+>>> print(s, end='') # Display s as is.
+# Result varies by OS and font. Try it.
+</pre></div>
+</div>
+<p>The <code class="docutils literal notranslate"><span class="pre">repr</span></code> function is used for interactive echo of expression
+values. It returns an altered version of the input string in which
+control codes, some BMP codepoints, and all non-BMP codepoints are
+replaced with escape codes. As demonstrated above, it allows one to
+identify the characters in a string, regardless of how they are displayed.</p>
<p>Normal and error output are generally kept separate (on separate lines)
from code input and each other. They each get different highlight colors.</p>
<p>For SyntaxError tracebacks, the normal ‘^’ marking where the error was
<div class="section" id="help-and-preferences">
<h2>Help and preferences<a class="headerlink" href="#help-and-preferences" title="Permalink to this headline">¶</a></h2>
<div class="section" id="help-sources">
-<h3>Help sources<a class="headerlink" href="#help-sources" title="Permalink to this headline">¶</a></h3>
+<span id="id6"></span><h3>Help sources<a class="headerlink" href="#help-sources" title="Permalink to this headline">¶</a></h3>
<p>Help menu entry “IDLE Help” displays a formatted html version of the
IDLE chapter of the Library Reference. The result, in a read-only
tkinter text window, is close to what one sees in a web browser.
General tab of the Configure IDLE dialog .</p>
</div>
<div class="section" id="setting-preferences">
-<h3>Setting preferences<a class="headerlink" href="#setting-preferences" title="Permalink to this headline">¶</a></h3>
+<span id="preferences"></span><h3>Setting preferences<a class="headerlink" href="#setting-preferences" title="Permalink to this headline">¶</a></h3>
<p>The font preferences, highlighting, keys, and general preferences can be
-changed via Configure IDLE on the Option menu. Keys can be user defined;
-IDLE ships with four built-in key sets. In addition, a user can create a
-custom key set in the Configure IDLE dialog under the keys tab.</p>
+changed via Configure IDLE on the Option menu.
+Non-default user settings are saved in a .idlerc directory in the user’s
+home directory. Problems caused by bad user configuration files are solved
+by editing or deleting one or more of the files in .idlerc.</p>
+<p>On the Font tab, see the text sample for the effect of font face and size
+on multiple characters in multiple languages. Edit the sample to add
+other characters of personal interest. Use the sample to select
+monospaced fonts. If particular characters have problems in Shell or an
+editor, add them to the top of the sample and try changing first size
+and then font.</p>
+<p>On the Highlights and Keys tab, select a built-in or custom color theme
+and key set. To use a newer built-in color theme or key set with older
+IDLEs, save it as a new custom theme or key set and it well be accessible
+to older IDLEs.</p>
</div>
<div class="section" id="idle-on-macos">
<h3>IDLE on macOS<a class="headerlink" href="#idle-on-macos" title="Permalink to this headline">¶</a></h3>
<li><a class="reference internal" href="#automatic-indentation">Automatic indentation</a></li>
<li><a class="reference internal" href="#completions">Completions</a></li>
<li><a class="reference internal" href="#calltips">Calltips</a></li>
+<li><a class="reference internal" href="#code-context">Code Context</a></li>
<li><a class="reference internal" href="#python-shell-window">Python Shell window</a></li>
<li><a class="reference internal" href="#text-colors">Text colors</a></li>
</ul>
<li>
- <a href="../index.html">3.8.0a0 Documentation</a> »
+ <a href="../index.html">3.8.0a1 Documentation</a> »
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
</ul>
</div>
<div class="footer">
- © <a href="../copyright.html">Copyright</a> 2001-2018, Python Software Foundation.
+ © <a href="../copyright.html">Copyright</a> 2001-2019, Python Software Foundation.
<br />
The Python Software Foundation is a non-profit corporation.
<br />
<br />
- Last updated on Nov 12, 2018.
+ Last updated on Feb 23, 2019.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
"Best to close editor first."
}
-# Update once issue21519 is resolved.
GetKeysDialog_spec = {
'file': 'config_key',
'kwds': {'title': 'Test keybindings',
'action': 'find-again',
- 'currentKeySequences': [''] ,
+ 'current_key_sequences': [['<Control-Key-g>', '<Key-F3>', '<Control-Key-G>']],
'_htest': True,
},
'msg': "Test for different key modifier sequences.\n"
drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None,
placeholder=' [...]')''')
+ def test_properly_formated(self):
+ def foo(s='a'*100):
+ pass
+
+ def bar(s='a'*100):
+ """Hello Guido"""
+ pass
+
+ def baz(s='a'*100, z='b'*100):
+ pass
+
+ indent = calltip._INDENT
+
+ str_foo = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\
+ "aaaaaaaaaa')"
+ str_bar = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\
+ "aaaaaaaaaa')\nHello Guido"
+ str_baz = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\
+ "aaaaaaaaaa', z='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"\
+ "bbbbbbbbbbbbbbbbb\n" + indent + "bbbbbbbbbbbbbbbbbbbbbb"\
+ "bbbbbbbbbbbbbbbbbbbbbb')"
+
+ self.assertEqual(calltip.get_argspec(foo), str_foo)
+ self.assertEqual(calltip.get_argspec(bar), str_bar)
+ self.assertEqual(calltip.get_argspec(baz), str_baz)
+
def test_docline_truncation(self):
def f(): pass
f.__doc__ = 'a'*300
self.top = root
self.text_frame = frame
self.text = text
+ self.label = ''
+
+ def update_menu_label(self, **kwargs):
+ self.label = kwargs['label']
class CodeContextTest(unittest.TestCase):
eq(cc.context['fg'], cc.colors['foreground'])
eq(cc.context['bg'], cc.colors['background'])
eq(cc.context.get('1.0', 'end-1c'), '')
+ eq(cc.editwin.label, 'Hide Code Context')
# Toggle off.
eq(toggle(), 'break')
self.assertIsNone(cc.context)
+ eq(cc.editwin.label, 'Show Code Context')
def test_get_context(self):
eq = self.assertEqual
-"Test colorizer, coverage 25%."
+"Test colorizer, coverage 93%."
from idlelib import colorizer
from test.support import requires
-from tkinter import Tk, Text
import unittest
+from unittest import mock
+
+from functools import partial
+from tkinter import Tk, Text
+from idlelib import config
+from idlelib.percolator import Percolator
+
+
+usercfg = colorizer.idleConf.userCfg
+testcfg = {
+ 'main': config.IdleUserConfParser(''),
+ 'highlight': config.IdleUserConfParser(''),
+ 'keys': config.IdleUserConfParser(''),
+ 'extensions': config.IdleUserConfParser(''),
+}
+
+source = (
+ "if True: int ('1') # keyword, builtin, string, comment\n"
+ "elif False: print(0) # 'string' in comment\n"
+ "else: float(None) # if in comment\n"
+ "if iF + If + IF: 'keyword matching must respect case'\n"
+ "if'': x or'' # valid string-keyword no-space combinations\n"
+ "async def f(): await g()\n"
+ "'x', '''x''', \"x\", \"\"\"x\"\"\"\n"
+ )
+
+
+def setUpModule():
+ colorizer.idleConf.userCfg = testcfg
+
+
+def tearDownModule():
+ colorizer.idleConf.userCfg = usercfg
class FunctionTest(unittest.TestCase):
def test_any(self):
- self.assertTrue(colorizer.any('test', ('a', 'b')))
+ self.assertEqual(colorizer.any('test', ('a', 'b', 'cd')),
+ '(?P<test>a|b|cd)')
def test_make_pat(self):
+ # Tested in more detail by testing prog.
self.assertTrue(colorizer.make_pat())
+ def test_prog(self):
+ prog = colorizer.prog
+ eq = self.assertEqual
+ line = 'def f():\n print("hello")\n'
+ m = prog.search(line)
+ eq(m.groupdict()['KEYWORD'], 'def')
+ m = prog.search(line, m.end())
+ eq(m.groupdict()['SYNC'], '\n')
+ m = prog.search(line, m.end())
+ eq(m.groupdict()['BUILTIN'], 'print')
+ m = prog.search(line, m.end())
+ eq(m.groupdict()['STRING'], '"hello"')
+ m = prog.search(line, m.end())
+ eq(m.groupdict()['SYNC'], '\n')
+
+ def test_idprog(self):
+ idprog = colorizer.idprog
+ m = idprog.match('nospace')
+ self.assertIsNone(m)
+ m = idprog.match(' space')
+ self.assertEqual(m.group(0), ' space')
+
class ColorConfigTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
requires('gui')
- cls.root = Tk()
- cls.text = Text(cls.root)
+ root = cls.root = Tk()
+ root.withdraw()
+ cls.text = Text(root)
+
+ @classmethod
+ def tearDownClass(cls):
+ del cls.text
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.root
+
+ def test_color_config(self):
+ text = self.text
+ eq = self.assertEqual
+ colorizer.color_config(text)
+ # Uses IDLE Classic theme as default.
+ eq(text['background'], '#ffffff')
+ eq(text['foreground'], '#000000')
+ eq(text['selectbackground'], 'gray')
+ eq(text['selectforeground'], '#000000')
+ eq(text['insertbackground'], 'black')
+ eq(text['inactiveselectbackground'], 'gray')
+
+
+class ColorDelegatorInstantiationTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ requires('gui')
+ root = cls.root = Tk()
+ root.withdraw()
+ text = cls.text = Text(root)
@classmethod
def tearDownClass(cls):
del cls.text
+ cls.root.update_idletasks()
cls.root.destroy()
del cls.root
- def test_colorizer(self):
- colorizer.color_config(self.text)
+ def setUp(self):
+ self.color = colorizer.ColorDelegator()
+
+ def tearDown(self):
+ self.color.close()
+ self.text.delete('1.0', 'end')
+ self.color.resetcache()
+ del self.color
+
+ def test_init(self):
+ color = self.color
+ self.assertIsInstance(color, colorizer.ColorDelegator)
+
+ def test_init_state(self):
+ # init_state() is called during the instantiation of
+ # ColorDelegator in setUp().
+ color = self.color
+ self.assertIsNone(color.after_id)
+ self.assertTrue(color.allow_colorizing)
+ self.assertFalse(color.colorizing)
+ self.assertFalse(color.stop_colorizing)
class ColorDelegatorTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
requires('gui')
- cls.root = Tk()
+ root = cls.root = Tk()
+ root.withdraw()
+ text = cls.text = Text(root)
+ cls.percolator = Percolator(text)
+ # Delegator stack = [Delegator(text)]
@classmethod
def tearDownClass(cls):
+ cls.percolator.redir.close()
+ del cls.percolator, cls.text
+ cls.root.update_idletasks()
cls.root.destroy()
del cls.root
- def test_colorizer(self):
- colorizer.ColorDelegator()
+ def setUp(self):
+ self.color = colorizer.ColorDelegator()
+ self.percolator.insertfilter(self.color)
+ # Calls color.setdelegate(Delegator(text)).
+
+ def tearDown(self):
+ self.color.close()
+ self.percolator.removefilter(self.color)
+ self.text.delete('1.0', 'end')
+ self.color.resetcache()
+ del self.color
+
+ def test_setdelegate(self):
+ # Called in setUp when filter is attached to percolator.
+ color = self.color
+ self.assertIsInstance(color.delegate, colorizer.Delegator)
+ # It is too late to mock notify_range, so test side effect.
+ self.assertEqual(self.root.tk.call(
+ 'after', 'info', color.after_id)[1], 'timer')
+
+ def test_LoadTagDefs(self):
+ highlight = partial(config.idleConf.GetHighlight, theme='IDLE Classic')
+ for tag, colors in self.color.tagdefs.items():
+ with self.subTest(tag=tag):
+ self.assertIn('background', colors)
+ self.assertIn('foreground', colors)
+ if tag not in ('SYNC', 'TODO'):
+ self.assertEqual(colors, highlight(element=tag.lower()))
+
+ def test_config_colors(self):
+ text = self.text
+ highlight = partial(config.idleConf.GetHighlight, theme='IDLE Classic')
+ for tag in self.color.tagdefs:
+ for plane in ('background', 'foreground'):
+ with self.subTest(tag=tag, plane=plane):
+ if tag in ('SYNC', 'TODO'):
+ self.assertEqual(text.tag_cget(tag, plane), '')
+ else:
+ self.assertEqual(text.tag_cget(tag, plane),
+ highlight(element=tag.lower())[plane])
+ # 'sel' is marked as the highest priority.
+ self.assertEqual(text.tag_names()[-1], 'sel')
+
+ @mock.patch.object(colorizer.ColorDelegator, 'notify_range')
+ def test_insert(self, mock_notify):
+ text = self.text
+ # Initial text.
+ text.insert('insert', 'foo')
+ self.assertEqual(text.get('1.0', 'end'), 'foo\n')
+ mock_notify.assert_called_with('1.0', '1.0+3c')
+ # Additional text.
+ text.insert('insert', 'barbaz')
+ self.assertEqual(text.get('1.0', 'end'), 'foobarbaz\n')
+ mock_notify.assert_called_with('1.3', '1.3+6c')
+
+ @mock.patch.object(colorizer.ColorDelegator, 'notify_range')
+ def test_delete(self, mock_notify):
+ text = self.text
+ # Initialize text.
+ text.insert('insert', 'abcdefghi')
+ self.assertEqual(text.get('1.0', 'end'), 'abcdefghi\n')
+ # Delete single character.
+ text.delete('1.7')
+ self.assertEqual(text.get('1.0', 'end'), 'abcdefgi\n')
+ mock_notify.assert_called_with('1.7')
+ # Delete multiple characters.
+ text.delete('1.3', '1.6')
+ self.assertEqual(text.get('1.0', 'end'), 'abcgi\n')
+ mock_notify.assert_called_with('1.3')
+
+ def test_notify_range(self):
+ text = self.text
+ color = self.color
+ eq = self.assertEqual
+
+ # Colorizing already scheduled.
+ save_id = color.after_id
+ eq(self.root.tk.call('after', 'info', save_id)[1], 'timer')
+ self.assertFalse(color.colorizing)
+ self.assertFalse(color.stop_colorizing)
+ self.assertTrue(color.allow_colorizing)
+
+ # Coloring scheduled and colorizing in progress.
+ color.colorizing = True
+ color.notify_range('1.0', 'end')
+ self.assertFalse(color.stop_colorizing)
+ eq(color.after_id, save_id)
+
+ # No colorizing scheduled and colorizing in progress.
+ text.after_cancel(save_id)
+ color.after_id = None
+ color.notify_range('1.0', '1.0+3c')
+ self.assertTrue(color.stop_colorizing)
+ self.assertIsNotNone(color.after_id)
+ eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
+ # New event scheduled.
+ self.assertNotEqual(color.after_id, save_id)
+
+ # No colorizing scheduled and colorizing off.
+ text.after_cancel(color.after_id)
+ color.after_id = None
+ color.allow_colorizing = False
+ color.notify_range('1.4', '1.4+10c')
+ # Nothing scheduled when colorizing is off.
+ self.assertIsNone(color.after_id)
+
+ def test_toggle_colorize_event(self):
+ color = self.color
+ eq = self.assertEqual
+
+ # Starts with colorizing allowed and scheduled.
+ self.assertFalse(color.colorizing)
+ self.assertFalse(color.stop_colorizing)
+ self.assertTrue(color.allow_colorizing)
+ eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
+
+ # Toggle colorizing off.
+ color.toggle_colorize_event()
+ self.assertIsNone(color.after_id)
+ self.assertFalse(color.colorizing)
+ self.assertFalse(color.stop_colorizing)
+ self.assertFalse(color.allow_colorizing)
+
+ # Toggle on while colorizing in progress (doesn't add timer).
+ color.colorizing = True
+ color.toggle_colorize_event()
+ self.assertIsNone(color.after_id)
+ self.assertTrue(color.colorizing)
+ self.assertFalse(color.stop_colorizing)
+ self.assertTrue(color.allow_colorizing)
+
+ # Toggle off while colorizing in progress.
+ color.toggle_colorize_event()
+ self.assertIsNone(color.after_id)
+ self.assertTrue(color.colorizing)
+ self.assertTrue(color.stop_colorizing)
+ self.assertFalse(color.allow_colorizing)
+
+ # Toggle on while colorizing not in progress.
+ color.colorizing = False
+ color.toggle_colorize_event()
+ eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
+ self.assertFalse(color.colorizing)
+ self.assertTrue(color.stop_colorizing)
+ self.assertTrue(color.allow_colorizing)
+
+ @mock.patch.object(colorizer.ColorDelegator, 'recolorize_main')
+ def test_recolorize(self, mock_recmain):
+ text = self.text
+ color = self.color
+ eq = self.assertEqual
+ # Call recolorize manually and not scheduled.
+ text.after_cancel(color.after_id)
+
+ # No delegate.
+ save_delegate = color.delegate
+ color.delegate = None
+ color.recolorize()
+ mock_recmain.assert_not_called()
+ color.delegate = save_delegate
+
+ # Toggle off colorizing.
+ color.allow_colorizing = False
+ color.recolorize()
+ mock_recmain.assert_not_called()
+ color.allow_colorizing = True
+
+ # Colorizing in progress.
+ color.colorizing = True
+ color.recolorize()
+ mock_recmain.assert_not_called()
+ color.colorizing = False
+
+ # Colorizing is done, but not completed, so rescheduled.
+ color.recolorize()
+ self.assertFalse(color.stop_colorizing)
+ self.assertFalse(color.colorizing)
+ mock_recmain.assert_called()
+ eq(mock_recmain.call_count, 1)
+ # Rescheduled when TODO tag still exists.
+ eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
+
+ # No changes to text, so no scheduling added.
+ text.tag_remove('TODO', '1.0', 'end')
+ color.recolorize()
+ self.assertFalse(color.stop_colorizing)
+ self.assertFalse(color.colorizing)
+ mock_recmain.assert_called()
+ eq(mock_recmain.call_count, 2)
+ self.assertIsNone(color.after_id)
+
+ @mock.patch.object(colorizer.ColorDelegator, 'notify_range')
+ def test_recolorize_main(self, mock_notify):
+ text = self.text
+ color = self.color
+ eq = self.assertEqual
+
+ text.insert('insert', source)
+ expected = (('1.0', ('KEYWORD',)), ('1.2', ()), ('1.3', ('KEYWORD',)),
+ ('1.7', ()), ('1.9', ('BUILTIN',)), ('1.14', ('STRING',)),
+ ('1.19', ('COMMENT',)),
+ ('2.1', ('KEYWORD',)), ('2.18', ()), ('2.25', ('COMMENT',)),
+ ('3.6', ('BUILTIN',)), ('3.12', ('KEYWORD',)), ('3.21', ('COMMENT',)),
+ ('4.0', ('KEYWORD',)), ('4.3', ()), ('4.6', ()),
+ ('5.2', ('STRING',)), ('5.8', ('KEYWORD',)), ('5.10', ('STRING',)),
+ ('6.0', ('KEYWORD',)), ('6.10', ('DEFINITION',)), ('6.11', ()),
+ ('7.0', ('STRING',)), ('7.4', ()), ('7.5', ('STRING',)),
+ ('7.12', ()), ('7.14', ('STRING',)),
+ # SYNC at the end of every line.
+ ('1.55', ('SYNC',)), ('2.50', ('SYNC',)), ('3.34', ('SYNC',)),
+ )
+
+ # Nothing marked to do therefore no tags in text.
+ text.tag_remove('TODO', '1.0', 'end')
+ color.recolorize_main()
+ for tag in text.tag_names():
+ with self.subTest(tag=tag):
+ eq(text.tag_ranges(tag), ())
+
+ # Source marked for processing.
+ text.tag_add('TODO', '1.0', 'end')
+ # Check some indexes.
+ color.recolorize_main()
+ for index, expected_tags in expected:
+ with self.subTest(index=index):
+ eq(text.tag_names(index), expected_tags)
+
+ # Check for some tags for ranges.
+ eq(text.tag_nextrange('TODO', '1.0'), ())
+ eq(text.tag_nextrange('KEYWORD', '1.0'), ('1.0', '1.2'))
+ eq(text.tag_nextrange('COMMENT', '2.0'), ('2.22', '2.43'))
+ eq(text.tag_nextrange('SYNC', '2.0'), ('2.43', '3.0'))
+ eq(text.tag_nextrange('STRING', '2.0'), ('4.17', '4.53'))
+ eq(text.tag_nextrange('STRING', '7.0'), ('7.0', '7.3'))
+ eq(text.tag_nextrange('STRING', '7.3'), ('7.5', '7.12'))
+ eq(text.tag_nextrange('STRING', '7.12'), ('7.14', '7.17'))
+ eq(text.tag_nextrange('STRING', '7.17'), ('7.19', '7.26'))
+ eq(text.tag_nextrange('SYNC', '7.0'), ('7.26', '9.0'))
+
+ @mock.patch.object(colorizer.ColorDelegator, 'recolorize')
+ @mock.patch.object(colorizer.ColorDelegator, 'notify_range')
+ def test_removecolors(self, mock_notify, mock_recolorize):
+ text = self.text
+ color = self.color
+ text.insert('insert', source)
+
+ color.recolorize_main()
+ # recolorize_main doesn't add these tags.
+ text.tag_add("ERROR", "1.0")
+ text.tag_add("TODO", "1.0")
+ text.tag_add("hit", "1.0")
+ for tag in color.tagdefs:
+ with self.subTest(tag=tag):
+ self.assertNotEqual(text.tag_ranges(tag), ())
+
+ color.removecolors()
+ for tag in color.tagdefs:
+ with self.subTest(tag=tag):
+ self.assertEqual(text.tag_ranges(tag), ())
if __name__ == '__main__':
-"Test config_key, coverage 75%"
+"""Test config_key, coverage 98%.
+
+Coverage is effectively 100%. Tkinter dialog is mocked, Mac-only line
+may be skipped, and dummy function in bind test should not be called.
+Not tested: exit with 'self.advanced or self.keys_ok(keys)) ...' False.
+"""
from idlelib import config_key
from test.support import requires
import unittest
-from tkinter import Tk
+from unittest import mock
+from tkinter import Tk, TclError
from idlelib.idle_test.mock_idle import Func
from idlelib.idle_test.mock_tk import Mbox_func
+gkd = config_key.GetKeysDialog
+
class ValidationTest(unittest.TestCase):
- "Test validation methods: OK, KeysOK, bind_ok."
+ "Test validation methods: ok, keys_ok, bind_ok."
- class Validator(config_key.GetKeysDialog):
+ class Validator(gkd):
def __init__(self, *args, **kwargs):
config_key.GetKeysDialog.__init__(self, *args, **kwargs)
- class listKeysFinal:
+ class list_keys_final:
get = Func()
- self.listKeysFinal = listKeysFinal
- GetModifiers = Func()
+ self.list_keys_final = list_keys_final
+ get_modifiers = Func()
showerror = Mbox_func()
@classmethod
@classmethod
def tearDownClass(cls):
- cls.dialog.Cancel()
+ cls.dialog.cancel()
cls.root.update_idletasks()
cls.root.destroy()
del cls.dialog, cls.root
# A test that sets a non-blank modifier list should reset it to [].
def test_ok_empty(self):
- self.dialog.keyString.set(' ')
- self.dialog.OK()
+ self.dialog.key_string.set(' ')
+ self.dialog.ok()
self.assertEqual(self.dialog.result, '')
self.assertEqual(self.dialog.showerror.message, 'No key specified.')
def test_ok_good(self):
- self.dialog.keyString.set('<Key-F11>')
- self.dialog.listKeysFinal.get.result = 'F11'
- self.dialog.OK()
+ self.dialog.key_string.set('<Key-F11>')
+ self.dialog.list_keys_final.get.result = 'F11'
+ self.dialog.ok()
self.assertEqual(self.dialog.result, '<Key-F11>')
self.assertEqual(self.dialog.showerror.message, '')
def test_keys_no_ending(self):
- self.assertFalse(self.dialog.KeysOK('<Control-Shift'))
+ self.assertFalse(self.dialog.keys_ok('<Control-Shift'))
self.assertIn('Missing the final', self.dialog.showerror.message)
def test_keys_no_modifier_bad(self):
- self.dialog.listKeysFinal.get.result = 'A'
- self.assertFalse(self.dialog.KeysOK('<Key-A>'))
+ self.dialog.list_keys_final.get.result = 'A'
+ self.assertFalse(self.dialog.keys_ok('<Key-A>'))
self.assertIn('No modifier', self.dialog.showerror.message)
def test_keys_no_modifier_ok(self):
- self.dialog.listKeysFinal.get.result = 'F11'
- self.assertTrue(self.dialog.KeysOK('<Key-F11>'))
+ self.dialog.list_keys_final.get.result = 'F11'
+ self.assertTrue(self.dialog.keys_ok('<Key-F11>'))
self.assertEqual(self.dialog.showerror.message, '')
def test_keys_shift_bad(self):
- self.dialog.listKeysFinal.get.result = 'a'
- self.dialog.GetModifiers.result = ['Shift']
- self.assertFalse(self.dialog.KeysOK('<a>'))
+ self.dialog.list_keys_final.get.result = 'a'
+ self.dialog.get_modifiers.result = ['Shift']
+ self.assertFalse(self.dialog.keys_ok('<a>'))
self.assertIn('shift modifier', self.dialog.showerror.message)
- self.dialog.GetModifiers.result = []
+ self.dialog.get_modifiers.result = []
def test_keys_dup(self):
for mods, final, seq in (([], 'F12', '<Key-F12>'),
(['Control'], 'x', '<Control-Key-x>'),
(['Control'], 'X', '<Control-Key-X>')):
with self.subTest(m=mods, f=final, s=seq):
- self.dialog.listKeysFinal.get.result = final
- self.dialog.GetModifiers.result = mods
- self.assertFalse(self.dialog.KeysOK(seq))
+ self.dialog.list_keys_final.get.result = final
+ self.dialog.get_modifiers.result = mods
+ self.assertFalse(self.dialog.keys_ok(seq))
self.assertIn('already in use', self.dialog.showerror.message)
- self.dialog.GetModifiers.result = []
+ self.dialog.get_modifiers.result = []
def test_bind_ok(self):
self.assertTrue(self.dialog.bind_ok('<Control-Shift-Key-a>'))
self.assertIn('not accepted', self.dialog.showerror.message)
+class ToggleLevelTest(unittest.TestCase):
+ "Test toggle between Basic and Advanced frames."
+
+ @classmethod
+ def setUpClass(cls):
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
+ cls.dialog = gkd(cls.root, 'Title', '<<Test>>', [], _utest=True)
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.dialog.cancel()
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.dialog, cls.root
+
+ def test_toggle_level(self):
+ dialog = self.dialog
+
+ def stackorder():
+ """Get the stack order of the children of the frame.
+
+ winfo_children() stores the children in stack order, so
+ this can be used to check whether a frame is above or
+ below another one.
+ """
+ for index, child in enumerate(dialog.frame.winfo_children()):
+ if child._name == 'keyseq_basic':
+ basic = index
+ if child._name == 'keyseq_advanced':
+ advanced = index
+ return basic, advanced
+
+ # New window starts at basic level.
+ self.assertFalse(dialog.advanced)
+ self.assertIn('Advanced', dialog.button_level['text'])
+ basic, advanced = stackorder()
+ self.assertGreater(basic, advanced)
+
+ # Toggle to advanced.
+ dialog.toggle_level()
+ self.assertTrue(dialog.advanced)
+ self.assertIn('Basic', dialog.button_level['text'])
+ basic, advanced = stackorder()
+ self.assertGreater(advanced, basic)
+
+ # Toggle to basic.
+ dialog.button_level.invoke()
+ self.assertFalse(dialog.advanced)
+ self.assertIn('Advanced', dialog.button_level['text'])
+ basic, advanced = stackorder()
+ self.assertGreater(basic, advanced)
+
+
+class KeySelectionTest(unittest.TestCase):
+ "Test selecting key on Basic frames."
+
+ class Basic(gkd):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ class list_keys_final:
+ get = Func()
+ select_clear = Func()
+ yview = Func()
+ self.list_keys_final = list_keys_final
+ def set_modifiers_for_platform(self):
+ self.modifiers = ['foo', 'bar', 'BAZ']
+ self.modifier_label = {'BAZ': 'ZZZ'}
+ showerror = Mbox_func()
+
+ @classmethod
+ def setUpClass(cls):
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
+ cls.dialog = cls.Basic(cls.root, 'Title', '<<Test>>', [], _utest=True)
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.dialog.cancel()
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.dialog, cls.root
+
+ def setUp(self):
+ self.dialog.clear_key_seq()
+
+ def test_get_modifiers(self):
+ dialog = self.dialog
+ gm = dialog.get_modifiers
+ eq = self.assertEqual
+
+ # Modifiers are set on/off by invoking the checkbutton.
+ dialog.modifier_checkbuttons['foo'].invoke()
+ eq(gm(), ['foo'])
+
+ dialog.modifier_checkbuttons['BAZ'].invoke()
+ eq(gm(), ['foo', 'BAZ'])
+
+ dialog.modifier_checkbuttons['foo'].invoke()
+ eq(gm(), ['BAZ'])
+
+ @mock.patch.object(gkd, 'get_modifiers')
+ def test_build_key_string(self, mock_modifiers):
+ dialog = self.dialog
+ key = dialog.list_keys_final
+ string = dialog.key_string.get
+ eq = self.assertEqual
+
+ key.get.result = 'a'
+ mock_modifiers.return_value = []
+ dialog.build_key_string()
+ eq(string(), '<Key-a>')
+
+ mock_modifiers.return_value = ['mymod']
+ dialog.build_key_string()
+ eq(string(), '<mymod-Key-a>')
+
+ key.get.result = ''
+ mock_modifiers.return_value = ['mymod', 'test']
+ dialog.build_key_string()
+ eq(string(), '<mymod-test>')
+
+ @mock.patch.object(gkd, 'get_modifiers')
+ def test_final_key_selected(self, mock_modifiers):
+ dialog = self.dialog
+ key = dialog.list_keys_final
+ string = dialog.key_string.get
+ eq = self.assertEqual
+
+ mock_modifiers.return_value = ['Shift']
+ key.get.result = '{'
+ dialog.final_key_selected()
+ eq(string(), '<Shift-Key-braceleft>')
+
+
+class CancelTest(unittest.TestCase):
+ "Simulate user clicking [Cancel] button."
+
+ @classmethod
+ def setUpClass(cls):
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
+ cls.dialog = gkd(cls.root, 'Title', '<<Test>>', [], _utest=True)
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.dialog.cancel()
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.dialog, cls.root
+
+ def test_cancel(self):
+ self.assertEqual(self.dialog.winfo_class(), 'Toplevel')
+ self.dialog.button_cancel.invoke()
+ with self.assertRaises(TclError):
+ self.dialog.winfo_class()
+ self.assertEqual(self.dialog.result, '')
+
+
+class HelperTest(unittest.TestCase):
+ "Test module level helper functions."
+
+ def test_translate_key(self):
+ tr = config_key.translate_key
+ eq = self.assertEqual
+
+ # Letters return unchanged with no 'Shift'.
+ eq(tr('q', []), 'Key-q')
+ eq(tr('q', ['Control', 'Alt']), 'Key-q')
+
+ # 'Shift' uppercases single lowercase letters.
+ eq(tr('q', ['Shift']), 'Key-Q')
+ eq(tr('q', ['Control', 'Shift']), 'Key-Q')
+ eq(tr('q', ['Control', 'Alt', 'Shift']), 'Key-Q')
+
+ # Convert key name to keysym.
+ eq(tr('Page Up', []), 'Key-Prior')
+ # 'Shift' doesn't change case when it's not a single char.
+ eq(tr('*', ['Shift']), 'Key-asterisk')
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
button.invoke()
get = dialog._current_textview.viewframe.textframe.text.get
lines = printer._Printer__lines
+ if len(lines) < 2:
+ self.fail(name + ' full text was not found')
self.assertEqual(lines[0], get('1.0', '1.end'))
self.assertEqual(lines[1], get('2.0', '2.end'))
dialog._current_textview.destroy()
import unittest
from test.support import requires
-from tkinter import Tk, Frame ##, BooleanVar, StringVar
+from tkinter import Tk
+from tkinter.ttk import Frame
from idlelib import searchengine as se
from idlelib import searchbase as sdb
from idlelib.idle_test.mock_idle import Func
self.dialog.top = self.root
frame, label = self.dialog.make_frame()
self.assertEqual(label, '')
- self.assertIsInstance(frame, Frame)
+ self.assertEqual(str(type(frame)), "<class 'tkinter.ttk.Frame'>")
+ # self.assertIsInstance(frame, Frame) fails when test is run by
+ # test_idle not run from IDLE editor. See issue 33987 PR.
frame, label = self.dialog.make_frame('testlabel')
self.assertEqual(label['text'], 'testlabel')
- self.assertIsInstance(frame, Frame)
def btn_test_setup(self, meth):
self.dialog.top = self.root
+"Test squeezer, coverage 95%"
+
from collections import namedtuple
+from textwrap import dedent
from tkinter import Text, Tk
import unittest
from unittest.mock import Mock, NonCallableMagicMock, patch, sentinel, ANY
class CountLinesTest(unittest.TestCase):
"""Tests for the count_lines_with_wrapping function."""
- def check(self, expected, text, linewidth, tabwidth):
+ def check(self, expected, text, linewidth):
return self.assertEqual(
expected,
- count_lines_with_wrapping(text, linewidth, tabwidth),
+ count_lines_with_wrapping(text, linewidth),
)
def test_count_empty(self):
"""Test with several lines of text."""
self.assertEqual(count_lines_with_wrapping("1\n2\n3\n"), 3)
- def test_tab_width(self):
- """Test with various tab widths and line widths."""
- self.check(expected=1, text='\t' * 1, linewidth=8, tabwidth=4)
- self.check(expected=1, text='\t' * 2, linewidth=8, tabwidth=4)
- self.check(expected=2, text='\t' * 3, linewidth=8, tabwidth=4)
- self.check(expected=2, text='\t' * 4, linewidth=8, tabwidth=4)
- self.check(expected=3, text='\t' * 5, linewidth=8, tabwidth=4)
+ def test_empty_lines(self):
+ self.check(expected=1, text='\n', linewidth=80)
+ self.check(expected=2, text='\n\n', linewidth=80)
+ self.check(expected=10, text='\n' * 10, linewidth=80)
- # test longer lines and various tab widths
- self.check(expected=4, text='\t' * 10, linewidth=12, tabwidth=4)
- self.check(expected=10, text='\t' * 10, linewidth=12, tabwidth=8)
- self.check(expected=2, text='\t' * 4, linewidth=10, tabwidth=3)
+ def test_long_line(self):
+ self.check(expected=3, text='a' * 200, linewidth=80)
+ self.check(expected=3, text='a' * 200 + '\n', linewidth=80)
- # test tabwidth=1
- self.check(expected=2, text='\t' * 9, linewidth=5, tabwidth=1)
- self.check(expected=2, text='\t' * 10, linewidth=5, tabwidth=1)
- self.check(expected=3, text='\t' * 11, linewidth=5, tabwidth=1)
+ def test_several_lines_different_lengths(self):
+ text = dedent("""\
+ 13 characters
+ 43 is the number of characters on this line
- # test for off-by-one errors
- self.check(expected=2, text='\t' * 6, linewidth=12, tabwidth=4)
- self.check(expected=3, text='\t' * 6, linewidth=11, tabwidth=4)
- self.check(expected=2, text='\t' * 6, linewidth=13, tabwidth=4)
+ 7 chars
+ 13 characters""")
+ self.check(expected=5, text=text, linewidth=80)
+ self.check(expected=5, text=text + '\n', linewidth=80)
+ self.check(expected=6, text=text, linewidth=40)
+ self.check(expected=7, text=text, linewidth=20)
+ self.check(expected=11, text=text, linewidth=10)
class SqueezerTest(unittest.TestCase):
"""Tests for the Squeezer class."""
- def make_mock_editor_window(self):
+ def tearDown(self):
+ # Clean up the Squeezer class's reference to its instance,
+ # to avoid side-effects from one test case upon another.
+ if Squeezer._instance_weakref is not None:
+ Squeezer._instance_weakref = None
+
+ def make_mock_editor_window(self, with_text_widget=False):
"""Create a mock EditorWindow instance."""
editwin = NonCallableMagicMock()
# isinstance(editwin, PyShell) must be true for Squeezer to enable
- # auto-squeezing; in practice this will always be true
+ # auto-squeezing; in practice this will always be true.
editwin.__class__ = PyShell
+
+ if with_text_widget:
+ editwin.root = get_test_tk_root(self)
+ text_widget = self.make_text_widget(root=editwin.root)
+ editwin.text = editwin.per.bottom = text_widget
+
return editwin
def make_squeezer_instance(self, editor_window=None):
"""Create an actual Squeezer instance with a mock EditorWindow."""
if editor_window is None:
editor_window = self.make_mock_editor_window()
- return Squeezer(editor_window)
+ squeezer = Squeezer(editor_window)
+ squeezer.get_line_width = Mock(return_value=80)
+ return squeezer
+
+ def make_text_widget(self, root=None):
+ if root is None:
+ root = get_test_tk_root(self)
+ text_widget = Text(root)
+ text_widget["font"] = ('Courier', 10)
+ text_widget.mark_set("iomark", "1.0")
+ return text_widget
+
+ def set_idleconf_option_with_cleanup(self, configType, section, option, value):
+ prev_val = idleConf.GetOption(configType, section, option)
+ idleConf.SetOption(configType, section, option, value)
+ self.addCleanup(idleConf.SetOption,
+ configType, section, option, prev_val)
def test_count_lines(self):
- """Test Squeezer.count_lines() with various inputs.
-
- This checks that Squeezer.count_lines() calls the
- count_lines_with_wrapping() function with the appropriate parameters.
- """
- for tabwidth, linewidth in [(4, 80), (1, 79), (8, 80), (3, 120)]:
- self._test_count_lines_helper(linewidth=linewidth,
- tabwidth=tabwidth)
-
- def _prepare_mock_editwin_for_count_lines(self, editwin,
- linewidth, tabwidth):
- """Prepare a mock EditorWindow object for Squeezer.count_lines."""
- CHAR_WIDTH = 10
- BORDER_WIDTH = 2
- PADDING_WIDTH = 1
-
- # Prepare all the required functionality on the mock EditorWindow object
- # so that the calculations in Squeezer.count_lines() can run.
- editwin.get_tk_tabwidth.return_value = tabwidth
- editwin.text.winfo_width.return_value = \
- linewidth * CHAR_WIDTH + 2 * (BORDER_WIDTH + PADDING_WIDTH)
- text_opts = {
- 'border': BORDER_WIDTH,
- 'padx': PADDING_WIDTH,
- 'font': None,
- }
- editwin.text.cget = lambda opt: text_opts[opt]
-
- # monkey-path tkinter.font.Font with a mock object, so that
- # Font.measure('0') returns CHAR_WIDTH
- mock_font = Mock()
- def measure(char):
- if char == '0':
- return CHAR_WIDTH
- raise ValueError("measure should only be called on '0'!")
- mock_font.return_value.measure = measure
- patcher = patch('idlelib.squeezer.Font', mock_font)
- patcher.start()
- self.addCleanup(patcher.stop)
-
- def _test_count_lines_helper(self, linewidth, tabwidth):
- """Helper for test_count_lines."""
+ """Test Squeezer.count_lines() with various inputs."""
editwin = self.make_mock_editor_window()
- self._prepare_mock_editwin_for_count_lines(editwin, linewidth, tabwidth)
squeezer = self.make_squeezer_instance(editwin)
- mock_count_lines = Mock(return_value=SENTINEL_VALUE)
- text = 'TEXT'
- with patch('idlelib.squeezer.count_lines_with_wrapping',
- mock_count_lines):
- self.assertIs(squeezer.count_lines(text), SENTINEL_VALUE)
- mock_count_lines.assert_called_with(text, linewidth, tabwidth)
+ for text_code, line_width, expected in [
+ (r"'\n'", 80, 1),
+ (r"'\n' * 3", 80, 3),
+ (r"'a' * 40 + '\n'", 80, 1),
+ (r"'a' * 80 + '\n'", 80, 1),
+ (r"'a' * 200 + '\n'", 80, 3),
+ (r"'aa\t' * 20", 80, 2),
+ (r"'aa\t' * 21", 80, 3),
+ (r"'aa\t' * 20", 40, 4),
+ ]:
+ with self.subTest(text_code=text_code,
+ line_width=line_width,
+ expected=expected):
+ text = eval(text_code)
+ squeezer.get_line_width.return_value = line_width
+ self.assertEqual(squeezer.count_lines(text), expected)
def test_init(self):
"""Test the creation of Squeezer instances."""
def test_write_stdout(self):
"""Test Squeezer's overriding of the EditorWindow's write() method."""
editwin = self.make_mock_editor_window()
- self._prepare_mock_editwin_for_count_lines(editwin,
- linewidth=80, tabwidth=8)
for text in ['', 'TEXT']:
editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE)
def test_auto_squeeze(self):
"""Test that the auto-squeezing creates an ExpandingButton properly."""
- root = get_test_tk_root(self)
- text_widget = Text(root)
- text_widget.mark_set("iomark", "1.0")
-
- editwin = self.make_mock_editor_window()
- editwin.text = text_widget
+ editwin = self.make_mock_editor_window(with_text_widget=True)
+ text_widget = editwin.text
squeezer = self.make_squeezer_instance(editwin)
squeezer.auto_squeeze_min_lines = 5
squeezer.count_lines = Mock(return_value=6)
def test_squeeze_current_text_event(self):
"""Test the squeeze_current_text event."""
- root = get_test_tk_root(self)
-
- # squeezing text should work for both stdout and stderr
+ # Squeezing text should work for both stdout and stderr.
for tag_name in ["stdout", "stderr"]:
- text_widget = Text(root)
- text_widget.mark_set("iomark", "1.0")
-
- editwin = self.make_mock_editor_window()
- editwin.text = editwin.per.bottom = text_widget
+ editwin = self.make_mock_editor_window(with_text_widget=True)
+ text_widget = editwin.text
squeezer = self.make_squeezer_instance(editwin)
squeezer.count_lines = Mock(return_value=6)
- # prepare some text in the Text widget
+ # Prepare some text in the Text widget.
text_widget.insert("1.0", "SOME\nTEXT\n", tag_name)
text_widget.mark_set("insert", "1.0")
self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
self.assertEqual(len(squeezer.expandingbuttons), 0)
- # test squeezing the current text
+ # Test squeezing the current text.
retval = squeezer.squeeze_current_text_event(event=Mock())
self.assertEqual(retval, "break")
self.assertEqual(text_widget.get('1.0', 'end'), '\n\n')
self.assertEqual(len(squeezer.expandingbuttons), 1)
self.assertEqual(squeezer.expandingbuttons[0].s, 'SOME\nTEXT')
- # test that expanding the squeezed text works and afterwards the
- # Text widget contains the original text
+ # Test that expanding the squeezed text works and afterwards
+ # the Text widget contains the original text.
squeezer.expandingbuttons[0].expand(event=Mock())
self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
self.assertEqual(len(squeezer.expandingbuttons), 0)
def test_squeeze_current_text_event_no_allowed_tags(self):
"""Test that the event doesn't squeeze text without a relevant tag."""
- root = get_test_tk_root(self)
-
- text_widget = Text(root)
- text_widget.mark_set("iomark", "1.0")
-
- editwin = self.make_mock_editor_window()
- editwin.text = editwin.per.bottom = text_widget
+ editwin = self.make_mock_editor_window(with_text_widget=True)
+ text_widget = editwin.text
squeezer = self.make_squeezer_instance(editwin)
squeezer.count_lines = Mock(return_value=6)
- # prepare some text in the Text widget
+ # Prepare some text in the Text widget.
text_widget.insert("1.0", "SOME\nTEXT\n", "TAG")
text_widget.mark_set("insert", "1.0")
self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
self.assertEqual(len(squeezer.expandingbuttons), 0)
- # test squeezing the current text
+ # Test squeezing the current text.
retval = squeezer.squeeze_current_text_event(event=Mock())
self.assertEqual(retval, "break")
self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
def test_squeeze_text_before_existing_squeezed_text(self):
"""Test squeezing text before existing squeezed text."""
- root = get_test_tk_root(self)
-
- text_widget = Text(root)
- text_widget.mark_set("iomark", "1.0")
-
- editwin = self.make_mock_editor_window()
- editwin.text = editwin.per.bottom = text_widget
+ editwin = self.make_mock_editor_window(with_text_widget=True)
+ text_widget = editwin.text
squeezer = self.make_squeezer_instance(editwin)
squeezer.count_lines = Mock(return_value=6)
- # prepare some text in the Text widget and squeeze it
+ # Prepare some text in the Text widget and squeeze it.
text_widget.insert("1.0", "SOME\nTEXT\n", "stdout")
text_widget.mark_set("insert", "1.0")
squeezer.squeeze_current_text_event(event=Mock())
self.assertEqual(len(squeezer.expandingbuttons), 1)
- # test squeezing the current text
+ # Test squeezing the current text.
text_widget.insert("1.0", "MORE\nSTUFF\n", "stdout")
text_widget.mark_set("insert", "1.0")
retval = squeezer.squeeze_current_text_event(event=Mock())
squeezer.expandingbuttons[1],
))
- GetOptionSignature = namedtuple('GetOptionSignature',
- 'configType section option default type warn_on_default raw')
- @classmethod
- def _make_sig(cls, configType, section, option, default=sentinel.NOT_GIVEN,
- type=sentinel.NOT_GIVEN,
- warn_on_default=sentinel.NOT_GIVEN,
- raw=sentinel.NOT_GIVEN):
- return cls.GetOptionSignature(configType, section, option, default,
- type, warn_on_default, raw)
-
- @classmethod
- def get_GetOption_signature(cls, mock_call_obj):
- args, kwargs = mock_call_obj[-2:]
- return cls._make_sig(*args, **kwargs)
-
def test_reload(self):
"""Test the reload() class-method."""
- self.assertIsInstance(Squeezer.auto_squeeze_min_lines, int)
- idleConf.SetOption('main', 'PyShell', 'auto-squeeze-min-lines', '42')
+ editwin = self.make_mock_editor_window(with_text_widget=True)
+ squeezer = self.make_squeezer_instance(editwin)
+ squeezer.load_font = Mock()
+
+ orig_auto_squeeze_min_lines = squeezer.auto_squeeze_min_lines
+
+ # Increase auto-squeeze-min-lines.
+ new_auto_squeeze_min_lines = orig_auto_squeeze_min_lines + 10
+ self.set_idleconf_option_with_cleanup(
+ 'main', 'PyShell', 'auto-squeeze-min-lines',
+ str(new_auto_squeeze_min_lines))
+
+ Squeezer.reload()
+ self.assertEqual(squeezer.auto_squeeze_min_lines,
+ new_auto_squeeze_min_lines)
+ squeezer.load_font.assert_called()
+
+ def test_reload_no_squeezer_instances(self):
+ """Test that Squeezer.reload() runs without any instances existing."""
Squeezer.reload()
- self.assertEqual(Squeezer.auto_squeeze_min_lines, 42)
class ExpandingButtonTest(unittest.TestCase):
squeezer = Mock()
squeezer.editwin.text = Text(root)
- # Set default values for the configuration settings
+ # Set default values for the configuration settings.
squeezer.auto_squeeze_min_lines = 50
return squeezer
expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
self.assertEqual(expandingbutton.s, 'TEXT')
- # check that the underlying tkinter.Button is properly configured
+ # Check that the underlying tkinter.Button is properly configured.
self.assertEqual(expandingbutton.master, text_widget)
self.assertTrue('50 lines' in expandingbutton.cget('text'))
- # check that the text widget still contains no text
+ # Check that the text widget still contains no text.
self.assertEqual(text_widget.get('1.0', 'end'), '\n')
- # check that the mouse events are bound
+ # Check that the mouse events are bound.
self.assertIn('<Double-Button-1>', expandingbutton.bind())
right_button_code = '<Button-%s>' % ('2' if macosx.isAquaTk() else '3')
self.assertIn(right_button_code, expandingbutton.bind())
- # check that ToolTip was called once, with appropriate values
+ # Check that ToolTip was called once, with appropriate values.
self.assertEqual(MockHovertip.call_count, 1)
MockHovertip.assert_called_with(expandingbutton, ANY, hover_delay=ANY)
- # check that 'right-click' appears in the tooltip text
+ # Check that 'right-click' appears in the tooltip text.
tooltip_text = MockHovertip.call_args[0][1]
self.assertIn('right-click', tooltip_text.lower())
squeezer = self.make_mock_squeezer()
expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
- # insert the button into the text widget
- # (this is normally done by the Squeezer class)
+ # Insert the button into the text widget
+ # (this is normally done by the Squeezer class).
text_widget = expandingbutton.text
text_widget.window_create("1.0", window=expandingbutton)
- # set base_text to the text widget, so that changes are actually made
- # to it (by ExpandingButton) and we can inspect these changes afterwards
+ # Set base_text to the text widget, so that changes are actually
+ # made to it (by ExpandingButton) and we can inspect these
+ # changes afterwards.
expandingbutton.base_text = expandingbutton.text
# trigger the expand event
retval = expandingbutton.expand(event=Mock())
self.assertEqual(retval, None)
- # check that the text was inserted into the text widget
+ # Check that the text was inserted into the text widget.
self.assertEqual(text_widget.get('1.0', 'end'), 'TEXT\n')
- # check that the 'TAGS' tag was set on the inserted text
+ # Check that the 'TAGS' tag was set on the inserted text.
text_end_index = text_widget.index('end-1c')
self.assertEqual(text_widget.get('1.0', text_end_index), 'TEXT')
self.assertEqual(text_widget.tag_nextrange('TAGS', '1.0'),
('1.0', text_end_index))
- # check that the button removed itself from squeezer.expandingbuttons
+ # Check that the button removed itself from squeezer.expandingbuttons.
self.assertEqual(squeezer.expandingbuttons.remove.call_count, 1)
squeezer.expandingbuttons.remove.assert_called_with(expandingbutton)
expandingbutton.set_is_dangerous()
self.assertTrue(expandingbutton.is_dangerous)
- # insert the button into the text widget
- # (this is normally done by the Squeezer class)
+ # Insert the button into the text widget
+ # (this is normally done by the Squeezer class).
text_widget = expandingbutton.text
text_widget.window_create("1.0", window=expandingbutton)
- # set base_text to the text widget, so that changes are actually made
- # to it (by ExpandingButton) and we can inspect these changes afterwards
+ # Set base_text to the text widget, so that changes are actually
+ # made to it (by ExpandingButton) and we can inspect these
+ # changes afterwards.
expandingbutton.base_text = expandingbutton.text
- # patch the message box module to always return False
+ # Patch the message box module to always return False.
with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox:
mock_msgbox.askokcancel.return_value = False
mock_msgbox.askyesno.return_value = False
-
- # trigger the expand event
+ # Trigger the expand event.
retval = expandingbutton.expand(event=Mock())
- # check that the event chain was broken and no text was inserted
+ # Check that the event chain was broken and no text was inserted.
self.assertEqual(retval, 'break')
self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), '')
- # patch the message box module to always return True
+ # Patch the message box module to always return True.
with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox:
mock_msgbox.askokcancel.return_value = True
mock_msgbox.askyesno.return_value = True
-
- # trigger the expand event
+ # Trigger the expand event.
retval = expandingbutton.expand(event=Mock())
- # check that the event chain wasn't broken and the text was inserted
+ # Check that the event chain wasn't broken and the text was inserted.
self.assertEqual(retval, None)
self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), text)
def test_copy(self):
"""Test the copy event."""
- # testing with the actual clipboard proved problematic, so this test
- # replaces the clipboard manipulation functions with mocks and checks
- # that they are called appropriately
+ # Testing with the actual clipboard proved problematic, so this
+ # test replaces the clipboard manipulation functions with mocks
+ # and checks that they are called appropriately.
squeezer = self.make_mock_squeezer()
expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
expandingbutton.clipboard_clear = Mock()
expandingbutton.clipboard_append = Mock()
- # trigger the copy event
+ # Trigger the copy event.
retval = expandingbutton.copy(event=Mock())
self.assertEqual(retval, None)
- # check that the expanding button called clipboard_clear() and
- # clipboard_append('TEXT') once each
+ # Vheck that the expanding button called clipboard_clear() and
+ # clipboard_append('TEXT') once each.
self.assertEqual(expandingbutton.clipboard_clear.call_count, 1)
self.assertEqual(expandingbutton.clipboard_append.call_count, 1)
expandingbutton.clipboard_append.assert_called_with('TEXT')
with patch('idlelib.squeezer.view_text', autospec=view_text)\
as mock_view_text:
- # trigger the view event
+ # Trigger the view event.
expandingbutton.view(event=Mock())
- # check that the expanding button called view_text
+ # Check that the expanding button called view_text.
self.assertEqual(mock_view_text.call_count, 1)
- # check that the proper text was passed
+ # Check that the proper text was passed.
self.assertEqual(mock_view_text.call_args[0][2], 'TEXT')
def test_rmenu(self):
del mainmenu.menudefs[-1][1][0:2]
# Remove the 'Configure Idle' entry from the options menu, it is in the
# application menu as 'Preferences'
- del mainmenu.menudefs[-2][1][0]
+ del mainmenu.menudefs[-3][1][0:2]
menubar = Menu(root)
root.configure(menu=menubar)
menudict = {}
('_View Last Restart', '<<view-restart>>'),
('_Restart Shell', '<<restart-shell>>'),
None,
+ ('_Previous History', '<<history-previous>>'),
+ ('_Next History', '<<history-next>>'),
+ None,
('_Interrupt Execution', '<<interrupt-execution>>'),
]),
('options', [
('Configure _IDLE', '<<open-config-dialog>>'),
- ('_Code Context', '<<toggle-code-context>>'),
+ None,
+ ('Show _Code Context', '<<toggle-code-context>>'),
+ ('Zoom Height', '<<zoom-height>>'),
]),
('window', [
- ('Zoom Height', '<<zoom-height>>'),
]),
('help', [
EditorWindow.__init__(self, *args)
self.text.bind("<<goto-file-line>>", self.goto_file_line)
self.text.unbind("<<toggle-code-context>>")
+ self.update_menu_state('options', '*Code Context', 'disabled')
# Customize EditorWindow
def ispythonsource(self, filename):
self.usetabs = True
# indentwidth must be 8 when using tabs. See note in EditorWindow:
self.indentwidth = 8
-
+ self.context_use_ps1 = True
self.sys_ps1 = sys.ps1 if hasattr(sys, 'ps1') else '>>> '
self.prompt_last_line = self.sys_ps1.split('\n')[-1]
self.prompt = self.sys_ps1 # Changes when debug active
if use_subprocess:
text.bind("<<view-restart>>", self.view_restart_mark)
text.bind("<<restart-shell>>", self.restart_shell)
+ squeezer = self.Squeezer(self)
+ text.bind("<<squeeze-current-text>>",
+ squeezer.squeeze_current_text_event)
self.save_stdout = sys.stdout
self.save_stderr = sys.stderr
if system() == 'Windows':
iconfile = os.path.join(icondir, 'idle.ico')
root.wm_iconbitmap(default=iconfile)
- else:
+ elif not macosx.isAquaTk():
ext = '.png' if TkVersion >= 8.6 else '.gif'
iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
for size in (16, 32, 48)]
"""
Dialogs that query users and verify the answer before accepting.
-Use ttk widgets, limiting use to tcl/tk 8.5+, as in IDLE 3.6+.
Query is the generic base class for a popup dialog.
The user must either enter a valid answer or close the dialog.
def _replace_dialog(parent): # htest #
from tkinter import Toplevel, Text, END, SEL
- from tkinter.ttk import Button
+ from tkinter.ttk import Frame, Button
- box = Toplevel(parent)
- box.title("Test ReplaceDialog")
+ top = Toplevel(parent)
+ top.title("Test ReplaceDialog")
x, y = map(int, parent.geometry().split('+')[1:])
- box.geometry("+%d+%d" % (x, y + 175))
+ top.geometry("+%d+%d" % (x, y + 175))
# mock undo delegator methods
def undo_block_start():
def undo_block_stop():
pass
- text = Text(box, inactiveselectbackground='gray')
+ frame = Frame(top)
+ frame.pack()
+ text = Text(frame, inactiveselectbackground='gray')
text.undo_block_start = undo_block_start
text.undo_block_stop = undo_block_stop
text.pack()
replace(text)
text.tag_remove(SEL, "1.0", END)
- button = Button(box, text="Replace", command=show_replace)
+ button = Button(frame, text="Replace", command=show_replace)
button.pack()
if __name__ == '__main__':
from tkinter import *
-from tkinter.ttk import Scrollbar
+from tkinter.ttk import Frame, Scrollbar
from idlelib import macosx
def _search_dialog(parent): # htest #
"Display search test box."
from tkinter import Toplevel, Text
- from tkinter.ttk import Button
+ from tkinter.ttk import Frame, Button
- box = Toplevel(parent)
- box.title("Test SearchDialog")
+ top = Toplevel(parent)
+ top.title("Test SearchDialog")
x, y = map(int, parent.geometry().split('+')[1:])
- box.geometry("+%d+%d" % (x, y + 175))
- text = Text(box, inactiveselectbackground='gray')
+ top.geometry("+%d+%d" % (x, y + 175))
+
+ frame = Frame(top)
+ frame.pack()
+ text = Text(frame, inactiveselectbackground='gray')
text.pack()
text.insert("insert","This is a sample string.\n"*5)
_setup(text).open(text)
text.tag_remove('sel', '1.0', 'end')
- button = Button(box, text="Search (selection ignored)", command=show_find)
+ button = Button(frame, text="Search (selection ignored)", command=show_find)
button.pack()
if __name__ == '__main__':
'''Define SearchDialogBase used by Search, Replace, and Grep dialogs.'''
-from tkinter import Toplevel, Frame
-from tkinter.ttk import Entry, Label, Button, Checkbutton, Radiobutton
+from tkinter import Toplevel
+from tkinter.ttk import Frame, Entry, Label, Button, Checkbutton, Radiobutton
class SearchDialogBase:
icon (of dialog): ditto, use unclear if cannot minimize dialog.
'''
self.root = root
+ self.bell = root.bell
self.engine = engine
self.top = None
top.wm_title(self.title)
top.wm_iconname(self.icon)
self.top = top
- self.bell = top.bell
self.row = 0
self.top.grid_columnconfigure(0, pad=2, weight=0)
messages and their tracebacks.
"""
import re
+import weakref
import tkinter as tk
from tkinter.font import Font
from idlelib import macosx
-def count_lines_with_wrapping(s, linewidth=80, tabwidth=8):
+def count_lines_with_wrapping(s, linewidth=80):
"""Count the number of lines in a given string.
Lines are counted as if the string was wrapped so that lines are never over
Tabs are considered tabwidth characters long.
"""
+ tabwidth = 8 # Currently always true in Shell.
pos = 0
linecount = 1
current_column = 0
for m in re.finditer(r"[\t\n]", s):
- # process the normal chars up to tab or newline
+ # Process the normal chars up to tab or newline.
numchars = m.start() - pos
pos += numchars
current_column += numchars
- # deal with tab or newline
+ # Deal with tab or newline.
if s[pos] == '\n':
+ # Avoid the `current_column == 0` edge-case, and while we're
+ # at it, don't bother adding 0.
+ if current_column > linewidth:
+ # If the current column was exactly linewidth, divmod
+ # would give (1,0), even though a new line hadn't yet
+ # been started. The same is true if length is any exact
+ # multiple of linewidth. Therefore, subtract 1 before
+ # dividing a non-empty line.
+ linecount += (current_column - 1) // linewidth
linecount += 1
current_column = 0
else:
assert s[pos] == '\t'
current_column += tabwidth - (current_column % tabwidth)
- # if a tab passes the end of the line, consider the entire tab as
- # being on the next line
+ # If a tab passes the end of the line, consider the entire
+ # tab as being on the next line.
if current_column > linewidth:
linecount += 1
current_column = tabwidth
- pos += 1 # after the tab or newline
-
- # avoid divmod(-1, linewidth)
- if current_column > 0:
- # If the length was exactly linewidth, divmod would give (1,0),
- # even though a new line hadn't yet been started. The same is true
- # if length is any exact multiple of linewidth. Therefore, subtract
- # 1 before doing divmod, and later add 1 to the column to
- # compensate.
- lines, column = divmod(current_column - 1, linewidth)
- linecount += lines
- current_column = column + 1
+ pos += 1 # After the tab or newline.
- # process remaining chars (no more tabs or newlines)
+ # Process remaining chars (no more tabs or newlines).
current_column += len(s) - pos
- # avoid divmod(-1, linewidth)
+ # Avoid divmod(-1, linewidth).
if current_column > 0:
linecount += (current_column - 1) // linewidth
else:
- # the text ended with a newline; don't count an extra line after it
+ # Text ended with newline; don't count an extra line after it.
linecount -= 1
return linecount
self.squeezer = squeezer
self.editwin = editwin = squeezer.editwin
self.text = text = editwin.text
-
- # the base Text widget of the PyShell object, used to change text
- # before the iomark
+ # The base Text widget is needed to change text before iomark.
self.base_text = editwin.per.bottom
- button_text = "Squeezed text (%d lines)." % self.numoflines
+ line_plurality = "lines" if numoflines != 1 else "line"
+ button_text = f"Squeezed text ({numoflines} {line_plurality})."
tk.Button.__init__(self, text, text=button_text,
background="#FFFFC0", activebackground="#FFFFE0")
self.bind("<Button-2>", self.context_menu_event)
else:
self.bind("<Button-3>", self.context_menu_event)
- self.selection_handle(
+ self.selection_handle( # X windows only.
lambda offset, length: s[int(offset):int(offset) + int(length)])
self.is_dangerous = None
modal=False, wrap='none')
rmenu_specs = (
- # item structure: (label, method_name)
+ # Item structure: (label, method_name).
('copy', 'copy'),
('view', 'view'),
)
This avoids IDLE's shell slowing down considerably, and even becoming
completely unresponsive, when very long outputs are written.
"""
+ _instance_weakref = None
+
@classmethod
def reload(cls):
"""Load class variables from config."""
type="int", default=50,
)
+ # Loading the font info requires a Tk root. IDLE doesn't rely
+ # on Tkinter's "default root", so the instance will reload
+ # font info using its editor windows's Tk root.
+ if cls._instance_weakref is not None:
+ instance = cls._instance_weakref()
+ if instance is not None:
+ instance.load_font()
+
def __init__(self, editwin):
"""Initialize settings for Squeezer.
self.editwin = editwin
self.text = text = editwin.text
- # Get the base Text widget of the PyShell object, used to change text
- # before the iomark. PyShell deliberately disables changing text before
- # the iomark via its 'text' attribute, which is actually a wrapper for
- # the actual Text widget. Squeezer, however, needs to make such changes.
+ # Get the base Text widget of the PyShell object, used to change
+ # text before the iomark. PyShell deliberately disables changing
+ # text before the iomark via its 'text' attribute, which is
+ # actually a wrapper for the actual Text widget. Squeezer,
+ # however, needs to make such changes.
self.base_text = editwin.per.bottom
+ Squeezer._instance_weakref = weakref.ref(self)
+ self.load_font()
+
+ # Twice the text widget's border width and internal padding;
+ # pre-calculated here for the get_line_width() method.
+ self.window_width_delta = 2 * (
+ int(text.cget('border')) +
+ int(text.cget('padx'))
+ )
+
self.expandingbuttons = []
- from idlelib.pyshell import PyShell # done here to avoid import cycle
- if isinstance(editwin, PyShell):
- # If we get a PyShell instance, replace its write method with a
- # wrapper, which inserts an ExpandingButton instead of a long text.
- def mywrite(s, tags=(), write=editwin.write):
- # only auto-squeeze text which has just the "stdout" tag
- if tags != "stdout":
- return write(s, tags)
-
- # only auto-squeeze text with at least the minimum
- # configured number of lines
- numoflines = self.count_lines(s)
- if numoflines < self.auto_squeeze_min_lines:
- return write(s, tags)
-
- # create an ExpandingButton instance
- expandingbutton = ExpandingButton(s, tags, numoflines,
- self)
-
- # insert the ExpandingButton into the Text widget
- text.mark_gravity("iomark", tk.RIGHT)
- text.window_create("iomark", window=expandingbutton,
- padx=3, pady=5)
- text.see("iomark")
- text.update()
- text.mark_gravity("iomark", tk.LEFT)
-
- # add the ExpandingButton to the Squeezer's list
- self.expandingbuttons.append(expandingbutton)
-
- editwin.write = mywrite
+
+ # Replace the PyShell instance's write method with a wrapper,
+ # which inserts an ExpandingButton instead of a long text.
+ def mywrite(s, tags=(), write=editwin.write):
+ # Only auto-squeeze text which has just the "stdout" tag.
+ if tags != "stdout":
+ return write(s, tags)
+
+ # Only auto-squeeze text with at least the minimum
+ # configured number of lines.
+ auto_squeeze_min_lines = self.auto_squeeze_min_lines
+ # First, a very quick check to skip very short texts.
+ if len(s) < auto_squeeze_min_lines:
+ return write(s, tags)
+ # Now the full line-count check.
+ numoflines = self.count_lines(s)
+ if numoflines < auto_squeeze_min_lines:
+ return write(s, tags)
+
+ # Create an ExpandingButton instance.
+ expandingbutton = ExpandingButton(s, tags, numoflines, self)
+
+ # Insert the ExpandingButton into the Text widget.
+ text.mark_gravity("iomark", tk.RIGHT)
+ text.window_create("iomark", window=expandingbutton,
+ padx=3, pady=5)
+ text.see("iomark")
+ text.update()
+ text.mark_gravity("iomark", tk.LEFT)
+
+ # Add the ExpandingButton to the Squeezer's list.
+ self.expandingbuttons.append(expandingbutton)
+
+ editwin.write = mywrite
def count_lines(self, s):
"""Count the number of lines in a given text.
Tabs are considered tabwidth characters long.
"""
- # Tab width is configurable
- tabwidth = self.editwin.get_tk_tabwidth()
-
- # Get the Text widget's size
- linewidth = self.editwin.text.winfo_width()
- # Deduct the border and padding
- linewidth -= 2*sum([int(self.editwin.text.cget(opt))
- for opt in ('border', 'padx')])
-
- # Get the Text widget's font
- font = Font(self.editwin.text, name=self.editwin.text.cget('font'))
- # Divide the size of the Text widget by the font's width.
- # According to Tk8.5 docs, the Text widget's width is set
- # according to the width of its font's '0' (zero) character,
- # so we will use this as an approximation.
- # see: http://www.tcl.tk/man/tcl8.5/TkCmd/text.htm#M-width
- linewidth //= font.measure('0')
-
- return count_lines_with_wrapping(s, linewidth, tabwidth)
+ linewidth = self.get_line_width()
+ return count_lines_with_wrapping(s, linewidth)
+
+ def get_line_width(self):
+ # The maximum line length in pixels: The width of the text
+ # widget, minus twice the border width and internal padding.
+ linewidth_pixels = \
+ self.base_text.winfo_width() - self.window_width_delta
+
+ # Divide the width of the Text widget by the font width,
+ # which is taken to be the width of '0' (zero).
+ # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21
+ return linewidth_pixels // self.zero_char_width
+
+ def load_font(self):
+ text = self.base_text
+ self.zero_char_width = \
+ Font(text, font=text.cget('font')).measure('0')
def squeeze_current_text_event(self, event):
"""squeeze-current-text event handler
If the insert cursor is not in a squeezable block of text, give the
user a small warning and do nothing.
"""
- # set tag_name to the first valid tag found on the "insert" cursor
+ # Set tag_name to the first valid tag found on the "insert" cursor.
tag_names = self.text.tag_names(tk.INSERT)
for tag_name in ("stdout", "stderr"):
if tag_name in tag_names:
break
else:
- # the insert cursor doesn't have a "stdout" or "stderr" tag
+ # The insert cursor doesn't have a "stdout" or "stderr" tag.
self.text.bell()
return "break"
- # find the range to squeeze
+ # Find the range to squeeze.
start, end = self.text.tag_prevrange(tag_name, tk.INSERT + "+1c")
s = self.text.get(start, end)
- # if the last char is a newline, remove it from the range
+ # If the last char is a newline, remove it from the range.
if len(s) > 0 and s[-1] == '\n':
end = self.text.index("%s-1c" % end)
s = s[:-1]
- # delete the text
+ # Delete the text.
self.base_text.delete(start, end)
- # prepare an ExpandingButton
+ # Prepare an ExpandingButton.
numoflines = self.count_lines(s)
expandingbutton = ExpandingButton(s, tag_name, numoflines, self)
self.text.window_create(start, window=expandingbutton,
padx=3, pady=5)
- # insert the ExpandingButton to the list of ExpandingButtons, while
- # keeping the list ordered according to the position of the buttons in
- # the Text widget
+ # Insert the ExpandingButton to the list of ExpandingButtons,
+ # while keeping the list ordered according to the position of
+ # the buttons in the Text widget.
i = len(self.expandingbuttons)
while i > 0 and self.text.compare(self.expandingbuttons[i-1],
">", expandingbutton):
import os
from tkinter import *
-from tkinter.ttk import Scrollbar
+from tkinter.ttk import Frame, Scrollbar
from idlelib.config import idleConf
from idlelib import zoomheight
-from tkinter import *
+from tkinter import Toplevel, TclError
+import sys
class WindowList:
def zoom_height_event(self, event=None):
top = self.editwin.top
- zoom_height(top)
+ zoomed = zoom_height(top)
+ menu_status = 'Restore' if zoomed else 'Zoom'
+ self.editwin.update_menu_label(menu='options', index='* Height',
+ label=f'{menu_status} Height')
return "break"
else:
newgeom = "%dx%d+%d+%d" % (width, newheight, x, newy)
top.wm_geometry(newgeom)
+ return newgeom != ""
if __name__ == "__main__":
DictProxy = MakeProxyType('DictProxy', (
'__contains__', '__delitem__', '__getitem__', '__iter__', '__len__',
- '__setitem__', 'clear', 'copy', 'get', 'has_key', 'items',
+ '__setitem__', 'clear', 'copy', 'get', 'items',
'keys', 'pop', 'popitem', 'setdefault', 'update', 'values'
))
DictProxy._method_to_typeid_ = {
WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
+
+def _path_eq(p1, p2):
+ return p1 == p2 or os.path.normcase(p1) == os.path.normcase(p2)
+
+WINENV = (hasattr(sys, '_base_executable') and
+ not _path_eq(sys.executable, sys._base_executable))
+
+
+def _close_handles(*handles):
+ for handle in handles:
+ _winapi.CloseHandle(handle)
+
+
#
# We define a Popen class similar to the one from subprocess, but
# whose constructor takes a process object as its argument.
pipe_handle=rhandle)
cmd = ' '.join('"%s"' % x for x in cmd)
+ python_exe = spawn.get_executable()
+
+ # bpo-35797: When running in a venv, we bypass the redirect
+ # executor and launch our base Python.
+ if WINENV and _path_eq(python_exe, sys.executable):
+ python_exe = sys._base_executable
+ env = os.environ.copy()
+ env["__PYVENV_LAUNCHER__"] = sys.executable
+ else:
+ env = None
+
with open(wfd, 'wb', closefd=True) as to_child:
# start process
try:
hp, ht, pid, tid = _winapi.CreateProcess(
- spawn.get_executable(), cmd,
- None, None, False, 0, None, None, None)
+ python_exe, cmd,
+ env, None, False, 0, None, None, None)
_winapi.CloseHandle(ht)
except:
_winapi.CloseHandle(rhandle)
WINEXE = False
WINSERVICE = False
else:
- WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
+ WINEXE = getattr(sys, 'frozen', False)
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
if WINSERVICE:
# EBADF - guard agains macOS `stat` throwing EBADF
_IGNORED_ERROS = (ENOENT, ENOTDIR, EBADF)
+_IGNORED_WINERRORS = (
+ 21, # ERROR_NOT_READY - drive exists but is not accessible
+)
+
+def _ignore_error(exception):
+ return (getattr(exception, 'errno', None) in _IGNORED_ERROS or
+ getattr(exception, 'winerror', None) in _IGNORED_WINERRORS)
+
+
def _is_wildcard_pattern(pat):
# Whether this pattern needs actual matching using fnmatch, or can
# be looked up directly as a file.
try:
entry_is_dir = entry.is_dir()
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
if entry_is_dir and not entry.is_symlink():
path = parent_path._make_child_relpath(entry.name)
def glob(self, pattern):
"""Iterate over this subtree and yield all existing files (of any
- kind, including directories) matching the given pattern.
+ kind, including directories) matching the given relative pattern.
"""
if not pattern:
raise ValueError("Unacceptable pattern: {!r}".format(pattern))
def rglob(self, pattern):
"""Recursively yield all existing files (of any kind, including
- directories) matching the given pattern, anywhere in this subtree.
+ directories) matching the given relative pattern, anywhere in
+ this subtree.
"""
pattern = self._flavour.casefold(pattern)
drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
try:
self.stat()
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
return False
return True
try:
return S_ISDIR(self.stat().st_mode)
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
try:
return S_ISREG(self.stat().st_mode)
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
try:
return S_ISLNK(self.lstat().st_mode)
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
# Path doesn't exist
return False
try:
return S_ISBLK(self.stat().st_mode)
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
try:
return S_ISCHR(self.stat().st_mode)
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
try:
return S_ISFIFO(self.stat().st_mode)
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
try:
return S_ISSOCK(self.stat().st_mode)
except OSError as e:
- if e.errno not in _IGNORED_ERROS:
+ if not _ignore_error(e):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
p = Pdb(self.completekey, self.stdin, self.stdout)
p.prompt = "(%s) " % self.prompt.strip()
self.message("ENTERING RECURSIVE DEBUGGER")
- sys.call_tracing(p.run, (arg, globals, locals))
+ try:
+ sys.call_tracing(p.run, (arg, globals, locals))
+ except Exception:
+ exc_info = sys.exc_info()[:2]
+ self.error(traceback.format_exception_only(*exc_info)[-1].strip())
self.message("LEAVING RECURSIVE DEBUGGER")
sys.settrace(self.trace_dispatch)
self.lastcmd = p.lastcmd
if object is None:
object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
p = PrettyPrinter()
- t1 = time.time()
+ t1 = time.perf_counter()
_safe_repr(object, {}, None, 0)
- t2 = time.time()
+ t2 = time.perf_counter()
p.pformat(object)
- t3 = time.time()
+ t3 = time.perf_counter()
print("_safe_repr:", t2 - t1)
print("pformat:", t3 - t2)
Let the server do its thing. We just need to monitor its status.
Use time.sleep so the loop doesn't hog the CPU.
- >>> starttime = time.time()
+ >>> starttime = time.monotonic()
>>> timeout = 1 #seconds
This is a short timeout for testing purposes.
>>> 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
# -*- coding: utf-8 -*-
-# Autogenerated by Sphinx on Sun Dec 23 16:24:58 2018
+# Autogenerated by Sphinx on Tue Mar 12 14:56:48 2019
topics = {'assert': 'The "assert" statement\n'
'**********************\n'
'\n'
'Annotated assignment statements\n'
'===============================\n'
'\n'
- 'Annotation assignment is the combination, in a single '
- 'statement, of a\n'
- 'variable or attribute annotation and an optional assignment '
+ '*Annotation* assignment is the combination, in a single '
+ 'statement, of\n'
+ 'a variable or attribute annotation and an optional assignment\n'
'statement:\n'
'\n'
' annotated_assignment_stmt ::= augtarget ":" expression ["=" '
'in a parent.)\n'
'\n'
'The space saved over using *__dict__* can be '
- 'significant.\n'
+ 'significant. Attribute\n'
+ 'lookup speed can be significantly improved as well.\n'
'\n'
'object.__slots__\n'
'\n'
'passed\n'
'used keyword arguments.\n'
'\n'
- 'Parameters may have annotations of the form “": expression"” '
- 'following\n'
- 'the parameter name. Any parameter may have an annotation even '
- 'those\n'
- 'of the form "*identifier" or "**identifier". Functions may '
- 'have\n'
- '“return” annotation of the form “"-> expression"” after the '
- 'parameter\n'
- 'list. These annotations can be any valid Python expression. '
- 'The\n'
- 'presence of annotations does not change the semantics of a '
- 'function.\n'
- 'The annotation values are available as values of a dictionary '
- 'keyed by\n'
- 'the parameters’ names in the "__annotations__" attribute of the\n'
- 'function object. If the "annotations" import from "__future__" '
- 'is\n'
- 'used, annotations are preserved as strings at runtime which '
- 'enables\n'
- 'postponed evaluation. Otherwise, they are evaluated when the '
- 'function\n'
- 'definition is executed. In this case annotations may be '
- 'evaluated in\n'
- 'a different order than they appear in the source code.\n'
+ 'Parameters may have an *annotation* of the form “": '
+ 'expression"”\n'
+ 'following the parameter name. Any parameter may have an '
+ 'annotation,\n'
+ 'even those of the form "*identifier" or "**identifier". '
+ 'Functions may\n'
+ 'have “return” annotation of the form “"-> expression"” after '
+ 'the\n'
+ 'parameter list. These annotations can be any valid Python '
+ 'expression.\n'
+ 'The presence of annotations does not change the semantics of a\n'
+ 'function. The annotation values are available as values of a\n'
+ 'dictionary keyed by the parameters’ names in the '
+ '"__annotations__"\n'
+ 'attribute of the function object. If the "annotations" import '
+ 'from\n'
+ '"__future__" is used, annotations are preserved as strings at '
+ 'runtime\n'
+ 'which enables postponed evaluation. Otherwise, they are '
+ 'evaluated\n'
+ 'when the function definition is executed. In this case '
+ 'annotations\n'
+ 'may be evaluated in a different order than they appear in the '
+ 'source\n'
+ 'code.\n'
'\n'
'It is also possible to create anonymous functions (functions not '
'bound\n'
'running\n'
'without the debugger using the "continue" command.\n'
'\n'
+ 'New in version 3.7: The built-in "breakpoint()", when called '
+ 'with\n'
+ 'defaults, can be used instead of "import pdb; pdb.set_trace()".\n'
+ '\n'
'The typical usage to inspect a crashed program is:\n'
'\n'
' >>> import pdb\n'
'passed\n'
'used keyword arguments.\n'
'\n'
- 'Parameters may have annotations of the form “": expression"” '
- 'following\n'
- 'the parameter name. Any parameter may have an annotation even '
- 'those\n'
- 'of the form "*identifier" or "**identifier". Functions may '
- 'have\n'
- '“return” annotation of the form “"-> expression"” after the '
- 'parameter\n'
- 'list. These annotations can be any valid Python expression. '
- 'The\n'
- 'presence of annotations does not change the semantics of a '
- 'function.\n'
- 'The annotation values are available as values of a dictionary '
- 'keyed by\n'
- 'the parameters’ names in the "__annotations__" attribute of the\n'
- 'function object. If the "annotations" import from "__future__" '
- 'is\n'
- 'used, annotations are preserved as strings at runtime which '
- 'enables\n'
- 'postponed evaluation. Otherwise, they are evaluated when the '
- 'function\n'
- 'definition is executed. In this case annotations may be '
- 'evaluated in\n'
- 'a different order than they appear in the source code.\n'
+ 'Parameters may have an *annotation* of the form “": '
+ 'expression"”\n'
+ 'following the parameter name. Any parameter may have an '
+ 'annotation,\n'
+ 'even those of the form "*identifier" or "**identifier". '
+ 'Functions may\n'
+ 'have “return” annotation of the form “"-> expression"” after '
+ 'the\n'
+ 'parameter list. These annotations can be any valid Python '
+ 'expression.\n'
+ 'The presence of annotations does not change the semantics of a\n'
+ 'function. The annotation values are available as values of a\n'
+ 'dictionary keyed by the parameters’ names in the '
+ '"__annotations__"\n'
+ 'attribute of the function object. If the "annotations" import '
+ 'from\n'
+ '"__future__" is used, annotations are preserved as strings at '
+ 'runtime\n'
+ 'which enables postponed evaluation. Otherwise, they are '
+ 'evaluated\n'
+ 'when the function definition is executed. In this case '
+ 'annotations\n'
+ 'may be evaluated in a different order than they appear in the '
+ 'source\n'
+ 'code.\n'
'\n'
'It is also possible to create anonymous functions (functions not '
'bound\n'
'(unless explicitly declared in *__slots__* or available in a '
'parent.)\n'
'\n'
- 'The space saved over using *__dict__* can be significant.\n'
+ 'The space saved over using *__dict__* can be significant. '
+ 'Attribute\n'
+ 'lookup speed can be significantly improved as well.\n'
'\n'
'object.__slots__\n'
'\n'
'Modules\n'
' Modules are a basic organizational unit of Python code, and are\n'
' created by the import system as invoked either by the "import"\n'
- ' statement (see "import"), or by calling functions such as\n'
+ ' statement, or by calling functions such as\n'
' "importlib.import_module()" and built-in "__import__()". A '
'module\n'
' object has a namespace implemented by a dictionary object (this '
'\n'
' Return a shallow copy of the dictionary.\n'
'\n'
- ' classmethod fromkeys(seq[, value])\n'
+ ' classmethod fromkeys(iterable[, value])\n'
'\n'
- ' Create a new dictionary with keys from *seq* and '
- 'values set to\n'
- ' *value*.\n'
+ ' Create a new dictionary with keys from *iterable* and '
+ 'values set\n'
+ ' to *value*.\n'
'\n'
' "fromkeys()" is a class method that returns a new '
'dictionary.\n'
sqsum = 0.0
smallest = 1e10
largest = -1e10
- t0 = time.time()
+ t0 = time.perf_counter()
for i in range(n):
x = func(*args)
total += x
sqsum = sqsum + x*x
smallest = min(x, smallest)
largest = max(x, largest)
- t1 = time.time()
+ t1 = time.perf_counter()
print(round(t1-t0, 3), 'sec,', end=' ')
avg = total/n
stddev = _sqrt(sqsum/n - avg*avg)
env = os.environ
if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in env:
- executable = os.environ['__PYVENV_LAUNCHER__']
+ executable = sys._base_executable = os.environ['__PYVENV_LAUNCHER__']
+ elif sys.platform == 'win32' and '__PYVENV_LAUNCHER__' in env:
+ executable = sys.executable
+ import _winapi
+ sys._base_executable = _winapi.GetModuleFileName(0)
+ # bpo-35873: Clear the environment variable to avoid it being
+ # inherited by child processes.
+ del os.environ['__PYVENV_LAUNCHER__']
else:
executable = sys.executable
exe_dir, _ = os.path.split(os.path.abspath(executable))
def service_actions(self):
"""Collect the zombie child processes regularly in the ForkingMixIn.
- service_actions is called in the BaseServer's serve_forver loop.
+ service_actions is called in the BaseServer's serve_forever loop.
"""
self.collect_children()
del ref
support.gc_collect()
+ def CheckDelIsolation_levelSegfault(self):
+ with self.assertRaises(AttributeError):
+ del self.con.isolation_level
+
class UnhashableFunc:
__hash__ = None
return False
_sys_home = getattr(sys, '_home', None)
-if (_sys_home and os.name == 'nt' and
- _sys_home.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
- _sys_home = os.path.dirname(os.path.dirname(_sys_home))
+
+if os.name == 'nt':
+ def _fix_pcbuild(d):
+ if d and os.path.normcase(d).startswith(
+ os.path.normcase(os.path.join(_PREFIX, "PCbuild"))):
+ return _PREFIX
+ return d
+ _PROJECT_BASE = _fix_pcbuild(_PROJECT_BASE)
+ _sys_home = _fix_pcbuild(_sys_home)
+
def is_python_build(check_home=False):
if check_home and _sys_home:
return _is_python_source_dir(_sys_home)
self.elapsed = None
def __call__(self, *args, **kwds):
- t = time.time()
+ t = time.monotonic()
try:
return self.func(*args, **kwds)
finally:
- self.elapsed = time.time() - t
+ self.elapsed = time.monotonic() - t
#
# Base class for test cases
def test_timeout(self):
q = multiprocessing.Queue()
- start = time.time()
+ start = time.monotonic()
self.assertRaises(pyqueue.Empty, q.get, True, 0.200)
- delta = time.time() - start
+ delta = time.monotonic() - start
# bpo-30317: Tolerate a delta of 100 ms because of the bad clock
# resolution on Windows (usually 15.6 ms). x86 Windows7 3.x once
# failed because the delta was only 135.8 ms.
sem.release()
with cond:
expected = 0.1
- dt = time.time()
+ dt = time.monotonic()
result = cond.wait_for(lambda : state.value==4, timeout=expected)
- dt = time.time() - dt
+ dt = time.monotonic() - dt
# borrow logic in assertTimeout() from test/lock_tests.py
if not result and expected * 0.6 < dt < expected * 10.0:
success.value = True
# process would fill the result queue (after the result handler thread
# terminated, hence not draining it anymore).
- t_start = time.time()
+ t_start = time.monotonic()
with self.assertRaises(ValueError):
with self.Pool(2) as p:
p.join()
# check that we indeed waited for all jobs
- self.assertGreater(time.time() - t_start, 0.9)
+ self.assertGreater(time.monotonic() - t_start, 0.9)
def test_release_task_refs(self):
# Issue #29861: task arguments and results should not be kept
address=(test.support.HOST, 0), authkey=authkey, serializer=SERIALIZER
)
manager.start()
+ self.addCleanup(manager.shutdown)
p = self.Process(target=self._putter, args=(manager.address, authkey))
p.daemon = True
# Make queue finalizer run before the server is stopped
del queue
- manager.shutdown()
class _TestManagerRestart(BaseTestCase):
authkey = os.urandom(32)
manager = QueueManager(
address=(test.support.HOST, 0), authkey=authkey, serializer=SERIALIZER)
- srvr = manager.get_server()
- addr = srvr.address
- # Close the connection.Listener socket which gets opened as a part
- # of manager.get_server(). It's not needed for the test.
- srvr.listener.close()
- manager.start()
+ try:
+ srvr = manager.get_server()
+ addr = srvr.address
+ # Close the connection.Listener socket which gets opened as a part
+ # of manager.get_server(). It's not needed for the test.
+ srvr.listener.close()
+ manager.start()
- p = self.Process(target=self._putter, args=(manager.address, authkey))
- p.start()
- p.join()
- queue = manager.get_queue()
- self.assertEqual(queue.get(), 'hello world')
- del queue
- manager.shutdown()
+ p = self.Process(target=self._putter, args=(manager.address, authkey))
+ p.start()
+ p.join()
+ queue = manager.get_queue()
+ self.assertEqual(queue.get(), 'hello world')
+ del queue
+ finally:
+ if hasattr(manager, "shutdown"):
+ manager.shutdown()
manager = QueueManager(
address=addr, authkey=authkey, serializer=SERIALIZER)
try:
manager.start()
+ self.addCleanup(manager.shutdown)
except OSError as e:
if e.errno != errno.EADDRINUSE:
raise
time.sleep(1.0)
manager = QueueManager(
address=addr, authkey=authkey, serializer=SERIALIZER)
- manager.shutdown()
+ if hasattr(manager, "shutdown"):
+ self.addCleanup(manager.shutdown)
#
#
expected = 5
a, b = multiprocessing.Pipe()
- start = time.time()
+ start = time.monotonic()
res = wait([a, b], expected)
- delta = time.time() - start
+ delta = time.monotonic() - start
self.assertEqual(res, [])
self.assertLess(delta, expected * 2)
b.send(None)
- start = time.time()
+ start = time.monotonic()
res = wait([a, b], 20)
- delta = time.time() - start
+ delta = time.monotonic() - start
self.assertEqual(res, [a])
self.assertLess(delta, 0.4)
self.assertIsInstance(p.sentinel, int)
self.assertTrue(sem.acquire(timeout=20))
- start = time.time()
+ start = time.monotonic()
res = wait([a, p.sentinel, b], expected + 20)
- delta = time.time() - start
+ delta = time.monotonic() - start
self.assertEqual(res, [p.sentinel])
self.assertLess(delta, expected + 2)
a.send(None)
- start = time.time()
+ start = time.monotonic()
res = wait([a, p.sentinel, b], 20)
- delta = time.time() - start
+ delta = time.monotonic() - start
self.assertEqual(sorted_(res), sorted_([p.sentinel, b]))
self.assertLess(delta, 0.4)
b.send(None)
- start = time.time()
+ start = time.monotonic()
res = wait([a, p.sentinel, b], 20)
- delta = time.time() - start
+ delta = time.monotonic() - start
self.assertEqual(sorted_(res), sorted_([a, p.sentinel, b]))
self.assertLess(delta, 0.4)
def test_neg_timeout(self):
from multiprocessing.connection import wait
a, b = multiprocessing.Pipe()
- t = time.time()
+ t = time.monotonic()
res = wait([a], timeout=-1)
- t = time.time() - t
+ t = time.monotonic() - t
self.assertEqual(res, [])
self.assertLess(t, 1)
a.close()
proc.join()
+
+class TestSyncManagerTypes(unittest.TestCase):
+ """Test all the types which can be shared between a parent and a
+ child process by using a manager which acts as an intermediary
+ between them.
+
+ In the following unit-tests the base type is created in the parent
+ process, the @classmethod represents the worker process and the
+ shared object is readable and editable between the two.
+
+ # The child.
+ @classmethod
+ def _test_list(cls, obj):
+ assert obj[0] == 5
+ assert obj.append(6)
+
+ # The parent.
+ def test_list(self):
+ o = self.manager.list()
+ o.append(5)
+ self.run_worker(self._test_list, o)
+ assert o[1] == 6
+ """
+ manager_class = multiprocessing.managers.SyncManager
+
+ def setUp(self):
+ self.manager = self.manager_class()
+ self.manager.start()
+ self.proc = None
+
+ def tearDown(self):
+ if self.proc is not None and self.proc.is_alive():
+ self.proc.terminate()
+ self.proc.join()
+ self.manager.shutdown()
+ self.manager = None
+ self.proc = None
+
+ @classmethod
+ def setUpClass(cls):
+ support.reap_children()
+
+ tearDownClass = setUpClass
+
+ def wait_proc_exit(self):
+ # Only the manager process should be returned by active_children()
+ # but this can take a bit on slow machines, so wait a few seconds
+ # if there are other children too (see #17395).
+ join_process(self.proc)
+ start_time = time.monotonic()
+ t = 0.01
+ while len(multiprocessing.active_children()) > 1:
+ time.sleep(t)
+ t *= 2
+ dt = time.monotonic() - start_time
+ if dt >= 5.0:
+ test.support.environment_altered = True
+ print("Warning -- multiprocessing.Manager still has %s active "
+ "children after %s seconds"
+ % (multiprocessing.active_children(), dt),
+ file=sys.stderr)
+ break
+
+ def run_worker(self, worker, obj):
+ self.proc = multiprocessing.Process(target=worker, args=(obj, ))
+ self.proc.daemon = True
+ self.proc.start()
+ self.wait_proc_exit()
+ self.assertEqual(self.proc.exitcode, 0)
+
+ @classmethod
+ def _test_queue(cls, obj):
+ assert obj.qsize() == 2
+ assert obj.full()
+ assert not obj.empty()
+ assert obj.get() == 5
+ assert not obj.empty()
+ assert obj.get() == 6
+ assert obj.empty()
+
+ def test_queue(self, qname="Queue"):
+ o = getattr(self.manager, qname)(2)
+ o.put(5)
+ o.put(6)
+ self.run_worker(self._test_queue, o)
+ assert o.empty()
+ assert not o.full()
+
+ def test_joinable_queue(self):
+ self.test_queue("JoinableQueue")
+
+ @classmethod
+ def _test_event(cls, obj):
+ assert obj.is_set()
+ obj.wait()
+ obj.clear()
+ obj.wait(0.001)
+
+ def test_event(self):
+ o = self.manager.Event()
+ o.set()
+ self.run_worker(self._test_event, o)
+ assert not o.is_set()
+ o.wait(0.001)
+
+ @classmethod
+ def _test_lock(cls, obj):
+ obj.acquire()
+
+ def test_lock(self, lname="Lock"):
+ o = getattr(self.manager, lname)()
+ self.run_worker(self._test_lock, o)
+ o.release()
+ self.assertRaises(RuntimeError, o.release) # already released
+
+ @classmethod
+ def _test_rlock(cls, obj):
+ obj.acquire()
+ obj.release()
+
+ def test_rlock(self, lname="Lock"):
+ o = getattr(self.manager, lname)()
+ self.run_worker(self._test_rlock, o)
+
+ @classmethod
+ def _test_semaphore(cls, obj):
+ obj.acquire()
+
+ def test_semaphore(self, sname="Semaphore"):
+ o = getattr(self.manager, sname)()
+ self.run_worker(self._test_semaphore, o)
+ o.release()
+
+ def test_bounded_semaphore(self):
+ self.test_semaphore(sname="BoundedSemaphore")
+
+ @classmethod
+ def _test_condition(cls, obj):
+ obj.acquire()
+ obj.release()
+
+ def test_condition(self):
+ o = self.manager.Condition()
+ self.run_worker(self._test_condition, o)
+
+ @classmethod
+ def _test_barrier(cls, obj):
+ assert obj.parties == 5
+ obj.reset()
+
+ def test_barrier(self):
+ o = self.manager.Barrier(5)
+ self.run_worker(self._test_barrier, o)
+
+ @classmethod
+ def _test_pool(cls, obj):
+ # TODO: fix https://bugs.python.org/issue35919
+ with obj:
+ pass
+
+ def test_pool(self):
+ o = self.manager.Pool(processes=4)
+ self.run_worker(self._test_pool, o)
+
+ @classmethod
+ def _test_list(cls, obj):
+ assert obj[0] == 5
+ assert obj.count(5) == 1
+ assert obj.index(5) == 0
+ obj.sort()
+ obj.reverse()
+ for x in obj:
+ pass
+ assert len(obj) == 1
+ assert obj.pop(0) == 5
+
+ def test_list(self):
+ o = self.manager.list()
+ o.append(5)
+ self.run_worker(self._test_list, o)
+ assert not o
+ self.assertEqual(len(o), 0)
+
+ @classmethod
+ def _test_dict(cls, obj):
+ assert len(obj) == 1
+ assert obj['foo'] == 5
+ assert obj.get('foo') == 5
+ assert list(obj.items()) == [('foo', 5)]
+ assert list(obj.keys()) == ['foo']
+ assert list(obj.values()) == [5]
+ assert obj.copy() == {'foo': 5}
+ assert obj.popitem() == ('foo', 5)
+
+ def test_dict(self):
+ o = self.manager.dict()
+ o['foo'] = 5
+ self.run_worker(self._test_dict, o)
+ assert not o
+ self.assertEqual(len(o), 0)
+
+ @classmethod
+ def _test_value(cls, obj):
+ assert obj.value == 1
+ assert obj.get() == 1
+ obj.set(2)
+
+ def test_value(self):
+ o = self.manager.Value('i', 1)
+ self.run_worker(self._test_value, o)
+ self.assertEqual(o.value, 2)
+ self.assertEqual(o.get(), 2)
+
+ @classmethod
+ def _test_array(cls, obj):
+ assert obj[0] == 0
+ assert obj[1] == 1
+ assert len(obj) == 2
+ assert list(obj) == [0, 1]
+
+ def test_array(self):
+ o = self.manager.Array('i', [0, 1])
+ self.run_worker(self._test_array, o)
+
+ @classmethod
+ def _test_namespace(cls, obj):
+ assert obj.x == 0
+ assert obj.y == 1
+
+ def test_namespace(self):
+ o = self.manager.Namespace()
+ o.x = 0
+ o.y = 1
+ self.run_worker(self._test_namespace, o)
+
+
#
# Mixins
#
+++ /dev/null
-#!/usr/bin/env python3
-"""
-Command line tool to bisect failing CPython tests.
-
-Find the test_os test method which alters the environment:
-
- ./python -m test.bisect --fail-env-changed test_os
-
-Find a reference leak in "test_os", write the list of failing tests into the
-"bisect" file:
-
- ./python -m test.bisect -o bisect -R 3:3 test_os
-
-Load an existing list of tests from a file using -i option:
-
- ./python -m test --list-cases -m FileTests test_os > tests
- ./python -m test.bisect -i tests test_os
-"""
-
-import argparse
-import datetime
-import os.path
-import math
-import random
-import subprocess
-import sys
-import tempfile
-import time
-
-
-def write_tests(filename, tests):
- with open(filename, "w") as fp:
- for name in tests:
- print(name, file=fp)
- fp.flush()
-
-
-def write_output(filename, tests):
- if not filename:
- return
- print("Writing %s tests into %s" % (len(tests), filename))
- write_tests(filename, tests)
- return filename
-
-
-def format_shell_args(args):
- return ' '.join(args)
-
-
-def list_cases(args):
- cmd = [sys.executable, '-m', 'test', '--list-cases']
- cmd.extend(args.test_args)
- proc = subprocess.run(cmd,
- stdout=subprocess.PIPE,
- universal_newlines=True)
- exitcode = proc.returncode
- if exitcode:
- cmd = format_shell_args(cmd)
- print("Failed to list tests: %s failed with exit code %s"
- % (cmd, exitcode))
- sys.exit(exitcode)
- tests = proc.stdout.splitlines()
- return tests
-
-
-def run_tests(args, tests, huntrleaks=None):
- tmp = tempfile.mktemp()
- try:
- write_tests(tmp, tests)
-
- cmd = [sys.executable, '-m', 'test', '--matchfile', tmp]
- cmd.extend(args.test_args)
- print("+ %s" % format_shell_args(cmd))
- proc = subprocess.run(cmd)
- return proc.returncode
- finally:
- if os.path.exists(tmp):
- os.unlink(tmp)
-
-
-def parse_args():
- parser = argparse.ArgumentParser()
- parser.add_argument('-i', '--input',
- help='Test names produced by --list-tests written '
- 'into a file. If not set, run --list-tests')
- parser.add_argument('-o', '--output',
- help='Result of the bisection')
- parser.add_argument('-n', '--max-tests', type=int, default=1,
- help='Maximum number of tests to stop the bisection '
- '(default: 1)')
- parser.add_argument('-N', '--max-iter', type=int, default=100,
- help='Maximum number of bisection iterations '
- '(default: 100)')
- # FIXME: document that following arguments are test arguments
-
- args, test_args = parser.parse_known_args()
- args.test_args = test_args
- return args
-
-
-def main():
- args = parse_args()
-
- if args.input:
- with open(args.input) as fp:
- tests = [line.strip() for line in fp]
- else:
- tests = list_cases(args)
-
- print("Start bisection with %s tests" % len(tests))
- print("Test arguments: %s" % format_shell_args(args.test_args))
- print("Bisection will stop when getting %s or less tests "
- "(-n/--max-tests option), or after %s iterations "
- "(-N/--max-iter option)"
- % (args.max_tests, args.max_iter))
- output = write_output(args.output, tests)
- print()
-
- start_time = time.monotonic()
- iteration = 1
- try:
- while len(tests) > args.max_tests and iteration <= args.max_iter:
- ntest = len(tests)
- ntest = max(ntest // 2, 1)
- subtests = random.sample(tests, ntest)
-
- print("[+] Iteration %s: run %s tests/%s"
- % (iteration, len(subtests), len(tests)))
- print()
-
- exitcode = run_tests(args, subtests)
-
- print("ran %s tests/%s" % (ntest, len(tests)))
- print("exit", exitcode)
- if exitcode:
- print("Tests failed: continuing with this subtest")
- tests = subtests
- output = write_output(args.output, tests)
- else:
- print("Tests succeeded: skipping this subtest, trying a new subset")
- print()
- iteration += 1
- except KeyboardInterrupt:
- print()
- print("Bisection interrupted!")
- print()
-
- print("Tests (%s):" % len(tests))
- for test in tests:
- print("* %s" % test)
- print()
-
- if output:
- print("Output written into %s" % output)
-
- dt = math.ceil(time.monotonic() - start_time)
- if len(tests) <= args.max_tests:
- print("Bisection completed in %s iterations and %s"
- % (iteration, datetime.timedelta(seconds=dt)))
- sys.exit(1)
- else:
- print("Bisection failed after %s iterations and %s"
- % (iteration, datetime.timedelta(seconds=dt)))
-
-
-if __name__ == "__main__":
- main()
--- /dev/null
+#!/usr/bin/env python3
+"""
+Command line tool to bisect failing CPython tests.
+
+Find the test_os test method which alters the environment:
+
+ ./python -m test.bisect --fail-env-changed test_os
+
+Find a reference leak in "test_os", write the list of failing tests into the
+"bisect" file:
+
+ ./python -m test.bisect -o bisect -R 3:3 test_os
+
+Load an existing list of tests from a file using -i option:
+
+ ./python -m test --list-cases -m FileTests test_os > tests
+ ./python -m test.bisect -i tests test_os
+"""
+
+import argparse
+import datetime
+import os.path
+import math
+import random
+import subprocess
+import sys
+import tempfile
+import time
+
+
+def write_tests(filename, tests):
+ with open(filename, "w") as fp:
+ for name in tests:
+ print(name, file=fp)
+ fp.flush()
+
+
+def write_output(filename, tests):
+ if not filename:
+ return
+ print("Writing %s tests into %s" % (len(tests), filename))
+ write_tests(filename, tests)
+ return filename
+
+
+def format_shell_args(args):
+ return ' '.join(args)
+
+
+def list_cases(args):
+ cmd = [sys.executable, '-m', 'test', '--list-cases']
+ cmd.extend(args.test_args)
+ proc = subprocess.run(cmd,
+ stdout=subprocess.PIPE,
+ universal_newlines=True)
+ exitcode = proc.returncode
+ if exitcode:
+ cmd = format_shell_args(cmd)
+ print("Failed to list tests: %s failed with exit code %s"
+ % (cmd, exitcode))
+ sys.exit(exitcode)
+ tests = proc.stdout.splitlines()
+ return tests
+
+
+def run_tests(args, tests, huntrleaks=None):
+ tmp = tempfile.mktemp()
+ try:
+ write_tests(tmp, tests)
+
+ cmd = [sys.executable, '-m', 'test', '--matchfile', tmp]
+ cmd.extend(args.test_args)
+ print("+ %s" % format_shell_args(cmd))
+ proc = subprocess.run(cmd)
+ return proc.returncode
+ finally:
+ if os.path.exists(tmp):
+ os.unlink(tmp)
+
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-i', '--input',
+ help='Test names produced by --list-tests written '
+ 'into a file. If not set, run --list-tests')
+ parser.add_argument('-o', '--output',
+ help='Result of the bisection')
+ parser.add_argument('-n', '--max-tests', type=int, default=1,
+ help='Maximum number of tests to stop the bisection '
+ '(default: 1)')
+ parser.add_argument('-N', '--max-iter', type=int, default=100,
+ help='Maximum number of bisection iterations '
+ '(default: 100)')
+ # FIXME: document that following arguments are test arguments
+
+ args, test_args = parser.parse_known_args()
+ args.test_args = test_args
+ return args
+
+
+def main():
+ args = parse_args()
+
+ if args.input:
+ with open(args.input) as fp:
+ tests = [line.strip() for line in fp]
+ else:
+ tests = list_cases(args)
+
+ print("Start bisection with %s tests" % len(tests))
+ print("Test arguments: %s" % format_shell_args(args.test_args))
+ print("Bisection will stop when getting %s or less tests "
+ "(-n/--max-tests option), or after %s iterations "
+ "(-N/--max-iter option)"
+ % (args.max_tests, args.max_iter))
+ output = write_output(args.output, tests)
+ print()
+
+ start_time = time.monotonic()
+ iteration = 1
+ try:
+ while len(tests) > args.max_tests and iteration <= args.max_iter:
+ ntest = len(tests)
+ ntest = max(ntest // 2, 1)
+ subtests = random.sample(tests, ntest)
+
+ print("[+] Iteration %s: run %s tests/%s"
+ % (iteration, len(subtests), len(tests)))
+ print()
+
+ exitcode = run_tests(args, subtests)
+
+ print("ran %s tests/%s" % (ntest, len(tests)))
+ print("exit", exitcode)
+ if exitcode:
+ print("Tests failed: continuing with this subtest")
+ tests = subtests
+ output = write_output(args.output, tests)
+ else:
+ print("Tests succeeded: skipping this subtest, trying a new subset")
+ print()
+ iteration += 1
+ except KeyboardInterrupt:
+ print()
+ print("Bisection interrupted!")
+ print()
+
+ print("Tests (%s):" % len(tests))
+ for test in tests:
+ print("* %s" % test)
+ print()
+
+ if output:
+ print("Output written into %s" % output)
+
+ dt = math.ceil(time.monotonic() - start_time)
+ if len(tests) <= args.max_tests:
+ print("Bisection completed in %s iterations and %s"
+ % (iteration, datetime.timedelta(seconds=dt)))
+ sys.exit(1)
+ else:
+ print("Bisection failed after %s iterations and %s"
+ % (iteration, datetime.timedelta(seconds=dt)))
+
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+/*[clinic input]
+output preset block
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c81ac2402d06a8b]*/
+
+/*[clinic input]
+test_object_converter
+
+ a: object
+ b: object(converter="PyUnicode_FSConverter")
+ c: object(subclass_of="&PyUnicode_Type")
+ d: object(type="PyUnicode_Object *")
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_object_converter__doc__,
+"test_object_converter($module, a, b, c, d, /)\n"
+"--\n"
+"\n");
+
+#define TEST_OBJECT_CONVERTER_METHODDEF \
+ {"test_object_converter", (PyCFunction)test_object_converter, METH_FASTCALL, test_object_converter__doc__},
+
+static PyObject *
+test_object_converter_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject *c, PyUnicode_Object *d);
+
+static PyObject *
+test_object_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *b;
+ PyObject *c;
+ PyUnicode_Object *d;
+
+ if (!_PyArg_ParseStack(args, nargs, "OO&O!O:test_object_converter",
+ &a, PyUnicode_FSConverter, &b, &PyUnicode_Type, &c, &d)) {
+ goto exit;
+ }
+ return_value = test_object_converter_impl(module, a, b, c, d);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_object_converter_impl(PyObject *module, PyObject *a, PyObject *b,
+ PyObject *c, PyUnicode_Object *d)
+/*[clinic end generated code: output=a82a013247de5d81 input=005e6a8a711a869b]*/
+
+/*[clinic input]
+test_object_converter_one_arg
+
+ a: object
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_object_converter_one_arg__doc__,
+"test_object_converter_one_arg($module, a, /)\n"
+"--\n"
+"\n");
+
+#define TEST_OBJECT_CONVERTER_ONE_ARG_METHODDEF \
+ {"test_object_converter_one_arg", (PyCFunction)test_object_converter_one_arg, METH_O, test_object_converter_one_arg__doc__},
+
+static PyObject *
+test_object_converter_one_arg(PyObject *module, PyObject *a)
+/*[clinic end generated code: output=6da755f8502139df input=d635d92a421f1ca3]*/
+
+/*[clinic input]
+test_objects_converter
+
+ a: object
+ b: object = NULL
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_objects_converter__doc__,
+"test_objects_converter($module, a, b=None, /)\n"
+"--\n"
+"\n");
+
+#define TEST_OBJECTS_CONVERTER_METHODDEF \
+ {"test_objects_converter", (PyCFunction)test_objects_converter, METH_FASTCALL, test_objects_converter__doc__},
+
+static PyObject *
+test_objects_converter_impl(PyObject *module, PyObject *a, PyObject *b);
+
+static PyObject *
+test_objects_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *b = NULL;
+
+ if (!_PyArg_UnpackStack(args, nargs, "test_objects_converter",
+ 1, 2,
+ &a, &b)) {
+ goto exit;
+ }
+ return_value = test_objects_converter_impl(module, a, b);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_objects_converter_impl(PyObject *module, PyObject *a, PyObject *b)
+/*[clinic end generated code: output=4bf98d3729b7bae7 input=4cbb3d9edd2a36f3]*/
+
+/*[clinic input]
+test_object_converter_subclass_of
+
+ a: object(subclass_of="&PyLong_Type")
+ b: object(subclass_of="&PyTuple_Type")
+ c: object(subclass_of="&PyList_Type")
+ d: object(subclass_of="&PySet_Type")
+ e: object(subclass_of="&PyFrozenSet_Type")
+ f: object(subclass_of="&PyDict_Type")
+ g: object(subclass_of="&PyUnicode_Type")
+ h: object(subclass_of="&PyBytes_Type")
+ i: object(subclass_of="&PyByteArray_Type")
+ j: object(subclass_of="&MyType")
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_object_converter_subclass_of__doc__,
+"test_object_converter_subclass_of($module, a, b, c, d, e, f, g, h, i,\n"
+" j, /)\n"
+"--\n"
+"\n");
+
+#define TEST_OBJECT_CONVERTER_SUBCLASS_OF_METHODDEF \
+ {"test_object_converter_subclass_of", (PyCFunction)test_object_converter_subclass_of, METH_FASTCALL, test_object_converter_subclass_of__doc__},
+
+static PyObject *
+test_object_converter_subclass_of_impl(PyObject *module, PyObject *a,
+ PyObject *b, PyObject *c, PyObject *d,
+ PyObject *e, PyObject *f, PyObject *g,
+ PyObject *h, PyObject *i, PyObject *j);
+
+static PyObject *
+test_object_converter_subclass_of(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *b;
+ PyObject *c;
+ PyObject *d;
+ PyObject *e;
+ PyObject *f;
+ PyObject *g;
+ PyObject *h;
+ PyObject *i;
+ PyObject *j;
+
+ if (!_PyArg_ParseStack(args, nargs, "O!O!O!O!O!O!O!O!O!O!:test_object_converter_subclass_of",
+ &PyLong_Type, &a, &PyTuple_Type, &b, &PyList_Type, &c, &PySet_Type, &d, &PyFrozenSet_Type, &e, &PyDict_Type, &f, &PyUnicode_Type, &g, &PyBytes_Type, &h, &PyByteArray_Type, &i, &MyType, &j)) {
+ goto exit;
+ }
+ return_value = test_object_converter_subclass_of_impl(module, a, b, c, d, e, f, g, h, i, j);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_object_converter_subclass_of_impl(PyObject *module, PyObject *a,
+ PyObject *b, PyObject *c, PyObject *d,
+ PyObject *e, PyObject *f, PyObject *g,
+ PyObject *h, PyObject *i, PyObject *j)
+/*[clinic end generated code: output=811bcace8eca7f92 input=31b06b772d5f983e]*/
+
+/*[clinic input]
+test_PyBytesObject_converter
+
+ a: PyBytesObject
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_PyBytesObject_converter__doc__,
+"test_PyBytesObject_converter($module, a, /)\n"
+"--\n"
+"\n");
+
+#define TEST_PYBYTESOBJECT_CONVERTER_METHODDEF \
+ {"test_PyBytesObject_converter", (PyCFunction)test_PyBytesObject_converter, METH_O, test_PyBytesObject_converter__doc__},
+
+static PyObject *
+test_PyBytesObject_converter_impl(PyObject *module, PyBytesObject *a);
+
+static PyObject *
+test_PyBytesObject_converter(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ PyBytesObject *a;
+
+ if (!PyArg_Parse(arg, "S:test_PyBytesObject_converter", &a)) {
+ goto exit;
+ }
+ return_value = test_PyBytesObject_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_PyBytesObject_converter_impl(PyObject *module, PyBytesObject *a)
+/*[clinic end generated code: output=8dbf43c604ced031 input=12b10c7cb5750400]*/
+
+/*[clinic input]
+test_PyByteArrayObject_converter
+
+ a: PyByteArrayObject
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_PyByteArrayObject_converter__doc__,
+"test_PyByteArrayObject_converter($module, a, /)\n"
+"--\n"
+"\n");
+
+#define TEST_PYBYTEARRAYOBJECT_CONVERTER_METHODDEF \
+ {"test_PyByteArrayObject_converter", (PyCFunction)test_PyByteArrayObject_converter, METH_O, test_PyByteArrayObject_converter__doc__},
+
+static PyObject *
+test_PyByteArrayObject_converter_impl(PyObject *module, PyByteArrayObject *a);
+
+static PyObject *
+test_PyByteArrayObject_converter(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ PyByteArrayObject *a;
+
+ if (!PyArg_Parse(arg, "Y:test_PyByteArrayObject_converter", &a)) {
+ goto exit;
+ }
+ return_value = test_PyByteArrayObject_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_PyByteArrayObject_converter_impl(PyObject *module, PyByteArrayObject *a)
+/*[clinic end generated code: output=ade99fc6705e7d6e input=5a657da535d194ae]*/
+
+/*[clinic input]
+test_unicode_converter
+
+ a: unicode
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_unicode_converter__doc__,
+"test_unicode_converter($module, a, /)\n"
+"--\n"
+"\n");
+
+#define TEST_UNICODE_CONVERTER_METHODDEF \
+ {"test_unicode_converter", (PyCFunction)test_unicode_converter, METH_O, test_unicode_converter__doc__},
+
+static PyObject *
+test_unicode_converter_impl(PyObject *module, PyObject *a);
+
+static PyObject *
+test_unicode_converter(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+
+ if (!PyArg_Parse(arg, "U:test_unicode_converter", &a)) {
+ goto exit;
+ }
+ return_value = test_unicode_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_unicode_converter_impl(PyObject *module, PyObject *a)
+/*[clinic end generated code: output=504a2c8d00370adf input=aa33612df92aa9c5]*/
+
+/*[clinic input]
+test_bool_converter
+
+ a: bool = True
+ b: bool(accept={object}) = True
+ c: bool(accept={int}) = True
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_bool_converter__doc__,
+"test_bool_converter($module, a=True, b=True, c=True, /)\n"
+"--\n"
+"\n");
+
+#define TEST_BOOL_CONVERTER_METHODDEF \
+ {"test_bool_converter", (PyCFunction)test_bool_converter, METH_FASTCALL, test_bool_converter__doc__},
+
+static PyObject *
+test_bool_converter_impl(PyObject *module, int a, int b, int c);
+
+static PyObject *
+test_bool_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ int a = 1;
+ int b = 1;
+ int c = 1;
+
+ if (!_PyArg_ParseStack(args, nargs, "|ppi:test_bool_converter",
+ &a, &b, &c)) {
+ goto exit;
+ }
+ return_value = test_bool_converter_impl(module, a, b, c);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_bool_converter_impl(PyObject *module, int a, int b, int c)
+/*[clinic end generated code: output=a3e8bc2f49647d1b input=939854fa9f248c60]*/
+
+/*[clinic input]
+test_char_converter
+
+ a: char
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_char_converter__doc__,
+"test_char_converter($module, a, /)\n"
+"--\n"
+"\n");
+
+#define TEST_CHAR_CONVERTER_METHODDEF \
+ {"test_char_converter", (PyCFunction)test_char_converter, METH_O, test_char_converter__doc__},
+
+static PyObject *
+test_char_converter_impl(PyObject *module, char a);
+
+static PyObject *
+test_char_converter(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ char a;
+
+ if (!PyArg_Parse(arg, "c:test_char_converter", &a)) {
+ goto exit;
+ }
+ return_value = test_char_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_char_converter_impl(PyObject *module, char a)
+/*[clinic end generated code: output=900f0c5a82453471 input=e802e90b9deadd17]*/
+
+/*[clinic input]
+test_unsigned_char_converter
+
+ c: unsigned_char(bitwise=True) = 56
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_unsigned_char_converter__doc__,
+"test_unsigned_char_converter($module, c=56, /)\n"
+"--\n"
+"\n");
+
+#define TEST_UNSIGNED_CHAR_CONVERTER_METHODDEF \
+ {"test_unsigned_char_converter", (PyCFunction)test_unsigned_char_converter, METH_FASTCALL, test_unsigned_char_converter__doc__},
+
+static PyObject *
+test_unsigned_char_converter_impl(PyObject *module, unsigned char c);
+
+static PyObject *
+test_unsigned_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ unsigned char c = 56;
+
+ if (!_PyArg_ParseStack(args, nargs, "|B:test_unsigned_char_converter",
+ &c)) {
+ goto exit;
+ }
+ return_value = test_unsigned_char_converter_impl(module, c);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_unsigned_char_converter_impl(PyObject *module, unsigned char c)
+/*[clinic end generated code: output=48eb2d10bdc8aa08 input=c761000cf94b2df3]*/
+
+/*[clinic input]
+test_short_converter
+
+ a: short = 12
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_short_converter__doc__,
+"test_short_converter($module, a=12, /)\n"
+"--\n"
+"\n");
+
+#define TEST_SHORT_CONVERTER_METHODDEF \
+ {"test_short_converter", (PyCFunction)test_short_converter, METH_FASTCALL, test_short_converter__doc__},
+
+static PyObject *
+test_short_converter_impl(PyObject *module, short a);
+
+static PyObject *
+test_short_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ short a = 12;
+
+ if (!_PyArg_ParseStack(args, nargs, "|h:test_short_converter",
+ &a)) {
+ goto exit;
+ }
+ return_value = test_short_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_short_converter_impl(PyObject *module, short a)
+/*[clinic end generated code: output=ce5b137b7baae608 input=6a8a7a509a498ff4]*/
+
+/*[clinic input]
+test_unsigned_short_converter
+
+ c: unsigned_short(bitwise=True) = 56
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_unsigned_short_converter__doc__,
+"test_unsigned_short_converter($module, c=56, /)\n"
+"--\n"
+"\n");
+
+#define TEST_UNSIGNED_SHORT_CONVERTER_METHODDEF \
+ {"test_unsigned_short_converter", (PyCFunction)test_unsigned_short_converter, METH_FASTCALL, test_unsigned_short_converter__doc__},
+
+static PyObject *
+test_unsigned_short_converter_impl(PyObject *module, unsigned short c);
+
+static PyObject *
+test_unsigned_short_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ unsigned short c = 56;
+
+ if (!_PyArg_ParseStack(args, nargs, "|H:test_unsigned_short_converter",
+ &c)) {
+ goto exit;
+ }
+ return_value = test_unsigned_short_converter_impl(module, c);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_unsigned_short_converter_impl(PyObject *module, unsigned short c)
+/*[clinic end generated code: output=1efab48251e8ac53 input=bdfdc5236f5eb7f8]*/
+
+/*[clinic input]
+test_int_converter
+
+ a: int = 12
+ b: int(accept={int}) = 34
+ c: int(accept={str}) = 45
+ d: int(type='myenum') = 67
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_int_converter__doc__,
+"test_int_converter($module, a=12, b=34, c=45, d=67, /)\n"
+"--\n"
+"\n");
+
+#define TEST_INT_CONVERTER_METHODDEF \
+ {"test_int_converter", (PyCFunction)test_int_converter, METH_FASTCALL, test_int_converter__doc__},
+
+static PyObject *
+test_int_converter_impl(PyObject *module, int a, int b, int c, myenum d);
+
+static PyObject *
+test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ int a = 12;
+ int b = 34;
+ int c = 45;
+ myenum d = 67;
+
+ if (!_PyArg_ParseStack(args, nargs, "|iiCi:test_int_converter",
+ &a, &b, &c, &d)) {
+ goto exit;
+ }
+ return_value = test_int_converter_impl(module, a, b, c, d);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_int_converter_impl(PyObject *module, int a, int b, int c, myenum d)
+/*[clinic end generated code: output=601e88039fdfa60a input=d20541fc1ca0553e]*/
+
+/*[clinic input]
+test_unsigned_int_converter
+
+ c: unsigned_int(bitwise=True) = 56
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_unsigned_int_converter__doc__,
+"test_unsigned_int_converter($module, c=56, /)\n"
+"--\n"
+"\n");
+
+#define TEST_UNSIGNED_INT_CONVERTER_METHODDEF \
+ {"test_unsigned_int_converter", (PyCFunction)test_unsigned_int_converter, METH_FASTCALL, test_unsigned_int_converter__doc__},
+
+static PyObject *
+test_unsigned_int_converter_impl(PyObject *module, unsigned int c);
+
+static PyObject *
+test_unsigned_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ unsigned int c = 56;
+
+ if (!_PyArg_ParseStack(args, nargs, "|I:test_unsigned_int_converter",
+ &c)) {
+ goto exit;
+ }
+ return_value = test_unsigned_int_converter_impl(module, c);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_unsigned_int_converter_impl(PyObject *module, unsigned int c)
+/*[clinic end generated code: output=cc53589104965088 input=378cd89bcaa7d54a]*/
+
+/*[clinic input]
+test_long_converter
+
+ a: long = 12
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_long_converter__doc__,
+"test_long_converter($module, a=12, /)\n"
+"--\n"
+"\n");
+
+#define TEST_LONG_CONVERTER_METHODDEF \
+ {"test_long_converter", (PyCFunction)test_long_converter, METH_FASTCALL, test_long_converter__doc__},
+
+static PyObject *
+test_long_converter_impl(PyObject *module, long a);
+
+static PyObject *
+test_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ long a = 12;
+
+ if (!_PyArg_ParseStack(args, nargs, "|l:test_long_converter",
+ &a)) {
+ goto exit;
+ }
+ return_value = test_long_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_long_converter_impl(PyObject *module, long a)
+/*[clinic end generated code: output=a9de1d6b8993931c input=d2179e3c9cdcde89]*/
+
+/*[clinic input]
+test_unsigned_long_converter
+
+ c: unsigned_long(bitwise=True) = 56
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_unsigned_long_converter__doc__,
+"test_unsigned_long_converter($module, c=56, /)\n"
+"--\n"
+"\n");
+
+#define TEST_UNSIGNED_LONG_CONVERTER_METHODDEF \
+ {"test_unsigned_long_converter", (PyCFunction)test_unsigned_long_converter, METH_FASTCALL, test_unsigned_long_converter__doc__},
+
+static PyObject *
+test_unsigned_long_converter_impl(PyObject *module, unsigned long c);
+
+static PyObject *
+test_unsigned_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ unsigned long c = 56;
+
+ if (!_PyArg_ParseStack(args, nargs, "|k:test_unsigned_long_converter",
+ &c)) {
+ goto exit;
+ }
+ return_value = test_unsigned_long_converter_impl(module, c);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_unsigned_long_converter_impl(PyObject *module, unsigned long c)
+/*[clinic end generated code: output=484caa61090cd6f4 input=c69803655925e29c]*/
+
+/*[clinic input]
+test_long_long_converter
+
+ a: long_long = 12
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_long_long_converter__doc__,
+"test_long_long_converter($module, a=12, /)\n"
+"--\n"
+"\n");
+
+#define TEST_LONG_LONG_CONVERTER_METHODDEF \
+ {"test_long_long_converter", (PyCFunction)test_long_long_converter, METH_FASTCALL, test_long_long_converter__doc__},
+
+static PyObject *
+test_long_long_converter_impl(PyObject *module, long long a);
+
+static PyObject *
+test_long_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ long long a = 12;
+
+ if (!_PyArg_ParseStack(args, nargs, "|L:test_long_long_converter",
+ &a)) {
+ goto exit;
+ }
+ return_value = test_long_long_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_long_long_converter_impl(PyObject *module, long long a)
+/*[clinic end generated code: output=7741ab7cfffae072 input=d5fc81577ff4dd02]*/
+
+/*[clinic input]
+test_unsigned_long_long_converter
+
+ c: unsigned_long_long(bitwise=True) = 56
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_unsigned_long_long_converter__doc__,
+"test_unsigned_long_long_converter($module, c=56, /)\n"
+"--\n"
+"\n");
+
+#define TEST_UNSIGNED_LONG_LONG_CONVERTER_METHODDEF \
+ {"test_unsigned_long_long_converter", (PyCFunction)test_unsigned_long_long_converter, METH_FASTCALL, test_unsigned_long_long_converter__doc__},
+
+static PyObject *
+test_unsigned_long_long_converter_impl(PyObject *module,
+ unsigned long long c);
+
+static PyObject *
+test_unsigned_long_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ unsigned long long c = 56;
+
+ if (!_PyArg_ParseStack(args, nargs, "|K:test_unsigned_long_long_converter",
+ &c)) {
+ goto exit;
+ }
+ return_value = test_unsigned_long_long_converter_impl(module, c);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_unsigned_long_long_converter_impl(PyObject *module,
+ unsigned long long c)
+/*[clinic end generated code: output=e07b58db59674c80 input=75cfdbbadef34439]*/
+
+/*[clinic input]
+test_Py_ssize_t_converter
+
+ a: Py_ssize_t = 12
+ b: Py_ssize_t(accept={int}) = 34
+ c: Py_ssize_t(accept={int, NoneType}) = 56
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_Py_ssize_t_converter__doc__,
+"test_Py_ssize_t_converter($module, a=12, b=34, c=56, /)\n"
+"--\n"
+"\n");
+
+#define TEST_PY_SSIZE_T_CONVERTER_METHODDEF \
+ {"test_Py_ssize_t_converter", (PyCFunction)test_Py_ssize_t_converter, METH_FASTCALL, test_Py_ssize_t_converter__doc__},
+
+static PyObject *
+test_Py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b,
+ Py_ssize_t c);
+
+static PyObject *
+test_Py_ssize_t_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t a = 12;
+ Py_ssize_t b = 34;
+ Py_ssize_t c = 56;
+
+ if (!_PyArg_ParseStack(args, nargs, "|nnO&:test_Py_ssize_t_converter",
+ &a, &b, _Py_convert_optional_to_ssize_t, &c)) {
+ goto exit;
+ }
+ return_value = test_Py_ssize_t_converter_impl(module, a, b, c);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_Py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b,
+ Py_ssize_t c)
+/*[clinic end generated code: output=504a11df58a5a277 input=3855f184bb3f299d]*/
+
+/*[clinic input]
+test_slice_index_converter
+
+ a: slice_index = 12
+ b: slice_index(accept={int}) = 34
+ c: slice_index(accept={int, NoneType}) = 56
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_slice_index_converter__doc__,
+"test_slice_index_converter($module, a=12, b=34, c=56, /)\n"
+"--\n"
+"\n");
+
+#define TEST_SLICE_INDEX_CONVERTER_METHODDEF \
+ {"test_slice_index_converter", (PyCFunction)test_slice_index_converter, METH_FASTCALL, test_slice_index_converter__doc__},
+
+static PyObject *
+test_slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b,
+ Py_ssize_t c);
+
+static PyObject *
+test_slice_index_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t a = 12;
+ Py_ssize_t b = 34;
+ Py_ssize_t c = 56;
+
+ if (!_PyArg_ParseStack(args, nargs, "|O&O&O&:test_slice_index_converter",
+ _PyEval_SliceIndex, &a, _PyEval_SliceIndexNotNone, &b, _PyEval_SliceIndex, &c)) {
+ goto exit;
+ }
+ return_value = test_slice_index_converter_impl(module, a, b, c);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b,
+ Py_ssize_t c)
+/*[clinic end generated code: output=b156931c01c9508a input=edeadb0ee126f531]*/
+
+/*[clinic input]
+test_float_converter
+
+ a: float = 12.5
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_float_converter__doc__,
+"test_float_converter($module, a=12.5, /)\n"
+"--\n"
+"\n");
+
+#define TEST_FLOAT_CONVERTER_METHODDEF \
+ {"test_float_converter", (PyCFunction)test_float_converter, METH_FASTCALL, test_float_converter__doc__},
+
+static PyObject *
+test_float_converter_impl(PyObject *module, float a);
+
+static PyObject *
+test_float_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ float a = 12.5;
+
+ if (!_PyArg_ParseStack(args, nargs, "|f:test_float_converter",
+ &a)) {
+ goto exit;
+ }
+ return_value = test_float_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_float_converter_impl(PyObject *module, float a)
+/*[clinic end generated code: output=d37bb4f773ffac06 input=259c0d98eca35034]*/
+
+/*[clinic input]
+test_double_converter
+
+ a: double = 12.5
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_double_converter__doc__,
+"test_double_converter($module, a=12.5, /)\n"
+"--\n"
+"\n");
+
+#define TEST_DOUBLE_CONVERTER_METHODDEF \
+ {"test_double_converter", (PyCFunction)test_double_converter, METH_FASTCALL, test_double_converter__doc__},
+
+static PyObject *
+test_double_converter_impl(PyObject *module, double a);
+
+static PyObject *
+test_double_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ double a = 12.5;
+
+ if (!_PyArg_ParseStack(args, nargs, "|d:test_double_converter",
+ &a)) {
+ goto exit;
+ }
+ return_value = test_double_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_double_converter_impl(PyObject *module, double a)
+/*[clinic end generated code: output=863371b11f7e55fd input=c6a9945706a41c27]*/
+
+/*[clinic input]
+test_Py_complex_converter
+
+ a: Py_complex
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_Py_complex_converter__doc__,
+"test_Py_complex_converter($module, a, /)\n"
+"--\n"
+"\n");
+
+#define TEST_PY_COMPLEX_CONVERTER_METHODDEF \
+ {"test_Py_complex_converter", (PyCFunction)test_Py_complex_converter, METH_O, test_Py_complex_converter__doc__},
+
+static PyObject *
+test_Py_complex_converter_impl(PyObject *module, Py_complex a);
+
+static PyObject *
+test_Py_complex_converter(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_complex a;
+
+ if (!PyArg_Parse(arg, "D:test_Py_complex_converter", &a)) {
+ goto exit;
+ }
+ return_value = test_Py_complex_converter_impl(module, a);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_Py_complex_converter_impl(PyObject *module, Py_complex a)
+/*[clinic end generated code: output=27efb4ff772d6170 input=070f216a515beb79]*/
+
+/*[clinic input]
+test_str_converter
+
+ a: str = NULL
+ b: str = "ab"
+ c: str(accept={str}) = "cd"
+ d: str(accept={robuffer}) = "cef"
+ e: str(accept={str, NoneType}) = "gh"
+ f: str(accept={robuffer}, zeroes=True) = "ij"
+ g: str(accept={robuffer, str}, zeroes=True) = "kl"
+ h: str(accept={robuffer, str, NoneType}, zeroes=True) = "mn"
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_str_converter__doc__,
+"test_str_converter($module, a=None, b=\'ab\', c=\'cd\', d=\'cef\', e=\'gh\',\n"
+" f=\'ij\', g=\'kl\', h=\'mn\', /)\n"
+"--\n"
+"\n");
+
+#define TEST_STR_CONVERTER_METHODDEF \
+ {"test_str_converter", (PyCFunction)test_str_converter, METH_FASTCALL, test_str_converter__doc__},
+
+static PyObject *
+test_str_converter_impl(PyObject *module, const char *a, const char *b,
+ const char *c, const char *d, const char *e,
+ const char *f, Py_ssize_clean_t f_length,
+ const char *g, Py_ssize_clean_t g_length,
+ const char *h, Py_ssize_clean_t h_length);
+
+static PyObject *
+test_str_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ const char *a = NULL;
+ const char *b = "ab";
+ const char *c = "cd";
+ const char *d = "cef";
+ const char *e = "gh";
+ const char *f = "ij";
+ Py_ssize_clean_t f_length;
+ const char *g = "kl";
+ Py_ssize_clean_t g_length;
+ const char *h = "mn";
+ Py_ssize_clean_t h_length;
+
+ if (!_PyArg_ParseStack(args, nargs, "|sssyzy#s#z#:test_str_converter",
+ &a, &b, &c, &d, &e, &f, &f_length, &g, &g_length, &h, &h_length)) {
+ goto exit;
+ }
+ return_value = test_str_converter_impl(module, a, b, c, d, e, f, f_length, g, g_length, h, h_length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_str_converter_impl(PyObject *module, const char *a, const char *b,
+ const char *c, const char *d, const char *e,
+ const char *f, Py_ssize_clean_t f_length,
+ const char *g, Py_ssize_clean_t g_length,
+ const char *h, Py_ssize_clean_t h_length)
+/*[clinic end generated code: output=94988a5346fd888e input=8afe9da8185cd38c]*/
+
+/*[clinic input]
+test_str_converter_encoding
+
+ a: str(encoding="idna")
+ b: str(encoding="idna", accept={str})
+ c: str(encoding="idna", accept={bytes, bytearray, str})
+ d: str(encoding="idna", zeroes=True)
+ e: str(encoding="idna", accept={bytes, bytearray, str}, zeroes=True)
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_str_converter_encoding__doc__,
+"test_str_converter_encoding($module, a, b, c, d, e, /)\n"
+"--\n"
+"\n");
+
+#define TEST_STR_CONVERTER_ENCODING_METHODDEF \
+ {"test_str_converter_encoding", (PyCFunction)test_str_converter_encoding, METH_FASTCALL, test_str_converter_encoding__doc__},
+
+static PyObject *
+test_str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c,
+ char *d, Py_ssize_clean_t d_length, char *e,
+ Py_ssize_clean_t e_length);
+
+static PyObject *
+test_str_converter_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ char *a = NULL;
+ char *b = NULL;
+ char *c = NULL;
+ char *d = NULL;
+ Py_ssize_clean_t d_length;
+ char *e = NULL;
+ Py_ssize_clean_t e_length;
+
+ if (!_PyArg_ParseStack(args, nargs, "esesetes#et#:test_str_converter_encoding",
+ "idna", &a, "idna", &b, "idna", &c, "idna", &d, &d_length, "idna", &e, &e_length)) {
+ goto exit;
+ }
+ return_value = test_str_converter_encoding_impl(module, a, b, c, d, d_length, e, e_length);
+
+exit:
+ /* Cleanup for a */
+ if (a) {
+ PyMem_FREE(a);
+ }
+ /* Cleanup for b */
+ if (b) {
+ PyMem_FREE(b);
+ }
+ /* Cleanup for c */
+ if (c) {
+ PyMem_FREE(c);
+ }
+ /* Cleanup for d */
+ if (d) {
+ PyMem_FREE(d);
+ }
+ /* Cleanup for e */
+ if (e) {
+ PyMem_FREE(e);
+ }
+
+ return return_value;
+}
+
+static PyObject *
+test_str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c,
+ char *d, Py_ssize_clean_t d_length, char *e,
+ Py_ssize_clean_t e_length)
+/*[clinic end generated code: output=1a63c67528fe9e74 input=eb4c38e1f898f402]*/
+
+/*[clinic input]
+test_Py_UNICODE_converter
+
+ a: Py_UNICODE
+ b: Py_UNICODE(accept={str})
+ c: Py_UNICODE(accept={str, NoneType})
+ d: Py_UNICODE(zeroes=True)
+ e: Py_UNICODE(accept={str, NoneType}, zeroes=True)
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_Py_UNICODE_converter__doc__,
+"test_Py_UNICODE_converter($module, a, b, c, d, e, /)\n"
+"--\n"
+"\n");
+
+#define TEST_PY_UNICODE_CONVERTER_METHODDEF \
+ {"test_Py_UNICODE_converter", (PyCFunction)test_Py_UNICODE_converter, METH_FASTCALL, test_Py_UNICODE_converter__doc__},
+
+static PyObject *
+test_Py_UNICODE_converter_impl(PyObject *module, const Py_UNICODE *a,
+ const Py_UNICODE *b, const Py_UNICODE *c,
+ const Py_UNICODE *d,
+ Py_ssize_clean_t d_length,
+ const Py_UNICODE *e,
+ Py_ssize_clean_t e_length);
+
+static PyObject *
+test_Py_UNICODE_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ const Py_UNICODE *a;
+ const Py_UNICODE *b;
+ const Py_UNICODE *c;
+ const Py_UNICODE *d;
+ Py_ssize_clean_t d_length;
+ const Py_UNICODE *e;
+ Py_ssize_clean_t e_length;
+
+ if (!_PyArg_ParseStack(args, nargs, "uuZu#Z#:test_Py_UNICODE_converter",
+ &a, &b, &c, &d, &d_length, &e, &e_length)) {
+ goto exit;
+ }
+ return_value = test_Py_UNICODE_converter_impl(module, a, b, c, d, d_length, e, e_length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+test_Py_UNICODE_converter_impl(PyObject *module, const Py_UNICODE *a,
+ const Py_UNICODE *b, const Py_UNICODE *c,
+ const Py_UNICODE *d,
+ Py_ssize_clean_t d_length,
+ const Py_UNICODE *e,
+ Py_ssize_clean_t e_length)
+/*[clinic end generated code: output=98f7ebc3ce76aff3 input=064a3b68ad7f04b0]*/
+
+/*[clinic input]
+test_Py_buffer_converter
+
+ a: Py_buffer
+ b: Py_buffer(accept={buffer})
+ c: Py_buffer(accept={str, buffer})
+ d: Py_buffer(accept={str, buffer, NoneType})
+ e: Py_buffer(accept={rwbuffer})
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_Py_buffer_converter__doc__,
+"test_Py_buffer_converter($module, a, b, c, d, e, /)\n"
+"--\n"
+"\n");
+
+#define TEST_PY_BUFFER_CONVERTER_METHODDEF \
+ {"test_Py_buffer_converter", (PyCFunction)test_Py_buffer_converter, METH_FASTCALL, test_Py_buffer_converter__doc__},
+
+static PyObject *
+test_Py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b,
+ Py_buffer *c, Py_buffer *d, Py_buffer *e);
+
+static PyObject *
+test_Py_buffer_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ Py_buffer a = {NULL, NULL};
+ Py_buffer b = {NULL, NULL};
+ Py_buffer c = {NULL, NULL};
+ Py_buffer d = {NULL, NULL};
+ Py_buffer e = {NULL, NULL};
+
+ if (!_PyArg_ParseStack(args, nargs, "y*y*s*z*w*:test_Py_buffer_converter",
+ &a, &b, &c, &d, &e)) {
+ goto exit;
+ }
+ return_value = test_Py_buffer_converter_impl(module, &a, &b, &c, &d, &e);
+
+exit:
+ /* Cleanup for a */
+ if (a.obj) {
+ PyBuffer_Release(&a);
+ }
+ /* Cleanup for b */
+ if (b.obj) {
+ PyBuffer_Release(&b);
+ }
+ /* Cleanup for c */
+ if (c.obj) {
+ PyBuffer_Release(&c);
+ }
+ /* Cleanup for d */
+ if (d.obj) {
+ PyBuffer_Release(&d);
+ }
+ /* Cleanup for e */
+ if (e.obj) {
+ PyBuffer_Release(&e);
+ }
+
+ return return_value;
+}
+
+static PyObject *
+test_Py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b,
+ Py_buffer *c, Py_buffer *d, Py_buffer *e)
+/*[clinic end generated code: output=92937215f10bc937 input=6a9da0f56f9525fd]*/
#check that this standard extension works
t.strftime("%f")
+ def test_strftime_trailing_percent(self):
+ # bpo-35066: make sure trailing '%' doesn't cause
+ # datetime's strftime to complain
+ t = self.theclass(2005, 3, 2)
+ try:
+ _time.strftime('%')
+ except ValueError:
+ self.skipTest('time module does not support trailing %')
+ self.assertEqual(t.strftime('%'), '%')
+ self.assertEqual(t.strftime("m:%m d:%d y:%y %"), "m:03 d:02 y:05 %")
+
def test_format(self):
dt = self.theclass(2007, 9, 10)
self.assertEqual(dt.__format__(''), str(dt))
import faulthandler
import fcntl
import os
+import platform
import select
import signal
import socket
self.stop_alarm()
proc.wait()
+ # Issue 35633: See https://bugs.python.org/issue35633#msg333662
+ # skip test rather than accept PermissionError from all platforms
+ @unittest.skipIf(platform.system() == "AIX", "AIX returns PermissionError")
def test_lockf(self):
self._lock(fcntl.lockf, "lockf")
2 billion objects, which only works on 64-bit systems. There are also some
tests that try to exhaust the address space of the process, which only makes
sense on 32-bit systems with at least 2Gb of memory. The passed-in memlimit,
-which is a string in the form of '2.5Gb', determines howmuch memory the
+which is a string in the form of '2.5Gb', determines how much memory the
tests will limit themselves to (but they may go slightly over.) The number
shouldn't be more memory than the machine has (including swap memory). You
should also keep in mind that swap memory is generally much, much slower
import datetime
import faulthandler
+import json
import locale
import os
import platform
if self.ns.tempdir:
TEMPDIR = self.ns.tempdir
+ elif self.ns.worker_args:
+ ns_dict, _ = json.loads(self.ns.worker_args)
+ TEMPDIR = ns_dict.get("tempdir") or TEMPDIR
os.makedirs(TEMPDIR, exist_ok=True)
abstest = get_abs_module(ns, test)
clear_caches()
with saved_test_environment(test, ns.verbose, ns.quiet, pgo=ns.pgo) as environment:
- start_time = time.time()
+ start_time = time.perf_counter()
the_module = importlib.import_module(abstest)
# If the test has a test_main, that will run the appropriate
# tests. If not, use normal unittest test loading.
refleak = dash_R(the_module, test, test_runner, ns.huntrleaks)
else:
test_runner()
- test_time = time.time() - start_time
+ test_time = time.perf_counter() - start_time
post_test_cleanup()
except support.ResourceDenied as msg:
if not ns.quiet and not ns.pgo:
self.assertEqual(a, b)
def test_getitem_error(self):
+ a = []
+ msg = "list indices must be integers or slices"
+ with self.assertRaisesRegex(TypeError, msg):
+ a['a']
+
+ def test_setitem_error(self):
+ a = []
msg = "list indices must be integers or slices"
with self.assertRaisesRegex(TypeError, msg):
- a = []
a['a'] = "python"
def test_repr(self):
support.reap_children()
def assertTimeout(self, actual, expected):
- # The waiting and/or time.time() can be imprecise, which
+ # The waiting and/or time.monotonic() can be imprecise, which
# is why comparing to the expected value would sometimes fail
# (especially under Windows).
self.assertGreaterEqual(actual, expected * 0.6)
# TIMEOUT_MAX is ok
lock.acquire(timeout=TIMEOUT_MAX)
lock.release()
- t1 = time.time()
+ t1 = time.monotonic()
self.assertTrue(lock.acquire(timeout=5))
- t2 = time.time()
+ t2 = time.monotonic()
# Just a sanity test that it didn't actually wait for the timeout.
self.assertLess(t2 - t1, 5)
results = []
def f():
- t1 = time.time()
+ t1 = time.monotonic()
results.append(lock.acquire(timeout=0.5))
- t2 = time.time()
+ t2 = time.monotonic()
results.append(t2 - t1)
Bunch(f, 1).wait_for_finished()
self.assertFalse(results[0])
N = 5
def f():
results1.append(evt.wait(0.0))
- t1 = time.time()
+ t1 = time.monotonic()
r = evt.wait(0.5)
- t2 = time.time()
+ t2 = time.monotonic()
results2.append((r, t2 - t1))
Bunch(f, N).wait_for_finished()
self.assertEqual(results1, [False] * N)
N = 5
def f():
cond.acquire()
- t1 = time.time()
+ t1 = time.monotonic()
result = cond.wait(0.5)
- t2 = time.time()
+ t2 = time.monotonic()
cond.release()
results.append((t2 - t1, result))
Bunch(f, N).wait_for_finished()
success = []
def f():
with cond:
- dt = time.time()
+ dt = time.monotonic()
result = cond.wait_for(lambda : state==4, timeout=0.1)
- dt = time.time() - dt
+ dt = time.monotonic() - dt
self.assertFalse(result)
self.assertTimeout(dt, 0.1)
success.append(None)
self.assertFalse(sem.acquire(timeout=0.005))
sem.release()
self.assertTrue(sem.acquire(timeout=0.005))
- t = time.time()
+ t = time.monotonic()
self.assertFalse(sem.acquire(timeout=0.5))
- dt = time.time() - t
+ dt = time.monotonic() - t
self.assertTimeout(dt, 0.5)
def test_default_value(self):
writer = self.writer(stream)
writer.reset()
+ def test_incrementalencoder_del_segfault(self):
+ e = self.incrementalencoder()
+ with self.assertRaises(AttributeError):
+ del e.errors
+
class TestBase_Mapping(unittest.TestCase):
pass_enctest = []
import dbm
import io
import functools
+import os
import pickle
import pickletools
+import shutil
import struct
import sys
+import threading
import unittest
import weakref
+from textwrap import dedent
from http.cookies import SimpleCookie
from test import support
from test.support import (
TestFailed, TESTFN, run_with_locale, no_tracing,
- _2G, _4G, bigmemtest,
+ _2G, _4G, bigmemtest, reap_threads, forget,
)
from pickle import bytes_types
for p in badpickles:
self.check_unpickling_error(self.truncated_errors, p)
+ @reap_threads
+ def test_unpickle_module_race(self):
+ # https://bugs.python.org/issue34572
+ locker_module = dedent("""
+ import threading
+ barrier = threading.Barrier(2)
+ """)
+ locking_import_module = dedent("""
+ import locker
+ locker.barrier.wait()
+ class ToBeUnpickled(object):
+ pass
+ """)
+
+ os.mkdir(TESTFN)
+ self.addCleanup(shutil.rmtree, TESTFN)
+ sys.path.insert(0, TESTFN)
+ self.addCleanup(sys.path.remove, TESTFN)
+ with open(os.path.join(TESTFN, "locker.py"), "wb") as f:
+ f.write(locker_module.encode('utf-8'))
+ with open(os.path.join(TESTFN, "locking_import.py"), "wb") as f:
+ f.write(locking_import_module.encode('utf-8'))
+ self.addCleanup(forget, "locker")
+ self.addCleanup(forget, "locking_import")
+
+ import locker
+
+ pickle_bytes = (
+ b'\x80\x03clocking_import\nToBeUnpickled\nq\x00)\x81q\x01.')
+
+ # Then try to unpickle two of these simultaneously
+ # One of them will cause the module import, and we want it to block
+ # until the other one either:
+ # - fails (before the patch for this issue)
+ # - blocks on the import lock for the module, as it should
+ results = []
+ barrier = threading.Barrier(3)
+ def t():
+ # This ensures the threads have all started
+ # presumably barrier release is faster than thread startup
+ barrier.wait()
+ results.append(pickle.loads(pickle_bytes))
+
+ t1 = threading.Thread(target=t)
+ t2 = threading.Thread(target=t)
+ t1.start()
+ t2.start()
+
+ barrier.wait()
+ # could have delay here
+ locker.barrier.wait()
+
+ t1.join()
+ t2.join()
+
+ from locking_import import ToBeUnpickled
+ self.assertEqual(
+ [type(x) for x in results],
+ [ToBeUnpickled] * 2)
+
+
class AbstractPickleTests(unittest.TestCase):
# Subclass must define self.dumps, self.loads.
value = resource.getrlimit(key)
info_add('resource.%s' % name, value)
+ call_func(info_add, 'resource.pagesize', resource, 'getpagesize')
+
def collect_test_socket(info_add):
try:
# module name.
TESTFN = "{}_{}_tmp".format(TESTFN, os.getpid())
+# Define the URL of a dedicated HTTP server for the network tests.
+# The URL must use clear-text HTTP: no redirection to encrypted HTTPS.
+TEST_HTTP_URL = "http://www.pythontest.net"
+
# FS_NONASCII: non-ASCII character encodable by os.fsencode(),
# or None if there is no such character.
FS_NONASCII = None
if junit_xml_list is not None:
junit_xml_list.append(result.get_xml_element())
- if not result.testsRun:
+ if not result.testsRun and not result.skipped:
raise TestDidNotRun
if not result.wasSuccessful():
if len(result.errors) == 1 and not result.failures:
patterns = ()
elif all(map(_is_full_match_test, patterns)):
# Simple case: all patterns are full test identifier.
- # The test.bisect utility only uses such full test identifiers.
+ # The test.bisect_cmd utility only uses such full test identifiers.
func = set(patterns).__contains__
else:
regex = '|'.join(map(fnmatch.translate, patterns))
try:
if unlock:
unlock()
- endtime = starttime = time.time()
+ endtime = starttime = time.monotonic()
for timeout in range(1, 16):
endtime += 60
for t in started:
- t.join(max(endtime - time.time(), 0.01))
- started = [t for t in started if t.isAlive()]
+ t.join(max(endtime - time.monotonic(), 0.01))
+ started = [t for t in started if t.is_alive()]
if not started:
break
if verbose:
print('Unable to join %d threads during a period of '
'%d minutes' % (len(started), timeout))
finally:
- started = [t for t in started if t.isAlive()]
+ started = [t for t in started if t.is_alive()]
if started:
faulthandler.dump_traceback(sys.stdout)
raise AssertionError('Unable to join %d threads' % len(started))
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApKgAwIBAgIBAjALBgkqhkiG9w0BAQswHzELMAkGA1UEBhMCVUsxEDAO
+BgNVBAMTB2NvZHktY2EwHhcNMTgwNjE4MTgwMDU4WhcNMjgwNjE0MTgwMDU4WjA7
+MQswCQYDVQQGEwJVSzEsMCoGA1UEAxMjY29kZW5vbWljb24tdm0tMi50ZXN0Lmxh
+bC5jaXNjby5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC63fGB
+J80A9Av1GB0bptslKRIUtJm8EeEu34HkDWbL6AJY0P8WfDtlXjlPaLqFa6sqH6ES
+V48prSm1ZUbDSVL8R6BYVYpOlK8/48xk4pGTgRzv69gf5SGtQLwHy8UPBKgjSZoD
+5a5k5wJXGswhKFFNqyyxqCvWmMnJWxXTt2XDCiWc4g4YAWi4O4+6SeeHVAV9rV7C
+1wxqjzKovVe2uZOHjKEzJbbIU6JBPb6TRfMdRdYOw98n1VXDcKVgdX2DuuqjCzHP
+WhU4Tw050M9NaK3eXp4Mh69VuiKoBGOLSOcS8reqHIU46Reg0hqeL8LIL6OhFHIF
+j7HR6V1X6F+BfRS/AgMBAAGjgdYwgdMwCQYDVR0TBAIwADAdBgNVHQ4EFgQUOktp
+HQjxDXXUg8prleY9jeLKeQ4wTwYDVR0jBEgwRoAUx6zgPygZ0ZErF9sPC4+5e2Io
+UU+hI6QhMB8xCzAJBgNVBAYTAlVLMRAwDgYDVQQDEwdjb2R5LWNhggkA1QEAuwb7
+2s0wCQYDVR0SBAIwADAuBgNVHREEJzAlgiNjb2Rlbm9taWNvbi12bS0yLnRlc3Qu
+bGFsLmNpc2NvLmNvbTAOBgNVHQ8BAf8EBAMCBaAwCwYDVR0fBAQwAjAAMAsGCSqG
+SIb3DQEBCwOCAQEAvqantx2yBlM11RoFiCfi+AfSblXPdrIrHvccepV4pYc/yO6p
+t1f2dxHQb8rWH3i6cWag/EgIZx+HJQvo0rgPY1BFJsX1WnYf1/znZpkUBGbVmlJr
+t/dW1gSkNS6sPsM0Q+7HPgEv8CPDNK5eo7vU2seE0iWOkxSyVUuiCEY9ZVGaLVit
+p0C78nZ35Pdv4I+1cosmHl28+es1WI22rrnmdBpH8J1eY6WvUw2xuZHLeNVN0TzV
+Q3qq53AaCWuLOD1AjESWuUCxMZTK9DPS4JKXTK8RLyDeqOvJGjsSWp3kL0y3GaQ+
+10T1rfkKJub2+m9A9duin1fn6tHc2wSvB7m3DA==
+-----END CERTIFICATE-----
self.loop.add_signal_handler(signal.SIGALRM, my_handler)
signal.setitimer(signal.ITIMER_REAL, 0.01, 0) # Send SIGALRM once.
+ self.loop.call_later(60, self.loop.stop)
self.loop.run_forever()
self.assertEqual(caught, 1)
nonlocal caught
caught += 1
self.assertEqual(args, some_args)
+ self.loop.stop()
self.loop.add_signal_handler(signal.SIGALRM, my_handler, *some_args)
signal.setitimer(signal.ITIMER_REAL, 0.1, 0) # Send SIGALRM once.
- self.loop.call_later(0.5, self.loop.stop)
+ self.loop.call_later(60, self.loop.stop)
self.loop.run_forever()
self.assertEqual(caught, 1)
except AttributeError:
cls = None
+ def test_future_del_segfault(self):
+ fut = self._new_future(loop=self.loop)
+ with self.assertRaises(AttributeError):
+ del fut._asyncio_future_blocking
+ with self.assertRaises(AttributeError):
+ del fut._log_traceback
+
@unittest.skipUnless(hasattr(futures, '_CFuture'),
'requires the C _asyncio module')
self.loop.run_until_complete(task)
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
+ def test_del__log_destroy_pending_segfault(self):
+ @asyncio.coroutine
+ def coro():
+ pass
+ task = self.new_task(self.loop, coro())
+ self.loop.run_until_complete(task)
+ with self.assertRaises(AttributeError):
+ del task._log_destroy_pending
+
@unittest.skipUnless(hasattr(futures, '_CFuture') and
hasattr(tasks, '_CTask'),
self.data = bytearray()
self.fut = loop.create_future()
self.transport = None
+ self._ready = loop.create_future()
def connection_made(self, transport):
self.started = True
self.transport = transport
+ self._ready.set_result(None)
def data_received(self, data):
self.data.extend(data)
server = self.run_loop(self.loop.create_server(
lambda: proto, sock=srv_sock))
self.run_loop(self.loop.sock_connect(sock, (support.HOST, port)))
+ self.run_loop(proto._ready)
def cleanup():
- if proto.transport is not None:
- # can be None if the task was cancelled before
- # connection_made callback
- proto.transport.close()
- self.run_loop(proto.wait_closed())
+ proto.transport.close()
+ self.run_loop(proto.wait_closed())
server.close()
self.run_loop(server.wait_closed())
def run_until(loop, pred, timeout=30):
- deadline = time.time() + timeout
+ deadline = time.monotonic() + timeout
while not pred():
if timeout is not None:
- timeout = deadline - time.time()
+ timeout = deadline - time.monotonic()
if timeout <= 0:
raise futures.TimeoutError()
loop.run_until_complete(tasks.sleep(0.001, loop=loop))
pass
else:
n = 200
- start = time.time()
- while n > 0 and time.time() - start < 3.0:
+ start = time.monotonic()
+ while n > 0 and time.monotonic() - start < 3.0:
r, w, e = select.select([conn], [], [], 0.1)
if r:
n -= 1
ascii_char_size = 1
ucs2_char_size = 2
ucs4_char_size = 4
+pointer_size = 4 if sys.maxsize < 2**32 else 8
class BaseStrTest:
# suffer for the list size. (Otherwise, it'd cost another 48 times
# size in bytes!) Nevertheless, a list of size takes
# 8*size bytes.
- @bigmemtest(size=_2G + 5, memuse=2 * ascii_char_size + 8)
+ @bigmemtest(size=_2G + 5, memuse=ascii_char_size * 2 + pointer_size)
def test_split_large(self, size):
_ = self.from_latin1
s = _(' a') * size + _(' ')
for name, memuse in self._adjusted.items():
getattr(type(self), name).memuse = memuse
- @bigmemtest(size=_2G, memuse=ucs4_char_size * 3)
+ @bigmemtest(size=_2G, memuse=ucs4_char_size * 3 + ascii_char_size * 2)
def test_capitalize(self, size):
self._test_capitalize(size)
- @bigmemtest(size=_2G, memuse=ucs4_char_size * 3)
+ @bigmemtest(size=_2G, memuse=ucs4_char_size * 3 + ascii_char_size * 2)
def test_title(self, size):
self._test_title(size)
- @bigmemtest(size=_2G, memuse=ucs4_char_size * 3)
+ @bigmemtest(size=_2G, memuse=ucs4_char_size * 3 + ascii_char_size * 2)
def test_swapcase(self, size):
self._test_swapcase(size)
except MemoryError:
pass # acceptable on 32-bit
- @bigmemtest(size=_4G // 5 + 70, memuse=ascii_char_size + ucs4_char_size + 1)
+ @bigmemtest(size=_4G // 5 + 70, memuse=ascii_char_size + 8 + 1)
def test_encode_utf7(self, size):
try:
return self.basic_encode_test(size, 'utf7')
# having more than 2<<31 references to any given object. Hence the
# use of different types of objects as contents in different tests.
- @bigmemtest(size=_2G + 2, memuse=16)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 2)
def test_compare(self, size):
t1 = ('',) * size
t2 = ('',) * size
t = t + t
self.assertEqual(len(t), size * 2)
- @bigmemtest(size=_2G // 2 + 2, memuse=24)
+ @bigmemtest(size=_2G // 2 + 2, memuse=pointer_size * 3)
def test_concat_small(self, size):
return self.basic_concat_test(size)
- @bigmemtest(size=_2G + 2, memuse=24)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 3)
def test_concat_large(self, size):
return self.basic_concat_test(size)
- @bigmemtest(size=_2G // 5 + 10, memuse=8 * 5)
+ @bigmemtest(size=_2G // 5 + 10, memuse=pointer_size * 5)
def test_contains(self, size):
t = (1, 2, 3, 4, 5) * size
self.assertEqual(len(t), size * 5)
self.assertFalse((1, 2, 3, 4, 5) in t)
self.assertFalse(0 in t)
- @bigmemtest(size=_2G + 10, memuse=8)
+ @bigmemtest(size=_2G + 10, memuse=pointer_size)
def test_hash(self, size):
t1 = (0,) * size
h1 = hash(t1)
t2 = (0,) * (size + 1)
self.assertFalse(h1 == hash(t2))
- @bigmemtest(size=_2G + 10, memuse=8)
+ @bigmemtest(size=_2G + 10, memuse=pointer_size)
def test_index_and_slice(self, size):
t = (None,) * size
self.assertEqual(len(t), size)
t = t * 2
self.assertEqual(len(t), size * 2)
- @bigmemtest(size=_2G // 2 + 2, memuse=24)
+ @bigmemtest(size=_2G // 2 + 2, memuse=pointer_size * 3)
def test_repeat_small(self, size):
return self.basic_test_repeat(size)
- @bigmemtest(size=_2G + 2, memuse=24)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 3)
def test_repeat_large(self, size):
return self.basic_test_repeat(size)
def test_repeat_large_2(self, size):
return self.basic_test_repeat(size)
- @bigmemtest(size=_1G - 1, memuse=9)
+ @bigmemtest(size=_1G - 1, memuse=pointer_size * 2)
def test_from_2G_generator(self, size):
- self.skipTest("test needs much more memory than advertised, see issue5438")
try:
- t = tuple(range(size))
+ t = tuple(iter([42]*size))
except MemoryError:
pass # acceptable on 32-bit
else:
- count = 0
- for item in t:
- self.assertEqual(item, count)
- count += 1
- self.assertEqual(count, size)
+ self.assertEqual(len(t), size)
+ self.assertEqual(t[:10], (42,) * 10)
+ self.assertEqual(t[-10:], (42,) * 10)
- @bigmemtest(size=_1G - 25, memuse=9)
+ @bigmemtest(size=_1G - 25, memuse=pointer_size * 2)
def test_from_almost_2G_generator(self, size):
- self.skipTest("test needs much more memory than advertised, see issue5438")
try:
- t = tuple(range(size))
- count = 0
- for item in t:
- self.assertEqual(item, count)
- count += 1
- self.assertEqual(count, size)
+ t = tuple(iter([42]*size))
except MemoryError:
- pass # acceptable, expected on 32-bit
+ pass # acceptable on 32-bit
+ else:
+ self.assertEqual(len(t), size)
+ self.assertEqual(t[:10], (42,) * 10)
+ self.assertEqual(t[-10:], (42,) * 10)
# Like test_concat, split in two.
def basic_test_repr(self, size):
- t = (0,) * size
+ t = (False,) * size
s = repr(t)
- # The repr of a tuple of 0's is exactly three times the tuple length.
- self.assertEqual(len(s), size * 3)
- self.assertEqual(s[:5], '(0, 0')
- self.assertEqual(s[-5:], '0, 0)')
- self.assertEqual(s.count('0'), size)
+ # The repr of a tuple of Falses is exactly 7 times the tuple length.
+ self.assertEqual(len(s), size * 7)
+ self.assertEqual(s[:10], '(False, Fa')
+ self.assertEqual(s[-10:], 'se, False)')
- @bigmemtest(size=_2G // 3 + 2, memuse=8 + 3 * ascii_char_size)
+ @bigmemtest(size=_2G // 7 + 2, memuse=pointer_size + ascii_char_size * 7)
def test_repr_small(self, size):
return self.basic_test_repr(size)
- @bigmemtest(size=_2G + 2, memuse=8 + 3 * ascii_char_size)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size + ascii_char_size * 7)
def test_repr_large(self, size):
return self.basic_test_repr(size)
# lists hold references to various objects to test their refcount
# limits.
- @bigmemtest(size=_2G + 2, memuse=16)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 2)
def test_compare(self, size):
l1 = [''] * size
l2 = [''] * size
l = l + l
self.assertEqual(len(l), size * 2)
- @bigmemtest(size=_2G // 2 + 2, memuse=24)
+ @bigmemtest(size=_2G // 2 + 2, memuse=pointer_size * 3)
def test_concat_small(self, size):
return self.basic_test_concat(size)
- @bigmemtest(size=_2G + 2, memuse=24)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 3)
def test_concat_large(self, size):
return self.basic_test_concat(size)
+ # XXX This tests suffers from overallocation, just like test_append.
+ # This should be fixed in future.
def basic_test_inplace_concat(self, size):
l = [sys.stdout] * size
l += l
self.assertTrue(l[0] is l[-1])
self.assertTrue(l[size - 1] is l[size + 1])
- @bigmemtest(size=_2G // 2 + 2, memuse=24)
+ @bigmemtest(size=_2G // 2 + 2, memuse=pointer_size * 2 * 9/8)
def test_inplace_concat_small(self, size):
return self.basic_test_inplace_concat(size)
- @bigmemtest(size=_2G + 2, memuse=24)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 2 * 9/8)
def test_inplace_concat_large(self, size):
return self.basic_test_inplace_concat(size)
- @bigmemtest(size=_2G // 5 + 10, memuse=8 * 5)
+ @bigmemtest(size=_2G // 5 + 10, memuse=pointer_size * 5)
def test_contains(self, size):
l = [1, 2, 3, 4, 5] * size
self.assertEqual(len(l), size * 5)
self.assertFalse([1, 2, 3, 4, 5] in l)
self.assertFalse(0 in l)
- @bigmemtest(size=_2G + 10, memuse=8)
+ @bigmemtest(size=_2G + 10, memuse=pointer_size)
def test_hash(self, size):
l = [0] * size
self.assertRaises(TypeError, hash, l)
- @bigmemtest(size=_2G + 10, memuse=8)
+ @bigmemtest(size=_2G + 10, memuse=pointer_size)
def test_index_and_slice(self, size):
l = [None] * size
self.assertEqual(len(l), size)
l = l * 2
self.assertEqual(len(l), size * 2)
- @bigmemtest(size=_2G // 2 + 2, memuse=24)
+ @bigmemtest(size=_2G // 2 + 2, memuse=pointer_size * 3)
def test_repeat_small(self, size):
return self.basic_test_repeat(size)
- @bigmemtest(size=_2G + 2, memuse=24)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 3)
def test_repeat_large(self, size):
return self.basic_test_repeat(size)
+ # XXX This tests suffers from overallocation, just like test_append.
+ # This should be fixed in future.
def basic_test_inplace_repeat(self, size):
l = ['']
l *= size
self.assertEqual(len(l), size * 2)
self.assertTrue(l[size - 1] is l[-1])
- @bigmemtest(size=_2G // 2 + 2, memuse=16)
+ @bigmemtest(size=_2G // 2 + 2, memuse=pointer_size * 2 * 9/8)
def test_inplace_repeat_small(self, size):
return self.basic_test_inplace_repeat(size)
- @bigmemtest(size=_2G + 2, memuse=16)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 2 * 9/8)
def test_inplace_repeat_large(self, size):
return self.basic_test_inplace_repeat(size)
def basic_test_repr(self, size):
- l = [0] * size
+ l = [False] * size
s = repr(l)
- # The repr of a list of 0's is exactly three times the list length.
- self.assertEqual(len(s), size * 3)
- self.assertEqual(s[:5], '[0, 0')
- self.assertEqual(s[-5:], '0, 0]')
- self.assertEqual(s.count('0'), size)
+ # The repr of a list of Falses is exactly 7 times the list length.
+ self.assertEqual(len(s), size * 7)
+ self.assertEqual(s[:10], '[False, Fa')
+ self.assertEqual(s[-10:], 'se, False]')
+ self.assertEqual(s.count('F'), size)
- @bigmemtest(size=_2G // 3 + 2, memuse=8 + 3 * ascii_char_size)
+ @bigmemtest(size=_2G // 7 + 2, memuse=pointer_size + ascii_char_size * 7)
def test_repr_small(self, size):
return self.basic_test_repr(size)
- @bigmemtest(size=_2G + 2, memuse=8 + 3 * ascii_char_size)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size + ascii_char_size * 7)
def test_repr_large(self, size):
return self.basic_test_repr(size)
# list overallocates ~1/8th of the total size (on first expansion) so
# the single list.append call puts memuse at 9 bytes per size.
- @bigmemtest(size=_2G, memuse=9)
+ @bigmemtest(size=_2G, memuse=pointer_size * 9/8)
def test_append(self, size):
l = [object()] * size
l.append(object())
self.assertTrue(l[-3] is l[-2])
self.assertFalse(l[-2] is l[-1])
- @bigmemtest(size=_2G // 5 + 2, memuse=8 * 5)
+ @bigmemtest(size=_2G // 5 + 2, memuse=pointer_size * 5)
def test_count(self, size):
l = [1, 2, 3, 4, 5] * size
self.assertEqual(l.count(1), size)
self.assertEqual(l.count("1"), 0)
+ # XXX This tests suffers from overallocation, just like test_append.
+ # This should be fixed in future.
def basic_test_extend(self, size):
l = [object] * size
l.extend(l)
self.assertTrue(l[0] is l[-1])
self.assertTrue(l[size - 1] is l[size + 1])
- @bigmemtest(size=_2G // 2 + 2, memuse=16)
+ @bigmemtest(size=_2G // 2 + 2, memuse=pointer_size * 2 * 9/8)
def test_extend_small(self, size):
return self.basic_test_extend(size)
- @bigmemtest(size=_2G + 2, memuse=16)
+ @bigmemtest(size=_2G + 2, memuse=pointer_size * 2 * 9/8)
def test_extend_large(self, size):
return self.basic_test_extend(size)
- @bigmemtest(size=_2G // 5 + 2, memuse=8 * 5)
+ @bigmemtest(size=_2G // 5 + 2, memuse=pointer_size * 5)
def test_index(self, size):
l = [1, 2, 3, 4, 5] * size
size *= 5
self.assertRaises(ValueError, l.index, 6)
# This tests suffers from overallocation, just like test_append.
- @bigmemtest(size=_2G + 10, memuse=9)
+ @bigmemtest(size=_2G + 10, memuse=pointer_size * 9/8)
def test_insert(self, size):
l = [1.0] * size
l.insert(size - 1, "A")
self.assertEqual(l[:3], [1.0, "C", 1.0])
self.assertEqual(l[size - 3:], ["A", 1.0, "B"])
- @bigmemtest(size=_2G // 5 + 4, memuse=8 * 5)
+ @bigmemtest(size=_2G // 5 + 4, memuse=pointer_size * 5)
def test_pop(self, size):
l = ["a", "b", "c", "d", "e"] * size
size *= 5
self.assertEqual(item, "c")
self.assertEqual(l[-2:], ["b", "d"])
- @bigmemtest(size=_2G + 10, memuse=8)
+ @bigmemtest(size=_2G + 10, memuse=pointer_size)
def test_remove(self, size):
l = [10] * size
self.assertEqual(len(l), size)
self.assertEqual(len(l), size)
self.assertEqual(l[-2:], [10, 10])
- @bigmemtest(size=_2G // 5 + 2, memuse=8 * 5)
+ @bigmemtest(size=_2G // 5 + 2, memuse=pointer_size * 5)
def test_reverse(self, size):
l = [1, 2, 3, 4, 5] * size
l.reverse()
self.assertEqual(l[-5:], [5, 4, 3, 2, 1])
self.assertEqual(l[:5], [5, 4, 3, 2, 1])
- @bigmemtest(size=_2G // 5 + 2, memuse=8 * 5)
+ @bigmemtest(size=_2G // 5 + 2, memuse=pointer_size * 5 * 1.5)
def test_sort(self, size):
l = [1, 2, 3, 4, 5] * size
l.sort()
def test_envar_unimportable(self):
for envar in (
'.', '..', '.foo', 'foo.', '.int', 'int.',
+ '.foo.bar', '..foo.bar', '/./',
'nosuchbuiltin',
'nosuchmodule.nosuchcallable',
):
self.assertRaises(OverflowError,
PyBytes_FromFormat, b'%c', c_int(256))
+ # Issue #33817: empty strings
+ self.assertEqual(PyBytes_FromFormat(b''),
+ b'')
+ self.assertEqual(PyBytes_FromFormat(b'%s', b''),
+ b'')
+
def test_bytes_blocking(self):
class IterationBlocked(list):
__bytes__ = None
class C:
pass
+ error_msg = r'C.__init__\(\) takes exactly one argument \(the instance to initialize\)'
+
with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
C(42)
with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
C.__new__(C, 42)
- with self.assertRaisesRegex(TypeError, r'C\(\).__init__\(\) takes no arguments'):
+ with self.assertRaisesRegex(TypeError, error_msg):
C().__init__(42)
with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'):
object.__new__(C, 42)
- with self.assertRaisesRegex(TypeError, r'C\(\).__init__\(\) takes no arguments'):
+ with self.assertRaisesRegex(TypeError, error_msg):
object.__init__(C(), 42)
# Class with both `__init__` & `__new__` method overridden
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'):
+ error_msg = r'object.__new__\(\) takes exactly one argument \(the type to instantiate\)'
+
+ with self.assertRaisesRegex(TypeError, error_msg):
D(42)
- with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'):
+ with self.assertRaisesRegex(TypeError, error_msg):
D.__new__(D, 42)
- with self.assertRaisesRegex(TypeError, r'object.__new__\(\) takes no argument'):
+ with self.assertRaisesRegex(TypeError, error_msg):
object.__new__(D, 42)
# Class that only overrides __init__
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- with self.assertRaisesRegex(TypeError, r'object.__init__\(\) takes no argument'):
+ error_msg = r'object.__init__\(\) takes exactly one argument \(the instance to initialize\)'
+
+ with self.assertRaisesRegex(TypeError, error_msg):
E().__init__(42)
- with self.assertRaisesRegex(TypeError, r'object.__init__\(\) takes no argument'):
+ with self.assertRaisesRegex(TypeError, error_msg):
object.__init__(E(), 42)
if __name__ == '__main__':
def get(self, name, default):
return self.used_converters.setdefault(name, FakeConverterFactory(name))
-clinic.Clinic.presets_text = ''
c = clinic.Clinic(language='C', filename = "file")
class FakeClinic:
self.assertEqual(stdout.getvalue(), 'Error in file "clown.txt" on line 69:\nThe igloos are melting!\n')
+class ClinicExternalTest(TestCase):
+ maxDiff = None
+
+ def test_external(self):
+ source = support.findfile('clinic.test')
+ with open(source, 'r', encoding='utf-8') as f:
+ original = f.read()
+ with support.temp_dir() as testdir:
+ testfile = os.path.join(testdir, 'clinic.test.c')
+ with open(testfile, 'w', encoding='utf-8') as f:
+ f.write(original)
+ clinic.parse_file(testfile, force=True)
+ with open(testfile, 'r', encoding='utf-8') as f:
+ result = f.read()
+ self.assertEqual(result, original)
+
+
if __name__ == "__main__":
unittest.main()
self.assertEqual(f['b'], 5) # find first in chain
self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
+ def test_ordering(self):
+ # Combined order matches a series of dict updates from last to first.
+ # This test relies on the ordering of the underlying dicts.
+
+ baseline = {'music': 'bach', 'art': 'rembrandt'}
+ adjustments = {'art': 'van gogh', 'opera': 'carmen'}
+
+ cm = ChainMap(adjustments, baseline)
+
+ combined = baseline.copy()
+ combined.update(adjustments)
+
+ self.assertEqual(list(combined.items()), list(cm.items()))
+
def test_constructor(self):
self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
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']
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:
Differences (ndiff with -expected +actual):
a
- <BLANKLINE>
- +
+ +\x20
b
<BLANKLINE>
<BLANKLINE>
"""
+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
######################################################################
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,
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, "<string>", "exec")
+ global_ns = {}
+ local_ls = {}
+ exec(code, global_ns, local_ls)
+
class TestOrder(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):
import signal
import subprocess
import sys
+import sysconfig
from test import support
from test.support import script_helper, is_android
import tempfile
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
else:
header = 'Stack'
regex = r"""
- ^{fatal_error}
+ (?m)^{fatal_error}
{header} \(most recent call first\):
File "<string>", line {lineno} in <module>
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:
@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:
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],
self.assertIs(None, wr())
-class FrameLocalsTest(unittest.TestCase):
- """
- Tests for the .f_locals attribute.
- """
+class FrameAttrsTest(unittest.TestCase):
def make_frames(self):
def outer():
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):
"""
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
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
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()
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'
("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),
("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)
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"})
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 " ", "":
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)
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,
import random
import signal
import sys
+import sysconfig
import threading
import time
import unittest
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:
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
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
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
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
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()
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
""" 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')
)
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)
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")
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 = """\
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...
["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:
@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):
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):
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):
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:
'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()')
# 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
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',
+ '> <string>(1)<module>()',
+ "((Pdb)) *** NameError: name 'doesnotexist' is not defined",
+ 'LEAVING RECURSIVE DEBUGGER',
+ '(Pdb) ',
+ ])
def load_tests(*args):
from test import test_pdb
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
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:
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<tag>\w+)/?>(?:(?P<text>.+?)</(?P=tag)>)?)"
+ s = "<test><foo2/></test>"
+ self.assertEqual(re.findall(p, s),
+ [('test', '<foo2/>'), ('foo2', '')])
+ self.assertEqual([m.groupdict() for m in re.finditer(p, s)],
+ [{'tag': 'test', 'text': '<foo2/>'},
+ {'tag': 'foo2', 'text': None}])
+ s = "<test>Hello</test><foo/>"
+ self.assertEqual([m.groupdict() for m in re.finditer(p, s)],
+ [{'tag': 'test', 'text': 'Hello'},
+ {'tag': 'foo', 'text': None}])
+ s = "<test>Hello</test><foo/><foo/>"
+ 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):
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
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
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
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
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
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):
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)
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()
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)
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)
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:
"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
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).
from test import support
import os
import sys
+import sysconfig
import subprocess
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)
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
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()
+import sys
import unittest
from doctest import DocTestSuite
from test import support
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
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:
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)
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')
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):
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()
''')
with self.assertRaises(urllib.error.ContentTooShortError):
try:
- urllib.request.urlretrieve('http://example.com/')
+ urllib.request.urlretrieve(support.TEST_HTTP_URL)
finally:
self.unfakehttp()
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
"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)
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)
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:
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:
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)
import contextlib
import socket
+import urllib.parse
import urllib.request
import os
import email.message
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()
+import sys
+import unicodedata
import unittest
import urllib.parse
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."""
import unittest
from test import support
+import os
+import stat
import sys
import uu
import io
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()
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):
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)
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
)
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."""
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
import copy
import threading
import time
+import random
from test import support
from test.support import script_helper
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
# xml.etree test for cElementTree
+import io
import struct
from test import support
from test.support import import_fresh_module
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 = '<a></a></b>'
+ 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 = '<a></a></b>'
+ parser = cET.XMLPullParser()
+ parser.feed(XML)
+ del parser
+ support.gc_collect()
+
@unittest.skipUnless(cET, 'requires _elementtree')
class TestAliasWorking(unittest.TestCase):
# 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()
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):
# 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__)
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__)
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]')
"""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.
"""
'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.
"""
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
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):
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)
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
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)))
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):
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
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
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
# 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]
"""
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)
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
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):
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()
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'):
+import functools
import sys
import types
import warnings
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()
+target = {'foo': 'FOO'}
+
+
def is_instance(obj, klass):
"""Version of is_instance that doesn't access __class__"""
return issubclass(type(obj), klass)
+import inspect
import time
import types
import unittest
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):
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
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()
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
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):
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:
<scheme>://<netloc>/<path>?<query>#<fragment>
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)
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)
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)
#
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
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
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):
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)
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:
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,
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
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):
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
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):
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',
},
),
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',
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:
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')
--- /dev/null
+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);
<key>CFBundleExecutable</key>
<string>IDLE</string>
<key>CFBundleGetInfoString</key>
- <string>%version%, © 2001-2018 Python Software Foundation</string>
+ <string>%version%, © 2001-2019 Python Software Foundation</string>
<key>CFBundleIconFile</key>
<string>IDLE.icns</string>
<key>CFBundleIdentifier</key>
<key>CFBundleExecutable</key>
<string>Python Launcher</string>
<key>CFBundleGetInfoString</key>
- <string>%VERSION%, © 2001-2018 Python Software Foundation</string>
+ <string>%VERSION%, © 2001-2019 Python Software Foundation</string>
<key>CFBundleIconFile</key>
<string>PythonLauncher.icns</string>
<key>CFBundleIdentifier</key>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
- <string>%version%, (c) 2001-2018 Python Software Foundation.</string>
+ <string>%version%, (c) 2001-2019 Python Software Foundation.</string>
<key>CFBundleName</key>
<string>Python</string>
<key>CFBundlePackageType</key>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
- <string>%VERSION%, (c) 2001-2018 Python Software Foundation.</string>
+ <string>%VERSION%, (c) 2001-2019 Python Software Foundation.</string>
<key>CFBundleLongVersionString</key>
- <string>%VERSION%, (c) 2001-2018 Python Software Foundation.</string>
+ <string>%VERSION%, (c) 2001-2019 Python Software Foundation.</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Ramchandra Apte
Éric Araujo
Alexandru Ardelean
+Emmanuel Arias
Alicia Arlen
Jeffrey Armstrong
Jason Asbahr
Andrew Langmead
Wolfgang Langner
Detlef Lannert
+Rémi Lapeyre
Soren Larsen
Amos Latteier
Piers Lauder
Gennadiy Zlobin
Doug Zongker
Peter Åstrand
+Zheao Li
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?
=================================
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.
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
-----
.br
[
.B \--check-hash-based-pycs
-\'default\'|\'always\'|\'never\'
+.I default
+|
+.I always
+|
+.I never
]
.br
[
"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,
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) {
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;
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;
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);
}
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;
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;
#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))
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') {
usednew += ntoappend;
assert(usednew <= totalnew);
} /* end while() */
-
+
if (_PyBytes_Resize(&newfmt, usednew) < 0)
goto Done;
{
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);
/* 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;
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;
/* 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;
}
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;
}
Py_DECREF(key);
return NULL;
}
+ self->misses++;
result = PyObject_Call(self->func, args, kwds);
if (!result) {
Py_DECREF(key);
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
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);
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;
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) {
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);
}
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;
}
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
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;
}
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);
}
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));
}
{
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;
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);
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);
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;
}
return NULL;
if (!locked_EVP_MD_CTX_copy(newobj->ctx, self)) {
+ Py_DECREF(newobj);
return _setException(PyExc_ValueError);
}
return (PyObject *)newobj;
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;
}
{
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;
}
}
- 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);
# 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
PY_LITTLE_ENDIAN,
0); /* unsigned */
if (res == -1) {
- PyMem_Free(key);
goto Done;
}
import re
CPP1 = re.compile("^//(.*)")
-CPP2 = re.compile("\ //(.*)")
+CPP2 = re.compile(r"\ //(.*)")
STATICS = ("void ", "int ", "HashReturn ",
"const UINT64 ", "UINT16 ", " int prefix##")
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) {
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;
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);
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++) {
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) {
_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
[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;
STARTUPINFOEXW si;
PyObject *environment = NULL;
wchar_t *wenvironment;
+ wchar_t *command_line_copy = NULL;
AttributeList attribute_list = {0};
ZeroMemory(&si, sizeof(si));
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,
pi.dwThreadId);
cleanup:
+ PyMem_Free(command_line_copy);
Py_XDECREF(environment);
freeattributelist(&attribute_list);
[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;
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;
"\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"
{"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;
}
exit:
return return_value;
}
-/*[clinic end generated code: output=baaf3d379b91be0a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=896d06ce2290aa86 input=a9049054013a1b77]*/
{"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)) {
#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]*/
" 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__},
{"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)
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,
{"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)
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)) {
#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]*/
}
+#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.
*/
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) {
goto done;
}
pymain_clear_cmdline(pymain, cmdline);
+ pymain_clear_pymain(pymain);
memset(cmdline, 0, sizeof(*cmdline));
cmdline_get_global_config(cmdline);
#endif /* !defined(HAVE_ERF) || !defined(HAVE_ERFC) */
static double
-sinpi(double x)
+m_sinpi(double x)
{
double y, r;
int n;
integer. */
if (absx > 200.0) {
if (x < 0.0) {
- return 0.0/sinpi(x);
+ return 0.0/m_sinpi(x);
}
else {
errno = ERANGE;
}
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);
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;
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)
{
}
}
- 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);
}
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
case ERROR_IO_PENDING:
Py_RETURN_FALSE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
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},
/* 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,
#define HAVE_STRUCT_STAT_ST_FSTYPE 1
#endif
+#ifdef _Py_MEMORY_SANITIZER
+# include <sanitizer/msan_interface.h>
+#endif
+
#ifdef HAVE_FORK
static void
run_at_forkers(PyObject *lst, int reverse)
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) {
return FALSE;
}
- if(!CloseHandle(hdl)) {
- PyMem_RawFree(buf);
- return FALSE;
- }
-
buf[result_length] = 0;
*target_path = buf;
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))
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);
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);
}
[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
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 */
#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
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);
[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;
#include "Python.h"
#include "structmember.h"
+#ifdef _Py_MEMORY_SANITIZER
+# include <sanitizer/msan_interface.h>
+#endif
+
/* Socket object documentation */
PyDoc_STRVAR(sock_doc,
"socket(family=AF_INET, type=SOCK_STREAM, proto=0) -> socket object\n\
#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
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);
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)
{
if (status != 0)
return status;
++ptr;
+ RESET_CAPTURE_GROUP();
}
return 0;
}
/* close but no cigar -- try again */
if (++ptr >= end)
return 0;
+ RESET_CAPTURE_GROUP();
}
i = overlap[i];
} while (i != 0);
if (status != 0)
break;
ptr++;
+ RESET_CAPTURE_GROUP();
}
} else {
/* general case */
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);
#endif /* MS_WINDOWS */
#endif /* !__WATCOMC__ || __QNX__ */
+#ifdef _Py_MEMORY_SANITIZER
+# include <sanitizer/msan_interface.h>
+#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 */
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
+#ifdef _Py_MEMORY_SANITIZER
+ __msan_unpoison(&clk_id, sizeof(clk_id));
+#endif
return PyLong_FromLong(clk_id);
}
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]");
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, '%'))
#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;
PyObject_GetItem(PyObject *o, PyObject *key)
{
PyMappingMethods *m;
+ PySequenceMethods *ms;
if (o == NULL || key == NULL) {
return null_error();
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);
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)) {
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;
/* 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);
static PyObject *
stdprinter_repr(PyStdPrinter_Object *self)
{
- return PyUnicode_FromFormat("<stdprinter(fd=%d) object at 0x%x>",
+ return PyUnicode_FromFormat("<stdprinter(fd=%d) object at %p>",
self->fd, self);
}
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,
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 &&
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;
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) {
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;
}
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;
}
{
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) {
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;
PyObject *thousands_sep,
Py_UCS4 *maxchar)
{
+ min_width = Py_MAX(0, min_width);
if (writer) {
assert(digits != NULL);
assert(maxchar == NULL);
}
assert(0 <= d_pos);
assert(0 <= n_digits);
- assert(0 <= min_width);
assert(grouping != NULL);
if (digits != NULL) {
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;
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();
}
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*
return msierror(status);
oresult = PyObject_NEW(struct msiobj, &summary_Type);
- if (!result) {
+ if (!oresult) {
MsiCloseHandle(result);
return NULL;
}
{"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;
{"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",
{"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)
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;
{"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)) {
{"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)
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;
{"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)) {
{"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;
{"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)) {
{"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 *
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;
{"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 *
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;
{"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)) {
{"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)) {
{"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)) {
{"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 *
{
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",
{"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;
exit:
return return_value;
}
-/*[clinic end generated code: output=d1c8e2678015dd7d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=60c92ffc7438f8cf input=a9049054013a1b77]*/
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 -- */
{"_stat", PyInit__stat},
{"_opcode", PyInit__opcode},
+ {"_contextvars", PyInit__contextvars},
+
/* Sentinel */
{0, 0}
};
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");
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 <exename>-script.py in
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_*")
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
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(
str(name),
doraise=True,
optimize=optimize,
- invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH,
+ invalidation_mode=mode,
)
)
except py_compile.PyCompileError:
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"))
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)
#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
#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
[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;
[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;
[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;
[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 );
[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);
[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
[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;
[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;
[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;
[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);
}
[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;
[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;
[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;
[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;
[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;
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
- <ItemGroup Label="ProjectConfigurations">\r
- <ProjectConfiguration Include="Debug|Win32">\r
- <Configuration>Debug</Configuration>\r
- <Platform>Win32</Platform>\r
- </ProjectConfiguration>\r
- <ProjectConfiguration Include="Debug|x64">\r
- <Configuration>Debug</Configuration>\r
- <Platform>x64</Platform>\r
- </ProjectConfiguration>\r
- <ProjectConfiguration Include="PGInstrument|Win32">\r
- <Configuration>PGInstrument</Configuration>\r
- <Platform>Win32</Platform>\r
- </ProjectConfiguration>\r
- <ProjectConfiguration Include="PGInstrument|x64">\r
- <Configuration>PGInstrument</Configuration>\r
- <Platform>x64</Platform>\r
- </ProjectConfiguration>\r
- <ProjectConfiguration Include="PGUpdate|Win32">\r
- <Configuration>PGUpdate</Configuration>\r
- <Platform>Win32</Platform>\r
- </ProjectConfiguration>\r
- <ProjectConfiguration Include="PGUpdate|x64">\r
- <Configuration>PGUpdate</Configuration>\r
- <Platform>x64</Platform>\r
- </ProjectConfiguration>\r
- <ProjectConfiguration Include="Release|Win32">\r
- <Configuration>Release</Configuration>\r
- <Platform>Win32</Platform>\r
- </ProjectConfiguration>\r
- <ProjectConfiguration Include="Release|x64">\r
- <Configuration>Release</Configuration>\r
- <Platform>x64</Platform>\r
- </ProjectConfiguration>\r
- </ItemGroup>\r
- <PropertyGroup Label="Globals">\r
- <ProjectGuid>{B8BF1D81-09DC-42D4-B406-4F868B33A89E}</ProjectGuid>\r
- <RootNamespace>_contextvars</RootNamespace>\r
- <Keyword>Win32Proj</Keyword>\r
- </PropertyGroup>\r
- <Import Project="python.props" />\r
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
- <PropertyGroup Label="Configuration">\r
- <ConfigurationType>DynamicLibrary</ConfigurationType>\r
- <CharacterSet>NotSet</CharacterSet>\r
- </PropertyGroup>\r
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
- <PropertyGroup>\r
- <TargetExt>.pyd</TargetExt>\r
- </PropertyGroup>\r
- <ImportGroup Label="ExtensionSettings">\r
- </ImportGroup>\r
- <ImportGroup Label="PropertySheets">\r
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
- <Import Project="pyproject.props" />\r
- </ImportGroup>\r
- <PropertyGroup Label="UserMacros" />\r
- <PropertyGroup>\r
- <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
- </PropertyGroup>\r
- <ItemGroup>\r
- <ClCompile Include="..\Modules\_contextvarsmodule.c" />\r
- </ItemGroup>\r
- <ItemGroup>\r
- <ResourceCompile Include="..\PC\python_nt.rc" />\r
- </ItemGroup>\r
- <ItemGroup>\r
- <ProjectReference Include="pythoncore.vcxproj">\r
- <Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>\r
- <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
- </ProjectReference>\r
- </ItemGroup>\r
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
- <ImportGroup Label="ExtensionTargets">\r
- </ImportGroup>\r
-</Project>\r
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
- <ItemGroup>\r
- <ResourceCompile Include="..\PC\python_nt.rc" />\r
- </ItemGroup>\r
- <ItemGroup>\r
- <Filter Include="Source Files">\r
- <UniqueIdentifier>{7CBD8910-233D-4E9A-9164-9BA66C1F0E6D}</UniqueIdentifier>\r
- </Filter>\r
- </ItemGroup>\r
- <ItemGroup>\r
- <ClCompile Include="..\Modules\_contextvarsmodule.c">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
- </ItemGroup>\r
-</Project>\r
:begin_search\r
@set PYTHON=\r
\r
-@set _Py_EXTERNALS_DIR=%EXTERNAL_DIR%\r
+@set _Py_EXTERNALS_DIR=%EXTERNALS_DIR%\r
@if "%_Py_EXTERNALS_DIR%"=="" (set _Py_EXTERNALS_DIR=%~dp0\..\externals)\r
\r
@rem If we have Python in externals, use that one\r
set libraries=%libraries% bzip2-1.0.6\r
if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.0j\r
set libraries=%libraries% sqlite-3.21.0.0\r
-if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.8.0\r
-if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.8.0\r
+if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0\r
+if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.0\r
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6\r
set libraries=%libraries% xz-5.2.2\r
set libraries=%libraries% zlib-1.2.11\r
\r
set binaries=\r
if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.0j\r
-if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.8.0\r
+if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0\r
if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06\r
\r
for %%b in (%binaries%) do (\r
<Copy SourceFiles="@(_SSLDLL)" DestinationFolder="$(OutDir)" />\r
</Target>\r
<Target Name="_CleanSSLDLL" BeforeTargets="Clean">\r
- <Delete Files="@(_SSLDLL->'$(OutDir)%(Filename)%(Extension)')" />\r
+ <Delete Files="@(_SSLDLL->'$(OutDir)%(Filename)%(Extension)')" TreatErrorsAsWarnings="true" />\r
</Target>\r
</Project>
\ No newline at end of file
<!-- pyshellext.dll -->\r
<Projects Include="pyshellext.vcxproj" />\r
<!-- Extension modules -->\r
- <ExtensionModules Include="_asyncio;_contextvars;_ctypes;_decimal;_elementtree;_msi;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound" />\r
+ <ExtensionModules Include="_asyncio;_ctypes;_decimal;_elementtree;_msi;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound" />\r
<!-- Extension modules that require external sources -->\r
<ExternalModules Include="_bz2;_lzma;_sqlite3" />\r
<!-- venv launchers -->\r
<SdkBinPath Condition="!Exists($(SdkBinPath))">$(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Kits\Installed Roots@KitsRoot)\bin\x86</SdkBinPath>\r
<SdkBinPath Condition="!Exists($(SdkBinPath))">$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A@InstallationFolder)\Bin\</SdkBinPath>\r
<_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>\r
+ <_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)"</_SignCommand>\r
<_MakeCatCommand Condition="Exists($(SdkBinPath))">"$(SdkBinPath)\makecat.exe"</_MakeCatCommand>\r
</PropertyGroup>\r
- \r
- <Target Name="_SignBuild" AfterTargets="AfterBuild" Condition="'$(SigningCertificate)' != '' and $(SupportSigning)">\r
+\r
+ <Target Name="_SignBuild" AfterTargets="AfterBuild" Condition="'$(_SignCommand)' != '' and $(SupportSigning)">\r
<Error Text="Unable to locate signtool.exe. Set /p:SignToolPath and rebuild" Condition="'$(_SignCommand)' == ''" />\r
<Exec Command='$(_SignCommand) "$(TargetPath)" || $(_SignCommand) "$(TargetPath)" || $(_SignCommand) "$(TargetPath)"' ContinueOnError="false" />\r
</Target>\r
matter which WinSDK version we use.\r
-->\r
<_RegistryVersion>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion)</_RegistryVersion>\r
- <_RegistryVersion Condition="$(_RegistryVersion) == ''">$(Registry:HKEY_LOCAL_MACHINE\WOW6432Node\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion)</_RegistryVersion>\r
+ <_RegistryVersion Condition="$(_RegistryVersion) == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion)</_RegistryVersion>\r
<!-- Sometimes the version in the registry has to .0 suffix, and sometimes it doesn't. Check and add it -->\r
<_RegistryVersion Condition="$(_RegistryVersion) != '' and !$(_RegistryVersion.EndsWith('.0'))">$(_RegistryVersion).0</_RegistryVersion>\r
\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\Modules\_abc.c" />\r
- <ClCompile Include="..\Modules\_asynciomodule.c" />\r
<ClCompile Include="..\Modules\_bisectmodule.c" />\r
<ClCompile Include="..\Modules\_blake2\blake2module.c" />\r
<ClCompile Include="..\Modules\_blake2\blake2b_impl.c" />\r
<ClCompile Include="..\PC\_findvs.cpp">\r
<Filter>PC</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\Modules\_asynciomodule.c">\r
- <Filter>Modules</Filter>\r
- </ClCompile>\r
<ClCompile Include="..\Modules\_contextvarsmodule.c">\r
<Filter>Modules</Filter>\r
</ClCompile>\r
<PropertyGroup>\r
<TclMajorVersion>8</TclMajorVersion>\r
<TclMinorVersion>6</TclMinorVersion>\r
- <TclPatchLevel>8</TclPatchLevel>\r
+ <TclPatchLevel>9</TclPatchLevel>\r
<TclRevision>0</TclRevision>\r
<TkMajorVersion>$(TclMajorVersion)</TkMajorVersion>\r
<TkMinorVersion>$(TclMinorVersion)</TkMinorVersion>\r
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. */
}
return 1;
}
-#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */
+#endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */
static struct {
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\
}
if (_PyState_AddModule(mod, def) < 0) {
PyMapping_DelItem(modules, name);
- Py_DECREF(mod);
return NULL;
}
if (Py_VerboseFlag)
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;
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(
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;
}
-This is Python version 3.7.2
+This is Python version 3.7.3
============================
.. image:: https://travis-ci.org/python/cpython.svg?branch=master
: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.
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``;
---------------------------------
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.
@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'
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
<EmbeddedResource Include="*.wxl" />
</ItemGroup>
<ItemGroup>
- <InstallFiles Include="$(PySourcePath)include\**\*.h">
+ <InstallFiles Include="$(PySourcePath)include\**\*.h"
+ Exclude="$(PySourcePath)include\pyconfig.h">
<SourceBase>$(PySourcePath)</SourceBase>
<Source>!(bindpath.src)</Source>
<TargetBase>$(PySourcePath)</TargetBase>
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
- <?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_msi;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue;_contextvars ?>
+ <?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_msi;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue ?>
<Fragment>
<DirectoryRef Id="Lib_venv_scripts_nt" />
$description = "Python";
}
}
+ if (-not $certsha1) {
+ $certsha1 = $env:SigningCertificateSha1;
+ }
if (-not $certname) {
$certname = $env:SigningCertificate;
}
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 {
<title>Python</title>
<version>0.0.0.0</version>
<authors>Python Software Foundation</authors>
- <licenseUrl>https://docs.python.org/3/license.html</licenseUrl>
+ <license type="file">tools\LICENSE.txt</license>
<projectUrl>https://www.python.org/</projectUrl>
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Installs 64-bit Python for use in build scenarios.</description>
<iconUrl>https://www.python.org/static/favicon.ico</iconUrl>
<tags>python</tags>
<metadata>
<id>pythondaily</id>
<title>Python (Daily build)</title>
- <version>0.0.0.0</version>
<authors>Python Software Foundation</authors>
- <licenseUrl>https://docs.python.org/3/license.html</licenseUrl>
+ <version>0.0.0.0</version>
+ <license type="file">tools\LICENSE.txt</license>
<projectUrl>https://www.python.org/</projectUrl>
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Installs an unsigned, untested build of Python for test purposes only.</description>
<iconUrl>https://www.python.org/static/favicon.ico</iconUrl>
<tags>python</tags>
<title>Python (Daily build)</title>
<version>0.0.0.0</version>
<authors>Python Software Foundation</authors>
- <licenseUrl>https://docs.python.org/3/license.html</licenseUrl>
<projectUrl>https://www.python.org/</projectUrl>
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains symbols for the daily build of Python.</description>
<iconUrl>https://www.python.org/static/favicon.ico</iconUrl>
<tags>python</tags>
<title>Python (32-bit)</title>
<authors>Python Software Foundation</authors>
<version>0.0.0.0</version>
- <licenseUrl>https://docs.python.org/3/license.html</licenseUrl>
+ <license type="file">tools\LICENSE.txt</license>
<projectUrl>https://www.python.org/</projectUrl>
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Installs 32-bit Python for use in build scenarios.</description>
<iconUrl>https://www.python.org/static/favicon.ico</iconUrl>
<tags>python</tags>
-# 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,
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 <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
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
docdir
oldincludedir
includedir
+runstatedir
localstatedir
sharedstatedir
sysconfdir
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
| -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=* \
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.
--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]
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 <crypt.h>
+
+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"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
+#include <stdlib.h>
+#include <unistd.h>
int main()
{
int val1 = nice(1);
])
)
+# 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 <crypt.h>
+]], [[
+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"
AC_MSG_CHECKING(for broken nice())
AC_CACHE_VAL(ac_cv_broken_nice, [
AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <stdlib.h>
+#include <unistd.h>
int main()
{
int val1 = nice(1);
/* Define to 1 if you have the <crypt.h> 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