diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index d460eee..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index af20f60..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/testpks.iml b/.idea/testpks.iml deleted file mode 100644 index 5c0fbc8..0000000 --- a/.idea/testpks.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.read_stats.py.swp b/.read_stats.py.swp deleted file mode 100644 index d016989..0000000 Binary files a/.read_stats.py.swp and /dev/null differ diff --git a/.venv/bin/Activate.ps1 b/.venv/bin/Activate.ps1 deleted file mode 100644 index b49d77b..0000000 --- a/.venv/bin/Activate.ps1 +++ /dev/null @@ -1,247 +0,0 @@ -<# -.Synopsis -Activate a Python virtual environment for the current PowerShell session. - -.Description -Pushes the python executable for a virtual environment to the front of the -$Env:PATH environment variable and sets the prompt to signify that you are -in a Python virtual environment. Makes use of the command line switches as -well as the `pyvenv.cfg` file values present in the virtual environment. - -.Parameter VenvDir -Path to the directory that contains the virtual environment to activate. The -default value for this is the parent of the directory that the Activate.ps1 -script is located within. - -.Parameter Prompt -The prompt prefix to display when this virtual environment is activated. By -default, this prompt is the name of the virtual environment folder (VenvDir) -surrounded by parentheses and followed by a single space (ie. '(.venv) '). - -.Example -Activate.ps1 -Activates the Python virtual environment that contains the Activate.ps1 script. - -.Example -Activate.ps1 -Verbose -Activates the Python virtual environment that contains the Activate.ps1 script, -and shows extra information about the activation as it executes. - -.Example -Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv -Activates the Python virtual environment located in the specified location. - -.Example -Activate.ps1 -Prompt "MyPython" -Activates the Python virtual environment that contains the Activate.ps1 script, -and prefixes the current prompt with the specified string (surrounded in -parentheses) while the virtual environment is active. - -.Notes -On Windows, it may be required to enable this Activate.ps1 script by setting the -execution policy for the user. You can do this by issuing the following PowerShell -command: - -PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser - -For more information on Execution Policies: -https://go.microsoft.com/fwlink/?LinkID=135170 - -#> -Param( - [Parameter(Mandatory = $false)] - [String] - $VenvDir, - [Parameter(Mandatory = $false)] - [String] - $Prompt -) - -<# Function declarations --------------------------------------------------- #> - -<# -.Synopsis -Remove all shell session elements added by the Activate script, including the -addition of the virtual environment's Python executable from the beginning of -the PATH variable. - -.Parameter NonDestructive -If present, do not remove this function from the global namespace for the -session. - -#> -function global:deactivate ([switch]$NonDestructive) { - # Revert to original values - - # The prior prompt: - if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { - Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt - Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT - } - - # The prior PYTHONHOME: - if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { - Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME - Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME - } - - # The prior PATH: - if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { - Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH - Remove-Item -Path Env:_OLD_VIRTUAL_PATH - } - - # Just remove the VIRTUAL_ENV altogether: - if (Test-Path -Path Env:VIRTUAL_ENV) { - Remove-Item -Path env:VIRTUAL_ENV - } - - # Just remove VIRTUAL_ENV_PROMPT altogether. - if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { - Remove-Item -Path env:VIRTUAL_ENV_PROMPT - } - - # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: - if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { - Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force - } - - # Leave deactivate function in the global namespace if requested: - if (-not $NonDestructive) { - Remove-Item -Path function:deactivate - } -} - -<# -.Description -Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the -given folder, and returns them in a map. - -For each line in the pyvenv.cfg file, if that line can be parsed into exactly -two strings separated by `=` (with any amount of whitespace surrounding the =) -then it is considered a `key = value` line. The left hand string is the key, -the right hand is the value. - -If the value starts with a `'` or a `"` then the first and last character is -stripped from the value before being captured. - -.Parameter ConfigDir -Path to the directory that contains the `pyvenv.cfg` file. -#> -function Get-PyVenvConfig( - [String] - $ConfigDir -) { - Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" - - # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). - $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue - - # An empty map will be returned if no config file is found. - $pyvenvConfig = @{ } - - if ($pyvenvConfigPath) { - - Write-Verbose "File exists, parse `key = value` lines" - $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath - - $pyvenvConfigContent | ForEach-Object { - $keyval = $PSItem -split "\s*=\s*", 2 - if ($keyval[0] -and $keyval[1]) { - $val = $keyval[1] - - # Remove extraneous quotations around a string value. - if ("'""".Contains($val.Substring(0, 1))) { - $val = $val.Substring(1, $val.Length - 2) - } - - $pyvenvConfig[$keyval[0]] = $val - Write-Verbose "Adding Key: '$($keyval[0])'='$val'" - } - } - } - return $pyvenvConfig -} - - -<# Begin Activate script --------------------------------------------------- #> - -# Determine the containing directory of this script -$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition -$VenvExecDir = Get-Item -Path $VenvExecPath - -Write-Verbose "Activation script is located in path: '$VenvExecPath'" -Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" -Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" - -# Set values required in priority: CmdLine, ConfigFile, Default -# First, get the location of the virtual environment, it might not be -# VenvExecDir if specified on the command line. -if ($VenvDir) { - Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" -} -else { - Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." - $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") - Write-Verbose "VenvDir=$VenvDir" -} - -# Next, read the `pyvenv.cfg` file to determine any required value such -# as `prompt`. -$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir - -# Next, set the prompt from the command line, or the config file, or -# just use the name of the virtual environment folder. -if ($Prompt) { - Write-Verbose "Prompt specified as argument, using '$Prompt'" -} -else { - Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" - if ($pyvenvCfg -and $pyvenvCfg['prompt']) { - Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" - $Prompt = $pyvenvCfg['prompt']; - } - else { - Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" - Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" - $Prompt = Split-Path -Path $venvDir -Leaf - } -} - -Write-Verbose "Prompt = '$Prompt'" -Write-Verbose "VenvDir='$VenvDir'" - -# Deactivate any currently active virtual environment, but leave the -# deactivate function in place. -deactivate -nondestructive - -# Now set the environment variable VIRTUAL_ENV, used by many tools to determine -# that there is an activated venv. -$env:VIRTUAL_ENV = $VenvDir - -if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { - - Write-Verbose "Setting prompt to '$Prompt'" - - # Set the prompt to include the env name - # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT { "" } - Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT - New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt - - function global:prompt { - Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " - _OLD_VIRTUAL_PROMPT - } - $env:VIRTUAL_ENV_PROMPT = $Prompt -} - -# Clear PYTHONHOME -if (Test-Path -Path Env:PYTHONHOME) { - Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME - Remove-Item -Path Env:PYTHONHOME -} - -# Add the venv to the PATH -Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH -$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/.venv/bin/activate b/.venv/bin/activate deleted file mode 100644 index 285e663..0000000 --- a/.venv/bin/activate +++ /dev/null @@ -1,70 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# You cannot run it directly - -deactivate () { - # reset old environment variables - if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then - PATH="${_OLD_VIRTUAL_PATH:-}" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then - PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # Call hash to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - hash -r 2> /dev/null - - if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then - PS1="${_OLD_VIRTUAL_PS1:-}" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - unset VIRTUAL_ENV_PROMPT - if [ ! "${1:-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -# on Windows, a path can contain colons and backslashes and has to be converted: -if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then - # transform D:\path\to\venv to /d/path/to/venv on MSYS - # and to /cygdrive/d/path/to/venv on Cygwin - export VIRTUAL_ENV=$(cygpath /home/jvved/dev/testpks/.venv) -else - # use the path as-is - export VIRTUAL_ENV=/home/jvved/dev/testpks/.venv -fi - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/"bin":$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "${PYTHONHOME:-}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1:-}" - PS1='(.venv) '"${PS1:-}" - export PS1 - VIRTUAL_ENV_PROMPT='(.venv) ' - export VIRTUAL_ENV_PROMPT -fi - -# Call hash to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -hash -r 2> /dev/null diff --git a/.venv/bin/activate.csh b/.venv/bin/activate.csh deleted file mode 100644 index aed6eca..0000000 --- a/.venv/bin/activate.csh +++ /dev/null @@ -1,27 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. - -# Created by Davide Di Blasi . -# Ported to Python 3.3 venv by Andrew Svetlov - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV /home/jvved/dev/testpks/.venv - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/"bin":$PATH" - - -set _OLD_VIRTUAL_PROMPT="$prompt" - -if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - set prompt = '(.venv) '"$prompt" - setenv VIRTUAL_ENV_PROMPT '(.venv) ' -endif - -alias pydoc python -m pydoc - -rehash diff --git a/.venv/bin/activate.fish b/.venv/bin/activate.fish deleted file mode 100644 index 5666715..0000000 --- a/.venv/bin/activate.fish +++ /dev/null @@ -1,69 +0,0 @@ -# This file must be used with "source /bin/activate.fish" *from fish* -# (https://fishshell.com/). You cannot run it directly. - -function deactivate -d "Exit virtual environment and return to normal shell environment" - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - set -e _OLD_FISH_PROMPT_OVERRIDE - # prevents error when using nested fish instances (Issue #93858) - if functions -q _old_fish_prompt - functions -e fish_prompt - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - end - end - - set -e VIRTUAL_ENV - set -e VIRTUAL_ENV_PROMPT - if test "$argv[1]" != "nondestructive" - # Self-destruct! - functions -e deactivate - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV /home/jvved/dev/testpks/.venv - -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx PATH "$VIRTUAL_ENV/"bin $PATH - -# Unset PYTHONHOME if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # fish uses a function instead of an env var to generate the prompt. - - # Save the current fish_prompt function as the function _old_fish_prompt. - functions -c fish_prompt _old_fish_prompt - - # With the original prompt function renamed, we can override with our own. - function fish_prompt - # Save the return status of the last command. - set -l old_status $status - - # Output the venv prompt; color taken from the blue of the Python logo. - printf "%s%s%s" (set_color 4B8BBE) '(.venv) ' (set_color normal) - - # Restore the return status of the previous command. - echo "exit $old_status" | . - # Output the original/"old" prompt. - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" - set -gx VIRTUAL_ENV_PROMPT '(.venv) ' -end diff --git a/.venv/bin/ipython b/.venv/bin/ipython deleted file mode 100755 index 0f53eb3..0000000 --- a/.venv/bin/ipython +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/jvved/dev/testpks/.venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from IPython import start_ipython -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(start_ipython()) diff --git a/.venv/bin/ipython3 b/.venv/bin/ipython3 deleted file mode 100755 index 0f53eb3..0000000 --- a/.venv/bin/ipython3 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/jvved/dev/testpks/.venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from IPython import start_ipython -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(start_ipython()) diff --git a/.venv/bin/markdown-it b/.venv/bin/markdown-it deleted file mode 100755 index 0fa5488..0000000 --- a/.venv/bin/markdown-it +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/jvved/dev/testpks/.venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from markdown_it.cli.parse import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/.venv/bin/pip b/.venv/bin/pip deleted file mode 100755 index 063c294..0000000 --- a/.venv/bin/pip +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/jvved/dev/testpks/.venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/.venv/bin/pip3 b/.venv/bin/pip3 deleted file mode 100755 index 063c294..0000000 --- a/.venv/bin/pip3 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/jvved/dev/testpks/.venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/.venv/bin/pip3.12 b/.venv/bin/pip3.12 deleted file mode 100755 index 063c294..0000000 --- a/.venv/bin/pip3.12 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/jvved/dev/testpks/.venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/.venv/bin/pygmentize b/.venv/bin/pygmentize deleted file mode 100755 index 860e239..0000000 --- a/.venv/bin/pygmentize +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/jvved/dev/testpks/.venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pygments.cmdline import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/.venv/bin/python b/.venv/bin/python deleted file mode 120000 index b8a0adb..0000000 --- a/.venv/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3 \ No newline at end of file diff --git a/.venv/bin/python3 b/.venv/bin/python3 deleted file mode 120000 index ae65fda..0000000 --- a/.venv/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -/usr/bin/python3 \ No newline at end of file diff --git a/.venv/bin/python3.12 b/.venv/bin/python3.12 deleted file mode 120000 index b8a0adb..0000000 --- a/.venv/bin/python3.12 +++ /dev/null @@ -1 +0,0 @@ -python3 \ No newline at end of file diff --git a/.venv/bin/uwsgi b/.venv/bin/uwsgi deleted file mode 100755 index 64f1994..0000000 Binary files a/.venv/bin/uwsgi and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/__init__.py b/.venv/lib/python3.12/site-packages/IPython/__init__.py deleted file mode 100644 index b723548..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/__init__.py +++ /dev/null @@ -1,163 +0,0 @@ -# PYTHON_ARGCOMPLETE_OK -""" -IPython: tools for interactive and parallel computing in Python. - -https://ipython.org -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2011, IPython Development Team. -# Copyright (c) 2001-2007, Fernando Perez -# Copyright (c) 2001, Janko Hauser -# Copyright (c) 2001, Nathaniel Gray -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import sys - -#----------------------------------------------------------------------------- -# Setup everything -#----------------------------------------------------------------------------- - -# Don't forget to also update setup.py when this changes! -if sys.version_info < (3, 10): - raise ImportError( - """ -IPython 8.19+ supports Python 3.10 and above, following SPEC0. -IPython 8.13+ supports Python 3.9 and above, following NEP 29. -IPython 8.0-8.12 supports Python 3.8 and above, following NEP 29. -When using Python 2.7, please install IPython 5.x LTS Long Term Support version. -Python 3.3 and 3.4 were supported up to IPython 6.x. -Python 3.5 was supported with IPython 7.0 to 7.9. -Python 3.6 was supported with IPython up to 7.16. -Python 3.7 was still supported with the 7.x branch. - -See IPython `README.rst` file for more information: - - https://github.com/ipython/ipython/blob/main/README.rst - -""" - ) - -#----------------------------------------------------------------------------- -# Setup the top level names -#----------------------------------------------------------------------------- - -from .core.getipython import get_ipython -from .core import release -from .core.application import Application -from .terminal.embed import embed - -from .core.interactiveshell import InteractiveShell -from .utils.sysinfo import sys_info -from .utils.frame import extract_module_locals - -__all__ = ["start_ipython", "embed", "start_kernel", "embed_kernel"] - -# Release data -__author__ = '%s <%s>' % (release.author, release.author_email) -__license__ = release.license -__version__ = release.version -version_info = release.version_info -# list of CVEs that should have been patched in this release. -# this is informational and should not be relied upon. -__patched_cves__ = {"CVE-2022-21699", "CVE-2023-24816"} - - -def embed_kernel(module=None, local_ns=None, **kwargs): - """Embed and start an IPython kernel in a given scope. - - If you don't want the kernel to initialize the namespace - from the scope of the surrounding function, - and/or you want to load full IPython configuration, - you probably want `IPython.start_kernel()` instead. - - Parameters - ---------- - module : types.ModuleType, optional - The module to load into IPython globals (default: caller) - local_ns : dict, optional - The namespace to load into IPython user namespace (default: caller) - **kwargs : various, optional - Further keyword args are relayed to the IPKernelApp constructor, - such as `config`, a traitlets :class:`Config` object (see :ref:`configure_start_ipython`), - allowing configuration of the kernel (see :ref:`kernel_options`). Will only have an effect - on the first embed_kernel call for a given process. - """ - - (caller_module, caller_locals) = extract_module_locals(1) - if module is None: - module = caller_module - if local_ns is None: - local_ns = caller_locals - - # Only import .zmq when we really need it - from ipykernel.embed import embed_kernel as real_embed_kernel - real_embed_kernel(module=module, local_ns=local_ns, **kwargs) - -def start_ipython(argv=None, **kwargs): - """Launch a normal IPython instance (as opposed to embedded) - - `IPython.embed()` puts a shell in a particular calling scope, - such as a function or method for debugging purposes, - which is often not desirable. - - `start_ipython()` does full, regular IPython initialization, - including loading startup files, configuration, etc. - much of which is skipped by `embed()`. - - This is a public API method, and will survive implementation changes. - - Parameters - ---------- - argv : list or None, optional - If unspecified or None, IPython will parse command-line options from sys.argv. - To prevent any command-line parsing, pass an empty list: `argv=[]`. - user_ns : dict, optional - specify this dictionary to initialize the IPython user namespace with particular values. - **kwargs : various, optional - Any other kwargs will be passed to the Application constructor, - such as `config`, a traitlets :class:`Config` object (see :ref:`configure_start_ipython`), - allowing configuration of the instance (see :ref:`terminal_options`). - """ - from IPython.terminal.ipapp import launch_new_instance - return launch_new_instance(argv=argv, **kwargs) - -def start_kernel(argv=None, **kwargs): - """Launch a normal IPython kernel instance (as opposed to embedded) - - `IPython.embed_kernel()` puts a shell in a particular calling scope, - such as a function or method for debugging purposes, - which is often not desirable. - - `start_kernel()` does full, regular IPython initialization, - including loading startup files, configuration, etc. - much of which is skipped by `embed_kernel()`. - - Parameters - ---------- - argv : list or None, optional - If unspecified or None, IPython will parse command-line options from sys.argv. - To prevent any command-line parsing, pass an empty list: `argv=[]`. - user_ns : dict, optional - specify this dictionary to initialize the IPython user namespace with particular values. - **kwargs : various, optional - Any other kwargs will be passed to the Application constructor, - such as `config`, a traitlets :class:`Config` object (see :ref:`configure_start_ipython`), - allowing configuration of the kernel (see :ref:`kernel_options`). - """ - import warnings - - warnings.warn( - "start_kernel is deprecated since IPython 8.0, use from `ipykernel.kernelapp.launch_new_instance`", - DeprecationWarning, - stacklevel=2, - ) - from ipykernel.kernelapp import launch_new_instance - return launch_new_instance(argv=argv, **kwargs) diff --git a/.venv/lib/python3.12/site-packages/IPython/__main__.py b/.venv/lib/python3.12/site-packages/IPython/__main__.py deleted file mode 100644 index 3b46056..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/__main__.py +++ /dev/null @@ -1,15 +0,0 @@ -# PYTHON_ARGCOMPLETE_OK -# encoding: utf-8 -"""Terminal-based IPython entry point. -""" -# ----------------------------------------------------------------------------- -# Copyright (c) 2012, IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -# ----------------------------------------------------------------------------- - -from IPython import start_ipython - -start_ipython() diff --git a/.venv/lib/python3.12/site-packages/IPython/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 4d0925b..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/__pycache__/__main__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/__pycache__/__main__.cpython-312.pyc deleted file mode 100644 index 6e662e7..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/__pycache__/__main__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/__pycache__/conftest.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/__pycache__/conftest.cpython-312.pyc deleted file mode 100644 index 3863884..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/__pycache__/conftest.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/__pycache__/consoleapp.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/__pycache__/consoleapp.cpython-312.pyc deleted file mode 100644 index 01c1063..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/__pycache__/consoleapp.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/__pycache__/display.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/__pycache__/display.cpython-312.pyc deleted file mode 100644 index bda6164..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/__pycache__/display.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/__pycache__/paths.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/__pycache__/paths.cpython-312.pyc deleted file mode 100644 index db4be62..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/__pycache__/paths.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/conftest.py b/.venv/lib/python3.12/site-packages/IPython/conftest.py deleted file mode 100644 index abf6131..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/conftest.py +++ /dev/null @@ -1,87 +0,0 @@ -import builtins -import inspect -import os -import pathlib -import shutil -import sys -import types - -import pytest - -# Must register before it gets imported -pytest.register_assert_rewrite("IPython.testing.tools") - -from .testing import tools - - -def pytest_collection_modifyitems(items): - """This function is automatically run by pytest passing all collected test - functions. - - We use it to add asyncio marker to all async tests and assert we don't use - test functions that are async generators which wouldn't make sense. - """ - for item in items: - if inspect.iscoroutinefunction(item.obj): - item.add_marker("asyncio") - assert not inspect.isasyncgenfunction(item.obj) - - -def get_ipython(): - from .terminal.interactiveshell import TerminalInteractiveShell - if TerminalInteractiveShell._instance: - return TerminalInteractiveShell.instance() - - config = tools.default_config() - config.TerminalInteractiveShell.simple_prompt = True - - # Create and initialize our test-friendly IPython instance. - shell = TerminalInteractiveShell.instance(config=config) - return shell - - -@pytest.fixture(scope='session', autouse=True) -def work_path(): - path = pathlib.Path("./tmp-ipython-pytest-profiledir") - os.environ["IPYTHONDIR"] = str(path.absolute()) - if path.exists(): - raise ValueError('IPython dir temporary path already exists ! Did previous test run exit successfully ?') - path.mkdir() - yield - shutil.rmtree(str(path.resolve())) - - -def nopage(strng, start=0, screen_lines=0, pager_cmd=None): - if isinstance(strng, dict): - strng = strng.get("text/plain", "") - print(strng) - - -def xsys(self, cmd): - """Replace the default system call with a capturing one for doctest. - """ - # We use getoutput, but we need to strip it because pexpect captures - # the trailing newline differently from commands.getoutput - print(self.getoutput(cmd, split=False, depth=1).rstrip(), end="", file=sys.stdout) - sys.stdout.flush() - - -# for things to work correctly we would need this as a session fixture; -# unfortunately this will fail on some test that get executed as _collection_ -# time (before the fixture run), in particular parametrized test that contain -# yields. so for now execute at import time. -#@pytest.fixture(autouse=True, scope='session') -def inject(): - - builtins.get_ipython = get_ipython - builtins._ip = get_ipython() - builtins.ip = get_ipython() - builtins.ip.system = types.MethodType(xsys, ip) - builtins.ip.builtin_trap.activate() - from .core import page - - page.pager_page = nopage - # yield - - -inject() diff --git a/.venv/lib/python3.12/site-packages/IPython/consoleapp.py b/.venv/lib/python3.12/site-packages/IPython/consoleapp.py deleted file mode 100644 index c2bbe18..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/consoleapp.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -Shim to maintain backwards compatibility with old IPython.consoleapp imports. -""" -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from warnings import warn - -warn("The `IPython.consoleapp` package has been deprecated since IPython 4.0." - "You should import from jupyter_client.consoleapp instead.", stacklevel=2) - -from jupyter_client.consoleapp import * diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__init__.py b/.venv/lib/python3.12/site-packages/IPython/core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index c98e21c..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/alias.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/alias.cpython-312.pyc deleted file mode 100644 index 307e267..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/alias.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/application.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/application.cpython-312.pyc deleted file mode 100644 index 1306fcc..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/application.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/async_helpers.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/async_helpers.cpython-312.pyc deleted file mode 100644 index 996e299..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/async_helpers.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/autocall.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/autocall.cpython-312.pyc deleted file mode 100644 index 4e8bea4..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/autocall.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/builtin_trap.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/builtin_trap.cpython-312.pyc deleted file mode 100644 index 5818aa0..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/builtin_trap.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/compilerop.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/compilerop.cpython-312.pyc deleted file mode 100644 index d2707d3..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/compilerop.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/completer.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/completer.cpython-312.pyc deleted file mode 100644 index 57fec08..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/completer.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/completerlib.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/completerlib.cpython-312.pyc deleted file mode 100644 index 548ed2d..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/completerlib.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/crashhandler.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/crashhandler.cpython-312.pyc deleted file mode 100644 index 9f3e8d8..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/crashhandler.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/debugger.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/debugger.cpython-312.pyc deleted file mode 100644 index 070f704..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/debugger.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display.cpython-312.pyc deleted file mode 100644 index bbebd04..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display_functions.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display_functions.cpython-312.pyc deleted file mode 100644 index c19e4e5..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display_functions.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display_trap.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display_trap.cpython-312.pyc deleted file mode 100644 index 3a63582..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/display_trap.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/displayhook.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/displayhook.cpython-312.pyc deleted file mode 100644 index b35f5ef..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/displayhook.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/displaypub.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/displaypub.cpython-312.pyc deleted file mode 100644 index d494d70..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/displaypub.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/error.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/error.cpython-312.pyc deleted file mode 100644 index 30b6103..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/error.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/events.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/events.cpython-312.pyc deleted file mode 100644 index 8a8e239..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/events.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/excolors.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/excolors.cpython-312.pyc deleted file mode 100644 index c207aaf..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/excolors.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/extensions.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/extensions.cpython-312.pyc deleted file mode 100644 index 62a4bf9..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/extensions.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/formatters.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/formatters.cpython-312.pyc deleted file mode 100644 index c1c56db..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/formatters.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/getipython.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/getipython.cpython-312.pyc deleted file mode 100644 index 2dae445..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/getipython.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/guarded_eval.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/guarded_eval.cpython-312.pyc deleted file mode 100644 index 65aee41..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/guarded_eval.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/history.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/history.cpython-312.pyc deleted file mode 100644 index 8cf0ca7..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/history.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/historyapp.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/historyapp.cpython-312.pyc deleted file mode 100644 index cd59e16..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/historyapp.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/hooks.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/hooks.cpython-312.pyc deleted file mode 100644 index f7b533d..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/hooks.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputsplitter.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputsplitter.cpython-312.pyc deleted file mode 100644 index 54cbddd..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputsplitter.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputtransformer.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputtransformer.cpython-312.pyc deleted file mode 100644 index fe30503..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputtransformer.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputtransformer2.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputtransformer2.cpython-312.pyc deleted file mode 100644 index b556a35..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/inputtransformer2.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/interactiveshell.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/interactiveshell.cpython-312.pyc deleted file mode 100644 index 67ca9b0..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/interactiveshell.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/latex_symbols.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/latex_symbols.cpython-312.pyc deleted file mode 100644 index c02fd4f..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/latex_symbols.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/logger.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/logger.cpython-312.pyc deleted file mode 100644 index 695e840..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/logger.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/macro.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/macro.cpython-312.pyc deleted file mode 100644 index 2d8a288..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/macro.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/magic.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/magic.cpython-312.pyc deleted file mode 100644 index 8306380..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/magic.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/magic_arguments.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/magic_arguments.cpython-312.pyc deleted file mode 100644 index d0d690c..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/magic_arguments.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/oinspect.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/oinspect.cpython-312.pyc deleted file mode 100644 index 352d26c..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/oinspect.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/page.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/page.cpython-312.pyc deleted file mode 100644 index 58a3cda..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/page.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/payload.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/payload.cpython-312.pyc deleted file mode 100644 index 049723e..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/payload.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/payloadpage.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/payloadpage.cpython-312.pyc deleted file mode 100644 index 7e55801..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/payloadpage.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/prefilter.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/prefilter.cpython-312.pyc deleted file mode 100644 index e4403a1..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/prefilter.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/profileapp.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/profileapp.cpython-312.pyc deleted file mode 100644 index c9c1331..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/profileapp.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/profiledir.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/profiledir.cpython-312.pyc deleted file mode 100644 index 19eaa78..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/profiledir.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/prompts.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/prompts.cpython-312.pyc deleted file mode 100644 index d7e7eef..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/prompts.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/pylabtools.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/pylabtools.cpython-312.pyc deleted file mode 100644 index 71a46fd..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/pylabtools.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/release.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/release.cpython-312.pyc deleted file mode 100644 index c33494f..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/release.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/shellapp.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/shellapp.cpython-312.pyc deleted file mode 100644 index dca3055..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/shellapp.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/splitinput.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/splitinput.cpython-312.pyc deleted file mode 100644 index aac67db..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/splitinput.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/ultratb.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/ultratb.cpython-312.pyc deleted file mode 100644 index 829fa56..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/ultratb.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/usage.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/usage.cpython-312.pyc deleted file mode 100644 index 72829a9..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/core/__pycache__/usage.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/core/alias.py b/.venv/lib/python3.12/site-packages/IPython/core/alias.py deleted file mode 100644 index 845e6b7..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/alias.py +++ /dev/null @@ -1,267 +0,0 @@ -# encoding: utf-8 -""" -System command aliases. - -Authors: - -* Fernando Perez -* Brian Granger -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import os -import re -import sys - -from traitlets.config.configurable import Configurable -from .error import UsageError - -from traitlets import List, Instance -from logging import error - -import typing as t - - -#----------------------------------------------------------------------------- -# Utilities -#----------------------------------------------------------------------------- - -# This is used as the pattern for calls to split_user_input. -shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)') - -def default_aliases() -> t.List[t.Tuple[str, str]]: - """Return list of shell aliases to auto-define. - """ - # Note: the aliases defined here should be safe to use on a kernel - # regardless of what frontend it is attached to. Frontends that use a - # kernel in-process can define additional aliases that will only work in - # their case. For example, things like 'less' or 'clear' that manipulate - # the terminal should NOT be declared here, as they will only work if the - # kernel is running inside a true terminal, and not over the network. - - if os.name == 'posix': - default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'), - ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'), - ('cat', 'cat'), - ] - # Useful set of ls aliases. The GNU and BSD options are a little - # different, so we make aliases that provide as similar as possible - # behavior in ipython, by passing the right flags for each platform - if sys.platform.startswith('linux'): - ls_aliases = [('ls', 'ls -F --color'), - # long ls - ('ll', 'ls -F -o --color'), - # ls normal files only - ('lf', 'ls -F -o --color %l | grep ^-'), - # ls symbolic links - ('lk', 'ls -F -o --color %l | grep ^l'), - # directories or links to directories, - ('ldir', 'ls -F -o --color %l | grep /$'), - # things which are executable - ('lx', 'ls -F -o --color %l | grep ^-..x'), - ] - elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'): - # OpenBSD, NetBSD. The ls implementation on these platforms do not support - # the -G switch and lack the ability to use colorized output. - ls_aliases = [('ls', 'ls -F'), - # long ls - ('ll', 'ls -F -l'), - # ls normal files only - ('lf', 'ls -F -l %l | grep ^-'), - # ls symbolic links - ('lk', 'ls -F -l %l | grep ^l'), - # directories or links to directories, - ('ldir', 'ls -F -l %l | grep /$'), - # things which are executable - ('lx', 'ls -F -l %l | grep ^-..x'), - ] - else: - # BSD, OSX, etc. - ls_aliases = [('ls', 'ls -F -G'), - # long ls - ('ll', 'ls -F -l -G'), - # ls normal files only - ('lf', 'ls -F -l -G %l | grep ^-'), - # ls symbolic links - ('lk', 'ls -F -l -G %l | grep ^l'), - # directories or links to directories, - ('ldir', 'ls -F -G -l %l | grep /$'), - # things which are executable - ('lx', 'ls -F -l -G %l | grep ^-..x'), - ] - default_aliases = default_aliases + ls_aliases - elif os.name in ['nt', 'dos']: - default_aliases = [('ls', 'dir /on'), - ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'), - ('mkdir', 'mkdir'), ('rmdir', 'rmdir'), - ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'), - ] - else: - default_aliases = [] - - return default_aliases - - -class AliasError(Exception): - pass - - -class InvalidAliasError(AliasError): - pass - -class Alias(object): - """Callable object storing the details of one alias. - - Instances are registered as magic functions to allow use of aliases. - """ - - # Prepare blacklist - blacklist = {'cd','popd','pushd','dhist','alias','unalias'} - - def __init__(self, shell, name, cmd): - self.shell = shell - self.name = name - self.cmd = cmd - self.__doc__ = "Alias for `!{}`".format(cmd) - self.nargs = self.validate() - - def validate(self): - """Validate the alias, and return the number of arguments.""" - if self.name in self.blacklist: - raise InvalidAliasError("The name %s can't be aliased " - "because it is a keyword or builtin." % self.name) - try: - caller = self.shell.magics_manager.magics['line'][self.name] - except KeyError: - pass - else: - if not isinstance(caller, Alias): - raise InvalidAliasError("The name %s can't be aliased " - "because it is another magic command." % self.name) - - if not (isinstance(self.cmd, str)): - raise InvalidAliasError("An alias command must be a string, " - "got: %r" % self.cmd) - - nargs = self.cmd.count('%s') - self.cmd.count('%%s') - - if (nargs > 0) and (self.cmd.find('%l') >= 0): - raise InvalidAliasError('The %s and %l specifiers are mutually ' - 'exclusive in alias definitions.') - - return nargs - - def __repr__(self): - return "".format(self.name, self.cmd) - - def __call__(self, rest=''): - cmd = self.cmd - nargs = self.nargs - # Expand the %l special to be the user's input line - if cmd.find('%l') >= 0: - cmd = cmd.replace('%l', rest) - rest = '' - - if nargs==0: - if cmd.find('%%s') >= 1: - cmd = cmd.replace('%%s', '%s') - # Simple, argument-less aliases - cmd = '%s %s' % (cmd, rest) - else: - # Handle aliases with positional arguments - args = rest.split(None, nargs) - if len(args) < nargs: - raise UsageError('Alias <%s> requires %s arguments, %s given.' % - (self.name, nargs, len(args))) - cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:])) - - self.shell.system(cmd) - -#----------------------------------------------------------------------------- -# Main AliasManager class -#----------------------------------------------------------------------------- - -class AliasManager(Configurable): - default_aliases: List = List(default_aliases()).tag(config=True) - user_aliases: List = List(default_value=[]).tag(config=True) - shell = Instance( - "IPython.core.interactiveshell.InteractiveShellABC", allow_none=True - ) - - def __init__(self, shell=None, **kwargs): - super(AliasManager, self).__init__(shell=shell, **kwargs) - # For convenient access - if self.shell is not None: - self.linemagics = self.shell.magics_manager.magics["line"] - self.init_aliases() - - def init_aliases(self): - # Load default & user aliases - for name, cmd in self.default_aliases + self.user_aliases: - if ( - cmd.startswith("ls ") - and self.shell is not None - and self.shell.colors == "NoColor" - ): - cmd = cmd.replace(" --color", "") - self.soft_define_alias(name, cmd) - - @property - def aliases(self): - return [(n, func.cmd) for (n, func) in self.linemagics.items() - if isinstance(func, Alias)] - - def soft_define_alias(self, name, cmd): - """Define an alias, but don't raise on an AliasError.""" - try: - self.define_alias(name, cmd) - except AliasError as e: - error("Invalid alias: %s" % e) - - def define_alias(self, name, cmd): - """Define a new alias after validating it. - - This will raise an :exc:`AliasError` if there are validation - problems. - """ - caller = Alias(shell=self.shell, name=name, cmd=cmd) - self.shell.magics_manager.register_function(caller, magic_kind='line', - magic_name=name) - - def get_alias(self, name): - """Return an alias, or None if no alias by that name exists.""" - aname = self.linemagics.get(name, None) - return aname if isinstance(aname, Alias) else None - - def is_alias(self, name): - """Return whether or not a given name has been defined as an alias""" - return self.get_alias(name) is not None - - def undefine_alias(self, name): - if self.is_alias(name): - del self.linemagics[name] - else: - raise ValueError('%s is not an alias' % name) - - def clear_aliases(self): - for name, _ in self.aliases: - self.undefine_alias(name) - - def retrieve_alias(self, name): - """Retrieve the command to which an alias expands.""" - caller = self.get_alias(name) - if caller: - return caller.cmd - else: - raise ValueError('%s is not an alias' % name) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/application.py b/.venv/lib/python3.12/site-packages/IPython/core/application.py deleted file mode 100644 index 841e867..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/application.py +++ /dev/null @@ -1,492 +0,0 @@ -# encoding: utf-8 -""" -An application for IPython. - -All top-level applications should use the classes in this module for -handling configuration and creating configurables. - -The job of an :class:`Application` is to create the master configuration -object and then create the configurable objects, passing the config to them. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import atexit -from copy import deepcopy -import logging -import os -import shutil -import sys - -from pathlib import Path - -from traitlets.config.application import Application, catch_config_error -from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader -from IPython.core import release, crashhandler -from IPython.core.profiledir import ProfileDir, ProfileDirError -from IPython.paths import get_ipython_dir, get_ipython_package_dir -from IPython.utils.path import ensure_dir_exists -from traitlets import ( - List, Unicode, Type, Bool, Set, Instance, Undefined, - default, observe, -) - -if os.name == "nt": - programdata = os.environ.get("PROGRAMDATA", None) - if programdata is not None: - SYSTEM_CONFIG_DIRS = [str(Path(programdata) / "ipython")] - else: # PROGRAMDATA is not defined by default on XP. - SYSTEM_CONFIG_DIRS = [] -else: - SYSTEM_CONFIG_DIRS = [ - "/usr/local/etc/ipython", - "/etc/ipython", - ] - - -ENV_CONFIG_DIRS = [] -_env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython') -if _env_config_dir not in SYSTEM_CONFIG_DIRS: - # only add ENV_CONFIG if sys.prefix is not already included - ENV_CONFIG_DIRS.append(_env_config_dir) - - -_envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS') -if _envvar in {None, ''}: - IPYTHON_SUPPRESS_CONFIG_ERRORS = None -else: - if _envvar.lower() in {'1','true'}: - IPYTHON_SUPPRESS_CONFIG_ERRORS = True - elif _envvar.lower() in {'0','false'} : - IPYTHON_SUPPRESS_CONFIG_ERRORS = False - else: - sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar ) - -# aliases and flags - -base_aliases = {} -if isinstance(Application.aliases, dict): - # traitlets 5 - base_aliases.update(Application.aliases) -base_aliases.update( - { - "profile-dir": "ProfileDir.location", - "profile": "BaseIPythonApplication.profile", - "ipython-dir": "BaseIPythonApplication.ipython_dir", - "log-level": "Application.log_level", - "config": "BaseIPythonApplication.extra_config_file", - } -) - -base_flags = dict() -if isinstance(Application.flags, dict): - # traitlets 5 - base_flags.update(Application.flags) -base_flags.update( - dict( - debug=( - {"Application": {"log_level": logging.DEBUG}}, - "set log level to logging.DEBUG (maximize logging output)", - ), - quiet=( - {"Application": {"log_level": logging.CRITICAL}}, - "set log level to logging.CRITICAL (minimize logging output)", - ), - init=( - { - "BaseIPythonApplication": { - "copy_config_files": True, - "auto_create": True, - } - }, - """Initialize profile with default config files. This is equivalent - to running `ipython profile create ` prior to startup. - """, - ), - ) -) - - -class ProfileAwareConfigLoader(PyFileConfigLoader): - """A Python file config loader that is aware of IPython profiles.""" - def load_subconfig(self, fname, path=None, profile=None): - if profile is not None: - try: - profile_dir = ProfileDir.find_profile_dir_by_name( - get_ipython_dir(), - profile, - ) - except ProfileDirError: - return - path = profile_dir.location - return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path) - -class BaseIPythonApplication(Application): - name = "ipython" - description = "IPython: an enhanced interactive Python shell." - version = Unicode(release.version) - - aliases = base_aliases - flags = base_flags - classes = List([ProfileDir]) - - # enable `load_subconfig('cfg.py', profile='name')` - python_config_loader_class = ProfileAwareConfigLoader - - # Track whether the config_file has changed, - # because some logic happens only if we aren't using the default. - config_file_specified = Set() - - config_file_name = Unicode() - @default('config_file_name') - def _config_file_name_default(self): - return self.name.replace('-','_') + u'_config.py' - @observe('config_file_name') - def _config_file_name_changed(self, change): - if change['new'] != change['old']: - self.config_file_specified.add(change['new']) - - # The directory that contains IPython's builtin profiles. - builtin_profile_dir = Unicode( - os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default') - ) - - config_file_paths = List(Unicode()) - @default('config_file_paths') - def _config_file_paths_default(self): - return [] - - extra_config_file = Unicode( - help="""Path to an extra config file to load. - - If specified, load this config file in addition to any other IPython config. - """).tag(config=True) - @observe('extra_config_file') - def _extra_config_file_changed(self, change): - old = change['old'] - new = change['new'] - try: - self.config_files.remove(old) - except ValueError: - pass - self.config_file_specified.add(new) - self.config_files.append(new) - - profile = Unicode(u'default', - help="""The IPython profile to use.""" - ).tag(config=True) - - @observe('profile') - def _profile_changed(self, change): - self.builtin_profile_dir = os.path.join( - get_ipython_package_dir(), u'config', u'profile', change['new'] - ) - - add_ipython_dir_to_sys_path = Bool( - False, - """Should the IPython profile directory be added to sys path ? - - This option was non-existing before IPython 8.0, and ipython_dir was added to - sys path to allow import of extensions present there. This was historical - baggage from when pip did not exist. This now default to false, - but can be set to true for legacy reasons. - """, - ).tag(config=True) - - ipython_dir = Unicode( - help=""" - The name of the IPython directory. This directory is used for logging - configuration (through profiles), history storage, etc. The default - is usually $HOME/.ipython. This option can also be specified through - the environment variable IPYTHONDIR. - """ - ).tag(config=True) - @default('ipython_dir') - def _ipython_dir_default(self): - d = get_ipython_dir() - self._ipython_dir_changed({ - 'name': 'ipython_dir', - 'old': d, - 'new': d, - }) - return d - - _in_init_profile_dir = False - - profile_dir = Instance(ProfileDir, allow_none=True) - - @default('profile_dir') - def _profile_dir_default(self): - # avoid recursion - if self._in_init_profile_dir: - return - # profile_dir requested early, force initialization - self.init_profile_dir() - return self.profile_dir - - overwrite = Bool(False, - help="""Whether to overwrite existing config files when copying""" - ).tag(config=True) - - auto_create = Bool(False, - help="""Whether to create profile dir if it doesn't exist""" - ).tag(config=True) - - config_files = List(Unicode()) - - @default('config_files') - def _config_files_default(self): - return [self.config_file_name] - - copy_config_files = Bool(False, - help="""Whether to install the default config files into the profile dir. - If a new profile is being created, and IPython contains config files for that - profile, then they will be staged into the new directory. Otherwise, - default config files will be automatically generated. - """).tag(config=True) - - verbose_crash = Bool(False, - help="""Create a massive crash report when IPython encounters what may be an - internal error. The default is to append a short message to the - usual traceback""").tag(config=True) - - # The class to use as the crash handler. - crash_handler_class = Type(crashhandler.CrashHandler) - - @catch_config_error - def __init__(self, **kwargs): - super(BaseIPythonApplication, self).__init__(**kwargs) - # ensure current working directory exists - try: - os.getcwd() - except: - # exit if cwd doesn't exist - self.log.error("Current working directory doesn't exist.") - self.exit(1) - - #------------------------------------------------------------------------- - # Various stages of Application creation - #------------------------------------------------------------------------- - - def init_crash_handler(self): - """Create a crash handler, typically setting sys.excepthook to it.""" - self.crash_handler = self.crash_handler_class(self) - sys.excepthook = self.excepthook - def unset_crashhandler(): - sys.excepthook = sys.__excepthook__ - atexit.register(unset_crashhandler) - - def excepthook(self, etype, evalue, tb): - """this is sys.excepthook after init_crashhandler - - set self.verbose_crash=True to use our full crashhandler, instead of - a regular traceback with a short message (crash_handler_lite) - """ - - if self.verbose_crash: - return self.crash_handler(etype, evalue, tb) - else: - return crashhandler.crash_handler_lite(etype, evalue, tb) - - @observe('ipython_dir') - def _ipython_dir_changed(self, change): - old = change['old'] - new = change['new'] - if old is not Undefined: - str_old = os.path.abspath(old) - if str_old in sys.path: - sys.path.remove(str_old) - if self.add_ipython_dir_to_sys_path: - str_path = os.path.abspath(new) - sys.path.append(str_path) - ensure_dir_exists(new) - readme = os.path.join(new, "README") - readme_src = os.path.join( - get_ipython_package_dir(), "config", "profile", "README" - ) - if not os.path.exists(readme) and os.path.exists(readme_src): - shutil.copy(readme_src, readme) - for d in ("extensions", "nbextensions"): - path = os.path.join(new, d) - try: - ensure_dir_exists(path) - except OSError as e: - # this will not be EEXIST - self.log.error("couldn't create path %s: %s", path, e) - self.log.debug("IPYTHONDIR set to: %s", new) - - def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS): - """Load the config file. - - By default, errors in loading config are handled, and a warning - printed on screen. For testing, the suppress_errors option is set - to False, so errors will make tests fail. - - `suppress_errors` default value is to be `None` in which case the - behavior default to the one of `traitlets.Application`. - - The default value can be set : - - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive). - - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive). - - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset. - - Any other value are invalid, and will make IPython exit with a non-zero return code. - """ - - - self.log.debug("Searching path %s for config files", self.config_file_paths) - base_config = 'ipython_config.py' - self.log.debug("Attempting to load config file: %s" % - base_config) - try: - if suppress_errors is not None: - old_value = Application.raise_config_file_errors - Application.raise_config_file_errors = not suppress_errors; - Application.load_config_file( - self, - base_config, - path=self.config_file_paths - ) - except ConfigFileNotFound: - # ignore errors loading parent - self.log.debug("Config file %s not found", base_config) - pass - if suppress_errors is not None: - Application.raise_config_file_errors = old_value - - for config_file_name in self.config_files: - if not config_file_name or config_file_name == base_config: - continue - self.log.debug("Attempting to load config file: %s" % - self.config_file_name) - try: - Application.load_config_file( - self, - config_file_name, - path=self.config_file_paths - ) - except ConfigFileNotFound: - # Only warn if the default config file was NOT being used. - if config_file_name in self.config_file_specified: - msg = self.log.warning - else: - msg = self.log.debug - msg("Config file not found, skipping: %s", config_file_name) - except Exception: - # For testing purposes. - if not suppress_errors: - raise - self.log.warning("Error loading config file: %s" % - self.config_file_name, exc_info=True) - - def init_profile_dir(self): - """initialize the profile dir""" - self._in_init_profile_dir = True - if self.profile_dir is not None: - # already ran - return - if 'ProfileDir.location' not in self.config: - # location not specified, find by profile name - try: - p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config) - except ProfileDirError: - # not found, maybe create it (always create default profile) - if self.auto_create or self.profile == 'default': - try: - p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config) - except ProfileDirError: - self.log.fatal("Could not create profile: %r"%self.profile) - self.exit(1) - else: - self.log.info("Created profile dir: %r"%p.location) - else: - self.log.fatal("Profile %r not found."%self.profile) - self.exit(1) - else: - self.log.debug("Using existing profile dir: %r", p.location) - else: - location = self.config.ProfileDir.location - # location is fully specified - try: - p = ProfileDir.find_profile_dir(location, self.config) - except ProfileDirError: - # not found, maybe create it - if self.auto_create: - try: - p = ProfileDir.create_profile_dir(location, self.config) - except ProfileDirError: - self.log.fatal("Could not create profile directory: %r"%location) - self.exit(1) - else: - self.log.debug("Creating new profile dir: %r"%location) - else: - self.log.fatal("Profile directory %r not found."%location) - self.exit(1) - else: - self.log.debug("Using existing profile dir: %r", p.location) - # if profile_dir is specified explicitly, set profile name - dir_name = os.path.basename(p.location) - if dir_name.startswith('profile_'): - self.profile = dir_name[8:] - - self.profile_dir = p - self.config_file_paths.append(p.location) - self._in_init_profile_dir = False - - def init_config_files(self): - """[optionally] copy default config files into profile dir.""" - self.config_file_paths.extend(ENV_CONFIG_DIRS) - self.config_file_paths.extend(SYSTEM_CONFIG_DIRS) - # copy config files - path = Path(self.builtin_profile_dir) - if self.copy_config_files: - src = self.profile - - cfg = self.config_file_name - if path and (path / cfg).exists(): - self.log.warning( - "Staging %r from %s into %r [overwrite=%s]" - % (cfg, src, self.profile_dir.location, self.overwrite) - ) - self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite) - else: - self.stage_default_config_file() - else: - # Still stage *bundled* config files, but not generated ones - # This is necessary for `ipython profile=sympy` to load the profile - # on the first go - files = path.glob("*.py") - for fullpath in files: - cfg = fullpath.name - if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False): - # file was copied - self.log.warning("Staging bundled %s from %s into %r"%( - cfg, self.profile, self.profile_dir.location) - ) - - - def stage_default_config_file(self): - """auto generate default config file, and stage it into the profile.""" - s = self.generate_config_file() - config_file = Path(self.profile_dir.location) / self.config_file_name - if self.overwrite or not config_file.exists(): - self.log.warning("Generating default config file: %r", (config_file)) - config_file.write_text(s, encoding="utf-8") - - @catch_config_error - def initialize(self, argv=None): - # don't hook up crash handler before parsing command-line - self.parse_command_line(argv) - self.init_crash_handler() - if self.subapp is not None: - # stop here if subapp is taking over - return - # save a copy of CLI config to re-load after config files - # so that it has highest priority - cl_config = deepcopy(self.config) - self.init_profile_dir() - self.init_config_files() - self.load_config_file() - # enforce cl-opts override configfile opts: - self.update_config(cl_config) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/async_helpers.py b/.venv/lib/python3.12/site-packages/IPython/core/async_helpers.py deleted file mode 100644 index 4dfac54..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/async_helpers.py +++ /dev/null @@ -1,155 +0,0 @@ -""" -Async helper function that are invalid syntax on Python 3.5 and below. - -This code is best effort, and may have edge cases not behaving as expected. In -particular it contain a number of heuristics to detect whether code is -effectively async and need to run in an event loop or not. - -Some constructs (like top-level `return`, or `yield`) are taken care of -explicitly to actually raise a SyntaxError and stay as close as possible to -Python semantics. -""" - -import ast -import asyncio -import inspect -from functools import wraps - -_asyncio_event_loop = None - - -def get_asyncio_loop(): - """asyncio has deprecated get_event_loop - - Replicate it here, with our desired semantics: - - - always returns a valid, not-closed loop - - not thread-local like asyncio's, - because we only want one loop for IPython - - if called from inside a coroutine (e.g. in ipykernel), - return the running loop - - .. versionadded:: 8.0 - """ - try: - return asyncio.get_running_loop() - except RuntimeError: - # not inside a coroutine, - # track our own global - pass - - # not thread-local like asyncio's, - # because we only track one event loop to run for IPython itself, - # always in the main thread. - global _asyncio_event_loop - if _asyncio_event_loop is None or _asyncio_event_loop.is_closed(): - _asyncio_event_loop = asyncio.new_event_loop() - return _asyncio_event_loop - - -class _AsyncIORunner: - def __call__(self, coro): - """ - Handler for asyncio autoawait - """ - return get_asyncio_loop().run_until_complete(coro) - - def __str__(self): - return "asyncio" - - -_asyncio_runner = _AsyncIORunner() - - -class _AsyncIOProxy: - """Proxy-object for an asyncio - - Any coroutine methods will be wrapped in event_loop.run_ - """ - - def __init__(self, obj, event_loop): - self._obj = obj - self._event_loop = event_loop - - def __repr__(self): - return f"<_AsyncIOProxy({self._obj!r})>" - - def __getattr__(self, key): - attr = getattr(self._obj, key) - if inspect.iscoroutinefunction(attr): - # if it's a coroutine method, - # return a threadsafe wrapper onto the _current_ asyncio loop - @wraps(attr) - def _wrapped(*args, **kwargs): - concurrent_future = asyncio.run_coroutine_threadsafe( - attr(*args, **kwargs), self._event_loop - ) - return asyncio.wrap_future(concurrent_future) - - return _wrapped - else: - return attr - - def __dir__(self): - return dir(self._obj) - - -def _curio_runner(coroutine): - """ - handler for curio autoawait - """ - import curio - - return curio.run(coroutine) - - -def _trio_runner(async_fn): - import trio - - async def loc(coro): - """ - We need the dummy no-op async def to protect from - trio's internal. See https://github.com/python-trio/trio/issues/89 - """ - return await coro - - return trio.run(loc, async_fn) - - -def _pseudo_sync_runner(coro): - """ - A runner that does not really allow async execution, and just advance the coroutine. - - See discussion in https://github.com/python-trio/trio/issues/608, - - Credit to Nathaniel Smith - """ - try: - coro.send(None) - except StopIteration as exc: - return exc.value - else: - # TODO: do not raise but return an execution result with the right info. - raise RuntimeError( - "{coro_name!r} needs a real async loop".format(coro_name=coro.__name__) - ) - - -def _should_be_async(cell: str) -> bool: - """Detect if a block of code need to be wrapped in an `async def` - - Attempt to parse the block of code, it it compile we're fine. - Otherwise we wrap if and try to compile. - - If it works, assume it should be async. Otherwise Return False. - - Not handled yet: If the block of code has a return statement as the top - level, it will be seen as async. This is a know limitation. - """ - try: - code = compile( - cell, "<>", "exec", flags=getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0) - ) - return inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE - except (SyntaxError, MemoryError): - return False diff --git a/.venv/lib/python3.12/site-packages/IPython/core/autocall.py b/.venv/lib/python3.12/site-packages/IPython/core/autocall.py deleted file mode 100644 index 54beec3..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/autocall.py +++ /dev/null @@ -1,70 +0,0 @@ -# encoding: utf-8 -""" -Autocall capabilities for IPython.core. - -Authors: - -* Brian Granger -* Fernando Perez -* Thomas Kluyver - -Notes ------ -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -class IPyAutocall(object): - """ Instances of this class are always autocalled - - This happens regardless of 'autocall' variable state. Use this to - develop macro-like mechanisms. - """ - _ip = None - rewrite = True - def __init__(self, ip=None): - self._ip = ip - - def set_ip(self, ip): - """Will be used to set _ip point to current ipython instance b/f call - - Override this method if you don't want this to happen. - - """ - self._ip = ip - - -class ExitAutocall(IPyAutocall): - """An autocallable object which will be added to the user namespace so that - exit, exit(), quit or quit() are all valid ways to close the shell.""" - rewrite = False - - def __call__(self): - self._ip.ask_exit() - -class ZMQExitAutocall(ExitAutocall): - """Exit IPython. Autocallable, so it needn't be explicitly called. - - Parameters - ---------- - keep_kernel : bool - If True, leave the kernel alive. Otherwise, tell the kernel to exit too - (default). - """ - def __call__(self, keep_kernel=False): - self._ip.keepkernel_on_exit = keep_kernel - self._ip.ask_exit() diff --git a/.venv/lib/python3.12/site-packages/IPython/core/builtin_trap.py b/.venv/lib/python3.12/site-packages/IPython/core/builtin_trap.py deleted file mode 100644 index a8ea4ab..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/builtin_trap.py +++ /dev/null @@ -1,86 +0,0 @@ -""" -A context manager for managing things injected into :mod:`builtins`. -""" -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. -import builtins as builtin_mod - -from traitlets.config.configurable import Configurable - -from traitlets import Instance - - -class __BuiltinUndefined(object): pass -BuiltinUndefined = __BuiltinUndefined() - -class __HideBuiltin(object): pass -HideBuiltin = __HideBuiltin() - - -class BuiltinTrap(Configurable): - - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', - allow_none=True) - - def __init__(self, shell=None): - super(BuiltinTrap, self).__init__(shell=shell, config=None) - self._orig_builtins = {} - # We define this to track if a single BuiltinTrap is nested. - # Only turn off the trap when the outermost call to __exit__ is made. - self._nested_level = 0 - self.shell = shell - # builtins we always add - if set to HideBuiltin, they will just - # be removed instead of being replaced by something else - self.auto_builtins = {'exit': HideBuiltin, - 'quit': HideBuiltin, - 'get_ipython': self.shell.get_ipython, - } - - def __enter__(self): - if self._nested_level == 0: - self.activate() - self._nested_level += 1 - # I return self, so callers can use add_builtin in a with clause. - return self - - def __exit__(self, type, value, traceback): - if self._nested_level == 1: - self.deactivate() - self._nested_level -= 1 - # Returning False will cause exceptions to propagate - return False - - def add_builtin(self, key, value): - """Add a builtin and save the original.""" - bdict = builtin_mod.__dict__ - orig = bdict.get(key, BuiltinUndefined) - if value is HideBuiltin: - if orig is not BuiltinUndefined: #same as 'key in bdict' - self._orig_builtins[key] = orig - del bdict[key] - else: - self._orig_builtins[key] = orig - bdict[key] = value - - def remove_builtin(self, key, orig): - """Remove an added builtin and re-set the original.""" - if orig is BuiltinUndefined: - del builtin_mod.__dict__[key] - else: - builtin_mod.__dict__[key] = orig - - def activate(self): - """Store ipython references in the __builtin__ namespace.""" - - add_builtin = self.add_builtin - for name, func in self.auto_builtins.items(): - add_builtin(name, func) - - def deactivate(self): - """Remove any builtins which might have been added by add_builtins, or - restore overwritten ones to their previous values.""" - remove_builtin = self.remove_builtin - for key, val in self._orig_builtins.items(): - remove_builtin(key, val) - self._orig_builtins.clear() - self._builtins_added = False diff --git a/.venv/lib/python3.12/site-packages/IPython/core/compilerop.py b/.venv/lib/python3.12/site-packages/IPython/core/compilerop.py deleted file mode 100644 index 7799a4f..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/compilerop.py +++ /dev/null @@ -1,214 +0,0 @@ -"""Compiler tools with improved interactive support. - -Provides compilation machinery similar to codeop, but with caching support so -we can provide interactive tracebacks. - -Authors -------- -* Robert Kern -* Fernando Perez -* Thomas Kluyver -""" - -# Note: though it might be more natural to name this module 'compiler', that -# name is in the stdlib and name collisions with the stdlib tend to produce -# weird problems (often with third-party tools). - -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team. -# -# Distributed under the terms of the BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib imports -import __future__ -from ast import PyCF_ONLY_AST -import codeop -import functools -import hashlib -import linecache -import operator -import time -from contextlib import contextmanager - -#----------------------------------------------------------------------------- -# Constants -#----------------------------------------------------------------------------- - -# Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h, -# this is used as a bitmask to extract future-related code flags. -PyCF_MASK = functools.reduce(operator.or_, - (getattr(__future__, fname).compiler_flag - for fname in __future__.all_feature_names)) - -#----------------------------------------------------------------------------- -# Local utilities -#----------------------------------------------------------------------------- - -def code_name(code, number=0): - """ Compute a (probably) unique name for code for caching. - - This now expects code to be unicode. - """ - hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest() - # Include the number and 12 characters of the hash in the name. It's - # pretty much impossible that in a single session we'll have collisions - # even with truncated hashes, and the full one makes tracebacks too long - return ''.format(number, hash_digest[:12]) - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -class CachingCompiler(codeop.Compile): - """A compiler that caches code compiled from interactive statements. - """ - - def __init__(self): - codeop.Compile.__init__(self) - - # Caching a dictionary { filename: execution_count } for nicely - # rendered tracebacks. The filename corresponds to the filename - # argument used for the builtins.compile function. - self._filename_map = {} - - def ast_parse(self, source, filename='', symbol='exec'): - """Parse code to an AST with the current compiler flags active. - - Arguments are exactly the same as ast.parse (in the standard library), - and are passed to the built-in compile function.""" - return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1) - - def reset_compiler_flags(self): - """Reset compiler flags to default state.""" - # This value is copied from codeop.Compile.__init__, so if that ever - # changes, it will need to be updated. - self.flags = codeop.PyCF_DONT_IMPLY_DEDENT - - @property - def compiler_flags(self): - """Flags currently active in the compilation process. - """ - return self.flags - - def get_code_name(self, raw_code, transformed_code, number): - """Compute filename given the code, and the cell number. - - Parameters - ---------- - raw_code : str - The raw cell code. - transformed_code : str - The executable Python source code to cache and compile. - number : int - A number which forms part of the code's name. Used for the execution - counter. - - Returns - ------- - The computed filename. - """ - return code_name(transformed_code, number) - - def format_code_name(self, name): - """Return a user-friendly label and name for a code block. - - Parameters - ---------- - name : str - The name for the code block returned from get_code_name - - Returns - ------- - A (label, name) pair that can be used in tracebacks, or None if the default formatting should be used. - """ - if name in self._filename_map: - return "Cell", "In[%s]" % self._filename_map[name] - - def cache(self, transformed_code, number=0, raw_code=None): - """Make a name for a block of code, and cache the code. - - Parameters - ---------- - transformed_code : str - The executable Python source code to cache and compile. - number : int - A number which forms part of the code's name. Used for the execution - counter. - raw_code : str - The raw code before transformation, if None, set to `transformed_code`. - - Returns - ------- - The name of the cached code (as a string). Pass this as the filename - argument to compilation, so that tracebacks are correctly hooked up. - """ - if raw_code is None: - raw_code = transformed_code - - name = self.get_code_name(raw_code, transformed_code, number) - - # Save the execution count - self._filename_map[name] = number - - # Since Python 2.5, setting mtime to `None` means the lines will - # never be removed by `linecache.checkcache`. This means all the - # monkeypatching has *never* been necessary, since this code was - # only added in 2010, at which point IPython had already stopped - # supporting Python 2.4. - # - # Note that `linecache.clearcache` and `linecache.updatecache` may - # still remove our code from the cache, but those show explicit - # intent, and we should not try to interfere. Normally the former - # is never called except when out of memory, and the latter is only - # called for lines *not* in the cache. - entry = ( - len(transformed_code), - None, - [line + "\n" for line in transformed_code.splitlines()], - name, - ) - linecache.cache[name] = entry - return name - - @contextmanager - def extra_flags(self, flags): - ## bits that we'll set to 1 - turn_on_bits = ~self.flags & flags - - - self.flags = self.flags | flags - try: - yield - finally: - # turn off only the bits we turned on so that something like - # __future__ that set flags stays. - self.flags &= ~turn_on_bits - - -def check_linecache_ipython(*args): - """Deprecated since IPython 8.6. Call linecache.checkcache() directly. - - It was already not necessary to call this function directly. If no - CachingCompiler had been created, this function would fail badly. If - an instance had been created, this function would've been monkeypatched - into place. - - As of IPython 8.6, the monkeypatching has gone away entirely. But there - were still internal callers of this function, so maybe external callers - also existed? - """ - import warnings - - warnings.warn( - "Deprecated Since IPython 8.6, Just call linecache.checkcache() directly.", - DeprecationWarning, - stacklevel=2, - ) - linecache.checkcache() diff --git a/.venv/lib/python3.12/site-packages/IPython/core/completer.py b/.venv/lib/python3.12/site-packages/IPython/core/completer.py deleted file mode 100644 index b39a922..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/completer.py +++ /dev/null @@ -1,3421 +0,0 @@ -"""Completion for IPython. - -This module started as fork of the rlcompleter module in the Python standard -library. The original enhancements made to rlcompleter have been sent -upstream and were accepted as of Python 2.3, - -This module now support a wide variety of completion mechanism both available -for normal classic Python code, as well as completer for IPython specific -Syntax like magics. - -Latex and Unicode completion -============================ - -IPython and compatible frontends not only can complete your code, but can help -you to input a wide range of characters. In particular we allow you to insert -a unicode character using the tab completion mechanism. - -Forward latex/unicode completion --------------------------------- - -Forward completion allows you to easily type a unicode character using its latex -name, or unicode long description. To do so type a backslash follow by the -relevant name and press tab: - - -Using latex completion: - -.. code:: - - \\alpha - α - -or using unicode completion: - - -.. code:: - - \\GREEK SMALL LETTER ALPHA - α - - -Only valid Python identifiers will complete. Combining characters (like arrow or -dots) are also available, unlike latex they need to be put after the their -counterpart that is to say, ``F\\\\vec`` is correct, not ``\\\\vecF``. - -Some browsers are known to display combining characters incorrectly. - -Backward latex completion -------------------------- - -It is sometime challenging to know how to type a character, if you are using -IPython, or any compatible frontend you can prepend backslash to the character -and press :kbd:`Tab` to expand it to its latex form. - -.. code:: - - \\α - \\alpha - - -Both forward and backward completions can be deactivated by setting the -:std:configtrait:`Completer.backslash_combining_completions` option to -``False``. - - -Experimental -============ - -Starting with IPython 6.0, this module can make use of the Jedi library to -generate completions both using static analysis of the code, and dynamically -inspecting multiple namespaces. Jedi is an autocompletion and static analysis -for Python. The APIs attached to this new mechanism is unstable and will -raise unless use in an :any:`provisionalcompleter` context manager. - -You will find that the following are experimental: - - - :any:`provisionalcompleter` - - :any:`IPCompleter.completions` - - :any:`Completion` - - :any:`rectify_completions` - -.. note:: - - better name for :any:`rectify_completions` ? - -We welcome any feedback on these new API, and we also encourage you to try this -module in debug mode (start IPython with ``--Completer.debug=True``) in order -to have extra logging information if :any:`jedi` is crashing, or if current -IPython completer pending deprecations are returning results not yet handled -by :any:`jedi` - -Using Jedi for tab completion allow snippets like the following to work without -having to execute any code: - - >>> myvar = ['hello', 42] - ... myvar[1].bi - -Tab completion will be able to infer that ``myvar[1]`` is a real number without -executing almost any code unlike the deprecated :any:`IPCompleter.greedy` -option. - -Be sure to update :any:`jedi` to the latest stable version or to try the -current development version to get better completions. - -Matchers -======== - -All completions routines are implemented using unified *Matchers* API. -The matchers API is provisional and subject to change without notice. - -The built-in matchers include: - -- :any:`IPCompleter.dict_key_matcher`: dictionary key completions, -- :any:`IPCompleter.magic_matcher`: completions for magics, -- :any:`IPCompleter.unicode_name_matcher`, - :any:`IPCompleter.fwd_unicode_matcher` - and :any:`IPCompleter.latex_name_matcher`: see `Forward latex/unicode completion`_, -- :any:`back_unicode_name_matcher` and :any:`back_latex_name_matcher`: see `Backward latex completion`_, -- :any:`IPCompleter.file_matcher`: paths to files and directories, -- :any:`IPCompleter.python_func_kw_matcher` - function keywords, -- :any:`IPCompleter.python_matches` - globals and attributes (v1 API), -- ``IPCompleter.jedi_matcher`` - static analysis with Jedi, -- :any:`IPCompleter.custom_completer_matcher` - pluggable completer with a default - implementation in :any:`InteractiveShell` which uses IPython hooks system - (`complete_command`) with string dispatch (including regular expressions). - Differently to other matchers, ``custom_completer_matcher`` will not suppress - Jedi results to match behaviour in earlier IPython versions. - -Custom matchers can be added by appending to ``IPCompleter.custom_matchers`` list. - -Matcher API ------------ - -Simplifying some details, the ``Matcher`` interface can described as - -.. code-block:: - - MatcherAPIv1 = Callable[[str], list[str]] - MatcherAPIv2 = Callable[[CompletionContext], SimpleMatcherResult] - - Matcher = MatcherAPIv1 | MatcherAPIv2 - -The ``MatcherAPIv1`` reflects the matcher API as available prior to IPython 8.6.0 -and remains supported as a simplest way for generating completions. This is also -currently the only API supported by the IPython hooks system `complete_command`. - -To distinguish between matcher versions ``matcher_api_version`` attribute is used. -More precisely, the API allows to omit ``matcher_api_version`` for v1 Matchers, -and requires a literal ``2`` for v2 Matchers. - -Once the API stabilises future versions may relax the requirement for specifying -``matcher_api_version`` by switching to :any:`functools.singledispatch`, therefore -please do not rely on the presence of ``matcher_api_version`` for any purposes. - -Suppression of competing matchers ---------------------------------- - -By default results from all matchers are combined, in the order determined by -their priority. Matchers can request to suppress results from subsequent -matchers by setting ``suppress`` to ``True`` in the ``MatcherResult``. - -When multiple matchers simultaneously request suppression, the results from of -the matcher with higher priority will be returned. - -Sometimes it is desirable to suppress most but not all other matchers; -this can be achieved by adding a set of identifiers of matchers which -should not be suppressed to ``MatcherResult`` under ``do_not_suppress`` key. - -The suppression behaviour can is user-configurable via -:std:configtrait:`IPCompleter.suppress_competing_matchers`. -""" - - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. -# -# Some of this code originated from rlcompleter in the Python standard library -# Copyright (C) 2001 Python Software Foundation, www.python.org - -from __future__ import annotations -import builtins as builtin_mod -import enum -import glob -import inspect -import itertools -import keyword -import ast -import os -import re -import string -import sys -import tokenize -import time -import unicodedata -import uuid -import warnings -from ast import literal_eval -from collections import defaultdict -from contextlib import contextmanager -from dataclasses import dataclass -from functools import cached_property, partial -from types import SimpleNamespace -from typing import ( - Iterable, - Iterator, - List, - Tuple, - Union, - Any, - Sequence, - Dict, - Optional, - TYPE_CHECKING, - Set, - Sized, - TypeVar, - Literal, -) - -from IPython.core.guarded_eval import guarded_eval, EvaluationContext -from IPython.core.error import TryNext -from IPython.core.inputtransformer2 import ESC_MAGIC -from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol -from IPython.core.oinspect import InspectColors -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils import generics -from IPython.utils.decorators import sphinx_options -from IPython.utils.dir2 import dir2, get_real_method -from IPython.utils.docs import GENERATING_DOCUMENTATION -from IPython.utils.path import ensure_dir_exists -from IPython.utils.process import arg_split -from traitlets import ( - Bool, - Enum, - Int, - List as ListTrait, - Unicode, - Dict as DictTrait, - Union as UnionTrait, - observe, -) -from traitlets.config.configurable import Configurable - -import __main__ - -# skip module docstests -__skip_doctest__ = True - - -try: - import jedi - jedi.settings.case_insensitive_completion = False - import jedi.api.helpers - import jedi.api.classes - JEDI_INSTALLED = True -except ImportError: - JEDI_INSTALLED = False - - -if TYPE_CHECKING or GENERATING_DOCUMENTATION and sys.version_info >= (3, 11): - from typing import cast - from typing_extensions import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard -else: - from typing import Generic - - def cast(type_, obj): - """Workaround for `TypeError: MatcherAPIv2() takes no arguments`""" - return obj - - # do not require on runtime - NotRequired = Tuple # requires Python >=3.11 - TypedDict = Dict # by extension of `NotRequired` requires 3.11 too - Protocol = object # requires Python >=3.8 - TypeAlias = Any # requires Python >=3.10 - TypeGuard = Generic # requires Python >=3.10 -if GENERATING_DOCUMENTATION: - from typing import TypedDict - -# ----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- - -# ranges where we have most of the valid unicode names. We could be more finer -# grained but is it worth it for performance While unicode have character in the -# range 0, 0x110000, we seem to have name for about 10% of those. (131808 as I -# write this). With below range we cover them all, with a density of ~67% -# biggest next gap we consider only adds up about 1% density and there are 600 -# gaps that would need hard coding. -_UNICODE_RANGES = [(32, 0x323B0), (0xE0001, 0xE01F0)] - -# Public API -__all__ = ["Completer", "IPCompleter"] - -if sys.platform == 'win32': - PROTECTABLES = ' ' -else: - PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&' - -# Protect against returning an enormous number of completions which the frontend -# may have trouble processing. -MATCHES_LIMIT = 500 - -# Completion type reported when no type can be inferred. -_UNKNOWN_TYPE = "" - -# sentinel value to signal lack of a match -not_found = object() - -class ProvisionalCompleterWarning(FutureWarning): - """ - Exception raise by an experimental feature in this module. - - Wrap code in :any:`provisionalcompleter` context manager if you - are certain you want to use an unstable feature. - """ - pass - -warnings.filterwarnings('error', category=ProvisionalCompleterWarning) - - -@skip_doctest -@contextmanager -def provisionalcompleter(action='ignore'): - """ - This context manager has to be used in any place where unstable completer - behavior and API may be called. - - >>> with provisionalcompleter(): - ... completer.do_experimental_things() # works - - >>> completer.do_experimental_things() # raises. - - .. note:: - - Unstable - - By using this context manager you agree that the API in use may change - without warning, and that you won't complain if they do so. - - You also understand that, if the API is not to your liking, you should report - a bug to explain your use case upstream. - - We'll be happy to get your feedback, feature requests, and improvements on - any of the unstable APIs! - """ - with warnings.catch_warnings(): - warnings.filterwarnings(action, category=ProvisionalCompleterWarning) - yield - - -def has_open_quotes(s: str) -> Union[str, bool]: - """Return whether a string has open quotes. - - This simply counts whether the number of quote characters of either type in - the string is odd. - - Returns - ------- - If there is an open quote, the quote character is returned. Else, return - False. - """ - # We check " first, then ', so complex cases with nested quotes will get - # the " to take precedence. - if s.count('"') % 2: - return '"' - elif s.count("'") % 2: - return "'" - else: - return False - - -def protect_filename(s: str, protectables: str = PROTECTABLES) -> str: - """Escape a string to protect certain characters.""" - if set(s) & set(protectables): - if sys.platform == "win32": - return '"' + s + '"' - else: - return "".join(("\\" + c if c in protectables else c) for c in s) - else: - return s - - -def expand_user(path:str) -> Tuple[str, bool, str]: - """Expand ``~``-style usernames in strings. - - This is similar to :func:`os.path.expanduser`, but it computes and returns - extra information that will be useful if the input was being used in - computing completions, and you wish to return the completions with the - original '~' instead of its expanded value. - - Parameters - ---------- - path : str - String to be expanded. If no ~ is present, the output is the same as the - input. - - Returns - ------- - newpath : str - Result of ~ expansion in the input path. - tilde_expand : bool - Whether any expansion was performed or not. - tilde_val : str - The value that ~ was replaced with. - """ - # Default values - tilde_expand = False - tilde_val = '' - newpath = path - - if path.startswith('~'): - tilde_expand = True - rest = len(path)-1 - newpath = os.path.expanduser(path) - if rest: - tilde_val = newpath[:-rest] - else: - tilde_val = newpath - - return newpath, tilde_expand, tilde_val - - -def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str: - """Does the opposite of expand_user, with its outputs. - """ - if tilde_expand: - return path.replace(tilde_val, '~') - else: - return path - - -def completions_sorting_key(word): - """key for sorting completions - - This does several things: - - - Demote any completions starting with underscores to the end - - Insert any %magic and %%cellmagic completions in the alphabetical order - by their name - """ - prio1, prio2 = 0, 0 - - if word.startswith('__'): - prio1 = 2 - elif word.startswith('_'): - prio1 = 1 - - if word.endswith('='): - prio1 = -1 - - if word.startswith('%%'): - # If there's another % in there, this is something else, so leave it alone - if "%" not in word[2:]: - word = word[2:] - prio2 = 2 - elif word.startswith('%'): - if "%" not in word[1:]: - word = word[1:] - prio2 = 1 - - return prio1, word, prio2 - - -class _FakeJediCompletion: - """ - This is a workaround to communicate to the UI that Jedi has crashed and to - report a bug. Will be used only id :any:`IPCompleter.debug` is set to true. - - Added in IPython 6.0 so should likely be removed for 7.0 - - """ - - def __init__(self, name): - - self.name = name - self.complete = name - self.type = 'crashed' - self.name_with_symbols = name - self.signature = "" - self._origin = "fake" - self.text = "crashed" - - def __repr__(self): - return '' - - -_JediCompletionLike = Union["jedi.api.Completion", _FakeJediCompletion] - - -class Completion: - """ - Completion object used and returned by IPython completers. - - .. warning:: - - Unstable - - This function is unstable, API may change without warning. - It will also raise unless use in proper context manager. - - This act as a middle ground :any:`Completion` object between the - :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion - object. While Jedi need a lot of information about evaluator and how the - code should be ran/inspected, PromptToolkit (and other frontend) mostly - need user facing information. - - - Which range should be replaced replaced by what. - - Some metadata (like completion type), or meta information to displayed to - the use user. - - For debugging purpose we can also store the origin of the completion (``jedi``, - ``IPython.python_matches``, ``IPython.magics_matches``...). - """ - - __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin'] - - def __init__( - self, - start: int, - end: int, - text: str, - *, - type: Optional[str] = None, - _origin="", - signature="", - ) -> None: - warnings.warn( - "``Completion`` is a provisional API (as of IPython 6.0). " - "It may change without warnings. " - "Use in corresponding context manager.", - category=ProvisionalCompleterWarning, - stacklevel=2, - ) - - self.start = start - self.end = end - self.text = text - self.type = type - self.signature = signature - self._origin = _origin - - def __repr__(self): - return '' % \ - (self.start, self.end, self.text, self.type or '?', self.signature or '?') - - def __eq__(self, other) -> bool: - """ - Equality and hash do not hash the type (as some completer may not be - able to infer the type), but are use to (partially) de-duplicate - completion. - - Completely de-duplicating completion is a bit tricker that just - comparing as it depends on surrounding text, which Completions are not - aware of. - """ - return self.start == other.start and \ - self.end == other.end and \ - self.text == other.text - - def __hash__(self): - return hash((self.start, self.end, self.text)) - - -class SimpleCompletion: - """Completion item to be included in the dictionary returned by new-style Matcher (API v2). - - .. warning:: - - Provisional - - This class is used to describe the currently supported attributes of - simple completion items, and any additional implementation details - should not be relied on. Additional attributes may be included in - future versions, and meaning of text disambiguated from the current - dual meaning of "text to insert" and "text to used as a label". - """ - - __slots__ = ["text", "type"] - - def __init__(self, text: str, *, type: Optional[str] = None): - self.text = text - self.type = type - - def __repr__(self): - return f"" - - -class _MatcherResultBase(TypedDict): - """Definition of dictionary to be returned by new-style Matcher (API v2).""" - - #: Suffix of the provided ``CompletionContext.token``, if not given defaults to full token. - matched_fragment: NotRequired[str] - - #: Whether to suppress results from all other matchers (True), some - #: matchers (set of identifiers) or none (False); default is False. - suppress: NotRequired[Union[bool, Set[str]]] - - #: Identifiers of matchers which should NOT be suppressed when this matcher - #: requests to suppress all other matchers; defaults to an empty set. - do_not_suppress: NotRequired[Set[str]] - - #: Are completions already ordered and should be left as-is? default is False. - ordered: NotRequired[bool] - - -@sphinx_options(show_inherited_members=True, exclude_inherited_from=["dict"]) -class SimpleMatcherResult(_MatcherResultBase, TypedDict): - """Result of new-style completion matcher.""" - - # note: TypedDict is added again to the inheritance chain - # in order to get __orig_bases__ for documentation - - #: List of candidate completions - completions: Sequence[SimpleCompletion] | Iterator[SimpleCompletion] - - -class _JediMatcherResult(_MatcherResultBase): - """Matching result returned by Jedi (will be processed differently)""" - - #: list of candidate completions - completions: Iterator[_JediCompletionLike] - - -AnyMatcherCompletion = Union[_JediCompletionLike, SimpleCompletion] -AnyCompletion = TypeVar("AnyCompletion", AnyMatcherCompletion, Completion) - - -@dataclass -class CompletionContext: - """Completion context provided as an argument to matchers in the Matcher API v2.""" - - # rationale: many legacy matchers relied on completer state (`self.text_until_cursor`) - # which was not explicitly visible as an argument of the matcher, making any refactor - # prone to errors; by explicitly passing `cursor_position` we can decouple the matchers - # from the completer, and make substituting them in sub-classes easier. - - #: Relevant fragment of code directly preceding the cursor. - #: The extraction of token is implemented via splitter heuristic - #: (following readline behaviour for legacy reasons), which is user configurable - #: (by switching the greedy mode). - token: str - - #: The full available content of the editor or buffer - full_text: str - - #: Cursor position in the line (the same for ``full_text`` and ``text``). - cursor_position: int - - #: Cursor line in ``full_text``. - cursor_line: int - - #: The maximum number of completions that will be used downstream. - #: Matchers can use this information to abort early. - #: The built-in Jedi matcher is currently excepted from this limit. - # If not given, return all possible completions. - limit: Optional[int] - - @cached_property - def text_until_cursor(self) -> str: - return self.line_with_cursor[: self.cursor_position] - - @cached_property - def line_with_cursor(self) -> str: - return self.full_text.split("\n")[self.cursor_line] - - -#: Matcher results for API v2. -MatcherResult = Union[SimpleMatcherResult, _JediMatcherResult] - - -class _MatcherAPIv1Base(Protocol): - def __call__(self, text: str) -> List[str]: - """Call signature.""" - ... - - #: Used to construct the default matcher identifier - __qualname__: str - - -class _MatcherAPIv1Total(_MatcherAPIv1Base, Protocol): - #: API version - matcher_api_version: Optional[Literal[1]] - - def __call__(self, text: str) -> List[str]: - """Call signature.""" - ... - - -#: Protocol describing Matcher API v1. -MatcherAPIv1: TypeAlias = Union[_MatcherAPIv1Base, _MatcherAPIv1Total] - - -class MatcherAPIv2(Protocol): - """Protocol describing Matcher API v2.""" - - #: API version - matcher_api_version: Literal[2] = 2 - - def __call__(self, context: CompletionContext) -> MatcherResult: - """Call signature.""" - ... - - #: Used to construct the default matcher identifier - __qualname__: str - - -Matcher: TypeAlias = Union[MatcherAPIv1, MatcherAPIv2] - - -def _is_matcher_v1(matcher: Matcher) -> TypeGuard[MatcherAPIv1]: - api_version = _get_matcher_api_version(matcher) - return api_version == 1 - - -def _is_matcher_v2(matcher: Matcher) -> TypeGuard[MatcherAPIv2]: - api_version = _get_matcher_api_version(matcher) - return api_version == 2 - - -def _is_sizable(value: Any) -> TypeGuard[Sized]: - """Determines whether objects is sizable""" - return hasattr(value, "__len__") - - -def _is_iterator(value: Any) -> TypeGuard[Iterator]: - """Determines whether objects is sizable""" - return hasattr(value, "__next__") - - -def has_any_completions(result: MatcherResult) -> bool: - """Check if any result includes any completions.""" - completions = result["completions"] - if _is_sizable(completions): - return len(completions) != 0 - if _is_iterator(completions): - try: - old_iterator = completions - first = next(old_iterator) - result["completions"] = cast( - Iterator[SimpleCompletion], - itertools.chain([first], old_iterator), - ) - return True - except StopIteration: - return False - raise ValueError( - "Completions returned by matcher need to be an Iterator or a Sizable" - ) - - -def completion_matcher( - *, - priority: Optional[float] = None, - identifier: Optional[str] = None, - api_version: int = 1, -) -> Callable[[Matcher], Matcher]: - """Adds attributes describing the matcher. - - Parameters - ---------- - priority : Optional[float] - The priority of the matcher, determines the order of execution of matchers. - Higher priority means that the matcher will be executed first. Defaults to 0. - identifier : Optional[str] - identifier of the matcher allowing users to modify the behaviour via traitlets, - and also used to for debugging (will be passed as ``origin`` with the completions). - - Defaults to matcher function's ``__qualname__`` (for example, - ``IPCompleter.file_matcher`` for the built-in matched defined - as a ``file_matcher`` method of the ``IPCompleter`` class). - api_version: Optional[int] - version of the Matcher API used by this matcher. - Currently supported values are 1 and 2. - Defaults to 1. - """ - - def wrapper(func: Matcher): - func.matcher_priority = priority or 0 # type: ignore - func.matcher_identifier = identifier or func.__qualname__ # type: ignore - func.matcher_api_version = api_version # type: ignore - if TYPE_CHECKING: - if api_version == 1: - func = cast(MatcherAPIv1, func) - elif api_version == 2: - func = cast(MatcherAPIv2, func) - return func - - return wrapper - - -def _get_matcher_priority(matcher: Matcher): - return getattr(matcher, "matcher_priority", 0) - - -def _get_matcher_id(matcher: Matcher): - return getattr(matcher, "matcher_identifier", matcher.__qualname__) - - -def _get_matcher_api_version(matcher): - return getattr(matcher, "matcher_api_version", 1) - - -context_matcher = partial(completion_matcher, api_version=2) - - -_IC = Iterable[Completion] - - -def _deduplicate_completions(text: str, completions: _IC)-> _IC: - """ - Deduplicate a set of completions. - - .. warning:: - - Unstable - - This function is unstable, API may change without warning. - - Parameters - ---------- - text : str - text that should be completed. - completions : Iterator[Completion] - iterator over the completions to deduplicate - - Yields - ------ - `Completions` objects - Completions coming from multiple sources, may be different but end up having - the same effect when applied to ``text``. If this is the case, this will - consider completions as equal and only emit the first encountered. - Not folded in `completions()` yet for debugging purpose, and to detect when - the IPython completer does return things that Jedi does not, but should be - at some point. - """ - completions = list(completions) - if not completions: - return - - new_start = min(c.start for c in completions) - new_end = max(c.end for c in completions) - - seen = set() - for c in completions: - new_text = text[new_start:c.start] + c.text + text[c.end:new_end] - if new_text not in seen: - yield c - seen.add(new_text) - - -def rectify_completions(text: str, completions: _IC, *, _debug: bool = False) -> _IC: - """ - Rectify a set of completions to all have the same ``start`` and ``end`` - - .. warning:: - - Unstable - - This function is unstable, API may change without warning. - It will also raise unless use in proper context manager. - - Parameters - ---------- - text : str - text that should be completed. - completions : Iterator[Completion] - iterator over the completions to rectify - _debug : bool - Log failed completion - - Notes - ----- - :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though - the Jupyter Protocol requires them to behave like so. This will readjust - the completion to have the same ``start`` and ``end`` by padding both - extremities with surrounding text. - - During stabilisation should support a ``_debug`` option to log which - completion are return by the IPython completer and not found in Jedi in - order to make upstream bug report. - """ - warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). " - "It may change without warnings. " - "Use in corresponding context manager.", - category=ProvisionalCompleterWarning, stacklevel=2) - - completions = list(completions) - if not completions: - return - starts = (c.start for c in completions) - ends = (c.end for c in completions) - - new_start = min(starts) - new_end = max(ends) - - seen_jedi = set() - seen_python_matches = set() - for c in completions: - new_text = text[new_start:c.start] + c.text + text[c.end:new_end] - if c._origin == 'jedi': - seen_jedi.add(new_text) - elif c._origin == "IPCompleter.python_matcher": - seen_python_matches.add(new_text) - yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature) - diff = seen_python_matches.difference(seen_jedi) - if diff and _debug: - print('IPython.python matches have extras:', diff) - - -if sys.platform == 'win32': - DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?' -else: - DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' - -GREEDY_DELIMS = ' =\r\n' - - -class CompletionSplitter(object): - """An object to split an input line in a manner similar to readline. - - By having our own implementation, we can expose readline-like completion in - a uniform manner to all frontends. This object only needs to be given the - line of text to be split and the cursor position on said line, and it - returns the 'word' to be completed on at the cursor after splitting the - entire line. - - What characters are used as splitting delimiters can be controlled by - setting the ``delims`` attribute (this is a property that internally - automatically builds the necessary regular expression)""" - - # Private interface - - # A string of delimiter characters. The default value makes sense for - # IPython's most typical usage patterns. - _delims = DELIMS - - # The expression (a normal string) to be compiled into a regular expression - # for actual splitting. We store it as an attribute mostly for ease of - # debugging, since this type of code can be so tricky to debug. - _delim_expr = None - - # The regular expression that does the actual splitting - _delim_re = None - - def __init__(self, delims=None): - delims = CompletionSplitter._delims if delims is None else delims - self.delims = delims - - @property - def delims(self): - """Return the string of delimiter characters.""" - return self._delims - - @delims.setter - def delims(self, delims): - """Set the delimiters for line splitting.""" - expr = '[' + ''.join('\\'+ c for c in delims) + ']' - self._delim_re = re.compile(expr) - self._delims = delims - self._delim_expr = expr - - def split_line(self, line, cursor_pos=None): - """Split a line of text with a cursor at the given position. - """ - cut_line = line if cursor_pos is None else line[:cursor_pos] - return self._delim_re.split(cut_line)[-1] - - - -class Completer(Configurable): - - greedy = Bool( - False, - help="""Activate greedy completion. - - .. deprecated:: 8.8 - Use :std:configtrait:`Completer.evaluation` and :std:configtrait:`Completer.auto_close_dict_keys` instead. - - When enabled in IPython 8.8 or newer, changes configuration as follows: - - - ``Completer.evaluation = 'unsafe'`` - - ``Completer.auto_close_dict_keys = True`` - """, - ).tag(config=True) - - evaluation = Enum( - ("forbidden", "minimal", "limited", "unsafe", "dangerous"), - default_value="limited", - help="""Policy for code evaluation under completion. - - Successive options allow to enable more eager evaluation for better - completion suggestions, including for nested dictionaries, nested lists, - or even results of function calls. - Setting ``unsafe`` or higher can lead to evaluation of arbitrary user - code on :kbd:`Tab` with potentially unwanted or dangerous side effects. - - Allowed values are: - - - ``forbidden``: no evaluation of code is permitted, - - ``minimal``: evaluation of literals and access to built-in namespace; - no item/attribute evaluationm no access to locals/globals, - no evaluation of any operations or comparisons. - - ``limited``: access to all namespaces, evaluation of hard-coded methods - (for example: :any:`dict.keys`, :any:`object.__getattr__`, - :any:`object.__getitem__`) on allow-listed objects (for example: - :any:`dict`, :any:`list`, :any:`tuple`, ``pandas.Series``), - - ``unsafe``: evaluation of all methods and function calls but not of - syntax with side-effects like `del x`, - - ``dangerous``: completely arbitrary evaluation. - """, - ).tag(config=True) - - use_jedi = Bool(default_value=JEDI_INSTALLED, - help="Experimental: Use Jedi to generate autocompletions. " - "Default to True if jedi is installed.").tag(config=True) - - jedi_compute_type_timeout = Int(default_value=400, - help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types. - Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt - performance by preventing jedi to build its cache. - """).tag(config=True) - - debug = Bool(default_value=False, - help='Enable debug for the Completer. Mostly print extra ' - 'information for experimental jedi integration.')\ - .tag(config=True) - - backslash_combining_completions = Bool(True, - help="Enable unicode completions, e.g. \\alpha . " - "Includes completion of latex commands, unicode names, and expanding " - "unicode characters back to latex commands.").tag(config=True) - - auto_close_dict_keys = Bool( - False, - help=""" - Enable auto-closing dictionary keys. - - When enabled string keys will be suffixed with a final quote - (matching the opening quote), tuple keys will also receive a - separating comma if needed, and keys which are final will - receive a closing bracket (``]``). - """, - ).tag(config=True) - - def __init__(self, namespace=None, global_namespace=None, **kwargs): - """Create a new completer for the command line. - - Completer(namespace=ns, global_namespace=ns2) -> completer instance. - - If unspecified, the default namespace where completions are performed - is __main__ (technically, __main__.__dict__). Namespaces should be - given as dictionaries. - - An optional second namespace can be given. This allows the completer - to handle cases where both the local and global scopes need to be - distinguished. - """ - - # Don't bind to namespace quite yet, but flag whether the user wants a - # specific namespace or to use __main__.__dict__. This will allow us - # to bind to __main__.__dict__ at completion time, not now. - if namespace is None: - self.use_main_ns = True - else: - self.use_main_ns = False - self.namespace = namespace - - # The global namespace, if given, can be bound directly - if global_namespace is None: - self.global_namespace = {} - else: - self.global_namespace = global_namespace - - self.custom_matchers = [] - - super(Completer, self).__init__(**kwargs) - - def complete(self, text, state): - """Return the next possible completion for 'text'. - - This is called successively with state == 0, 1, 2, ... until it - returns None. The completion should begin with 'text'. - - """ - if self.use_main_ns: - self.namespace = __main__.__dict__ - - if state == 0: - if "." in text: - self.matches = self.attr_matches(text) - else: - self.matches = self.global_matches(text) - try: - return self.matches[state] - except IndexError: - return None - - def global_matches(self, text): - """Compute matches when text is a simple name. - - Return a list of all keywords, built-in functions and names currently - defined in self.namespace or self.global_namespace that match. - - """ - matches = [] - match_append = matches.append - n = len(text) - for lst in [ - keyword.kwlist, - builtin_mod.__dict__.keys(), - list(self.namespace.keys()), - list(self.global_namespace.keys()), - ]: - for word in lst: - if word[:n] == text and word != "__builtins__": - match_append(word) - - snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z") - for lst in [list(self.namespace.keys()), list(self.global_namespace.keys())]: - shortened = { - "_".join([sub[0] for sub in word.split("_")]): word - for word in lst - if snake_case_re.match(word) - } - for word in shortened.keys(): - if word[:n] == text and word != "__builtins__": - match_append(shortened[word]) - return matches - - def attr_matches(self, text): - """Compute matches when text contains a dot. - - Assuming the text is of the form NAME.NAME....[NAME], and is - evaluatable in self.namespace or self.global_namespace, it will be - evaluated and its attributes (as revealed by dir()) are used as - possible completions. (For class instances, class members are - also considered.) - - WARNING: this can still invoke arbitrary C code, if an object - with a __getattr__ hook is evaluated. - - """ - return self._attr_matches(text)[0] - - # we simple attribute matching with normal identifiers. - _ATTR_MATCH_RE = re.compile(r"(.+)\.(\w*)$") - - def _attr_matches( - self, text: str, include_prefix: bool = True - ) -> Tuple[Sequence[str], str]: - m2 = self._ATTR_MATCH_RE.match(self.line_buffer) - if not m2: - return [], "" - expr, attr = m2.group(1, 2) - - obj = self._evaluate_expr(expr) - - if obj is not_found: - return [], "" - - if self.limit_to__all__ and hasattr(obj, '__all__'): - words = get__all__entries(obj) - else: - words = dir2(obj) - - try: - words = generics.complete_object(obj, words) - except TryNext: - pass - except AssertionError: - raise - except Exception: - # Silence errors from completion function - pass - # Build match list to return - n = len(attr) - - # Note: ideally we would just return words here and the prefix - # reconciliator would know that we intend to append to rather than - # replace the input text; this requires refactoring to return range - # which ought to be replaced (as does jedi). - if include_prefix: - tokens = _parse_tokens(expr) - rev_tokens = reversed(tokens) - skip_over = {tokenize.ENDMARKER, tokenize.NEWLINE} - name_turn = True - - parts = [] - for token in rev_tokens: - if token.type in skip_over: - continue - if token.type == tokenize.NAME and name_turn: - parts.append(token.string) - name_turn = False - elif ( - token.type == tokenize.OP and token.string == "." and not name_turn - ): - parts.append(token.string) - name_turn = True - else: - # short-circuit if not empty nor name token - break - - prefix_after_space = "".join(reversed(parts)) - else: - prefix_after_space = "" - - return ( - ["%s.%s" % (prefix_after_space, w) for w in words if w[:n] == attr], - "." + attr, - ) - - def _trim_expr(self, code: str) -> str: - """ - Trim the code until it is a valid expression and not a tuple; - - return the trimmed expression for guarded_eval. - """ - while code: - code = code[1:] - try: - res = ast.parse(code) - except SyntaxError: - continue - - assert res is not None - if len(res.body) != 1: - continue - expr = res.body[0].value - if isinstance(expr, ast.Tuple) and not code[-1] == ")": - # we skip implicit tuple, like when trimming `fun(a,b` - # as `a,b` would be a tuple, and we actually expect to get only `b` - continue - return code - return "" - - def _evaluate_expr(self, expr): - obj = not_found - done = False - while not done and expr: - try: - obj = guarded_eval( - expr, - EvaluationContext( - globals=self.global_namespace, - locals=self.namespace, - evaluation=self.evaluation, - ), - ) - done = True - except Exception as e: - if self.debug: - print("Evaluation exception", e) - # trim the expression to remove any invalid prefix - # e.g. user starts `(d[`, so we get `expr = '(d'`, - # where parenthesis is not closed. - # TODO: make this faster by reusing parts of the computation? - expr = self._trim_expr(expr) - return obj - -def get__all__entries(obj): - """returns the strings in the __all__ attribute""" - try: - words = getattr(obj, '__all__') - except Exception: - return [] - - return [w for w in words if isinstance(w, str)] - - -class _DictKeyState(enum.Flag): - """Represent state of the key match in context of other possible matches. - - - given `d1 = {'a': 1}` completion on `d1['` will yield `{'a': END_OF_ITEM}` as there is no tuple. - - given `d2 = {('a', 'b'): 1}`: `d2['a', '` will yield `{'b': END_OF_TUPLE}` as there is no tuple members to add beyond `'b'`. - - given `d3 = {('a', 'b'): 1}`: `d3['` will yield `{'a': IN_TUPLE}` as `'a'` can be added. - - given `d4 = {'a': 1, ('a', 'b'): 2}`: `d4['` will yield `{'a': END_OF_ITEM & END_OF_TUPLE}` - """ - - BASELINE = 0 - END_OF_ITEM = enum.auto() - END_OF_TUPLE = enum.auto() - IN_TUPLE = enum.auto() - - -def _parse_tokens(c): - """Parse tokens even if there is an error.""" - tokens = [] - token_generator = tokenize.generate_tokens(iter(c.splitlines()).__next__) - while True: - try: - tokens.append(next(token_generator)) - except tokenize.TokenError: - return tokens - except StopIteration: - return tokens - - -def _match_number_in_dict_key_prefix(prefix: str) -> Union[str, None]: - """Match any valid Python numeric literal in a prefix of dictionary keys. - - References: - - https://docs.python.org/3/reference/lexical_analysis.html#numeric-literals - - https://docs.python.org/3/library/tokenize.html - """ - if prefix[-1].isspace(): - # if user typed a space we do not have anything to complete - # even if there was a valid number token before - return None - tokens = _parse_tokens(prefix) - rev_tokens = reversed(tokens) - skip_over = {tokenize.ENDMARKER, tokenize.NEWLINE} - number = None - for token in rev_tokens: - if token.type in skip_over: - continue - if number is None: - if token.type == tokenize.NUMBER: - number = token.string - continue - else: - # we did not match a number - return None - if token.type == tokenize.OP: - if token.string == ",": - break - if token.string in {"+", "-"}: - number = token.string + number - else: - return None - return number - - -_INT_FORMATS = { - "0b": bin, - "0o": oct, - "0x": hex, -} - - -def match_dict_keys( - keys: List[Union[str, bytes, Tuple[Union[str, bytes], ...]]], - prefix: str, - delims: str, - extra_prefix: Optional[Tuple[Union[str, bytes], ...]] = None, -) -> Tuple[str, int, Dict[str, _DictKeyState]]: - """Used by dict_key_matches, matching the prefix to a list of keys - - Parameters - ---------- - keys - list of keys in dictionary currently being completed. - prefix - Part of the text already typed by the user. E.g. `mydict[b'fo` - delims - String of delimiters to consider when finding the current key. - extra_prefix : optional - Part of the text already typed in multi-key index cases. E.g. for - `mydict['foo', "bar", 'b`, this would be `('foo', 'bar')`. - - Returns - ------- - A tuple of three elements: ``quote``, ``token_start``, ``matched``, with - ``quote`` being the quote that need to be used to close current string. - ``token_start`` the position where the replacement should start occurring, - ``matches`` a dictionary of replacement/completion keys on keys and values - indicating whether the state. - """ - prefix_tuple = extra_prefix if extra_prefix else () - - prefix_tuple_size = sum( - [ - # for pandas, do not count slices as taking space - not isinstance(k, slice) - for k in prefix_tuple - ] - ) - text_serializable_types = (str, bytes, int, float, slice) - - def filter_prefix_tuple(key): - # Reject too short keys - if len(key) <= prefix_tuple_size: - return False - # Reject keys which cannot be serialised to text - for k in key: - if not isinstance(k, text_serializable_types): - return False - # Reject keys that do not match the prefix - for k, pt in zip(key, prefix_tuple): - if k != pt and not isinstance(pt, slice): - return False - # All checks passed! - return True - - filtered_key_is_final: Dict[Union[str, bytes, int, float], _DictKeyState] = ( - defaultdict(lambda: _DictKeyState.BASELINE) - ) - - for k in keys: - # If at least one of the matches is not final, mark as undetermined. - # This can happen with `d = {111: 'b', (111, 222): 'a'}` where - # `111` appears final on first match but is not final on the second. - - if isinstance(k, tuple): - if filter_prefix_tuple(k): - key_fragment = k[prefix_tuple_size] - filtered_key_is_final[key_fragment] |= ( - _DictKeyState.END_OF_TUPLE - if len(k) == prefix_tuple_size + 1 - else _DictKeyState.IN_TUPLE - ) - elif prefix_tuple_size > 0: - # we are completing a tuple but this key is not a tuple, - # so we should ignore it - pass - else: - if isinstance(k, text_serializable_types): - filtered_key_is_final[k] |= _DictKeyState.END_OF_ITEM - - filtered_keys = filtered_key_is_final.keys() - - if not prefix: - return "", 0, {repr(k): v for k, v in filtered_key_is_final.items()} - - quote_match = re.search("(?:\"|')", prefix) - is_user_prefix_numeric = False - - if quote_match: - quote = quote_match.group() - valid_prefix = prefix + quote - try: - prefix_str = literal_eval(valid_prefix) - except Exception: - return "", 0, {} - else: - # If it does not look like a string, let's assume - # we are dealing with a number or variable. - number_match = _match_number_in_dict_key_prefix(prefix) - - # We do not want the key matcher to suggest variable names so we yield: - if number_match is None: - # The alternative would be to assume that user forgort the quote - # and if the substring matches, suggest adding it at the start. - return "", 0, {} - - prefix_str = number_match - is_user_prefix_numeric = True - quote = "" - - pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$' - token_match = re.search(pattern, prefix, re.UNICODE) - assert token_match is not None # silence mypy - token_start = token_match.start() - token_prefix = token_match.group() - - matched: Dict[str, _DictKeyState] = {} - - str_key: Union[str, bytes] - - for key in filtered_keys: - if isinstance(key, (int, float)): - # User typed a number but this key is not a number. - if not is_user_prefix_numeric: - continue - str_key = str(key) - if isinstance(key, int): - int_base = prefix_str[:2].lower() - # if user typed integer using binary/oct/hex notation: - if int_base in _INT_FORMATS: - int_format = _INT_FORMATS[int_base] - str_key = int_format(key) - else: - # User typed a string but this key is a number. - if is_user_prefix_numeric: - continue - str_key = key - try: - if not str_key.startswith(prefix_str): - continue - except (AttributeError, TypeError, UnicodeError): - # Python 3+ TypeError on b'a'.startswith('a') or vice-versa - continue - - # reformat remainder of key to begin with prefix - rem = str_key[len(prefix_str) :] - # force repr wrapped in ' - rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"') - rem_repr = rem_repr[1 + rem_repr.index("'"):-2] - if quote == '"': - # The entered prefix is quoted with ", - # but the match is quoted with '. - # A contained " hence needs escaping for comparison: - rem_repr = rem_repr.replace('"', '\\"') - - # then reinsert prefix from start of token - match = "%s%s" % (token_prefix, rem_repr) - - matched[match] = filtered_key_is_final[key] - return quote, token_start, matched - - -def cursor_to_position(text:str, line:int, column:int)->int: - """ - Convert the (line,column) position of the cursor in text to an offset in a - string. - - Parameters - ---------- - text : str - The text in which to calculate the cursor offset - line : int - Line of the cursor; 0-indexed - column : int - Column of the cursor 0-indexed - - Returns - ------- - Position of the cursor in ``text``, 0-indexed. - - See Also - -------- - position_to_cursor : reciprocal of this function - - """ - lines = text.split('\n') - assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines))) - - return sum(len(line) + 1 for line in lines[:line]) + column - -def position_to_cursor(text:str, offset:int)->Tuple[int, int]: - """ - Convert the position of the cursor in text (0 indexed) to a line - number(0-indexed) and a column number (0-indexed) pair - - Position should be a valid position in ``text``. - - Parameters - ---------- - text : str - The text in which to calculate the cursor offset - offset : int - Position of the cursor in ``text``, 0-indexed. - - Returns - ------- - (line, column) : (int, int) - Line of the cursor; 0-indexed, column of the cursor 0-indexed - - See Also - -------- - cursor_to_position : reciprocal of this function - - """ - - assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text)) - - before = text[:offset] - blines = before.split('\n') # ! splitnes trim trailing \n - line = before.count('\n') - col = len(blines[-1]) - return line, col - - -def _safe_isinstance(obj, module, class_name, *attrs): - """Checks if obj is an instance of module.class_name if loaded - """ - if module in sys.modules: - m = sys.modules[module] - for attr in [class_name, *attrs]: - m = getattr(m, attr) - return isinstance(obj, m) - - -@context_matcher() -def back_unicode_name_matcher(context: CompletionContext): - """Match Unicode characters back to Unicode name - - Same as :any:`back_unicode_name_matches`, but adopted to new Matcher API. - """ - fragment, matches = back_unicode_name_matches(context.text_until_cursor) - return _convert_matcher_v1_result_to_v2( - matches, type="unicode", fragment=fragment, suppress_if_matches=True - ) - - -def back_unicode_name_matches(text: str) -> Tuple[str, Sequence[str]]: - """Match Unicode characters back to Unicode name - - This does ``☃`` -> ``\\snowman`` - - Note that snowman is not a valid python3 combining character but will be expanded. - Though it will not recombine back to the snowman character by the completion machinery. - - This will not either back-complete standard sequences like \\n, \\b ... - - .. deprecated:: 8.6 - You can use :meth:`back_unicode_name_matcher` instead. - - Returns - ======= - - Return a tuple with two elements: - - - The Unicode character that was matched (preceded with a backslash), or - empty string, - - a sequence (of 1), name for the match Unicode character, preceded by - backslash, or empty if no match. - """ - if len(text)<2: - return '', () - maybe_slash = text[-2] - if maybe_slash != '\\': - return '', () - - char = text[-1] - # no expand on quote for completion in strings. - # nor backcomplete standard ascii keys - if char in string.ascii_letters or char in ('"',"'"): - return '', () - try : - unic = unicodedata.name(char) - return '\\'+char,('\\'+unic,) - except KeyError: - pass - return '', () - - -@context_matcher() -def back_latex_name_matcher(context: CompletionContext): - """Match latex characters back to unicode name - - Same as :any:`back_latex_name_matches`, but adopted to new Matcher API. - """ - fragment, matches = back_latex_name_matches(context.text_until_cursor) - return _convert_matcher_v1_result_to_v2( - matches, type="latex", fragment=fragment, suppress_if_matches=True - ) - - -def back_latex_name_matches(text: str) -> Tuple[str, Sequence[str]]: - """Match latex characters back to unicode name - - This does ``\\ℵ`` -> ``\\aleph`` - - .. deprecated:: 8.6 - You can use :meth:`back_latex_name_matcher` instead. - """ - if len(text)<2: - return '', () - maybe_slash = text[-2] - if maybe_slash != '\\': - return '', () - - - char = text[-1] - # no expand on quote for completion in strings. - # nor backcomplete standard ascii keys - if char in string.ascii_letters or char in ('"',"'"): - return '', () - try : - latex = reverse_latex_symbol[char] - # '\\' replace the \ as well - return '\\'+char,[latex] - except KeyError: - pass - return '', () - - -def _formatparamchildren(parameter) -> str: - """ - Get parameter name and value from Jedi Private API - - Jedi does not expose a simple way to get `param=value` from its API. - - Parameters - ---------- - parameter - Jedi's function `Param` - - Returns - ------- - A string like 'a', 'b=1', '*args', '**kwargs' - - """ - description = parameter.description - if not description.startswith('param '): - raise ValueError('Jedi function parameter description have change format.' - 'Expected "param ...", found %r".' % description) - return description[6:] - -def _make_signature(completion)-> str: - """ - Make the signature from a jedi completion - - Parameters - ---------- - completion : jedi.Completion - object does not complete a function type - - Returns - ------- - a string consisting of the function signature, with the parenthesis but - without the function name. example: - `(a, *args, b=1, **kwargs)` - - """ - - # it looks like this might work on jedi 0.17 - if hasattr(completion, 'get_signatures'): - signatures = completion.get_signatures() - if not signatures: - return '(?)' - - c0 = completion.get_signatures()[0] - return '('+c0.to_string().split('(', maxsplit=1)[1] - - return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures() - for p in signature.defined_names()) if f]) - - -_CompleteResult = Dict[str, MatcherResult] - - -DICT_MATCHER_REGEX = re.compile( - r"""(?x) -( # match dict-referring - or any get item object - expression - .+ -) -\[ # open bracket -\s* # and optional whitespace -# Capture any number of serializable objects (e.g. "a", "b", 'c') -# and slices -((?:(?: - (?: # closed string - [uUbB]? # string prefix (r not handled) - (?: - '(?:[^']|(? SimpleMatcherResult: - """Utility to help with transition""" - result = { - "completions": [SimpleCompletion(text=match, type=type) for match in matches], - "suppress": (True if matches else False) if suppress_if_matches else False, - } - if fragment is not None: - result["matched_fragment"] = fragment - return cast(SimpleMatcherResult, result) - - -class IPCompleter(Completer): - """Extension of the completer class with IPython-specific features""" - - @observe('greedy') - def _greedy_changed(self, change): - """update the splitter and readline delims when greedy is changed""" - if change["new"]: - self.evaluation = "unsafe" - self.auto_close_dict_keys = True - self.splitter.delims = GREEDY_DELIMS - else: - self.evaluation = "limited" - self.auto_close_dict_keys = False - self.splitter.delims = DELIMS - - dict_keys_only = Bool( - False, - help=""" - Whether to show dict key matches only. - - (disables all matchers except for `IPCompleter.dict_key_matcher`). - """, - ) - - suppress_competing_matchers = UnionTrait( - [Bool(allow_none=True), DictTrait(Bool(None, allow_none=True))], - default_value=None, - help=""" - Whether to suppress completions from other *Matchers*. - - When set to ``None`` (default) the matchers will attempt to auto-detect - whether suppression of other matchers is desirable. For example, at - the beginning of a line followed by `%` we expect a magic completion - to be the only applicable option, and after ``my_dict['`` we usually - expect a completion with an existing dictionary key. - - If you want to disable this heuristic and see completions from all matchers, - set ``IPCompleter.suppress_competing_matchers = False``. - To disable the heuristic for specific matchers provide a dictionary mapping: - ``IPCompleter.suppress_competing_matchers = {'IPCompleter.dict_key_matcher': False}``. - - Set ``IPCompleter.suppress_competing_matchers = True`` to limit - completions to the set of matchers with the highest priority; - this is equivalent to ``IPCompleter.merge_completions`` and - can be beneficial for performance, but will sometimes omit relevant - candidates from matchers further down the priority list. - """, - ).tag(config=True) - - merge_completions = Bool( - True, - help="""Whether to merge completion results into a single list - - If False, only the completion results from the first non-empty - completer will be returned. - - As of version 8.6.0, setting the value to ``False`` is an alias for: - ``IPCompleter.suppress_competing_matchers = True.``. - """, - ).tag(config=True) - - disable_matchers = ListTrait( - Unicode(), - help="""List of matchers to disable. - - The list should contain matcher identifiers (see :any:`completion_matcher`). - """, - ).tag(config=True) - - omit__names = Enum( - (0, 1, 2), - default_value=2, - help="""Instruct the completer to omit private method names - - Specifically, when completing on ``object.``. - - When 2 [default]: all names that start with '_' will be excluded. - - When 1: all 'magic' names (``__foo__``) will be excluded. - - When 0: nothing will be excluded. - """ - ).tag(config=True) - limit_to__all__ = Bool(False, - help=""" - DEPRECATED as of version 5.0. - - Instruct the completer to use __all__ for the completion - - Specifically, when completing on ``object.``. - - When True: only those names in obj.__all__ will be included. - - When False [default]: the __all__ attribute is ignored - """, - ).tag(config=True) - - profile_completions = Bool( - default_value=False, - help="If True, emit profiling data for completion subsystem using cProfile." - ).tag(config=True) - - profiler_output_dir = Unicode( - default_value=".completion_profiles", - help="Template for path at which to output profile data for completions." - ).tag(config=True) - - @observe('limit_to__all__') - def _limit_to_all_changed(self, change): - warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration ' - 'value has been deprecated since IPython 5.0, will be made to have ' - 'no effects and then removed in future version of IPython.', - UserWarning) - - def __init__( - self, shell=None, namespace=None, global_namespace=None, config=None, **kwargs - ): - """IPCompleter() -> completer - - Return a completer object. - - Parameters - ---------- - shell - a pointer to the ipython shell itself. This is needed - because this completer knows about magic functions, and those can - only be accessed via the ipython instance. - namespace : dict, optional - an optional dict where completions are performed. - global_namespace : dict, optional - secondary optional dict for completions, to - handle cases (such as IPython embedded inside functions) where - both Python scopes are visible. - config : Config - traitlet's config object - **kwargs - passed to super class unmodified. - """ - - self.magic_escape = ESC_MAGIC - self.splitter = CompletionSplitter() - - # _greedy_changed() depends on splitter and readline being defined: - super().__init__( - namespace=namespace, - global_namespace=global_namespace, - config=config, - **kwargs, - ) - - # List where completion matches will be stored - self.matches = [] - self.shell = shell - # Regexp to split filenames with spaces in them - self.space_name_re = re.compile(r'([^\\] )') - # Hold a local ref. to glob.glob for speed - self.glob = glob.glob - - # Determine if we are running on 'dumb' terminals, like (X)Emacs - # buffers, to avoid completion problems. - term = os.environ.get('TERM','xterm') - self.dumb_terminal = term in ['dumb','emacs'] - - # Special handling of backslashes needed in win32 platforms - if sys.platform == "win32": - self.clean_glob = self._clean_glob_win32 - else: - self.clean_glob = self._clean_glob - - #regexp to parse docstring for function signature - self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*') - self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)') - #use this if positional argument name is also needed - #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)') - - self.magic_arg_matchers = [ - self.magic_config_matcher, - self.magic_color_matcher, - ] - - # This is set externally by InteractiveShell - self.custom_completers = None - - # This is a list of names of unicode characters that can be completed - # into their corresponding unicode value. The list is large, so we - # lazily initialize it on first use. Consuming code should access this - # attribute through the `@unicode_names` property. - self._unicode_names = None - - self._backslash_combining_matchers = [ - self.latex_name_matcher, - self.unicode_name_matcher, - back_latex_name_matcher, - back_unicode_name_matcher, - self.fwd_unicode_matcher, - ] - - if not self.backslash_combining_completions: - for matcher in self._backslash_combining_matchers: - self.disable_matchers.append(_get_matcher_id(matcher)) - - if not self.merge_completions: - self.suppress_competing_matchers = True - - @property - def matchers(self) -> List[Matcher]: - """All active matcher routines for completion""" - if self.dict_keys_only: - return [self.dict_key_matcher] - - if self.use_jedi: - return [ - *self.custom_matchers, - *self._backslash_combining_matchers, - *self.magic_arg_matchers, - self.custom_completer_matcher, - self.magic_matcher, - self._jedi_matcher, - self.dict_key_matcher, - self.file_matcher, - ] - else: - return [ - *self.custom_matchers, - *self._backslash_combining_matchers, - *self.magic_arg_matchers, - self.custom_completer_matcher, - self.dict_key_matcher, - self.magic_matcher, - self.python_matcher, - self.file_matcher, - self.python_func_kw_matcher, - ] - - def all_completions(self, text:str) -> List[str]: - """ - Wrapper around the completion methods for the benefit of emacs. - """ - prefix = text.rpartition('.')[0] - with provisionalcompleter(): - return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text - for c in self.completions(text, len(text))] - - return self.complete(text)[1] - - def _clean_glob(self, text:str): - return self.glob("%s*" % text) - - def _clean_glob_win32(self, text:str): - return [f.replace("\\","/") - for f in self.glob("%s*" % text)] - - @context_matcher() - def file_matcher(self, context: CompletionContext) -> SimpleMatcherResult: - """Same as :any:`file_matches`, but adopted to new Matcher API.""" - matches = self.file_matches(context.token) - # TODO: add a heuristic for suppressing (e.g. if it has OS-specific delimiter, - # starts with `/home/`, `C:\`, etc) - return _convert_matcher_v1_result_to_v2(matches, type="path") - - def file_matches(self, text: str) -> List[str]: - """Match filenames, expanding ~USER type strings. - - Most of the seemingly convoluted logic in this completer is an - attempt to handle filenames with spaces in them. And yet it's not - quite perfect, because Python's readline doesn't expose all of the - GNU readline details needed for this to be done correctly. - - For a filename with a space in it, the printed completions will be - only the parts after what's already been typed (instead of the - full completions, as is normally done). I don't think with the - current (as of Python 2.3) Python readline it's possible to do - better. - - .. deprecated:: 8.6 - You can use :meth:`file_matcher` instead. - """ - - # chars that require escaping with backslash - i.e. chars - # that readline treats incorrectly as delimiters, but we - # don't want to treat as delimiters in filename matching - # when escaped with backslash - if text.startswith('!'): - text = text[1:] - text_prefix = u'!' - else: - text_prefix = u'' - - text_until_cursor = self.text_until_cursor - # track strings with open quotes - open_quotes = has_open_quotes(text_until_cursor) - - if '(' in text_until_cursor or '[' in text_until_cursor: - lsplit = text - else: - try: - # arg_split ~ shlex.split, but with unicode bugs fixed by us - lsplit = arg_split(text_until_cursor)[-1] - except ValueError: - # typically an unmatched ", or backslash without escaped char. - if open_quotes: - lsplit = text_until_cursor.split(open_quotes)[-1] - else: - return [] - except IndexError: - # tab pressed on empty line - lsplit = "" - - if not open_quotes and lsplit != protect_filename(lsplit): - # if protectables are found, do matching on the whole escaped name - has_protectables = True - text0,text = text,lsplit - else: - has_protectables = False - text = os.path.expanduser(text) - - if text == "": - return [text_prefix + protect_filename(f) for f in self.glob("*")] - - # Compute the matches from the filesystem - if sys.platform == 'win32': - m0 = self.clean_glob(text) - else: - m0 = self.clean_glob(text.replace('\\', '')) - - if has_protectables: - # If we had protectables, we need to revert our changes to the - # beginning of filename so that we don't double-write the part - # of the filename we have so far - len_lsplit = len(lsplit) - matches = [text_prefix + text0 + - protect_filename(f[len_lsplit:]) for f in m0] - else: - if open_quotes: - # if we have a string with an open quote, we don't need to - # protect the names beyond the quote (and we _shouldn't_, as - # it would cause bugs when the filesystem call is made). - matches = m0 if sys.platform == "win32" else\ - [protect_filename(f, open_quotes) for f in m0] - else: - matches = [text_prefix + - protect_filename(f) for f in m0] - - # Mark directories in input list by appending '/' to their names. - return [x+'/' if os.path.isdir(x) else x for x in matches] - - @context_matcher() - def magic_matcher(self, context: CompletionContext) -> SimpleMatcherResult: - """Match magics.""" - text = context.token - matches = self.magic_matches(text) - result = _convert_matcher_v1_result_to_v2(matches, type="magic") - is_magic_prefix = len(text) > 0 and text[0] == "%" - result["suppress"] = is_magic_prefix and bool(result["completions"]) - return result - - def magic_matches(self, text: str) -> List[str]: - """Match magics. - - .. deprecated:: 8.6 - You can use :meth:`magic_matcher` instead. - """ - # Get all shell magics now rather than statically, so magics loaded at - # runtime show up too. - lsm = self.shell.magics_manager.lsmagic() - line_magics = lsm['line'] - cell_magics = lsm['cell'] - pre = self.magic_escape - pre2 = pre+pre - - explicit_magic = text.startswith(pre) - - # Completion logic: - # - user gives %%: only do cell magics - # - user gives %: do both line and cell magics - # - no prefix: do both - # In other words, line magics are skipped if the user gives %% explicitly - # - # We also exclude magics that match any currently visible names: - # https://github.com/ipython/ipython/issues/4877, unless the user has - # typed a %: - # https://github.com/ipython/ipython/issues/10754 - bare_text = text.lstrip(pre) - global_matches = self.global_matches(bare_text) - if not explicit_magic: - def matches(magic): - """ - Filter magics, in particular remove magics that match - a name present in global namespace. - """ - return ( magic.startswith(bare_text) and - magic not in global_matches ) - else: - def matches(magic): - return magic.startswith(bare_text) - - comp = [ pre2+m for m in cell_magics if matches(m)] - if not text.startswith(pre2): - comp += [ pre+m for m in line_magics if matches(m)] - - return comp - - @context_matcher() - def magic_config_matcher(self, context: CompletionContext) -> SimpleMatcherResult: - """Match class names and attributes for %config magic.""" - # NOTE: uses `line_buffer` equivalent for compatibility - matches = self.magic_config_matches(context.line_with_cursor) - return _convert_matcher_v1_result_to_v2(matches, type="param") - - def magic_config_matches(self, text: str) -> List[str]: - """Match class names and attributes for %config magic. - - .. deprecated:: 8.6 - You can use :meth:`magic_config_matcher` instead. - """ - texts = text.strip().split() - - if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'): - # get all configuration classes - classes = sorted(set([ c for c in self.shell.configurables - if c.__class__.class_traits(config=True) - ]), key=lambda x: x.__class__.__name__) - classnames = [ c.__class__.__name__ for c in classes ] - - # return all classnames if config or %config is given - if len(texts) == 1: - return classnames - - # match classname - classname_texts = texts[1].split('.') - classname = classname_texts[0] - classname_matches = [ c for c in classnames - if c.startswith(classname) ] - - # return matched classes or the matched class with attributes - if texts[1].find('.') < 0: - return classname_matches - elif len(classname_matches) == 1 and \ - classname_matches[0] == classname: - cls = classes[classnames.index(classname)].__class__ - help = cls.class_get_help() - # strip leading '--' from cl-args: - help = re.sub(re.compile(r'^--', re.MULTILINE), '', help) - return [ attr.split('=')[0] - for attr in help.strip().splitlines() - if attr.startswith(texts[1]) ] - return [] - - @context_matcher() - def magic_color_matcher(self, context: CompletionContext) -> SimpleMatcherResult: - """Match color schemes for %colors magic.""" - # NOTE: uses `line_buffer` equivalent for compatibility - matches = self.magic_color_matches(context.line_with_cursor) - return _convert_matcher_v1_result_to_v2(matches, type="param") - - def magic_color_matches(self, text: str) -> List[str]: - """Match color schemes for %colors magic. - - .. deprecated:: 8.6 - You can use :meth:`magic_color_matcher` instead. - """ - texts = text.split() - if text.endswith(' '): - # .split() strips off the trailing whitespace. Add '' back - # so that: '%colors ' -> ['%colors', ''] - texts.append('') - - if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'): - prefix = texts[1] - return [ color for color in InspectColors.keys() - if color.startswith(prefix) ] - return [] - - @context_matcher(identifier="IPCompleter.jedi_matcher") - def _jedi_matcher(self, context: CompletionContext) -> _JediMatcherResult: - matches = self._jedi_matches( - cursor_column=context.cursor_position, - cursor_line=context.cursor_line, - text=context.full_text, - ) - return { - "completions": matches, - # static analysis should not suppress other matchers - "suppress": False, - } - - def _jedi_matches( - self, cursor_column: int, cursor_line: int, text: str - ) -> Iterator[_JediCompletionLike]: - """ - Return a list of :any:`jedi.api.Completion`\\s object from a ``text`` and - cursor position. - - Parameters - ---------- - cursor_column : int - column position of the cursor in ``text``, 0-indexed. - cursor_line : int - line position of the cursor in ``text``, 0-indexed - text : str - text to complete - - Notes - ----- - If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion` - object containing a string with the Jedi debug information attached. - - .. deprecated:: 8.6 - You can use :meth:`_jedi_matcher` instead. - """ - namespaces = [self.namespace] - if self.global_namespace is not None: - namespaces.append(self.global_namespace) - - completion_filter = lambda x:x - offset = cursor_to_position(text, cursor_line, cursor_column) - # filter output if we are completing for object members - if offset: - pre = text[offset-1] - if pre == '.': - if self.omit__names == 2: - completion_filter = lambda c:not c.name.startswith('_') - elif self.omit__names == 1: - completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__')) - elif self.omit__names == 0: - completion_filter = lambda x:x - else: - raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names)) - - interpreter = jedi.Interpreter(text[:offset], namespaces) - try_jedi = True - - try: - # find the first token in the current tree -- if it is a ' or " then we are in a string - completing_string = False - try: - first_child = next(c for c in interpreter._get_module().tree_node.children if hasattr(c, 'value')) - except StopIteration: - pass - else: - # note the value may be ', ", or it may also be ''' or """, or - # in some cases, """what/you/typed..., but all of these are - # strings. - completing_string = len(first_child.value) > 0 and first_child.value[0] in {"'", '"'} - - # if we are in a string jedi is likely not the right candidate for - # now. Skip it. - try_jedi = not completing_string - except Exception as e: - # many of things can go wrong, we are using private API just don't crash. - if self.debug: - print("Error detecting if completing a non-finished string :", e, '|') - - if not try_jedi: - return iter([]) - try: - return filter(completion_filter, interpreter.complete(column=cursor_column, line=cursor_line + 1)) - except Exception as e: - if self.debug: - return iter( - [ - _FakeJediCompletion( - 'Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' - % (e) - ) - ] - ) - else: - return iter([]) - - @context_matcher() - def python_matcher(self, context: CompletionContext) -> SimpleMatcherResult: - """Match attributes or global python names""" - text = context.line_with_cursor - if "." in text: - try: - matches, fragment = self._attr_matches(text, include_prefix=False) - if text.endswith(".") and self.omit__names: - if self.omit__names == 1: - # true if txt is _not_ a __ name, false otherwise: - no__name = lambda txt: re.match(r".*\.__.*?__", txt) is None - else: - # true if txt is _not_ a _ name, false otherwise: - no__name = ( - lambda txt: re.match(r"\._.*?", txt[txt.rindex(".") :]) - is None - ) - matches = filter(no__name, matches) - return _convert_matcher_v1_result_to_v2( - matches, type="attribute", fragment=fragment - ) - except NameError: - # catches . - matches = [] - return _convert_matcher_v1_result_to_v2(matches, type="attribute") - else: - matches = self.global_matches(context.token) - # TODO: maybe distinguish between functions, modules and just "variables" - return _convert_matcher_v1_result_to_v2(matches, type="variable") - - @completion_matcher(api_version=1) - def python_matches(self, text: str) -> Iterable[str]: - """Match attributes or global python names. - - .. deprecated:: 8.27 - You can use :meth:`python_matcher` instead.""" - if "." in text: - try: - matches = self.attr_matches(text) - if text.endswith('.') and self.omit__names: - if self.omit__names == 1: - # true if txt is _not_ a __ name, false otherwise: - no__name = (lambda txt: - re.match(r'.*\.__.*?__',txt) is None) - else: - # true if txt is _not_ a _ name, false otherwise: - no__name = (lambda txt: - re.match(r'\._.*?',txt[txt.rindex('.'):]) is None) - matches = filter(no__name, matches) - except NameError: - # catches . - matches = [] - else: - matches = self.global_matches(text) - return matches - - def _default_arguments_from_docstring(self, doc): - """Parse the first line of docstring for call signature. - - Docstring should be of the form 'min(iterable[, key=func])\n'. - It can also parse cython docstring of the form - 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'. - """ - if doc is None: - return [] - - #care only the firstline - line = doc.lstrip().splitlines()[0] - - #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*') - #'min(iterable[, key=func])\n' -> 'iterable[, key=func]' - sig = self.docstring_sig_re.search(line) - if sig is None: - return [] - # iterable[, key=func]' -> ['iterable[' ,' key=func]'] - sig = sig.groups()[0].split(',') - ret = [] - for s in sig: - #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)') - ret += self.docstring_kwd_re.findall(s) - return ret - - def _default_arguments(self, obj): - """Return the list of default arguments of obj if it is callable, - or empty list otherwise.""" - call_obj = obj - ret = [] - if inspect.isbuiltin(obj): - pass - elif not (inspect.isfunction(obj) or inspect.ismethod(obj)): - if inspect.isclass(obj): - #for cython embedsignature=True the constructor docstring - #belongs to the object itself not __init__ - ret += self._default_arguments_from_docstring( - getattr(obj, '__doc__', '')) - # for classes, check for __init__,__new__ - call_obj = (getattr(obj, '__init__', None) or - getattr(obj, '__new__', None)) - # for all others, check if they are __call__able - elif hasattr(obj, '__call__'): - call_obj = obj.__call__ - ret += self._default_arguments_from_docstring( - getattr(call_obj, '__doc__', '')) - - _keeps = (inspect.Parameter.KEYWORD_ONLY, - inspect.Parameter.POSITIONAL_OR_KEYWORD) - - try: - sig = inspect.signature(obj) - ret.extend(k for k, v in sig.parameters.items() if - v.kind in _keeps) - except ValueError: - pass - - return list(set(ret)) - - @context_matcher() - def python_func_kw_matcher(self, context: CompletionContext) -> SimpleMatcherResult: - """Match named parameters (kwargs) of the last open function.""" - matches = self.python_func_kw_matches(context.token) - return _convert_matcher_v1_result_to_v2(matches, type="param") - - def python_func_kw_matches(self, text): - """Match named parameters (kwargs) of the last open function. - - .. deprecated:: 8.6 - You can use :meth:`python_func_kw_matcher` instead. - """ - - if "." in text: # a parameter cannot be dotted - return [] - try: regexp = self.__funcParamsRegex - except AttributeError: - regexp = self.__funcParamsRegex = re.compile(r''' - '.*?(?,a=1)", the candidate is "foo" - tokens = regexp.findall(self.text_until_cursor) - iterTokens = reversed(tokens) - openPar = 0 - - for token in iterTokens: - if token == ')': - openPar -= 1 - elif token == '(': - openPar += 1 - if openPar > 0: - # found the last unclosed parenthesis - break - else: - return [] - # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" ) - ids = [] - isId = re.compile(r'\w+$').match - - while True: - try: - ids.append(next(iterTokens)) - if not isId(ids[-1]): - ids.pop() - break - if not next(iterTokens) == '.': - break - except StopIteration: - break - - # Find all named arguments already assigned to, as to avoid suggesting - # them again - usedNamedArgs = set() - par_level = -1 - for token, next_token in zip(tokens, tokens[1:]): - if token == '(': - par_level += 1 - elif token == ')': - par_level -= 1 - - if par_level != 0: - continue - - if next_token != '=': - continue - - usedNamedArgs.add(token) - - argMatches = [] - try: - callableObj = '.'.join(ids[::-1]) - namedArgs = self._default_arguments(eval(callableObj, - self.namespace)) - - # Remove used named arguments from the list, no need to show twice - for namedArg in set(namedArgs) - usedNamedArgs: - if namedArg.startswith(text): - argMatches.append("%s=" %namedArg) - except: - pass - - return argMatches - - @staticmethod - def _get_keys(obj: Any) -> List[Any]: - # Objects can define their own completions by defining an - # _ipy_key_completions_() method. - method = get_real_method(obj, '_ipython_key_completions_') - if method is not None: - return method() - - # Special case some common in-memory dict-like types - if isinstance(obj, dict) or _safe_isinstance(obj, "pandas", "DataFrame"): - try: - return list(obj.keys()) - except Exception: - return [] - elif _safe_isinstance(obj, "pandas", "core", "indexing", "_LocIndexer"): - try: - return list(obj.obj.keys()) - except Exception: - return [] - elif _safe_isinstance(obj, 'numpy', 'ndarray') or\ - _safe_isinstance(obj, 'numpy', 'void'): - return obj.dtype.names or [] - return [] - - @context_matcher() - def dict_key_matcher(self, context: CompletionContext) -> SimpleMatcherResult: - """Match string keys in a dictionary, after e.g. ``foo[``.""" - matches = self.dict_key_matches(context.token) - return _convert_matcher_v1_result_to_v2( - matches, type="dict key", suppress_if_matches=True - ) - - def dict_key_matches(self, text: str) -> List[str]: - """Match string keys in a dictionary, after e.g. ``foo[``. - - .. deprecated:: 8.6 - You can use :meth:`dict_key_matcher` instead. - """ - - # Short-circuit on closed dictionary (regular expression would - # not match anyway, but would take quite a while). - if self.text_until_cursor.strip().endswith("]"): - return [] - - match = DICT_MATCHER_REGEX.search(self.text_until_cursor) - - if match is None: - return [] - - expr, prior_tuple_keys, key_prefix = match.groups() - - obj = self._evaluate_expr(expr) - - if obj is not_found: - return [] - - keys = self._get_keys(obj) - if not keys: - return keys - - tuple_prefix = guarded_eval( - prior_tuple_keys, - EvaluationContext( - globals=self.global_namespace, - locals=self.namespace, - evaluation=self.evaluation, # type: ignore - in_subscript=True, - ), - ) - - closing_quote, token_offset, matches = match_dict_keys( - keys, key_prefix, self.splitter.delims, extra_prefix=tuple_prefix - ) - if not matches: - return [] - - # get the cursor position of - # - the text being completed - # - the start of the key text - # - the start of the completion - text_start = len(self.text_until_cursor) - len(text) - if key_prefix: - key_start = match.start(3) - completion_start = key_start + token_offset - else: - key_start = completion_start = match.end() - - # grab the leading prefix, to make sure all completions start with `text` - if text_start > key_start: - leading = '' - else: - leading = text[text_start:completion_start] - - # append closing quote and bracket as appropriate - # this is *not* appropriate if the opening quote or bracket is outside - # the text given to this method, e.g. `d["""a\nt - can_close_quote = False - can_close_bracket = False - - continuation = self.line_buffer[len(self.text_until_cursor) :].strip() - - if continuation.startswith(closing_quote): - # do not close if already closed, e.g. `d['a'` - continuation = continuation[len(closing_quote) :] - else: - can_close_quote = True - - continuation = continuation.strip() - - # e.g. `pandas.DataFrame` has different tuple indexer behaviour, - # handling it is out of scope, so let's avoid appending suffixes. - has_known_tuple_handling = isinstance(obj, dict) - - can_close_bracket = ( - not continuation.startswith("]") and self.auto_close_dict_keys - ) - can_close_tuple_item = ( - not continuation.startswith(",") - and has_known_tuple_handling - and self.auto_close_dict_keys - ) - can_close_quote = can_close_quote and self.auto_close_dict_keys - - # fast path if closing quote should be appended but not suffix is allowed - if not can_close_quote and not can_close_bracket and closing_quote: - return [leading + k for k in matches] - - results = [] - - end_of_tuple_or_item = _DictKeyState.END_OF_TUPLE | _DictKeyState.END_OF_ITEM - - for k, state_flag in matches.items(): - result = leading + k - if can_close_quote and closing_quote: - result += closing_quote - - if state_flag == end_of_tuple_or_item: - # We do not know which suffix to add, - # e.g. both tuple item and string - # match this item. - pass - - if state_flag in end_of_tuple_or_item and can_close_bracket: - result += "]" - if state_flag == _DictKeyState.IN_TUPLE and can_close_tuple_item: - result += ", " - results.append(result) - return results - - @context_matcher() - def unicode_name_matcher(self, context: CompletionContext): - """Same as :any:`unicode_name_matches`, but adopted to new Matcher API.""" - fragment, matches = self.unicode_name_matches(context.text_until_cursor) - return _convert_matcher_v1_result_to_v2( - matches, type="unicode", fragment=fragment, suppress_if_matches=True - ) - - @staticmethod - def unicode_name_matches(text: str) -> Tuple[str, List[str]]: - """Match Latex-like syntax for unicode characters base - on the name of the character. - - This does ``\\GREEK SMALL LETTER ETA`` -> ``η`` - - Works only on valid python 3 identifier, or on combining characters that - will combine to form a valid identifier. - """ - slashpos = text.rfind('\\') - if slashpos > -1: - s = text[slashpos+1:] - try : - unic = unicodedata.lookup(s) - # allow combining chars - if ('a'+unic).isidentifier(): - return '\\'+s,[unic] - except KeyError: - pass - return '', [] - - @context_matcher() - def latex_name_matcher(self, context: CompletionContext): - """Match Latex syntax for unicode characters. - - This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α`` - """ - fragment, matches = self.latex_matches(context.text_until_cursor) - return _convert_matcher_v1_result_to_v2( - matches, type="latex", fragment=fragment, suppress_if_matches=True - ) - - def latex_matches(self, text: str) -> Tuple[str, Sequence[str]]: - """Match Latex syntax for unicode characters. - - This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α`` - - .. deprecated:: 8.6 - You can use :meth:`latex_name_matcher` instead. - """ - slashpos = text.rfind('\\') - if slashpos > -1: - s = text[slashpos:] - if s in latex_symbols: - # Try to complete a full latex symbol to unicode - # \\alpha -> α - return s, [latex_symbols[s]] - else: - # If a user has partially typed a latex symbol, give them - # a full list of options \al -> [\aleph, \alpha] - matches = [k for k in latex_symbols if k.startswith(s)] - if matches: - return s, matches - return '', () - - @context_matcher() - def custom_completer_matcher(self, context): - """Dispatch custom completer. - - If a match is found, suppresses all other matchers except for Jedi. - """ - matches = self.dispatch_custom_completer(context.token) or [] - result = _convert_matcher_v1_result_to_v2( - matches, type=_UNKNOWN_TYPE, suppress_if_matches=True - ) - result["ordered"] = True - result["do_not_suppress"] = {_get_matcher_id(self._jedi_matcher)} - return result - - def dispatch_custom_completer(self, text): - """ - .. deprecated:: 8.6 - You can use :meth:`custom_completer_matcher` instead. - """ - if not self.custom_completers: - return - - line = self.line_buffer - if not line.strip(): - return None - - # Create a little structure to pass all the relevant information about - # the current completion to any custom completer. - event = SimpleNamespace() - event.line = line - event.symbol = text - cmd = line.split(None,1)[0] - event.command = cmd - event.text_until_cursor = self.text_until_cursor - - # for foo etc, try also to find completer for %foo - if not cmd.startswith(self.magic_escape): - try_magic = self.custom_completers.s_matches( - self.magic_escape + cmd) - else: - try_magic = [] - - for c in itertools.chain(self.custom_completers.s_matches(cmd), - try_magic, - self.custom_completers.flat_matches(self.text_until_cursor)): - try: - res = c(event) - if res: - # first, try case sensitive match - withcase = [r for r in res if r.startswith(text)] - if withcase: - return withcase - # if none, then case insensitive ones are ok too - text_low = text.lower() - return [r for r in res if r.lower().startswith(text_low)] - except TryNext: - pass - except KeyboardInterrupt: - """ - If custom completer take too long, - let keyboard interrupt abort and return nothing. - """ - break - - return None - - def completions(self, text: str, offset: int)->Iterator[Completion]: - """ - Returns an iterator over the possible completions - - .. warning:: - - Unstable - - This function is unstable, API may change without warning. - It will also raise unless use in proper context manager. - - Parameters - ---------- - text : str - Full text of the current input, multi line string. - offset : int - Integer representing the position of the cursor in ``text``. Offset - is 0-based indexed. - - Yields - ------ - Completion - - Notes - ----- - The cursor on a text can either be seen as being "in between" - characters or "On" a character depending on the interface visible to - the user. For consistency the cursor being on "in between" characters X - and Y is equivalent to the cursor being "on" character Y, that is to say - the character the cursor is on is considered as being after the cursor. - - Combining characters may span more that one position in the - text. - - .. note:: - - If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--`` - fake Completion token to distinguish completion returned by Jedi - and usual IPython completion. - - .. note:: - - Completions are not completely deduplicated yet. If identical - completions are coming from different sources this function does not - ensure that each completion object will only be present once. - """ - warnings.warn("_complete is a provisional API (as of IPython 6.0). " - "It may change without warnings. " - "Use in corresponding context manager.", - category=ProvisionalCompleterWarning, stacklevel=2) - - seen = set() - profiler:Optional[cProfile.Profile] - try: - if self.profile_completions: - import cProfile - profiler = cProfile.Profile() - profiler.enable() - else: - profiler = None - - for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000): - if c and (c in seen): - continue - yield c - seen.add(c) - except KeyboardInterrupt: - """if completions take too long and users send keyboard interrupt, - do not crash and return ASAP. """ - pass - finally: - if profiler is not None: - profiler.disable() - ensure_dir_exists(self.profiler_output_dir) - output_path = os.path.join(self.profiler_output_dir, str(uuid.uuid4())) - print("Writing profiler output to", output_path) - profiler.dump_stats(output_path) - - def _completions(self, full_text: str, offset: int, *, _timeout) -> Iterator[Completion]: - """ - Core completion module.Same signature as :any:`completions`, with the - extra `timeout` parameter (in seconds). - - Computing jedi's completion ``.type`` can be quite expensive (it is a - lazy property) and can require some warm-up, more warm up than just - computing the ``name`` of a completion. The warm-up can be : - - - Long warm-up the first time a module is encountered after - install/update: actually build parse/inference tree. - - - first time the module is encountered in a session: load tree from - disk. - - We don't want to block completions for tens of seconds so we give the - completer a "budget" of ``_timeout`` seconds per invocation to compute - completions types, the completions that have not yet been computed will - be marked as "unknown" an will have a chance to be computed next round - are things get cached. - - Keep in mind that Jedi is not the only thing treating the completion so - keep the timeout short-ish as if we take more than 0.3 second we still - have lots of processing to do. - - """ - deadline = time.monotonic() + _timeout - - before = full_text[:offset] - cursor_line, cursor_column = position_to_cursor(full_text, offset) - - jedi_matcher_id = _get_matcher_id(self._jedi_matcher) - - def is_non_jedi_result( - result: MatcherResult, identifier: str - ) -> TypeGuard[SimpleMatcherResult]: - return identifier != jedi_matcher_id - - results = self._complete( - full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column - ) - - non_jedi_results: Dict[str, SimpleMatcherResult] = { - identifier: result - for identifier, result in results.items() - if is_non_jedi_result(result, identifier) - } - - jedi_matches = ( - cast(_JediMatcherResult, results[jedi_matcher_id])["completions"] - if jedi_matcher_id in results - else () - ) - - iter_jm = iter(jedi_matches) - if _timeout: - for jm in iter_jm: - try: - type_ = jm.type - except Exception: - if self.debug: - print("Error in Jedi getting type of ", jm) - type_ = None - delta = len(jm.name_with_symbols) - len(jm.complete) - if type_ == 'function': - signature = _make_signature(jm) - else: - signature = '' - yield Completion(start=offset - delta, - end=offset, - text=jm.name_with_symbols, - type=type_, - signature=signature, - _origin='jedi') - - if time.monotonic() > deadline: - break - - for jm in iter_jm: - delta = len(jm.name_with_symbols) - len(jm.complete) - yield Completion( - start=offset - delta, - end=offset, - text=jm.name_with_symbols, - type=_UNKNOWN_TYPE, # don't compute type for speed - _origin="jedi", - signature="", - ) - - # TODO: - # Suppress this, right now just for debug. - if jedi_matches and non_jedi_results and self.debug: - some_start_offset = before.rfind( - next(iter(non_jedi_results.values()))["matched_fragment"] - ) - yield Completion( - start=some_start_offset, - end=offset, - text="--jedi/ipython--", - _origin="debug", - type="none", - signature="", - ) - - ordered: List[Completion] = [] - sortable: List[Completion] = [] - - for origin, result in non_jedi_results.items(): - matched_text = result["matched_fragment"] - start_offset = before.rfind(matched_text) - is_ordered = result.get("ordered", False) - container = ordered if is_ordered else sortable - - # I'm unsure if this is always true, so let's assert and see if it - # crash - assert before.endswith(matched_text) - - for simple_completion in result["completions"]: - completion = Completion( - start=start_offset, - end=offset, - text=simple_completion.text, - _origin=origin, - signature="", - type=simple_completion.type or _UNKNOWN_TYPE, - ) - container.append(completion) - - yield from list(self._deduplicate(ordered + self._sort(sortable)))[ - :MATCHES_LIMIT - ] - - def complete(self, text=None, line_buffer=None, cursor_pos=None) -> Tuple[str, Sequence[str]]: - """Find completions for the given text and line context. - - Note that both the text and the line_buffer are optional, but at least - one of them must be given. - - Parameters - ---------- - text : string, optional - Text to perform the completion on. If not given, the line buffer - is split using the instance's CompletionSplitter object. - line_buffer : string, optional - If not given, the completer attempts to obtain the current line - buffer via readline. This keyword allows clients which are - requesting for text completions in non-readline contexts to inform - the completer of the entire text. - cursor_pos : int, optional - Index of the cursor in the full line buffer. Should be provided by - remote frontends where kernel has no access to frontend state. - - Returns - ------- - Tuple of two items: - text : str - Text that was actually used in the completion. - matches : list - A list of completion matches. - - Notes - ----- - This API is likely to be deprecated and replaced by - :any:`IPCompleter.completions` in the future. - - """ - warnings.warn('`Completer.complete` is pending deprecation since ' - 'IPython 6.0 and will be replaced by `Completer.completions`.', - PendingDeprecationWarning) - # potential todo, FOLD the 3rd throw away argument of _complete - # into the first 2 one. - # TODO: Q: does the above refer to jedi completions (i.e. 0-indexed?) - # TODO: should we deprecate now, or does it stay? - - results = self._complete( - line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0 - ) - - jedi_matcher_id = _get_matcher_id(self._jedi_matcher) - - return self._arrange_and_extract( - results, - # TODO: can we confirm that excluding Jedi here was a deliberate choice in previous version? - skip_matchers={jedi_matcher_id}, - # this API does not support different start/end positions (fragments of token). - abort_if_offset_changes=True, - ) - - def _arrange_and_extract( - self, - results: Dict[str, MatcherResult], - skip_matchers: Set[str], - abort_if_offset_changes: bool, - ): - sortable: List[AnyMatcherCompletion] = [] - ordered: List[AnyMatcherCompletion] = [] - most_recent_fragment = None - for identifier, result in results.items(): - if identifier in skip_matchers: - continue - if not result["completions"]: - continue - if not most_recent_fragment: - most_recent_fragment = result["matched_fragment"] - if ( - abort_if_offset_changes - and result["matched_fragment"] != most_recent_fragment - ): - break - if result.get("ordered", False): - ordered.extend(result["completions"]) - else: - sortable.extend(result["completions"]) - - if not most_recent_fragment: - most_recent_fragment = "" # to satisfy typechecker (and just in case) - - return most_recent_fragment, [ - m.text for m in self._deduplicate(ordered + self._sort(sortable)) - ] - - def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None, - full_text=None) -> _CompleteResult: - """ - Like complete but can also returns raw jedi completions as well as the - origin of the completion text. This could (and should) be made much - cleaner but that will be simpler once we drop the old (and stateful) - :any:`complete` API. - - With current provisional API, cursor_pos act both (depending on the - caller) as the offset in the ``text`` or ``line_buffer``, or as the - ``column`` when passing multiline strings this could/should be renamed - but would add extra noise. - - Parameters - ---------- - cursor_line - Index of the line the cursor is on. 0 indexed. - cursor_pos - Position of the cursor in the current line/line_buffer/text. 0 - indexed. - line_buffer : optional, str - The current line the cursor is in, this is mostly due to legacy - reason that readline could only give a us the single current line. - Prefer `full_text`. - text : str - The current "token" the cursor is in, mostly also for historical - reasons. as the completer would trigger only after the current line - was parsed. - full_text : str - Full text of the current cell. - - Returns - ------- - An ordered dictionary where keys are identifiers of completion - matchers and values are ``MatcherResult``s. - """ - - # if the cursor position isn't given, the only sane assumption we can - # make is that it's at the end of the line (the common case) - if cursor_pos is None: - cursor_pos = len(line_buffer) if text is None else len(text) - - if self.use_main_ns: - self.namespace = __main__.__dict__ - - # if text is either None or an empty string, rely on the line buffer - if (not line_buffer) and full_text: - line_buffer = full_text.split('\n')[cursor_line] - if not text: # issue #11508: check line_buffer before calling split_line - text = ( - self.splitter.split_line(line_buffer, cursor_pos) if line_buffer else "" - ) - - # If no line buffer is given, assume the input text is all there was - if line_buffer is None: - line_buffer = text - - # deprecated - do not use `line_buffer` in new code. - self.line_buffer = line_buffer - self.text_until_cursor = self.line_buffer[:cursor_pos] - - if not full_text: - full_text = line_buffer - - context = CompletionContext( - full_text=full_text, - cursor_position=cursor_pos, - cursor_line=cursor_line, - token=text, - limit=MATCHES_LIMIT, - ) - - # Start with a clean slate of completions - results: Dict[str, MatcherResult] = {} - - jedi_matcher_id = _get_matcher_id(self._jedi_matcher) - - suppressed_matchers: Set[str] = set() - - matchers = { - _get_matcher_id(matcher): matcher - for matcher in sorted( - self.matchers, key=_get_matcher_priority, reverse=True - ) - } - - for matcher_id, matcher in matchers.items(): - matcher_id = _get_matcher_id(matcher) - - if matcher_id in self.disable_matchers: - continue - - if matcher_id in results: - warnings.warn(f"Duplicate matcher ID: {matcher_id}.") - - if matcher_id in suppressed_matchers: - continue - - result: MatcherResult - try: - if _is_matcher_v1(matcher): - result = _convert_matcher_v1_result_to_v2( - matcher(text), type=_UNKNOWN_TYPE - ) - elif _is_matcher_v2(matcher): - result = matcher(context) - else: - api_version = _get_matcher_api_version(matcher) - raise ValueError(f"Unsupported API version {api_version}") - except BaseException: - # Show the ugly traceback if the matcher causes an - # exception, but do NOT crash the kernel! - sys.excepthook(*sys.exc_info()) - continue - - # set default value for matched fragment if suffix was not selected. - result["matched_fragment"] = result.get("matched_fragment", context.token) - - if not suppressed_matchers: - suppression_recommended: Union[bool, Set[str]] = result.get( - "suppress", False - ) - - suppression_config = ( - self.suppress_competing_matchers.get(matcher_id, None) - if isinstance(self.suppress_competing_matchers, dict) - else self.suppress_competing_matchers - ) - should_suppress = ( - (suppression_config is True) - or (suppression_recommended and (suppression_config is not False)) - ) and has_any_completions(result) - - if should_suppress: - suppression_exceptions: Set[str] = result.get( - "do_not_suppress", set() - ) - if isinstance(suppression_recommended, Iterable): - to_suppress = set(suppression_recommended) - else: - to_suppress = set(matchers) - suppressed_matchers = to_suppress - suppression_exceptions - - new_results = {} - for previous_matcher_id, previous_result in results.items(): - if previous_matcher_id not in suppressed_matchers: - new_results[previous_matcher_id] = previous_result - results = new_results - - results[matcher_id] = result - - _, matches = self._arrange_and_extract( - results, - # TODO Jedi completions non included in legacy stateful API; was this deliberate or omission? - # if it was omission, we can remove the filtering step, otherwise remove this comment. - skip_matchers={jedi_matcher_id}, - abort_if_offset_changes=False, - ) - - # populate legacy stateful API - self.matches = matches - - return results - - @staticmethod - def _deduplicate( - matches: Sequence[AnyCompletion], - ) -> Iterable[AnyCompletion]: - filtered_matches: Dict[str, AnyCompletion] = {} - for match in matches: - text = match.text - if ( - text not in filtered_matches - or filtered_matches[text].type == _UNKNOWN_TYPE - ): - filtered_matches[text] = match - - return filtered_matches.values() - - @staticmethod - def _sort(matches: Sequence[AnyCompletion]): - return sorted(matches, key=lambda x: completions_sorting_key(x.text)) - - @context_matcher() - def fwd_unicode_matcher(self, context: CompletionContext): - """Same as :any:`fwd_unicode_match`, but adopted to new Matcher API.""" - # TODO: use `context.limit` to terminate early once we matched the maximum - # number that will be used downstream; can be added as an optional to - # `fwd_unicode_match(text: str, limit: int = None)` or we could re-implement here. - fragment, matches = self.fwd_unicode_match(context.text_until_cursor) - return _convert_matcher_v1_result_to_v2( - matches, type="unicode", fragment=fragment, suppress_if_matches=True - ) - - def fwd_unicode_match(self, text: str) -> Tuple[str, Sequence[str]]: - """ - Forward match a string starting with a backslash with a list of - potential Unicode completions. - - Will compute list of Unicode character names on first call and cache it. - - .. deprecated:: 8.6 - You can use :meth:`fwd_unicode_matcher` instead. - - Returns - ------- - At tuple with: - - matched text (empty if no matches) - - list of potential completions, empty tuple otherwise) - """ - # TODO: self.unicode_names is here a list we traverse each time with ~100k elements. - # We could do a faster match using a Trie. - - # Using pygtrie the following seem to work: - - # s = PrefixSet() - - # for c in range(0,0x10FFFF + 1): - # try: - # s.add(unicodedata.name(chr(c))) - # except ValueError: - # pass - # [''.join(k) for k in s.iter(prefix)] - - # But need to be timed and adds an extra dependency. - - slashpos = text.rfind('\\') - # if text starts with slash - if slashpos > -1: - # PERF: It's important that we don't access self._unicode_names - # until we're inside this if-block. _unicode_names is lazily - # initialized, and it takes a user-noticeable amount of time to - # initialize it, so we don't want to initialize it unless we're - # actually going to use it. - s = text[slashpos + 1 :] - sup = s.upper() - candidates = [x for x in self.unicode_names if x.startswith(sup)] - if candidates: - return s, candidates - candidates = [x for x in self.unicode_names if sup in x] - if candidates: - return s, candidates - splitsup = sup.split(" ") - candidates = [ - x for x in self.unicode_names if all(u in x for u in splitsup) - ] - if candidates: - return s, candidates - - return "", () - - # if text does not start with slash - else: - return '', () - - @property - def unicode_names(self) -> List[str]: - """List of names of unicode code points that can be completed. - - The list is lazily initialized on first access. - """ - if self._unicode_names is None: - names = [] - for c in range(0,0x10FFFF + 1): - try: - names.append(unicodedata.name(chr(c))) - except ValueError: - pass - self._unicode_names = _unicode_name_compute(_UNICODE_RANGES) - - return self._unicode_names - -def _unicode_name_compute(ranges:List[Tuple[int,int]]) -> List[str]: - names = [] - for start,stop in ranges: - for c in range(start, stop) : - try: - names.append(unicodedata.name(chr(c))) - except ValueError: - pass - return names diff --git a/.venv/lib/python3.12/site-packages/IPython/core/completerlib.py b/.venv/lib/python3.12/site-packages/IPython/core/completerlib.py deleted file mode 100644 index f15490f..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/completerlib.py +++ /dev/null @@ -1,382 +0,0 @@ -# encoding: utf-8 -"""Implementations for various useful completers. - -These are all loaded by default by IPython. -""" -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team. -# -# Distributed under the terms of the BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib imports -import glob -import inspect -import os -import re -import sys -from importlib import import_module -from importlib.machinery import all_suffixes - - -# Third-party imports -from time import time -from zipimport import zipimporter - -# Our own imports -from .completer import expand_user, compress_user -from .error import TryNext -from ..utils._process_common import arg_split - -# FIXME: this should be pulled in with the right call via the component system -from IPython import get_ipython - -from typing import List - -#----------------------------------------------------------------------------- -# Globals and constants -#----------------------------------------------------------------------------- -_suffixes = all_suffixes() - -# Time in seconds after which the rootmodules will be stored permanently in the -# ipython ip.db database (kept in the user's .ipython dir). -TIMEOUT_STORAGE = 2 - -# Time in seconds after which we give up -TIMEOUT_GIVEUP = 20 - -# Regular expression for the python import statement -import_re = re.compile(r'(?P[^\W\d]\w*?)' - r'(?P[/\\]__init__)?' - r'(?P%s)$' % - r'|'.join(re.escape(s) for s in _suffixes)) - -# RE for the ipython %run command (python + ipython scripts) -magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$') - -#----------------------------------------------------------------------------- -# Local utilities -#----------------------------------------------------------------------------- - - -def module_list(path: str) -> List[str]: - """ - Return the list containing the names of the modules available in the given - folder. - """ - # sys.path has the cwd as an empty string, but isdir/listdir need it as '.' - if path == '': - path = '.' - - # A few local constants to be used in loops below - pjoin = os.path.join - - if os.path.isdir(path): - # Build a list of all files in the directory and all files - # in its subdirectories. For performance reasons, do not - # recurse more than one level into subdirectories. - files: List[str] = [] - for root, dirs, nondirs in os.walk(path, followlinks=True): - subdir = root[len(path)+1:] - if subdir: - files.extend(pjoin(subdir, f) for f in nondirs) - dirs[:] = [] # Do not recurse into additional subdirectories. - else: - files.extend(nondirs) - - else: - try: - files = list(zipimporter(path)._files.keys()) # type: ignore - except Exception: - files = [] - - # Build a list of modules which match the import_re regex. - modules = [] - for f in files: - m = import_re.match(f) - if m: - modules.append(m.group('name')) - return list(set(modules)) - - -def get_root_modules(): - """ - Returns a list containing the names of all the modules available in the - folders of the pythonpath. - - ip.db['rootmodules_cache'] maps sys.path entries to list of modules. - """ - ip = get_ipython() - if ip is None: - # No global shell instance to store cached list of modules. - # Don't try to scan for modules every time. - return list(sys.builtin_module_names) - - if getattr(ip.db, "_mock", False): - rootmodules_cache = {} - else: - rootmodules_cache = ip.db.get("rootmodules_cache", {}) - rootmodules = list(sys.builtin_module_names) - start_time = time() - store = False - for path in sys.path: - try: - modules = rootmodules_cache[path] - except KeyError: - modules = module_list(path) - try: - modules.remove('__init__') - except ValueError: - pass - if path not in ('', '.'): # cwd modules should not be cached - rootmodules_cache[path] = modules - if time() - start_time > TIMEOUT_STORAGE and not store: - store = True - print("\nCaching the list of root modules, please wait!") - print("(This will only be done once - type '%rehashx' to " - "reset cache!)\n") - sys.stdout.flush() - if time() - start_time > TIMEOUT_GIVEUP: - print("This is taking too long, we give up.\n") - return [] - rootmodules.extend(modules) - if store: - ip.db['rootmodules_cache'] = rootmodules_cache - rootmodules = list(set(rootmodules)) - return rootmodules - - -def is_importable(module, attr: str, only_modules) -> bool: - if only_modules: - try: - mod = getattr(module, attr) - except ModuleNotFoundError: - # See gh-14434 - return False - return inspect.ismodule(mod) - else: - return not(attr[:2] == '__' and attr[-2:] == '__') - -def is_possible_submodule(module, attr): - try: - obj = getattr(module, attr) - except AttributeError: - # Is possibly an unimported submodule - return True - except TypeError: - # https://github.com/ipython/ipython/issues/9678 - return False - return inspect.ismodule(obj) - - -def try_import(mod: str, only_modules=False) -> List[str]: - """ - Try to import given module and return list of potential completions. - """ - mod = mod.rstrip('.') - try: - m = import_module(mod) - except: - return [] - - m_is_init = '__init__' in (getattr(m, '__file__', '') or '') - - completions = [] - if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init: - completions.extend( [attr for attr in dir(m) if - is_importable(m, attr, only_modules)]) - - m_all = getattr(m, "__all__", []) - if only_modules: - completions.extend(attr for attr in m_all if is_possible_submodule(m, attr)) - else: - completions.extend(m_all) - - if m_is_init: - file_ = m.__file__ - file_path = os.path.dirname(file_) # type: ignore - if file_path is not None: - completions.extend(module_list(file_path)) - completions_set = {c for c in completions if isinstance(c, str)} - completions_set.discard('__init__') - return list(completions_set) - - -#----------------------------------------------------------------------------- -# Completion-related functions. -#----------------------------------------------------------------------------- - -def quick_completer(cmd, completions): - r""" Easily create a trivial completer for a command. - - Takes either a list of completions, or all completions in string (that will - be split on whitespace). - - Example:: - - [d:\ipython]|1> import ipy_completers - [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz']) - [d:\ipython]|3> foo b - bar baz - [d:\ipython]|3> foo ba - """ - - if isinstance(completions, str): - completions = completions.split() - - def do_complete(self, event): - return completions - - get_ipython().set_hook('complete_command',do_complete, str_key = cmd) - -def module_completion(line): - """ - Returns a list containing the completion possibilities for an import line. - - The line looks like this : - 'import xml.d' - 'from xml.dom import' - """ - - words = line.split(' ') - nwords = len(words) - - # from whatever -> 'import ' - if nwords == 3 and words[0] == 'from': - return ['import '] - - # 'from xy' or 'import xy' - if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) : - if nwords == 1: - return get_root_modules() - mod = words[1].split('.') - if len(mod) < 2: - return get_root_modules() - completion_list = try_import('.'.join(mod[:-1]), True) - return ['.'.join(mod[:-1] + [el]) for el in completion_list] - - # 'from xyz import abc' - if nwords >= 3 and words[0] == 'from': - mod = words[1] - return try_import(mod) - -#----------------------------------------------------------------------------- -# Completers -#----------------------------------------------------------------------------- -# These all have the func(self, event) signature to be used as custom -# completers - -def module_completer(self,event): - """Give completions after user has typed 'import ...' or 'from ...'""" - - # This works in all versions of python. While 2.5 has - # pkgutil.walk_packages(), that particular routine is fairly dangerous, - # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full - # of possibly problematic side effects. - # This search the folders in the sys.path for available modules. - - return module_completion(event.line) - -# FIXME: there's a lot of logic common to the run, cd and builtin file -# completers, that is currently reimplemented in each. - -def magic_run_completer(self, event): - """Complete files that end in .py or .ipy or .ipynb for the %run command. - """ - comps = arg_split(event.line, strict=False) - # relpath should be the current token that we need to complete. - if (len(comps) > 1) and (not event.line.endswith(' ')): - relpath = comps[-1].strip("'\"") - else: - relpath = '' - - #print("\nev=", event) # dbg - #print("rp=", relpath) # dbg - #print('comps=', comps) # dbg - - lglob = glob.glob - isdir = os.path.isdir - relpath, tilde_expand, tilde_val = expand_user(relpath) - - # Find if the user has already typed the first filename, after which we - # should complete on all files, since after the first one other files may - # be arguments to the input script. - - if any(magic_run_re.match(c) for c in comps): - matches = [f.replace('\\','/') + ('/' if isdir(f) else '') - for f in lglob(relpath+'*')] - else: - dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)] - pys = [f.replace('\\','/') - for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') + - lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')] - - matches = dirs + pys - - #print('run comp:', dirs+pys) # dbg - return [compress_user(p, tilde_expand, tilde_val) for p in matches] - - -def cd_completer(self, event): - """Completer function for cd, which only returns directories.""" - ip = get_ipython() - relpath = event.symbol - - #print(event) # dbg - if event.line.endswith('-b') or ' -b ' in event.line: - # return only bookmark completions - bkms = self.db.get('bookmarks', None) - if bkms: - return bkms.keys() - else: - return [] - - if event.symbol == '-': - width_dh = str(len(str(len(ip.user_ns['_dh']) + 1))) - # jump in directory history by number - fmt = '-%0' + width_dh +'d [%s]' - ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])] - if len(ents) > 1: - return ents - return [] - - if event.symbol.startswith('--'): - return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']] - - # Expand ~ in path and normalize directory separators. - relpath, tilde_expand, tilde_val = expand_user(relpath) - relpath = relpath.replace('\\','/') - - found = [] - for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*') - if os.path.isdir(f)]: - if ' ' in d: - # we don't want to deal with any of that, complex code - # for this is elsewhere - raise TryNext - - found.append(d) - - if not found: - if os.path.isdir(relpath): - return [compress_user(relpath, tilde_expand, tilde_val)] - - # if no completions so far, try bookmarks - bks = self.db.get('bookmarks',{}) - bkmatches = [s for s in bks if s.startswith(event.symbol)] - if bkmatches: - return bkmatches - - raise TryNext - - return [compress_user(p, tilde_expand, tilde_val) for p in found] - -def reset_completer(self, event): - "A completer for %reset magic" - return '-f -s in out array dhist'.split() diff --git a/.venv/lib/python3.12/site-packages/IPython/core/crashhandler.py b/.venv/lib/python3.12/site-packages/IPython/core/crashhandler.py deleted file mode 100644 index 9c75c5d..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/crashhandler.py +++ /dev/null @@ -1,248 +0,0 @@ -# encoding: utf-8 -"""sys.excepthook for IPython itself, leaves a detailed report on disk. - -Authors: - -* Fernando Perez -* Brian E. Granger -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2001-2007 Fernando Perez. -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import sys -import traceback -from pprint import pformat -from pathlib import Path - -import builtins as builtin_mod - -from IPython.core import ultratb -from IPython.core.application import Application -from IPython.core.release import author_email -from IPython.utils.sysinfo import sys_info - -from IPython.core.release import __version__ as version - -from typing import Optional, Dict -import types - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -# Template for the user message. -_default_message_template = """\ -Oops, {app_name} crashed. We do our best to make it stable, but... - -A crash report was automatically generated with the following information: - - A verbatim copy of the crash traceback. - - A copy of your input history during this session. - - Data on your current {app_name} configuration. - -It was left in the file named: -\t'{crash_report_fname}' -If you can email this file to the developers, the information in it will help -them in understanding and correcting the problem. - -You can mail it to: {contact_name} at {contact_email} -with the subject '{app_name} Crash Report'. - -If you want to do it now, the following command will work (under Unix): -mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname} - -In your email, please also include information about: -- The operating system under which the crash happened: Linux, macOS, Windows, - other, and which exact version (for example: Ubuntu 16.04.3, macOS 10.13.2, - Windows 10 Pro), and whether it is 32-bit or 64-bit; -- How {app_name} was installed: using pip or conda, from GitHub, as part of - a Docker container, or other, providing more detail if possible; -- How to reproduce the crash: what exact sequence of instructions can one - input to get the same crash? Ideally, find a minimal yet complete sequence - of instructions that yields the crash. - -To ensure accurate tracking of this issue, please file a report about it at: -{bug_tracker} -""" - -_lite_message_template = """ -If you suspect this is an IPython {version} bug, please report it at: - https://github.com/ipython/ipython/issues -or send an email to the mailing list at {email} - -You can print a more detailed traceback right now with "%tb", or use "%debug" -to interactively debug it. - -Extra-detailed tracebacks for bug-reporting purposes can be enabled via: - {config}Application.verbose_crash=True -""" - - -class CrashHandler: - """Customizable crash handlers for IPython applications. - - Instances of this class provide a :meth:`__call__` method which can be - used as a ``sys.excepthook``. The :meth:`__call__` signature is:: - - def __call__(self, etype, evalue, etb) - """ - - message_template = _default_message_template - section_sep = '\n\n'+'*'*75+'\n\n' - info: Dict[str, Optional[str]] - - def __init__( - self, - app: Application, - contact_name: Optional[str] = None, - contact_email: Optional[str] = None, - bug_tracker: Optional[str] = None, - show_crash_traceback: bool = True, - call_pdb: bool = False, - ): - """Create a new crash handler - - Parameters - ---------- - app : Application - A running :class:`Application` instance, which will be queried at - crash time for internal information. - contact_name : str - A string with the name of the person to contact. - contact_email : str - A string with the email address of the contact. - bug_tracker : str - A string with the URL for your project's bug tracker. - show_crash_traceback : bool - If false, don't print the crash traceback on stderr, only generate - the on-disk report - call_pdb - Whether to call pdb on crash - - Attributes - ---------- - These instances contain some non-argument attributes which allow for - further customization of the crash handler's behavior. Please see the - source for further details. - - """ - self.crash_report_fname = "Crash_report_%s.txt" % app.name - self.app = app - self.call_pdb = call_pdb - #self.call_pdb = True # dbg - self.show_crash_traceback = show_crash_traceback - self.info = dict(app_name = app.name, - contact_name = contact_name, - contact_email = contact_email, - bug_tracker = bug_tracker, - crash_report_fname = self.crash_report_fname) - - def __call__( - self, - etype: type[BaseException], - evalue: BaseException, - etb: types.TracebackType, - ) -> None: - """Handle an exception, call for compatible with sys.excepthook""" - - # do not allow the crash handler to be called twice without reinstalling it - # this prevents unlikely errors in the crash handling from entering an - # infinite loop. - sys.excepthook = sys.__excepthook__ - - # Report tracebacks shouldn't use color in general (safer for users) - color_scheme = 'NoColor' - - # Use this ONLY for developer debugging (keep commented out for release) - # color_scheme = 'Linux' # dbg - ipython_dir = getattr(self.app, "ipython_dir", None) - if ipython_dir is not None: - assert isinstance(ipython_dir, str) - rptdir = Path(ipython_dir) - else: - rptdir = Path.cwd() - if not rptdir.is_dir(): - rptdir = Path.cwd() - report_name = rptdir / self.crash_report_fname - # write the report filename into the instance dict so it can get - # properly expanded out in the user message template - self.crash_report_fname = str(report_name) - self.info["crash_report_fname"] = str(report_name) - TBhandler = ultratb.VerboseTB( - color_scheme=color_scheme, - long_header=True, - call_pdb=self.call_pdb, - ) - if self.call_pdb: - TBhandler(etype,evalue,etb) - return - else: - traceback = TBhandler.text(etype,evalue,etb,context=31) - - # print traceback to screen - if self.show_crash_traceback: - print(traceback, file=sys.stderr) - - # and generate a complete report on disk - try: - report = open(report_name, "w", encoding="utf-8") - except: - print('Could not create crash report on disk.', file=sys.stderr) - return - - with report: - # Inform user on stderr of what happened - print('\n'+'*'*70+'\n', file=sys.stderr) - print(self.message_template.format(**self.info), file=sys.stderr) - - # Construct report on disk - report.write(self.make_report(str(traceback))) - - builtin_mod.input("Hit to quit (your terminal may close):") - - def make_report(self, traceback: str) -> str: - """Return a string containing a crash report.""" - - sec_sep = self.section_sep - - report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n'] - rpt_add = report.append - rpt_add(sys_info()) - - try: - config = pformat(self.app.config) - rpt_add(sec_sep) - rpt_add("Application name: %s\n\n" % self.app.name) - rpt_add("Current user configuration structure:\n\n") - rpt_add(config) - except: - pass - rpt_add(sec_sep+'Crash traceback:\n\n' + traceback) - - return ''.join(report) - - -def crash_handler_lite( - etype: type[BaseException], evalue: BaseException, tb: types.TracebackType -) -> None: - """a light excepthook, adding a small message to the usual traceback""" - traceback.print_exception(etype, evalue, tb) - - from IPython.core.interactiveshell import InteractiveShell - if InteractiveShell.initialized(): - # we are in a Shell environment, give %magic example - config = "%config " - else: - # we are not in a shell, show generic config - config = "c." - print(_lite_message_template.format(email=author_email, config=config, version=version), file=sys.stderr) - diff --git a/.venv/lib/python3.12/site-packages/IPython/core/debugger.py b/.venv/lib/python3.12/site-packages/IPython/core/debugger.py deleted file mode 100644 index 76c42e0..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/debugger.py +++ /dev/null @@ -1,1136 +0,0 @@ -""" -Pdb debugger class. - - -This is an extension to PDB which adds a number of new features. -Note that there is also the `IPython.terminal.debugger` class which provides UI -improvements. - -We also strongly recommend to use this via the `ipdb` package, which provides -extra configuration options. - -Among other things, this subclass of PDB: - - supports many IPython magics like pdef/psource - - hide frames in tracebacks based on `__tracebackhide__` - - allows to skip frames based on `__debuggerskip__` - - -Global Configuration --------------------- - -The IPython debugger will by read the global ``~/.pdbrc`` file. -That is to say you can list all commands supported by ipdb in your `~/.pdbrc` -configuration file, to globally configure pdb. - -Example:: - - # ~/.pdbrc - skip_predicates debuggerskip false - skip_hidden false - context 25 - -Features --------- - -The IPython debugger can hide and skip frames when printing or moving through -the stack. This can have a performance impact, so can be configures. - -The skipping and hiding frames are configurable via the `skip_predicates` -command. - -By default, frames from readonly files will be hidden, frames containing -``__tracebackhide__ = True`` will be hidden. - -Frames containing ``__debuggerskip__`` will be stepped over, frames whose parent -frames value of ``__debuggerskip__`` is ``True`` will also be skipped. - - >>> def helpers_helper(): - ... pass - ... - ... def helper_1(): - ... print("don't step in me") - ... helpers_helpers() # will be stepped over unless breakpoint set. - ... - ... - ... def helper_2(): - ... print("in me neither") - ... - -One can define a decorator that wraps a function between the two helpers: - - >>> def pdb_skipped_decorator(function): - ... - ... - ... def wrapped_fn(*args, **kwargs): - ... __debuggerskip__ = True - ... helper_1() - ... __debuggerskip__ = False - ... result = function(*args, **kwargs) - ... __debuggerskip__ = True - ... helper_2() - ... # setting __debuggerskip__ to False again is not necessary - ... return result - ... - ... return wrapped_fn - -When decorating a function, ipdb will directly step into ``bar()`` by -default: - - >>> @foo_decorator - ... def bar(x, y): - ... return x * y - - -You can toggle the behavior with - - ipdb> skip_predicates debuggerskip false - -or configure it in your ``.pdbrc`` - - - -License -------- - -Modified from the standard pdb.Pdb class to avoid including readline, so that -the command line completion of other programs which include this isn't -damaged. - -In the future, this class will be expanded with improvements over the standard -pdb. - -The original code in this file is mainly lifted out of cmd.py in Python 2.2, -with minor changes. Licensing should therefore be under the standard Python -terms. For details on the PSF (Python Software Foundation) standard license, -see: - -https://docs.python.org/2/license.html - - -All the changes since then are under the same license as IPython. - -""" - -#***************************************************************************** -# -# This file is licensed under the PSF license. -# -# Copyright (C) 2001 Python Software Foundation, www.python.org -# Copyright (C) 2005-2006 Fernando Perez. -# -# -#***************************************************************************** - -from __future__ import annotations - -import inspect -import linecache -import os -import re -import sys -from contextlib import contextmanager -from functools import lru_cache - -from IPython import get_ipython -from IPython.core.excolors import exception_colors -from IPython.utils import PyColorize, coloransi, py3compat - -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - # otherwise circular import - from IPython.core.interactiveshell import InteractiveShell - -# skip module docstests -__skip_doctest__ = True - -prompt = 'ipdb> ' - -# We have to check this directly from sys.argv, config struct not yet available -from pdb import Pdb as OldPdb - -# Allow the set_trace code to operate outside of an ipython instance, even if -# it does so with some limitations. The rest of this support is implemented in -# the Tracer constructor. - -DEBUGGERSKIP = "__debuggerskip__" - - -# this has been implemented in Pdb in Python 3.13 (https://github.com/python/cpython/pull/106676 -# on lower python versions, we backported the feature. -CHAIN_EXCEPTIONS = sys.version_info < (3, 13) - - -def make_arrow(pad): - """generate the leading arrow in front of traceback or debugger""" - if pad >= 2: - return '-'*(pad-2) + '> ' - elif pad == 1: - return '>' - return '' - - -def BdbQuit_excepthook(et, ev, tb, excepthook=None): - """Exception hook which handles `BdbQuit` exceptions. - - All other exceptions are processed using the `excepthook` - parameter. - """ - raise ValueError( - "`BdbQuit_excepthook` is deprecated since version 5.1. It is still around only because it is still imported by ipdb.", - ) - - -RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+') - - -def strip_indentation(multiline_string): - return RGX_EXTRA_INDENT.sub('', multiline_string) - - -def decorate_fn_with_doc(new_fn, old_fn, additional_text=""): - """Make new_fn have old_fn's doc string. This is particularly useful - for the ``do_...`` commands that hook into the help system. - Adapted from from a comp.lang.python posting - by Duncan Booth.""" - def wrapper(*args, **kw): - return new_fn(*args, **kw) - if old_fn.__doc__: - wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text - return wrapper - - -class Pdb(OldPdb): - """Modified Pdb class, does not load readline. - - for a standalone version that uses prompt_toolkit, see - `IPython.terminal.debugger.TerminalPdb` and - `IPython.terminal.debugger.set_trace()` - - - This debugger can hide and skip frames that are tagged according to some predicates. - See the `skip_predicates` commands. - - """ - - shell: InteractiveShell - - if CHAIN_EXCEPTIONS: - MAX_CHAINED_EXCEPTION_DEPTH = 999 - - default_predicates = { - "tbhide": True, - "readonly": False, - "ipython_internal": True, - "debuggerskip": True, - } - - def __init__(self, completekey=None, stdin=None, stdout=None, context=5, **kwargs): - """Create a new IPython debugger. - - Parameters - ---------- - completekey : default None - Passed to pdb.Pdb. - stdin : default None - Passed to pdb.Pdb. - stdout : default None - Passed to pdb.Pdb. - context : int - Number of lines of source code context to show when - displaying stacktrace information. - **kwargs - Passed to pdb.Pdb. - - Notes - ----- - The possibilities are python version dependent, see the python - docs for more info. - """ - - # Parent constructor: - try: - self.context = int(context) - if self.context <= 0: - raise ValueError("Context must be a positive integer") - except (TypeError, ValueError) as e: - raise ValueError("Context must be a positive integer") from e - - # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`. - OldPdb.__init__(self, completekey, stdin, stdout, **kwargs) - - # IPython changes... - self.shell = get_ipython() - - if self.shell is None: - save_main = sys.modules['__main__'] - # No IPython instance running, we must create one - from IPython.terminal.interactiveshell import \ - TerminalInteractiveShell - self.shell = TerminalInteractiveShell.instance() - # needed by any code which calls __import__("__main__") after - # the debugger was entered. See also #9941. - sys.modules["__main__"] = save_main - - - color_scheme = self.shell.colors - - self.aliases = {} - - # Create color table: we copy the default one from the traceback - # module and add a few attributes needed for debugging - self.color_scheme_table = exception_colors() - - # shorthands - C = coloransi.TermColors - cst = self.color_scheme_table - - - # Add a python parser so we can syntax highlight source while - # debugging. - self.parser = PyColorize.Parser(style=color_scheme) - self.set_colors(color_scheme) - - # Set the prompt - the default prompt is '(Pdb)' - self.prompt = prompt - self.skip_hidden = True - self.report_skipped = True - - # list of predicates we use to skip frames - self._predicates = self.default_predicates - - if CHAIN_EXCEPTIONS: - self._chained_exceptions = tuple() - self._chained_exception_index = 0 - - # - def set_colors(self, scheme): - """Shorthand access to the color table scheme selector method.""" - self.color_scheme_table.set_active_scheme(scheme) - self.parser.style = scheme - - def set_trace(self, frame=None): - if frame is None: - frame = sys._getframe().f_back - self.initial_frame = frame - return super().set_trace(frame) - - def _hidden_predicate(self, frame): - """ - Given a frame return whether it it should be hidden or not by IPython. - """ - - if self._predicates["readonly"]: - fname = frame.f_code.co_filename - # we need to check for file existence and interactively define - # function would otherwise appear as RO. - if os.path.isfile(fname) and not os.access(fname, os.W_OK): - return True - - if self._predicates["tbhide"]: - if frame in (self.curframe, getattr(self, "initial_frame", None)): - return False - frame_locals = self._get_frame_locals(frame) - if "__tracebackhide__" not in frame_locals: - return False - return frame_locals["__tracebackhide__"] - return False - - def hidden_frames(self, stack): - """ - Given an index in the stack return whether it should be skipped. - - This is used in up/down and where to skip frames. - """ - # The f_locals dictionary is updated from the actual frame - # locals whenever the .f_locals accessor is called, so we - # avoid calling it here to preserve self.curframe_locals. - # Furthermore, there is no good reason to hide the current frame. - ip_hide = [self._hidden_predicate(s[0]) for s in stack] - ip_start = [i for i, s in enumerate(ip_hide) if s == "__ipython_bottom__"] - if ip_start and self._predicates["ipython_internal"]: - ip_hide = [h if i > ip_start[0] else True for (i, h) in enumerate(ip_hide)] - return ip_hide - - if CHAIN_EXCEPTIONS: - - def _get_tb_and_exceptions(self, tb_or_exc): - """ - Given a tracecack or an exception, return a tuple of chained exceptions - and current traceback to inspect. - This will deal with selecting the right ``__cause__`` or ``__context__`` - as well as handling cycles, and return a flattened list of exceptions we - can jump to with do_exceptions. - """ - _exceptions = [] - if isinstance(tb_or_exc, BaseException): - traceback, current = tb_or_exc.__traceback__, tb_or_exc - - while current is not None: - if current in _exceptions: - break - _exceptions.append(current) - if current.__cause__ is not None: - current = current.__cause__ - elif ( - current.__context__ is not None - and not current.__suppress_context__ - ): - current = current.__context__ - - if len(_exceptions) >= self.MAX_CHAINED_EXCEPTION_DEPTH: - self.message( - f"More than {self.MAX_CHAINED_EXCEPTION_DEPTH}" - " chained exceptions found, not all exceptions" - "will be browsable with `exceptions`." - ) - break - else: - traceback = tb_or_exc - return tuple(reversed(_exceptions)), traceback - - @contextmanager - def _hold_exceptions(self, exceptions): - """ - Context manager to ensure proper cleaning of exceptions references - When given a chained exception instead of a traceback, - pdb may hold references to many objects which may leak memory. - We use this context manager to make sure everything is properly cleaned - """ - try: - self._chained_exceptions = exceptions - self._chained_exception_index = len(exceptions) - 1 - yield - finally: - # we can't put those in forget as otherwise they would - # be cleared on exception change - self._chained_exceptions = tuple() - self._chained_exception_index = 0 - - def do_exceptions(self, arg): - """exceptions [number] - List or change current exception in an exception chain. - Without arguments, list all the current exception in the exception - chain. Exceptions will be numbered, with the current exception indicated - with an arrow. - If given an integer as argument, switch to the exception at that index. - """ - if not self._chained_exceptions: - self.message( - "Did not find chained exceptions. To move between" - " exceptions, pdb/post_mortem must be given an exception" - " object rather than a traceback." - ) - return - if not arg: - for ix, exc in enumerate(self._chained_exceptions): - prompt = ">" if ix == self._chained_exception_index else " " - rep = repr(exc) - if len(rep) > 80: - rep = rep[:77] + "..." - indicator = ( - " -" - if self._chained_exceptions[ix].__traceback__ is None - else f"{ix:>3}" - ) - self.message(f"{prompt} {indicator} {rep}") - else: - try: - number = int(arg) - except ValueError: - self.error("Argument must be an integer") - return - if 0 <= number < len(self._chained_exceptions): - if self._chained_exceptions[number].__traceback__ is None: - self.error( - "This exception does not have a traceback, cannot jump to it" - ) - return - - self._chained_exception_index = number - self.setup(None, self._chained_exceptions[number].__traceback__) - self.print_stack_entry(self.stack[self.curindex]) - else: - self.error("No exception with that number") - - def interaction(self, frame, tb_or_exc): - try: - if CHAIN_EXCEPTIONS: - # this context manager is part of interaction in 3.13 - _chained_exceptions, tb = self._get_tb_and_exceptions(tb_or_exc) - if isinstance(tb_or_exc, BaseException): - assert tb is not None, "main exception must have a traceback" - with self._hold_exceptions(_chained_exceptions): - OldPdb.interaction(self, frame, tb) - else: - OldPdb.interaction(self, frame, tb_or_exc) - - except KeyboardInterrupt: - self.stdout.write("\n" + self.shell.get_exception_only()) - - def precmd(self, line): - """Perform useful escapes on the command before it is executed.""" - - if line.endswith("??"): - line = "pinfo2 " + line[:-2] - elif line.endswith("?"): - line = "pinfo " + line[:-1] - - line = super().precmd(line) - - return line - - def new_do_quit(self, arg): - return OldPdb.do_quit(self, arg) - - do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit) - - def print_stack_trace(self, context=None): - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - if context is None: - context = self.context - try: - context = int(context) - if context <= 0: - raise ValueError("Context must be a positive integer") - except (TypeError, ValueError) as e: - raise ValueError("Context must be a positive integer") from e - try: - skipped = 0 - for hidden, frame_lineno in zip(self.hidden_frames(self.stack), self.stack): - if hidden and self.skip_hidden: - skipped += 1 - continue - if skipped: - print( - f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n" - ) - skipped = 0 - self.print_stack_entry(frame_lineno, context=context) - if skipped: - print( - f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n" - ) - except KeyboardInterrupt: - pass - - def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ', - context=None): - if context is None: - context = self.context - try: - context = int(context) - if context <= 0: - raise ValueError("Context must be a positive integer") - except (TypeError, ValueError) as e: - raise ValueError("Context must be a positive integer") from e - print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout) - - # vds: >> - frame, lineno = frame_lineno - filename = frame.f_code.co_filename - self.shell.hooks.synchronize_with_editor(filename, lineno, 0) - # vds: << - - def _get_frame_locals(self, frame): - """ " - Accessing f_local of current frame reset the namespace, so we want to avoid - that or the following can happen - - ipdb> foo - "old" - ipdb> foo = "new" - ipdb> foo - "new" - ipdb> where - ipdb> foo - "old" - - So if frame is self.current_frame we instead return self.curframe_locals - - """ - if frame is getattr(self, "curframe", None): - return self.curframe_locals - else: - return frame.f_locals - - def format_stack_entry(self, frame_lineno, lprefix=': ', context=None): - if context is None: - context = self.context - try: - context = int(context) - if context <= 0: - print("Context must be a positive integer", file=self.stdout) - except (TypeError, ValueError): - print("Context must be a positive integer", file=self.stdout) - - import reprlib - - ret = [] - - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal) - tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal) - tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal) - tpl_line_em = "%%s%s%%s %s%%s%s" % (Colors.linenoEm, Colors.line, ColorsNormal) - - frame, lineno = frame_lineno - - return_value = '' - loc_frame = self._get_frame_locals(frame) - if "__return__" in loc_frame: - rv = loc_frame["__return__"] - # return_value += '->' - return_value += reprlib.repr(rv) + "\n" - ret.append(return_value) - - #s = filename + '(' + `lineno` + ')' - filename = self.canonic(frame.f_code.co_filename) - link = tpl_link % py3compat.cast_unicode(filename) - - if frame.f_code.co_name: - func = frame.f_code.co_name - else: - func = "" - - call = "" - if func != "?": - if "__args__" in loc_frame: - args = reprlib.repr(loc_frame["__args__"]) - else: - args = '()' - call = tpl_call % (func, args) - - # The level info should be generated in the same format pdb uses, to - # avoid breaking the pdbtrack functionality of python-mode in *emacs. - if frame is self.curframe: - ret.append('> ') - else: - ret.append(" ") - ret.append("%s(%s)%s\n" % (link, lineno, call)) - - start = lineno - 1 - context//2 - lines = linecache.getlines(filename) - start = min(start, len(lines) - context) - start = max(start, 0) - lines = lines[start : start + context] - - for i, line in enumerate(lines): - show_arrow = start + 1 + i == lineno - linetpl = (frame is self.curframe or show_arrow) and tpl_line_em or tpl_line - ret.append( - self.__format_line( - linetpl, filename, start + 1 + i, line, arrow=show_arrow - ) - ) - return "".join(ret) - - def __format_line(self, tpl_line, filename, lineno, line, arrow=False): - bp_mark = "" - bp_mark_color = "" - - new_line, err = self.parser.format2(line, 'str') - if not err: - line = new_line - - bp = None - if lineno in self.get_file_breaks(filename): - bps = self.get_breaks(filename, lineno) - bp = bps[-1] - - if bp: - Colors = self.color_scheme_table.active_colors - bp_mark = str(bp.number) - bp_mark_color = Colors.breakpoint_enabled - if not bp.enabled: - bp_mark_color = Colors.breakpoint_disabled - - numbers_width = 7 - if arrow: - # This is the line with the error - pad = numbers_width - len(str(lineno)) - len(bp_mark) - num = '%s%s' % (make_arrow(pad), str(lineno)) - else: - num = '%*s' % (numbers_width - len(bp_mark), str(lineno)) - - return tpl_line % (bp_mark_color + bp_mark, num, line) - - def print_list_lines(self, filename, first, last): - """The printing (as opposed to the parsing part of a 'list' - command.""" - try: - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) - tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal) - src = [] - if filename == "" and hasattr(self, "_exec_filename"): - filename = self._exec_filename - - for lineno in range(first, last+1): - line = linecache.getline(filename, lineno) - if not line: - break - - if lineno == self.curframe.f_lineno: - line = self.__format_line( - tpl_line_em, filename, lineno, line, arrow=True - ) - else: - line = self.__format_line( - tpl_line, filename, lineno, line, arrow=False - ) - - src.append(line) - self.lineno = lineno - - print(''.join(src), file=self.stdout) - - except KeyboardInterrupt: - pass - - def do_skip_predicates(self, args): - """ - Turn on/off individual predicates as to whether a frame should be hidden/skip. - - The global option to skip (or not) hidden frames is set with skip_hidden - - To change the value of a predicate - - skip_predicates key [true|false] - - Call without arguments to see the current values. - - To permanently change the value of an option add the corresponding - command to your ``~/.pdbrc`` file. If you are programmatically using the - Pdb instance you can also change the ``default_predicates`` class - attribute. - """ - if not args.strip(): - print("current predicates:") - for p, v in self._predicates.items(): - print(" ", p, ":", v) - return - type_value = args.strip().split(" ") - if len(type_value) != 2: - print( - f"Usage: skip_predicates , with one of {set(self._predicates.keys())}" - ) - return - - type_, value = type_value - if type_ not in self._predicates: - print(f"{type_!r} not in {set(self._predicates.keys())}") - return - if value.lower() not in ("true", "yes", "1", "no", "false", "0"): - print( - f"{value!r} is invalid - use one of ('true', 'yes', '1', 'no', 'false', '0')" - ) - return - - self._predicates[type_] = value.lower() in ("true", "yes", "1") - if not any(self._predicates.values()): - print( - "Warning, all predicates set to False, skip_hidden may not have any effects." - ) - - def do_skip_hidden(self, arg): - """ - Change whether or not we should skip frames with the - __tracebackhide__ attribute. - """ - if not arg.strip(): - print( - f"skip_hidden = {self.skip_hidden}, use 'yes','no', 'true', or 'false' to change." - ) - elif arg.strip().lower() in ("true", "yes"): - self.skip_hidden = True - elif arg.strip().lower() in ("false", "no"): - self.skip_hidden = False - if not any(self._predicates.values()): - print( - "Warning, all predicates set to False, skip_hidden may not have any effects." - ) - - def do_list(self, arg): - """Print lines of code from the current stack frame - """ - self.lastcmd = 'list' - last = None - if arg and arg != ".": - try: - x = eval(arg, {}, {}) - if type(x) == type(()): - first, last = x - first = int(first) - last = int(last) - if last < first: - # Assume it's a count - last = first + last - else: - first = max(1, int(x) - 5) - except: - print('*** Error in argument:', repr(arg), file=self.stdout) - return - elif self.lineno is None or arg == ".": - first = max(1, self.curframe.f_lineno - 5) - else: - first = self.lineno + 1 - if last is None: - last = first + 10 - self.print_list_lines(self.curframe.f_code.co_filename, first, last) - - # vds: >> - lineno = first - filename = self.curframe.f_code.co_filename - self.shell.hooks.synchronize_with_editor(filename, lineno, 0) - # vds: << - - do_l = do_list - - def getsourcelines(self, obj): - lines, lineno = inspect.findsource(obj) - if inspect.isframe(obj) and obj.f_globals is self._get_frame_locals(obj): - # must be a module frame: do not try to cut a block out of it - return lines, 1 - elif inspect.ismodule(obj): - return lines, 1 - return inspect.getblock(lines[lineno:]), lineno+1 - - def do_longlist(self, arg): - """Print lines of code from the current stack frame. - - Shows more lines than 'list' does. - """ - self.lastcmd = 'longlist' - try: - lines, lineno = self.getsourcelines(self.curframe) - except OSError as err: - self.error(err) - return - last = lineno + len(lines) - self.print_list_lines(self.curframe.f_code.co_filename, lineno, last) - do_ll = do_longlist - - def do_debug(self, arg): - """debug code - Enter a recursive debugger that steps through the code - argument (which is an arbitrary expression or statement to be - executed in the current environment). - """ - trace_function = sys.gettrace() - sys.settrace(None) - globals = self.curframe.f_globals - locals = self.curframe_locals - p = self.__class__(completekey=self.completekey, - stdin=self.stdin, stdout=self.stdout) - p.use_rawinput = self.use_rawinput - p.prompt = "(%s) " % self.prompt.strip() - self.message("ENTERING RECURSIVE DEBUGGER") - sys.call_tracing(p.run, (arg, globals, locals)) - self.message("LEAVING RECURSIVE DEBUGGER") - sys.settrace(trace_function) - self.lastcmd = p.lastcmd - - def do_pdef(self, arg): - """Print the call signature for any callable object. - - The debugger interface to %pdef""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pdef")(arg, namespaces=namespaces) - - def do_pdoc(self, arg): - """Print the docstring for an object. - - The debugger interface to %pdoc.""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pdoc")(arg, namespaces=namespaces) - - def do_pfile(self, arg): - """Print (or run through pager) the file where an object is defined. - - The debugger interface to %pfile. - """ - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pfile")(arg, namespaces=namespaces) - - def do_pinfo(self, arg): - """Provide detailed information about an object. - - The debugger interface to %pinfo, i.e., obj?.""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pinfo")(arg, namespaces=namespaces) - - def do_pinfo2(self, arg): - """Provide extra detailed information about an object. - - The debugger interface to %pinfo2, i.e., obj??.""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pinfo2")(arg, namespaces=namespaces) - - def do_psource(self, arg): - """Print (or run through pager) the source code for an object.""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("psource")(arg, namespaces=namespaces) - - def do_where(self, arg): - """w(here) - Print a stack trace, with the most recent frame at the bottom. - An arrow indicates the "current frame", which determines the - context of most commands. 'bt' is an alias for this command. - - Take a number as argument as an (optional) number of context line to - print""" - if arg: - try: - context = int(arg) - except ValueError as err: - self.error(err) - return - self.print_stack_trace(context) - else: - self.print_stack_trace() - - do_w = do_where - - def break_anywhere(self, frame): - """ - _stop_in_decorator_internals is overly restrictive, as we may still want - to trace function calls, so we need to also update break_anywhere so - that is we don't `stop_here`, because of debugger skip, we may still - stop at any point inside the function - - """ - - sup = super().break_anywhere(frame) - if sup: - return sup - if self._predicates["debuggerskip"]: - if DEBUGGERSKIP in frame.f_code.co_varnames: - return True - if frame.f_back and self._get_frame_locals(frame.f_back).get(DEBUGGERSKIP): - return True - return False - - def _is_in_decorator_internal_and_should_skip(self, frame): - """ - Utility to tell us whether we are in a decorator internal and should stop. - - """ - # if we are disabled don't skip - if not self._predicates["debuggerskip"]: - return False - - return self._cachable_skip(frame) - - @lru_cache(1024) - def _cached_one_parent_frame_debuggerskip(self, frame): - """ - Cache looking up for DEBUGGERSKIP on parent frame. - - This should speedup walking through deep frame when one of the highest - one does have a debugger skip. - - This is likely to introduce fake positive though. - """ - while getattr(frame, "f_back", None): - frame = frame.f_back - if self._get_frame_locals(frame).get(DEBUGGERSKIP): - return True - return None - - @lru_cache(1024) - def _cachable_skip(self, frame): - # if frame is tagged, skip by default. - if DEBUGGERSKIP in frame.f_code.co_varnames: - return True - - # if one of the parent frame value set to True skip as well. - if self._cached_one_parent_frame_debuggerskip(frame): - return True - - return False - - def stop_here(self, frame): - if self._is_in_decorator_internal_and_should_skip(frame) is True: - return False - - hidden = False - if self.skip_hidden: - hidden = self._hidden_predicate(frame) - if hidden: - if self.report_skipped: - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - print( - f"{Colors.excName} [... skipped 1 hidden frame]{ColorsNormal}\n" - ) - return super().stop_here(frame) - - def do_up(self, arg): - """u(p) [count] - Move the current frame count (default one) levels up in the - stack trace (to an older frame). - - Will skip hidden frames. - """ - # modified version of upstream that skips - # frames with __tracebackhide__ - if self.curindex == 0: - self.error("Oldest frame") - return - try: - count = int(arg or 1) - except ValueError: - self.error("Invalid frame count (%s)" % arg) - return - skipped = 0 - if count < 0: - _newframe = 0 - else: - counter = 0 - hidden_frames = self.hidden_frames(self.stack) - for i in range(self.curindex - 1, -1, -1): - if hidden_frames[i] and self.skip_hidden: - skipped += 1 - continue - counter += 1 - if counter >= count: - break - else: - # if no break occurred. - self.error( - "all frames above hidden, use `skip_hidden False` to get get into those." - ) - return - - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - _newframe = i - self._select_frame(_newframe) - if skipped: - print( - f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n" - ) - - def do_down(self, arg): - """d(own) [count] - Move the current frame count (default one) levels down in the - stack trace (to a newer frame). - - Will skip hidden frames. - """ - if self.curindex + 1 == len(self.stack): - self.error("Newest frame") - return - try: - count = int(arg or 1) - except ValueError: - self.error("Invalid frame count (%s)" % arg) - return - if count < 0: - _newframe = len(self.stack) - 1 - else: - counter = 0 - skipped = 0 - hidden_frames = self.hidden_frames(self.stack) - for i in range(self.curindex + 1, len(self.stack)): - if hidden_frames[i] and self.skip_hidden: - skipped += 1 - continue - counter += 1 - if counter >= count: - break - else: - self.error( - "all frames below hidden, use `skip_hidden False` to get get into those." - ) - return - - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - if skipped: - print( - f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n" - ) - _newframe = i - - self._select_frame(_newframe) - - do_d = do_down - do_u = do_up - - def do_context(self, context): - """context number_of_lines - Set the number of lines of source code to show when displaying - stacktrace information. - """ - try: - new_context = int(context) - if new_context <= 0: - raise ValueError() - self.context = new_context - except ValueError: - self.error( - f"The 'context' command requires a positive integer argument (current value {self.context})." - ) - - -class InterruptiblePdb(Pdb): - """Version of debugger where KeyboardInterrupt exits the debugger altogether.""" - - def cmdloop(self, intro=None): - """Wrap cmdloop() such that KeyboardInterrupt stops the debugger.""" - try: - return OldPdb.cmdloop(self, intro=intro) - except KeyboardInterrupt: - self.stop_here = lambda frame: False - self.do_quit("") - sys.settrace(None) - self.quitting = False - raise - - def _cmdloop(self): - while True: - try: - # keyboard interrupts allow for an easy way to cancel - # the current command, so allow them during interactive input - self.allow_kbdint = True - self.cmdloop() - self.allow_kbdint = False - break - except KeyboardInterrupt: - self.message('--KeyboardInterrupt--') - raise - - -def set_trace(frame=None, header=None): - """ - Start debugging from `frame`. - - If frame is not specified, debugging starts from caller's frame. - """ - pdb = Pdb() - if header is not None: - pdb.message(header) - pdb.set_trace(frame or sys._getframe().f_back) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/display.py b/.venv/lib/python3.12/site-packages/IPython/core/display.py deleted file mode 100644 index a943447..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/display.py +++ /dev/null @@ -1,1373 +0,0 @@ -# -*- coding: utf-8 -*- -"""Top-level display functions for displaying object in different formats.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -from binascii import b2a_base64, hexlify -import html -import json -import mimetypes -import os -import struct -import warnings -from copy import deepcopy -from os.path import splitext -from pathlib import Path, PurePath - -from typing import Optional - -from IPython.testing.skipdoctest import skip_doctest -from . import display_functions - - -__all__ = [ - "display_pretty", - "display_html", - "display_markdown", - "display_svg", - "display_png", - "display_jpeg", - "display_webp", - "display_latex", - "display_json", - "display_javascript", - "display_pdf", - "DisplayObject", - "TextDisplayObject", - "Pretty", - "HTML", - "Markdown", - "Math", - "Latex", - "SVG", - "ProgressBar", - "JSON", - "GeoJSON", - "Javascript", - "Image", - "set_matplotlib_formats", - "set_matplotlib_close", - "Video", -] - -_deprecated_names = ["display", "clear_output", "publish_display_data", "update_display", "DisplayHandle"] - -__all__ = __all__ + _deprecated_names - - -# ----- warn to import from IPython.display ----- - -from warnings import warn - - -def __getattr__(name): - if name in _deprecated_names: - warn( - f"Importing {name} from IPython.core.display is deprecated since IPython 7.14, please import from IPython.display", - DeprecationWarning, - stacklevel=2, - ) - return getattr(display_functions, name) - - if name in globals().keys(): - return globals()[name] - else: - raise AttributeError(f"module {__name__} has no attribute {name}") - - -#----------------------------------------------------------------------------- -# utility functions -#----------------------------------------------------------------------------- - -def _safe_exists(path): - """Check path, but don't let exceptions raise""" - try: - return os.path.exists(path) - except Exception: - return False - - -def _display_mimetype(mimetype, objs, raw=False, metadata=None): - """internal implementation of all display_foo methods - - Parameters - ---------- - mimetype : str - The mimetype to be published (e.g. 'image/png') - *objs : object - The Python objects to display, or if raw=True raw text data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - if metadata: - metadata = {mimetype: metadata} - if raw: - # turn list of pngdata into list of { 'image/png': pngdata } - objs = [ {mimetype: obj} for obj in objs ] - display_functions.display(*objs, raw=raw, metadata=metadata, include=[mimetype]) - -#----------------------------------------------------------------------------- -# Main functions -#----------------------------------------------------------------------------- - - -def display_pretty(*objs, **kwargs): - """Display the pretty (default) representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw text data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('text/plain', objs, **kwargs) - - -def display_html(*objs, **kwargs): - """Display the HTML representation of an object. - - Note: If raw=False and the object does not have a HTML - representation, no HTML will be shown. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw HTML data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('text/html', objs, **kwargs) - - -def display_markdown(*objs, **kwargs): - """Displays the Markdown representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw markdown data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - - _display_mimetype('text/markdown', objs, **kwargs) - - -def display_svg(*objs, **kwargs): - """Display the SVG representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw svg data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('image/svg+xml', objs, **kwargs) - - -def display_png(*objs, **kwargs): - """Display the PNG representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw png data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('image/png', objs, **kwargs) - - -def display_jpeg(*objs, **kwargs): - """Display the JPEG representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw JPEG data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('image/jpeg', objs, **kwargs) - - -def display_webp(*objs, **kwargs): - """Display the WEBP representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw JPEG data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype("image/webp", objs, **kwargs) - - -def display_latex(*objs, **kwargs): - """Display the LaTeX representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw latex data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('text/latex', objs, **kwargs) - - -def display_json(*objs, **kwargs): - """Display the JSON representation of an object. - - Note that not many frontends support displaying JSON. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw json data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('application/json', objs, **kwargs) - - -def display_javascript(*objs, **kwargs): - """Display the Javascript representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw javascript data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('application/javascript', objs, **kwargs) - - -def display_pdf(*objs, **kwargs): - """Display the PDF representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw javascript data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('application/pdf', objs, **kwargs) - - -#----------------------------------------------------------------------------- -# Smart classes -#----------------------------------------------------------------------------- - - -class DisplayObject(object): - """An object that wraps data to be displayed.""" - - _read_flags = 'r' - _show_mem_addr = False - metadata = None - - def __init__(self, data=None, url=None, filename=None, metadata=None): - """Create a display object given raw data. - - When this object is returned by an expression or passed to the - display function, it will result in the data being displayed - in the frontend. The MIME type of the data should match the - subclasses used, so the Png subclass should be used for 'image/png' - data. If the data is a URL, the data will first be downloaded - and then displayed. - - Parameters - ---------- - data : unicode, str or bytes - The raw data or a URL or file to load the data from - url : unicode - A URL to download the data from. - filename : unicode - Path to a local file to load the data from. - metadata : dict - Dict of metadata associated to be the object when displayed - """ - if isinstance(data, (Path, PurePath)): - data = str(data) - - if data is not None and isinstance(data, str): - if data.startswith('http') and url is None: - url = data - filename = None - data = None - elif _safe_exists(data) and filename is None: - url = None - filename = data - data = None - - self.url = url - self.filename = filename - # because of @data.setter methods in - # subclasses ensure url and filename are set - # before assigning to self.data - self.data = data - - if metadata is not None: - self.metadata = metadata - elif self.metadata is None: - self.metadata = {} - - self.reload() - self._check_data() - - def __repr__(self): - if not self._show_mem_addr: - cls = self.__class__ - r = "<%s.%s object>" % (cls.__module__, cls.__name__) - else: - r = super(DisplayObject, self).__repr__() - return r - - def _check_data(self): - """Override in subclasses if there's something to check.""" - pass - - def _data_and_metadata(self): - """shortcut for returning metadata with shape information, if defined""" - if self.metadata: - return self.data, deepcopy(self.metadata) - else: - return self.data - - def reload(self): - """Reload the raw data from file or URL.""" - if self.filename is not None: - encoding = None if "b" in self._read_flags else "utf-8" - with open(self.filename, self._read_flags, encoding=encoding) as f: - self.data = f.read() - elif self.url is not None: - # Deferred import - from urllib.request import urlopen - response = urlopen(self.url) - data = response.read() - # extract encoding from header, if there is one: - encoding = None - if 'content-type' in response.headers: - for sub in response.headers['content-type'].split(';'): - sub = sub.strip() - if sub.startswith('charset'): - encoding = sub.split('=')[-1].strip() - break - if 'content-encoding' in response.headers: - # TODO: do deflate? - if 'gzip' in response.headers['content-encoding']: - import gzip - from io import BytesIO - - # assume utf-8 if encoding is not specified - with gzip.open( - BytesIO(data), "rt", encoding=encoding or "utf-8" - ) as fp: - encoding = None - data = fp.read() - - # decode data, if an encoding was specified - # We only touch self.data once since - # subclasses such as SVG have @data.setter methods - # that transform self.data into ... well svg. - if encoding: - self.data = data.decode(encoding, 'replace') - else: - self.data = data - - -class TextDisplayObject(DisplayObject): - """Create a text display object given raw data. - - Parameters - ---------- - data : str or unicode - The raw data or a URL or file to load the data from. - url : unicode - A URL to download the data from. - filename : unicode - Path to a local file to load the data from. - metadata : dict - Dict of metadata associated to be the object when displayed - """ - def _check_data(self): - if self.data is not None and not isinstance(self.data, str): - raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data)) - -class Pretty(TextDisplayObject): - - def _repr_pretty_(self, pp, cycle): - return pp.text(self.data) - - -class HTML(TextDisplayObject): - - def __init__(self, data=None, url=None, filename=None, metadata=None): - def warn(): - if not data: - return False - - # - # Avoid calling lower() on the entire data, because it could be a - # long string and we're only interested in its beginning and end. - # - prefix = data[:10].lower() - suffix = data[-10:].lower() - return prefix.startswith("') - m_warn.assert_not_called() - - display.HTML('') - m_warn.assert_called_with('Consider using IPython.display.IFrame instead') - - m_warn.reset_mock() - display.HTML('') - m_warn.assert_called_with('Consider using IPython.display.IFrame instead') - -def test_progress(): - p = display.ProgressBar(10) - assert "0/10" in repr(p) - p.html_width = "100%" - p.progress = 5 - assert ( - p._repr_html_() == "" - ) - - -def test_progress_iter(): - with capture_output(display=False) as captured: - for i in display.ProgressBar(5): - out = captured.stdout - assert "{0}/5".format(i) in out - out = captured.stdout - assert "5/5" in out - - -def test_json(): - d = {'a': 5} - lis = [d] - metadata = [ - {'expanded': False, 'root': 'root'}, - {'expanded': True, 'root': 'root'}, - {'expanded': False, 'root': 'custom'}, - {'expanded': True, 'root': 'custom'}, - ] - json_objs = [ - display.JSON(d), - display.JSON(d, expanded=True), - display.JSON(d, root='custom'), - display.JSON(d, expanded=True, root='custom'), - ] - for j, md in zip(json_objs, metadata): - assert j._repr_json_() == (d, md) - - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - j = display.JSON(json.dumps(d)) - assert len(w) == 1 - assert j._repr_json_() == (d, metadata[0]) - - json_objs = [ - display.JSON(lis), - display.JSON(lis, expanded=True), - display.JSON(lis, root='custom'), - display.JSON(lis, expanded=True, root='custom'), - ] - for j, md in zip(json_objs, metadata): - assert j._repr_json_() == (lis, md) - - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - j = display.JSON(json.dumps(lis)) - assert len(w) == 1 - assert j._repr_json_() == (lis, metadata[0]) - - -def test_video_embedding(): - """use a tempfile, with dummy-data, to ensure that video embedding doesn't crash""" - v = display.Video("http://ignored") - assert not v.embed - html = v._repr_html_() - assert 'src="data:' not in html - assert 'src="http://ignored"' in html - - with pytest.raises(ValueError): - v = display.Video(b'abc') - - with NamedFileInTemporaryDirectory('test.mp4') as f: - f.write(b'abc') - f.close() - - v = display.Video(f.name) - assert not v.embed - html = v._repr_html_() - assert 'src="data:' not in html - - v = display.Video(f.name, embed=True) - html = v._repr_html_() - assert 'src="data:video/mp4;base64,YWJj"' in html - - v = display.Video(f.name, embed=True, mimetype='video/other') - html = v._repr_html_() - assert 'src="data:video/other;base64,YWJj"' in html - - v = display.Video(b'abc', embed=True, mimetype='video/mp4') - html = v._repr_html_() - assert 'src="data:video/mp4;base64,YWJj"' in html - - v = display.Video(u'YWJj', embed=True, mimetype='video/xyz') - html = v._repr_html_() - assert 'src="data:video/xyz;base64,YWJj"' in html - -def test_html_metadata(): - s = "

Test

" - h = display.HTML(s, metadata={"isolated": True}) - assert h._repr_html_() == (s, {"isolated": True}) - - -def test_display_id(): - ip = get_ipython() - with mock.patch.object(ip.display_pub, 'publish') as pub: - handle = display.display('x') - assert handle is None - handle = display.display('y', display_id='secret') - assert isinstance(handle, display.DisplayHandle) - handle2 = display.display('z', display_id=True) - assert isinstance(handle2, display.DisplayHandle) - assert handle.display_id != handle2.display_id - - assert pub.call_count == 3 - args, kwargs = pub.call_args_list[0] - assert args == () - assert kwargs == { - 'data': { - 'text/plain': repr('x') - }, - 'metadata': {}, - } - args, kwargs = pub.call_args_list[1] - assert args == () - assert kwargs == { - 'data': { - 'text/plain': repr('y') - }, - 'metadata': {}, - 'transient': { - 'display_id': handle.display_id, - }, - } - args, kwargs = pub.call_args_list[2] - assert args == () - assert kwargs == { - 'data': { - 'text/plain': repr('z') - }, - 'metadata': {}, - 'transient': { - 'display_id': handle2.display_id, - }, - } - - -def test_update_display(): - ip = get_ipython() - with mock.patch.object(ip.display_pub, 'publish') as pub: - with pytest.raises(TypeError): - display.update_display('x') - display.update_display('x', display_id='1') - display.update_display('y', display_id='2') - args, kwargs = pub.call_args_list[0] - assert args == () - assert kwargs == { - 'data': { - 'text/plain': repr('x') - }, - 'metadata': {}, - 'transient': { - 'display_id': '1', - }, - 'update': True, - } - args, kwargs = pub.call_args_list[1] - assert args == () - assert kwargs == { - 'data': { - 'text/plain': repr('y') - }, - 'metadata': {}, - 'transient': { - 'display_id': '2', - }, - 'update': True, - } - - -def test_display_handle(): - ip = get_ipython() - handle = display.DisplayHandle() - assert isinstance(handle.display_id, str) - handle = display.DisplayHandle("my-id") - assert handle.display_id == "my-id" - with mock.patch.object(ip.display_pub, "publish") as pub: - handle.display("x") - handle.update("y") - - args, kwargs = pub.call_args_list[0] - assert args == () - assert kwargs == { - 'data': { - 'text/plain': repr('x') - }, - 'metadata': {}, - 'transient': { - 'display_id': handle.display_id, - } - } - args, kwargs = pub.call_args_list[1] - assert args == () - assert kwargs == { - 'data': { - 'text/plain': repr('y') - }, - 'metadata': {}, - 'transient': { - 'display_id': handle.display_id, - }, - 'update': True, - } - - -def test_image_alt_tag(): - """Simple test for display.Image(args, alt=x,)""" - thisurl = "http://example.com/image.png" - img = display.Image(url=thisurl, alt="an image") - assert 'an image' % (thisurl) == img._repr_html_() - img = display.Image(url=thisurl, unconfined=True, alt="an image") - assert ( - 'an image' % (thisurl) - == img._repr_html_() - ) - img = display.Image(url=thisurl, alt='>"& <') - assert '>"& <' % (thisurl) == img._repr_html_() - - img = display.Image(url=thisurl, metadata={"alt": "an image"}) - assert img.alt == "an image" - here = os.path.dirname(__file__) - img = display.Image(os.path.join(here, "2x2.png"), alt="an image") - assert img.alt == "an image" - _, md = img._repr_png_() - assert md["alt"] == "an image" - - -def test_image_bad_filename_raises_proper_exception(): - with pytest.raises(FileNotFoundError): - display.Image("/this/file/does/not/exist/")._repr_png_() diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_displayhook.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_displayhook.py deleted file mode 100644 index 22899f3..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_displayhook.py +++ /dev/null @@ -1,112 +0,0 @@ -import sys -from IPython.testing.tools import AssertPrints, AssertNotPrints -from IPython.core.displayhook import CapturingDisplayHook -from IPython.utils.capture import CapturedIO - -def test_output_displayed(): - """Checking to make sure that output is displayed""" - - with AssertPrints('2'): - ip.run_cell('1+1', store_history=True) - - with AssertPrints('2'): - ip.run_cell('1+1 # comment with a semicolon;', store_history=True) - - with AssertPrints('2'): - ip.run_cell('1+1\n#commented_out_function();', store_history=True) - - -def test_output_quiet(): - """Checking to make sure that output is quiet""" - - with AssertNotPrints('2'): - ip.run_cell('1+1;', store_history=True) - - with AssertNotPrints('2'): - ip.run_cell('1+1; # comment with a semicolon', store_history=True) - - with AssertNotPrints('2'): - ip.run_cell('1+1;\n#commented_out_function()', store_history=True) - -def test_underscore_no_overwrite_user(): - ip.run_cell('_ = 42', store_history=True) - ip.run_cell('1+1', store_history=True) - - with AssertPrints('42'): - ip.run_cell('print(_)', store_history=True) - - ip.run_cell('del _', store_history=True) - ip.run_cell('6+6', store_history=True) - with AssertPrints('12'): - ip.run_cell('_', store_history=True) - - -def test_underscore_no_overwrite_builtins(): - ip.run_cell("import gettext ; gettext.install('foo')", store_history=True) - ip.run_cell('3+3', store_history=True) - - with AssertPrints('gettext'): - ip.run_cell('print(_)', store_history=True) - - ip.run_cell('_ = "userset"', store_history=True) - - with AssertPrints('userset'): - ip.run_cell('print(_)', store_history=True) - ip.run_cell('import builtins; del builtins._') - - -def test_interactivehooks_ast_modes(): - """ - Test that ast nodes can be triggered with different modes - """ - saved_mode = ip.ast_node_interactivity - ip.ast_node_interactivity = 'last_expr_or_assign' - - try: - with AssertPrints('2'): - ip.run_cell('a = 1+1', store_history=True) - - with AssertPrints('9'): - ip.run_cell('b = 1+8 # comment with a semicolon;', store_history=False) - - with AssertPrints('7'): - ip.run_cell('c = 1+6\n#commented_out_function();', store_history=True) - - ip.run_cell('d = 11', store_history=True) - with AssertPrints('12'): - ip.run_cell('d += 1', store_history=True) - - with AssertNotPrints('42'): - ip.run_cell('(u,v) = (41+1, 43-1)') - - finally: - ip.ast_node_interactivity = saved_mode - -def test_interactivehooks_ast_modes_semi_suppress(): - """ - Test that ast nodes can be triggered with different modes and suppressed - by semicolon - """ - saved_mode = ip.ast_node_interactivity - ip.ast_node_interactivity = 'last_expr_or_assign' - - try: - with AssertNotPrints('2'): - ip.run_cell('x = 1+1;', store_history=True) - - with AssertNotPrints('7'): - ip.run_cell('y = 1+6; # comment with a semicolon', store_history=True) - - with AssertNotPrints('9'): - ip.run_cell('z = 1+8;\n#commented_out_function()', store_history=True) - - finally: - ip.ast_node_interactivity = saved_mode - -def test_capture_display_hook_format(): - """Tests that the capture display hook conforms to the CapturedIO output format""" - hook = CapturingDisplayHook(ip) - hook({"foo": "bar"}) - captured = CapturedIO(sys.stdout, sys.stderr, hook.outputs) - # Should not raise with RichOutput transformation error - captured.outputs diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_events.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_events.py deleted file mode 100644 index 61bc01d..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_events.py +++ /dev/null @@ -1,78 +0,0 @@ -import unittest -from unittest.mock import Mock - -from IPython.core import events -import IPython.testing.tools as tt - - -@events._define_event -def ping_received(): - pass - - -@events._define_event -def event_with_argument(argument): - pass - - -class CallbackTests(unittest.TestCase): - def setUp(self): - self.em = events.EventManager(get_ipython(), - {'ping_received': ping_received, - 'event_with_argument': event_with_argument}) - - def test_register_unregister(self): - cb = Mock() - - self.em.register('ping_received', cb) - self.em.trigger('ping_received') - self.assertEqual(cb.call_count, 1) - - self.em.unregister('ping_received', cb) - self.em.trigger('ping_received') - self.assertEqual(cb.call_count, 1) - - def test_bare_function_missed_unregister(self): - def cb1(): - ... - - def cb2(): - ... - - self.em.register("ping_received", cb1) - self.assertRaises(ValueError, self.em.unregister, "ping_received", cb2) - self.em.unregister("ping_received", cb1) - - def test_cb_error(self): - cb = Mock(side_effect=ValueError) - self.em.register('ping_received', cb) - with tt.AssertPrints("Error in callback"): - self.em.trigger('ping_received') - - def test_cb_keyboard_interrupt(self): - cb = Mock(side_effect=KeyboardInterrupt) - self.em.register('ping_received', cb) - with tt.AssertPrints("Error in callback"): - self.em.trigger('ping_received') - - def test_unregister_during_callback(self): - invoked = [False] * 3 - - def func1(*_): - invoked[0] = True - self.em.unregister('ping_received', func1) - self.em.register('ping_received', func3) - - def func2(*_): - invoked[1] = True - self.em.unregister('ping_received', func2) - - def func3(*_): - invoked[2] = True - - self.em.register('ping_received', func1) - self.em.register('ping_received', func2) - - self.em.trigger('ping_received') - self.assertEqual([True, True, False], invoked) - self.assertEqual([func3], self.em.callbacks['ping_received']) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_exceptiongroup_tb.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_exceptiongroup_tb.py deleted file mode 100644 index c8e8002..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_exceptiongroup_tb.py +++ /dev/null @@ -1,112 +0,0 @@ -import unittest -import re -from IPython.utils.capture import capture_output -import sys -import pytest -from tempfile import TemporaryDirectory -from IPython.testing import tools as tt - - -def _exceptiongroup_common( - outer_chain: str, - inner_chain: str, - native: bool, -) -> None: - pre_raise = "exceptiongroup." if not native else "" - pre_catch = pre_raise if sys.version_info < (3, 11) else "" - filestr = f""" - {"import exceptiongroup" if not native else ""} - import pytest - - def f(): raise ValueError("From f()") - def g(): raise BaseException("From g()") - - def inner(inner_chain): - excs = [] - for callback in [f, g]: - try: - callback() - except BaseException as err: - excs.append(err) - if excs: - if inner_chain == "none": - raise {pre_raise}BaseExceptionGroup("Oops", excs) - try: - raise SyntaxError() - except SyntaxError as e: - if inner_chain == "from": - raise {pre_raise}BaseExceptionGroup("Oops", excs) from e - else: - raise {pre_raise}BaseExceptionGroup("Oops", excs) - - def outer(outer_chain, inner_chain): - try: - inner(inner_chain) - except {pre_catch}BaseExceptionGroup as e: - if outer_chain == "none": - raise - if outer_chain == "from": - raise IndexError() from e - else: - raise IndexError - - - outer("{outer_chain}", "{inner_chain}") - """ - with capture_output() as cap: - ip.run_cell(filestr) - - match_lines = [] - if inner_chain == "another": - match_lines += [ - "During handling of the above exception, another exception occurred:", - ] - elif inner_chain == "from": - match_lines += [ - "The above exception was the direct cause of the following exception:", - ] - - match_lines += [ - " + Exception Group Traceback (most recent call last):", - f" | {pre_catch}BaseExceptionGroup: Oops (2 sub-exceptions)", - " | ValueError: From f()", - " | BaseException: From g()", - ] - - if outer_chain == "another": - match_lines += [ - "During handling of the above exception, another exception occurred:", - "IndexError", - ] - elif outer_chain == "from": - match_lines += [ - "The above exception was the direct cause of the following exception:", - "IndexError", - ] - - error_lines = cap.stderr.split("\n") - - err_index = match_index = 0 - for expected in match_lines: - for i, actual in enumerate(error_lines): - if actual == expected: - error_lines = error_lines[i + 1 :] - break - else: - assert False, f"{expected} not found in cap.stderr" - - -@pytest.mark.skipif( - sys.version_info < (3, 11), reason="Native ExceptionGroup not implemented" -) -@pytest.mark.parametrize("outer_chain", ["none", "from", "another"]) -@pytest.mark.parametrize("inner_chain", ["none", "from", "another"]) -def test_native_exceptiongroup(outer_chain, inner_chain) -> None: - _exceptiongroup_common(outer_chain, inner_chain, native=True) - - -@pytest.mark.parametrize("outer_chain", ["none", "from", "another"]) -@pytest.mark.parametrize("inner_chain", ["none", "from", "another"]) -def test_native_exceptiongroup(outer_chain, inner_chain) -> None: - pytest.importorskip("exceptiongroup") - _exceptiongroup_common(outer_chain, inner_chain, native=False) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_extension.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_extension.py deleted file mode 100644 index 24ecf7e..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_extension.py +++ /dev/null @@ -1,95 +0,0 @@ -import os.path - -from tempfile import TemporaryDirectory - -import IPython.testing.tools as tt -from IPython.utils.syspathcontext import prepended_to_syspath - -ext1_content = """ -def load_ipython_extension(ip): - print("Running ext1 load") - -def unload_ipython_extension(ip): - print("Running ext1 unload") -""" - -ext2_content = """ -def load_ipython_extension(ip): - print("Running ext2 load") -""" - -ext3_content = """ -def load_ipython_extension(ip): - ip2 = get_ipython() - print(ip is ip2) -""" - -def test_extension_loading(): - em = get_ipython().extension_manager - with TemporaryDirectory() as td: - ext1 = os.path.join(td, "ext1.py") - with open(ext1, "w", encoding="utf-8") as f: - f.write(ext1_content) - - ext2 = os.path.join(td, "ext2.py") - with open(ext2, "w", encoding="utf-8") as f: - f.write(ext2_content) - - with prepended_to_syspath(td): - assert 'ext1' not in em.loaded - assert 'ext2' not in em.loaded - - # Load extension - with tt.AssertPrints("Running ext1 load"): - assert em.load_extension('ext1') is None - assert 'ext1' in em.loaded - - # Should refuse to load it again - with tt.AssertNotPrints("Running ext1 load"): - assert em.load_extension('ext1') == 'already loaded' - - # Reload - with tt.AssertPrints("Running ext1 unload"): - with tt.AssertPrints("Running ext1 load", suppress=False): - em.reload_extension('ext1') - - # Unload - with tt.AssertPrints("Running ext1 unload"): - assert em.unload_extension('ext1') is None - - # Can't unload again - with tt.AssertNotPrints("Running ext1 unload"): - assert em.unload_extension('ext1') == 'not loaded' - assert em.unload_extension('ext2') == 'not loaded' - - # Load extension 2 - with tt.AssertPrints("Running ext2 load"): - assert em.load_extension('ext2') is None - - # Can't unload this - assert em.unload_extension('ext2') == 'no unload function' - - # But can reload it - with tt.AssertPrints("Running ext2 load"): - em.reload_extension('ext2') - - -def test_extension_builtins(): - em = get_ipython().extension_manager - with TemporaryDirectory() as td: - ext3 = os.path.join(td, "ext3.py") - with open(ext3, "w", encoding="utf-8") as f: - f.write(ext3_content) - - assert 'ext3' not in em.loaded - - with prepended_to_syspath(td): - # Load extension - with tt.AssertPrints("True"): - assert em.load_extension('ext3') is None - assert 'ext3' in em.loaded - - -def test_non_extension(): - em = get_ipython().extension_manager - assert em.load_extension("sys") == "no load function" diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_formatters.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_formatters.py deleted file mode 100644 index 5f8eeda..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_formatters.py +++ /dev/null @@ -1,545 +0,0 @@ -"""Tests for the Formatters.""" - -from math import pi - -try: - import numpy -except: - numpy = None -import pytest - -from IPython import get_ipython -from traitlets.config import Config -from IPython.core.formatters import ( - PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key, - DisplayFormatter, JSONFormatter, -) -from IPython.utils.io import capture_output - -class A(object): - def __repr__(self): - return 'A()' - -class B(A): - def __repr__(self): - return 'B()' - -class C: - pass - -class BadRepr(object): - def __repr__(self): - raise ValueError("bad repr") - -class BadPretty(object): - _repr_pretty_ = None - -class GoodPretty(object): - def _repr_pretty_(self, pp, cycle): - pp.text('foo') - - def __repr__(self): - return 'GoodPretty()' - -def foo_printer(obj, pp, cycle): - pp.text('foo') - -def test_pretty(): - f = PlainTextFormatter() - f.for_type(A, foo_printer) - assert f(A()) == "foo" - assert f(B()) == "B()" - assert f(GoodPretty()) == "foo" - # Just don't raise an exception for the following: - f(BadPretty()) - - f.pprint = False - assert f(A()) == "A()" - assert f(B()) == "B()" - assert f(GoodPretty()) == "GoodPretty()" - - -def test_deferred(): - f = PlainTextFormatter() - -def test_precision(): - """test various values for float_precision.""" - f = PlainTextFormatter() - assert f(pi) == repr(pi) - f.float_precision = 0 - if numpy: - po = numpy.get_printoptions() - assert po["precision"] == 0 - assert f(pi) == "3" - f.float_precision = 2 - if numpy: - po = numpy.get_printoptions() - assert po["precision"] == 2 - assert f(pi) == "3.14" - f.float_precision = "%g" - if numpy: - po = numpy.get_printoptions() - assert po["precision"] == 2 - assert f(pi) == "3.14159" - f.float_precision = "%e" - assert f(pi) == "3.141593e+00" - f.float_precision = "" - if numpy: - po = numpy.get_printoptions() - assert po["precision"] == 8 - assert f(pi) == repr(pi) - - -def test_bad_precision(): - """test various invalid values for float_precision.""" - f = PlainTextFormatter() - def set_fp(p): - f.float_precision = p - - pytest.raises(ValueError, set_fp, "%") - pytest.raises(ValueError, set_fp, "%.3f%i") - pytest.raises(ValueError, set_fp, "foo") - pytest.raises(ValueError, set_fp, -1) - -def test_for_type(): - f = PlainTextFormatter() - - # initial return, None - assert f.for_type(C, foo_printer) is None - # no func queries - assert f.for_type(C) is foo_printer - # shouldn't change anything - assert f.for_type(C) is foo_printer - # None should do the same - assert f.for_type(C, None) is foo_printer - assert f.for_type(C, None) is foo_printer - -def test_for_type_string(): - f = PlainTextFormatter() - - type_str = '%s.%s' % (C.__module__, 'C') - - # initial return, None - assert f.for_type(type_str, foo_printer) is None - # no func queries - assert f.for_type(type_str) is foo_printer - assert _mod_name_key(C) in f.deferred_printers - assert f.for_type(C) is foo_printer - assert _mod_name_key(C) not in f.deferred_printers - assert C in f.type_printers - -def test_for_type_by_name(): - f = PlainTextFormatter() - - mod = C.__module__ - - # initial return, None - assert f.for_type_by_name(mod, "C", foo_printer) is None - # no func queries - assert f.for_type_by_name(mod, "C") is foo_printer - # shouldn't change anything - assert f.for_type_by_name(mod, "C") is foo_printer - # None should do the same - assert f.for_type_by_name(mod, "C", None) is foo_printer - assert f.for_type_by_name(mod, "C", None) is foo_printer - - -def test_lookup(): - f = PlainTextFormatter() - - f.for_type(C, foo_printer) - assert f.lookup(C()) is foo_printer - with pytest.raises(KeyError): - f.lookup(A()) - -def test_lookup_string(): - f = PlainTextFormatter() - type_str = '%s.%s' % (C.__module__, 'C') - - f.for_type(type_str, foo_printer) - assert f.lookup(C()) is foo_printer - # should move from deferred to imported dict - assert _mod_name_key(C) not in f.deferred_printers - assert C in f.type_printers - -def test_lookup_by_type(): - f = PlainTextFormatter() - f.for_type(C, foo_printer) - assert f.lookup_by_type(C) is foo_printer - with pytest.raises(KeyError): - f.lookup_by_type(A) - -def test_lookup_by_type_string(): - f = PlainTextFormatter() - type_str = '%s.%s' % (C.__module__, 'C') - f.for_type(type_str, foo_printer) - - # verify insertion - assert _mod_name_key(C) in f.deferred_printers - assert C not in f.type_printers - - assert f.lookup_by_type(type_str) is foo_printer - # lookup by string doesn't cause import - assert _mod_name_key(C) in f.deferred_printers - assert C not in f.type_printers - - assert f.lookup_by_type(C) is foo_printer - # should move from deferred to imported dict - assert _mod_name_key(C) not in f.deferred_printers - assert C in f.type_printers - -def test_in_formatter(): - f = PlainTextFormatter() - f.for_type(C, foo_printer) - type_str = '%s.%s' % (C.__module__, 'C') - assert C in f - assert type_str in f - -def test_string_in_formatter(): - f = PlainTextFormatter() - type_str = '%s.%s' % (C.__module__, 'C') - f.for_type(type_str, foo_printer) - assert type_str in f - assert C in f - -def test_pop(): - f = PlainTextFormatter() - f.for_type(C, foo_printer) - assert f.lookup_by_type(C) is foo_printer - assert f.pop(C, None) is foo_printer - f.for_type(C, foo_printer) - assert f.pop(C) is foo_printer - with pytest.raises(KeyError): - f.lookup_by_type(C) - with pytest.raises(KeyError): - f.pop(C) - with pytest.raises(KeyError): - f.pop(A) - assert f.pop(A, None) is None - -def test_pop_string(): - f = PlainTextFormatter() - type_str = '%s.%s' % (C.__module__, 'C') - - with pytest.raises(KeyError): - f.pop(type_str) - - f.for_type(type_str, foo_printer) - f.pop(type_str) - with pytest.raises(KeyError): - f.lookup_by_type(C) - with pytest.raises(KeyError): - f.pop(type_str) - - f.for_type(C, foo_printer) - assert f.pop(type_str, None) is foo_printer - with pytest.raises(KeyError): - f.lookup_by_type(C) - with pytest.raises(KeyError): - f.pop(type_str) - assert f.pop(type_str, None) is None - - -def test_error_method(): - f = HTMLFormatter() - class BadHTML(object): - def _repr_html_(self): - raise ValueError("Bad HTML") - bad = BadHTML() - with capture_output() as captured: - result = f(bad) - assert result is None - assert "Traceback" in captured.stdout - assert "Bad HTML" in captured.stdout - assert "_repr_html_" in captured.stdout - -def test_nowarn_notimplemented(): - f = HTMLFormatter() - class HTMLNotImplemented(object): - def _repr_html_(self): - raise NotImplementedError - h = HTMLNotImplemented() - with capture_output() as captured: - result = f(h) - assert result is None - assert "" == captured.stderr - assert "" == captured.stdout - - -def test_warn_error_for_type(): - f = HTMLFormatter() - f.for_type(int, lambda i: name_error) - with capture_output() as captured: - result = f(5) - assert result is None - assert "Traceback" in captured.stdout - assert "NameError" in captured.stdout - assert "name_error" in captured.stdout - -def test_error_pretty_method(): - f = PlainTextFormatter() - class BadPretty(object): - def _repr_pretty_(self): - return "hello" - bad = BadPretty() - with capture_output() as captured: - result = f(bad) - assert result is None - assert "Traceback" in captured.stdout - assert "_repr_pretty_" in captured.stdout - assert "given" in captured.stdout - assert "argument" in captured.stdout - - -def test_bad_repr_traceback(): - f = PlainTextFormatter() - bad = BadRepr() - with capture_output() as captured: - result = f(bad) - # catches error, returns None - assert result is None - assert "Traceback" in captured.stdout - assert "__repr__" in captured.stdout - assert "ValueError" in captured.stdout - - -class MakePDF(object): - def _repr_pdf_(self): - return 'PDF' - -def test_pdf_formatter(): - pdf = MakePDF() - f = PDFFormatter() - assert f(pdf) == "PDF" - - -def test_print_method_bound(): - f = HTMLFormatter() - class MyHTML(object): - def _repr_html_(self): - return "hello" - with capture_output() as captured: - result = f(MyHTML) - assert result is None - assert "FormatterWarning" not in captured.stderr - - with capture_output() as captured: - result = f(MyHTML()) - assert result == "hello" - assert captured.stderr == "" - - -def test_print_method_weird(): - - class TextMagicHat(object): - def __getattr__(self, key): - return key - - f = HTMLFormatter() - - text_hat = TextMagicHat() - assert text_hat._repr_html_ == "_repr_html_" - with capture_output() as captured: - result = f(text_hat) - - assert result is None - assert "FormatterWarning" not in captured.stderr - - class CallableMagicHat(object): - def __getattr__(self, key): - return lambda : key - - call_hat = CallableMagicHat() - with capture_output() as captured: - result = f(call_hat) - - assert result is None - - class BadReprArgs(object): - def _repr_html_(self, extra, args): - return "html" - - bad = BadReprArgs() - with capture_output() as captured: - result = f(bad) - - assert result is None - assert "FormatterWarning" not in captured.stderr - - -def test_format_config(): - """config objects don't pretend to support fancy reprs with lazy attrs""" - f = HTMLFormatter() - cfg = Config() - with capture_output() as captured: - result = f(cfg) - assert result is None - assert captured.stderr == "" - - with capture_output() as captured: - result = f(Config) - assert result is None - assert captured.stderr == "" - - -def test_pretty_max_seq_length(): - f = PlainTextFormatter(max_seq_length=1) - lis = list(range(3)) - text = f(lis) - assert text == "[0, ...]" - f.max_seq_length = 0 - text = f(lis) - assert text == "[0, 1, 2]" - text = f(list(range(1024))) - lines = text.splitlines() - assert len(lines) == 1024 - - -def test_ipython_display_formatter(): - """Objects with _ipython_display_ defined bypass other formatters""" - f = get_ipython().display_formatter - catcher = [] - class SelfDisplaying(object): - def _ipython_display_(self): - catcher.append(self) - - class NotSelfDisplaying(object): - def __repr__(self): - return "NotSelfDisplaying" - - def _ipython_display_(self): - raise NotImplementedError - - save_enabled = f.ipython_display_formatter.enabled - f.ipython_display_formatter.enabled = True - - yes = SelfDisplaying() - no = NotSelfDisplaying() - - d, md = f.format(no) - assert d == {"text/plain": repr(no)} - assert md == {} - assert catcher == [] - - d, md = f.format(yes) - assert d == {} - assert md == {} - assert catcher == [yes] - - f.ipython_display_formatter.enabled = save_enabled - - -def test_repr_mime(): - class HasReprMime(object): - def _repr_mimebundle_(self, include=None, exclude=None): - return { - 'application/json+test.v2': { - 'x': 'y' - }, - 'plain/text' : '', - 'image/png' : 'i-overwrite' - } - - def _repr_png_(self): - return 'should-be-overwritten' - def _repr_html_(self): - return 'hi!' - - f = get_ipython().display_formatter - html_f = f.formatters['text/html'] - save_enabled = html_f.enabled - html_f.enabled = True - obj = HasReprMime() - d, md = f.format(obj) - html_f.enabled = save_enabled - - assert sorted(d) == [ - "application/json+test.v2", - "image/png", - "plain/text", - "text/html", - "text/plain", - ] - assert md == {} - - d, md = f.format(obj, include={"image/png"}) - assert list(d.keys()) == [ - "image/png" - ], "Include should filter out even things from repr_mimebundle" - - assert d["image/png"] == "i-overwrite", "_repr_mimebundle_ take precedence" - - -def test_pass_correct_include_exclude(): - class Tester(object): - - def __init__(self, include=None, exclude=None): - self.include = include - self.exclude = exclude - - def _repr_mimebundle_(self, include, exclude, **kwargs): - if include and (include != self.include): - raise ValueError('include got modified: display() may be broken.') - if exclude and (exclude != self.exclude): - raise ValueError('exclude got modified: display() may be broken.') - - return None - - include = {'a', 'b', 'c'} - exclude = {'c', 'e' , 'f'} - - f = get_ipython().display_formatter - f.format(Tester(include=include, exclude=exclude), include=include, exclude=exclude) - f.format(Tester(exclude=exclude), exclude=exclude) - f.format(Tester(include=include), include=include) - - -def test_repr_mime_meta(): - class HasReprMimeMeta(object): - def _repr_mimebundle_(self, include=None, exclude=None): - data = { - 'image/png': 'base64-image-data', - } - metadata = { - 'image/png': { - 'width': 5, - 'height': 10, - } - } - return (data, metadata) - - f = get_ipython().display_formatter - obj = HasReprMimeMeta() - d, md = f.format(obj) - assert sorted(d) == ["image/png", "text/plain"] - assert md == { - "image/png": { - "width": 5, - "height": 10, - } - } - - -def test_repr_mime_failure(): - class BadReprMime(object): - def _repr_mimebundle_(self, include=None, exclude=None): - raise RuntimeError - - f = get_ipython().display_formatter - obj = BadReprMime() - d, md = f.format(obj) - assert "text/plain" in d - - -def test_custom_repr_namedtuple_partialmethod(): - from functools import partialmethod - from typing import NamedTuple - - class Foo(NamedTuple): ... - - Foo.__repr__ = partialmethod(lambda obj: "Hello World") - foo = Foo() - - f = PlainTextFormatter() - assert f.pprint - assert f(foo) == "Hello World" diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_guarded_eval.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_guarded_eval.py deleted file mode 100644 index f9057d8..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_guarded_eval.py +++ /dev/null @@ -1,785 +0,0 @@ -import sys -from contextlib import contextmanager -from typing import ( - Annotated, - AnyStr, - NamedTuple, - Literal, - NewType, - Optional, - Protocol, - TypeGuard, - Union, - TypedDict, -) -from functools import partial -from IPython.core.guarded_eval import ( - EvaluationContext, - GuardRejection, - guarded_eval, - _unbind_method, -) -from IPython.testing import decorators as dec -import pytest - - -if sys.version_info < (3, 11): - from typing_extensions import Self, LiteralString -else: - from typing import Self, LiteralString - -if sys.version_info < (3, 12): - from typing_extensions import TypeAliasType -else: - from typing import TypeAliasType - - -def create_context(evaluation: str, **kwargs): - return EvaluationContext(locals=kwargs, globals={}, evaluation=evaluation) - - -forbidden = partial(create_context, "forbidden") -minimal = partial(create_context, "minimal") -limited = partial(create_context, "limited") -unsafe = partial(create_context, "unsafe") -dangerous = partial(create_context, "dangerous") - -LIMITED_OR_HIGHER = [limited, unsafe, dangerous] -MINIMAL_OR_HIGHER = [minimal, *LIMITED_OR_HIGHER] - - -@contextmanager -def module_not_installed(module: str): - import sys - - try: - to_restore = sys.modules[module] - del sys.modules[module] - except KeyError: - to_restore = None - try: - yield - finally: - sys.modules[module] = to_restore - - -def test_external_not_installed(): - """ - Because attribute check requires checking if object is not of allowed - external type, this tests logic for absence of external module. - """ - - class Custom: - def __init__(self): - self.test = 1 - - def __getattr__(self, key): - return key - - with module_not_installed("pandas"): - context = limited(x=Custom()) - with pytest.raises(GuardRejection): - guarded_eval("x.test", context) - - -@dec.skip_without("pandas") -def test_external_changed_api(monkeypatch): - """Check that the execution rejects if external API changed paths""" - import pandas as pd - - series = pd.Series([1], index=["a"]) - - with monkeypatch.context() as m: - m.delattr(pd, "Series") - context = limited(data=series) - with pytest.raises(GuardRejection): - guarded_eval("data.iloc[0]", context) - - -@dec.skip_without("pandas") -def test_pandas_series_iloc(): - import pandas as pd - - series = pd.Series([1], index=["a"]) - context = limited(data=series) - assert guarded_eval("data.iloc[0]", context) == 1 - - -def test_rejects_custom_properties(): - class BadProperty: - @property - def iloc(self): - return [None] - - series = BadProperty() - context = limited(data=series) - - with pytest.raises(GuardRejection): - guarded_eval("data.iloc[0]", context) - - -@dec.skip_without("pandas") -def test_accepts_non_overriden_properties(): - import pandas as pd - - class GoodProperty(pd.Series): - pass - - series = GoodProperty([1], index=["a"]) - context = limited(data=series) - - assert guarded_eval("data.iloc[0]", context) == 1 - - -@dec.skip_without("pandas") -def test_pandas_series(): - import pandas as pd - - context = limited(data=pd.Series([1], index=["a"])) - assert guarded_eval('data["a"]', context) == 1 - with pytest.raises(KeyError): - guarded_eval('data["c"]', context) - - -@dec.skip_without("pandas") -def test_pandas_bad_series(): - import pandas as pd - - class BadItemSeries(pd.Series): - def __getitem__(self, key): - return "CUSTOM_ITEM" - - class BadAttrSeries(pd.Series): - def __getattr__(self, key): - return "CUSTOM_ATTR" - - bad_series = BadItemSeries([1], index=["a"]) - context = limited(data=bad_series) - - with pytest.raises(GuardRejection): - guarded_eval('data["a"]', context) - with pytest.raises(GuardRejection): - guarded_eval('data["c"]', context) - - # note: here result is a bit unexpected because - # pandas `__getattr__` calls `__getitem__`; - # FIXME - special case to handle it? - assert guarded_eval("data.a", context) == "CUSTOM_ITEM" - - context = unsafe(data=bad_series) - assert guarded_eval('data["a"]', context) == "CUSTOM_ITEM" - - bad_attr_series = BadAttrSeries([1], index=["a"]) - context = limited(data=bad_attr_series) - assert guarded_eval('data["a"]', context) == 1 - with pytest.raises(GuardRejection): - guarded_eval("data.a", context) - - -@dec.skip_without("pandas") -def test_pandas_dataframe_loc(): - import pandas as pd - from pandas.testing import assert_series_equal - - data = pd.DataFrame([{"a": 1}]) - context = limited(data=data) - assert_series_equal(guarded_eval('data.loc[:, "a"]', context), data["a"]) - - -def test_named_tuple(): - class GoodNamedTuple(NamedTuple): - a: str - pass - - class BadNamedTuple(NamedTuple): - a: str - - def __getitem__(self, key): - return None - - good = GoodNamedTuple(a="x") - bad = BadNamedTuple(a="x") - - context = limited(data=good) - assert guarded_eval("data[0]", context) == "x" - - context = limited(data=bad) - with pytest.raises(GuardRejection): - guarded_eval("data[0]", context) - - -def test_dict(): - context = limited(data={"a": 1, "b": {"x": 2}, ("x", "y"): 3}) - assert guarded_eval('data["a"]', context) == 1 - assert guarded_eval('data["b"]', context) == {"x": 2} - assert guarded_eval('data["b"]["x"]', context) == 2 - assert guarded_eval('data["x", "y"]', context) == 3 - - assert guarded_eval("data.keys", context) - - -def test_set(): - context = limited(data={"a", "b"}) - assert guarded_eval("data.difference", context) - - -def test_list(): - context = limited(data=[1, 2, 3]) - assert guarded_eval("data[1]", context) == 2 - assert guarded_eval("data.copy", context) - - -def test_dict_literal(): - context = limited() - assert guarded_eval("{}", context) == {} - assert guarded_eval('{"a": 1}', context) == {"a": 1} - - -def test_list_literal(): - context = limited() - assert guarded_eval("[]", context) == [] - assert guarded_eval('[1, "a"]', context) == [1, "a"] - - -def test_set_literal(): - context = limited() - assert guarded_eval("set()", context) == set() - assert guarded_eval('{"a"}', context) == {"a"} - - -def test_evaluates_if_expression(): - context = limited() - assert guarded_eval("2 if True else 3", context) == 2 - assert guarded_eval("4 if False else 5", context) == 5 - - -def test_object(): - obj = object() - context = limited(obj=obj) - assert guarded_eval("obj.__dir__", context) == obj.__dir__ - - -@pytest.mark.parametrize( - "code,expected", - [ - ["int.numerator", int.numerator], - ["float.is_integer", float.is_integer], - ["complex.real", complex.real], - ], -) -def test_number_attributes(code, expected): - assert guarded_eval(code, limited()) == expected - - -def test_method_descriptor(): - context = limited() - assert guarded_eval("list.copy.__name__", context) == "copy" - - -class HeapType: - pass - - -class CallCreatesHeapType: - def __call__(self) -> HeapType: - return HeapType() - - -class CallCreatesBuiltin: - def __call__(self) -> frozenset: - return frozenset() - - -class HasStaticMethod: - @staticmethod - def static_method() -> HeapType: - return HeapType() - - -class InitReturnsFrozenset: - def __new__(self) -> frozenset: # type:ignore[misc] - return frozenset() - - -class StringAnnotation: - def heap(self) -> "HeapType": - return HeapType() - - def copy(self) -> "StringAnnotation": - return StringAnnotation() - - -CustomIntType = NewType("CustomIntType", int) -CustomHeapType = NewType("CustomHeapType", HeapType) -IntTypeAlias = TypeAliasType("IntTypeAlias", int) -HeapTypeAlias = TypeAliasType("HeapTypeAlias", HeapType) - - -class TestProtocol(Protocol): - def test_method(self) -> bool: - pass - - -class TestProtocolImplementer(TestProtocol): - def test_method(self) -> bool: - return True - - -class Movie(TypedDict): - name: str - year: int - - -class SpecialTyping: - def custom_int_type(self) -> CustomIntType: - return CustomIntType(1) - - def custom_heap_type(self) -> CustomHeapType: - return CustomHeapType(HeapType()) - - # TODO: remove type:ignore comment once mypy - # supports explicit calls to `TypeAliasType`, see: - # https://github.com/python/mypy/issues/16614 - def int_type_alias(self) -> IntTypeAlias: # type:ignore[valid-type] - return 1 - - def heap_type_alias(self) -> HeapTypeAlias: # type:ignore[valid-type] - return 1 - - def literal(self) -> Literal[False]: - return False - - def literal_string(self) -> LiteralString: - return "test" - - def self(self) -> Self: - return self - - def any_str(self, x: AnyStr) -> AnyStr: - return x - - def annotated(self) -> Annotated[float, "positive number"]: - return 1 - - def annotated_self(self) -> Annotated[Self, "self with metadata"]: - self._metadata = "test" - return self - - def int_type_guard(self, x) -> TypeGuard[int]: - return isinstance(x, int) - - def optional_float(self) -> Optional[float]: - return 1.0 - - def union_str_and_int(self) -> Union[str, int]: - return "" - - def protocol(self) -> TestProtocol: - return TestProtocolImplementer() - - def typed_dict(self) -> Movie: - return {"name": "The Matrix", "year": 1999} - - -@pytest.mark.parametrize( - "data,code,expected,equality", - [ - [[1, 2, 3], "data.index(2)", 1, True], - [{"a": 1}, "data.keys().isdisjoint({})", True, True], - [StringAnnotation(), "data.heap()", HeapType, False], - [StringAnnotation(), "data.copy()", StringAnnotation, False], - # test cases for `__call__` - [CallCreatesHeapType(), "data()", HeapType, False], - [CallCreatesBuiltin(), "data()", frozenset, False], - # Test cases for `__init__` - [HeapType, "data()", HeapType, False], - [InitReturnsFrozenset, "data()", frozenset, False], - [HeapType(), "data.__class__()", HeapType, False], - # supported special cases for typing - [SpecialTyping(), "data.custom_int_type()", int, False], - [SpecialTyping(), "data.custom_heap_type()", HeapType, False], - [SpecialTyping(), "data.int_type_alias()", int, False], - [SpecialTyping(), "data.heap_type_alias()", HeapType, False], - [SpecialTyping(), "data.self()", SpecialTyping, False], - [SpecialTyping(), "data.literal()", False, True], - [SpecialTyping(), "data.literal_string()", str, False], - [SpecialTyping(), "data.any_str('a')", str, False], - [SpecialTyping(), "data.any_str(b'a')", bytes, False], - [SpecialTyping(), "data.annotated()", float, False], - [SpecialTyping(), "data.annotated_self()", SpecialTyping, False], - [SpecialTyping(), "data.int_type_guard()", int, False], - # test cases for static methods - [HasStaticMethod, "data.static_method()", HeapType, False], - ], -) -def test_evaluates_calls(data, code, expected, equality): - context = limited(data=data, HeapType=HeapType, StringAnnotation=StringAnnotation) - value = guarded_eval(code, context) - if equality: - assert value == expected - else: - assert isinstance(value, expected) - - -@pytest.mark.parametrize( - "data,code,expected_attributes", - [ - [SpecialTyping(), "data.optional_float()", ["is_integer"]], - [ - SpecialTyping(), - "data.union_str_and_int()", - ["capitalize", "as_integer_ratio"], - ], - [SpecialTyping(), "data.protocol()", ["test_method"]], - [SpecialTyping(), "data.typed_dict()", ["keys", "values", "items"]], - ], -) -def test_mocks_attributes_of_call_results(data, code, expected_attributes): - context = limited(data=data, HeapType=HeapType, StringAnnotation=StringAnnotation) - result = guarded_eval(code, context) - for attr in expected_attributes: - assert hasattr(result, attr) - assert attr in dir(result) - - -@pytest.mark.parametrize( - "data,code,expected_items", - [ - [SpecialTyping(), "data.typed_dict()", {"year": int, "name": str}], - ], -) -def test_mocks_items_of_call_results(data, code, expected_items): - context = limited(data=data, HeapType=HeapType, StringAnnotation=StringAnnotation) - result = guarded_eval(code, context) - ipython_keys = result._ipython_key_completions_() - for key, value in expected_items.items(): - assert isinstance(result[key], value) - assert key in ipython_keys - - -@pytest.mark.parametrize( - "data,bad", - [ - [[1, 2, 3], "data.append(4)"], - [{"a": 1}, "data.update()"], - ], -) -def test_rejects_calls_with_side_effects(data, bad): - context = limited(data=data) - - with pytest.raises(GuardRejection): - guarded_eval(bad, context) - - -@pytest.mark.parametrize( - "code,expected", - [ - ["(1\n+\n1)", 2], - ["list(range(10))[-1:]", [9]], - ["list(range(20))[3:-2:3]", [3, 6, 9, 12, 15]], - ], -) -@pytest.mark.parametrize("context", LIMITED_OR_HIGHER) -def test_evaluates_complex_cases(code, expected, context): - assert guarded_eval(code, context()) == expected - - -@pytest.mark.parametrize( - "code,expected", - [ - ["1", 1], - ["1.0", 1.0], - ["0xdeedbeef", 0xDEEDBEEF], - ["True", True], - ["None", None], - ["{}", {}], - ["[]", []], - ], -) -@pytest.mark.parametrize("context", MINIMAL_OR_HIGHER) -def test_evaluates_literals(code, expected, context): - assert guarded_eval(code, context()) == expected - - -@pytest.mark.parametrize( - "code,expected", - [ - ["-5", -5], - ["+5", +5], - ["~5", -6], - ], -) -@pytest.mark.parametrize("context", LIMITED_OR_HIGHER) -def test_evaluates_unary_operations(code, expected, context): - assert guarded_eval(code, context()) == expected - - -@pytest.mark.parametrize( - "code,expected", - [ - ["1 + 1", 2], - ["3 - 1", 2], - ["2 * 3", 6], - ["5 // 2", 2], - ["5 / 2", 2.5], - ["5**2", 25], - ["2 >> 1", 1], - ["2 << 1", 4], - ["1 | 2", 3], - ["1 & 1", 1], - ["1 & 2", 0], - ], -) -@pytest.mark.parametrize("context", LIMITED_OR_HIGHER) -def test_evaluates_binary_operations(code, expected, context): - assert guarded_eval(code, context()) == expected - - -@pytest.mark.parametrize( - "code,expected", - [ - ["2 > 1", True], - ["2 < 1", False], - ["2 <= 1", False], - ["2 <= 2", True], - ["1 >= 2", False], - ["2 >= 2", True], - ["2 == 2", True], - ["1 == 2", False], - ["1 != 2", True], - ["1 != 1", False], - ["1 < 4 < 3", False], - ["(1 < 4) < 3", True], - ["4 > 3 > 2 > 1", True], - ["4 > 3 > 2 > 9", False], - ["1 < 2 < 3 < 4", True], - ["9 < 2 < 3 < 4", False], - ["1 < 2 > 1 > 0 > -1 < 1", True], - ["1 in [1] in [[1]]", True], - ["1 in [1] in [[2]]", False], - ["1 in [1]", True], - ["0 in [1]", False], - ["1 not in [1]", False], - ["0 not in [1]", True], - ["True is True", True], - ["False is False", True], - ["True is False", False], - ["True is not True", False], - ["False is not True", True], - ], -) -@pytest.mark.parametrize("context", LIMITED_OR_HIGHER) -def test_evaluates_comparisons(code, expected, context): - assert guarded_eval(code, context()) == expected - - -def test_guards_comparisons(): - class GoodEq(int): - pass - - class BadEq(int): - def __eq__(self, other): - assert False - - context = limited(bad=BadEq(1), good=GoodEq(1)) - - with pytest.raises(GuardRejection): - guarded_eval("bad == 1", context) - - with pytest.raises(GuardRejection): - guarded_eval("bad != 1", context) - - with pytest.raises(GuardRejection): - guarded_eval("1 == bad", context) - - with pytest.raises(GuardRejection): - guarded_eval("1 != bad", context) - - assert guarded_eval("good == 1", context) is True - assert guarded_eval("good != 1", context) is False - assert guarded_eval("1 == good", context) is True - assert guarded_eval("1 != good", context) is False - - -def test_guards_unary_operations(): - class GoodOp(int): - pass - - class BadOpInv(int): - def __inv__(self, other): - assert False - - class BadOpInverse(int): - def __inv__(self, other): - assert False - - context = limited(good=GoodOp(1), bad1=BadOpInv(1), bad2=BadOpInverse(1)) - - with pytest.raises(GuardRejection): - guarded_eval("~bad1", context) - - with pytest.raises(GuardRejection): - guarded_eval("~bad2", context) - - -def test_guards_binary_operations(): - class GoodOp(int): - pass - - class BadOp(int): - def __add__(self, other): - assert False - - context = limited(good=GoodOp(1), bad=BadOp(1)) - - with pytest.raises(GuardRejection): - guarded_eval("1 + bad", context) - - with pytest.raises(GuardRejection): - guarded_eval("bad + 1", context) - - assert guarded_eval("good + 1", context) == 2 - assert guarded_eval("1 + good", context) == 2 - - -def test_guards_attributes(): - class GoodAttr(float): - pass - - class BadAttr1(float): - def __getattr__(self, key): - assert False - - class BadAttr2(float): - def __getattribute__(self, key): - assert False - - context = limited(good=GoodAttr(0.5), bad1=BadAttr1(0.5), bad2=BadAttr2(0.5)) - - with pytest.raises(GuardRejection): - guarded_eval("bad1.as_integer_ratio", context) - - with pytest.raises(GuardRejection): - guarded_eval("bad2.as_integer_ratio", context) - - assert guarded_eval("good.as_integer_ratio()", context) == (1, 2) - - -@pytest.mark.parametrize("context", MINIMAL_OR_HIGHER) -def test_access_builtins(context): - assert guarded_eval("round", context()) == round - - -def test_access_builtins_fails(): - context = limited() - with pytest.raises(NameError): - guarded_eval("this_is_not_builtin", context) - - -def test_rejects_forbidden(): - context = forbidden() - with pytest.raises(GuardRejection): - guarded_eval("1", context) - - -def test_guards_locals_and_globals(): - context = EvaluationContext( - locals={"local_a": "a"}, globals={"global_b": "b"}, evaluation="minimal" - ) - - with pytest.raises(GuardRejection): - guarded_eval("local_a", context) - - with pytest.raises(GuardRejection): - guarded_eval("global_b", context) - - -def test_access_locals_and_globals(): - context = EvaluationContext( - locals={"local_a": "a"}, globals={"global_b": "b"}, evaluation="limited" - ) - assert guarded_eval("local_a", context) == "a" - assert guarded_eval("global_b", context) == "b" - - -@pytest.mark.parametrize( - "code", - ["def func(): pass", "class C: pass", "x = 1", "x += 1", "del x", "import ast"], -) -@pytest.mark.parametrize("context", [minimal(), limited(), unsafe()]) -def test_rejects_side_effect_syntax(code, context): - with pytest.raises(SyntaxError): - guarded_eval(code, context) - - -def test_subscript(): - context = EvaluationContext( - locals={}, globals={}, evaluation="limited", in_subscript=True - ) - empty_slice = slice(None, None, None) - assert guarded_eval("", context) == tuple() - assert guarded_eval(":", context) == empty_slice - assert guarded_eval("1:2:3", context) == slice(1, 2, 3) - assert guarded_eval(':, "a"', context) == (empty_slice, "a") - - -def test_unbind_method(): - class X(list): - def index(self, k): - return "CUSTOM" - - x = X() - assert _unbind_method(x.index) is X.index - assert _unbind_method([].index) is list.index - assert _unbind_method(list.index) is None - - -def test_assumption_instance_attr_do_not_matter(): - """This is semi-specified in Python documentation. - - However, since the specification says 'not guaranteed - to work' rather than 'is forbidden to work', future - versions could invalidate this assumptions. This test - is meant to catch such a change if it ever comes true. - """ - - class T: - def __getitem__(self, k): - return "a" - - def __getattr__(self, k): - return "a" - - def f(self): - return "b" - - t = T() - t.__getitem__ = f - t.__getattr__ = f - assert t[1] == "a" - assert t[1] == "a" - - -def test_assumption_named_tuples_share_getitem(): - """Check assumption on named tuples sharing __getitem__""" - from typing import NamedTuple - - class A(NamedTuple): - pass - - class B(NamedTuple): - pass - - assert A.__getitem__ == B.__getitem__ - - -@dec.skip_without("numpy") -def test_module_access(): - import numpy - - context = limited(numpy=numpy) - assert guarded_eval("numpy.linalg.norm", context) == numpy.linalg.norm - - context = minimal(numpy=numpy) - with pytest.raises(GuardRejection): - guarded_eval("np.linalg.norm", context) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_handlers.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_handlers.py deleted file mode 100644 index 905d9ab..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_handlers.py +++ /dev/null @@ -1,75 +0,0 @@ -"""Tests for input handlers. -""" -#----------------------------------------------------------------------------- -# Module imports -#----------------------------------------------------------------------------- - -# our own packages -from IPython.core import autocall -from IPython.testing import tools as tt -import pytest -from collections.abc import Callable - -#----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- - -# Test functions -#----------------------------------------------------------------------------- - -class CallableIndexable(object): - def __getitem__(self, idx): return True - def __call__(self, *args, **kws): return True - - -class Autocallable(autocall.IPyAutocall): - def __call__(self): - return "called" - - -@pytest.mark.parametrize( - "autocall, input, output", - [ - # For many of the below, we're also checking that leading whitespace - # turns off the esc char, which it should unless there is a continuation - # line. - ("1", '"no change"', '"no change"'), # normal - ("1", "lsmagic", "get_ipython().run_line_magic('lsmagic', '')"), # magic - # Only explicit escapes or instances of IPyAutocallable should get - # expanded - ("0", 'len "abc"', 'len "abc"'), - ("0", "autocallable", "autocallable()"), - # Don't add extra brackets (gh-1117) - ("0", "autocallable()", "autocallable()"), - ("1", 'len "abc"', 'len("abc")'), - ("1", 'len "abc";', 'len("abc");'), # ; is special -- moves out of parens - # Autocall is turned off if first arg is [] and the object - # is both callable and indexable. Like so: - ("1", "len [1,2]", "len([1,2])"), # len doesn't support __getitem__... - ("1", "call_idx [1]", "call_idx [1]"), # call_idx *does*.. - ("1", "call_idx 1", "call_idx(1)"), - ("1", "len", "len"), # only at 2 does it auto-call on single args - ("2", 'len "abc"', 'len("abc")'), - ("2", 'len "abc";', 'len("abc");'), - ("2", "len [1,2]", "len([1,2])"), - ("2", "call_idx [1]", "call_idx [1]"), - ("2", "call_idx 1", "call_idx(1)"), - # T his is what's different: - ("2", "len", "len()"), # only at 2 does it auto-call on single args - ("0", "Callable[[int], None]", "Callable[[int], None]"), - ("1", "Callable[[int], None]", "Callable[[int], None]"), - ("1", "Callable[[int], None]", "Callable[[int], None]"), - ], -) -def test_handlers_I(autocall, input, output): - autocallable = Autocallable() - ip.user_ns["autocallable"] = autocallable - - call_idx = CallableIndexable() - ip.user_ns["call_idx"] = call_idx - - ip.user_ns["Callable"] = Callable - - ip.run_line_magic("autocall", autocall) - assert ip.prefilter_manager.prefilter_lines(input) == output - ip.run_line_magic("autocall", "1") diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_history.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_history.py deleted file mode 100644 index fa64fe0..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_history.py +++ /dev/null @@ -1,306 +0,0 @@ -# coding: utf-8 -"""Tests for the IPython tab-completion machinery. -""" -#----------------------------------------------------------------------------- -# Module imports -#----------------------------------------------------------------------------- - -# stdlib -import io -import sys -import tempfile -from datetime import datetime -from pathlib import Path - -from tempfile import TemporaryDirectory -# our own packages -from traitlets.config.loader import Config - -from IPython.core.history import HistoryAccessor, HistoryManager, extract_hist_ranges - - -def test_proper_default_encoding(): - assert sys.getdefaultencoding() == "utf-8" - -def test_history(): - ip = get_ipython() - with TemporaryDirectory() as tmpdir: - tmp_path = Path(tmpdir) - hist_manager_ori = ip.history_manager - hist_file = tmp_path / "history.sqlite" - try: - ip.history_manager = HistoryManager(shell=ip, hist_file=hist_file) - hist = ["a=1", "def f():\n test = 1\n return test", "b='€Æ¾÷ß'"] - for i, h in enumerate(hist, start=1): - ip.history_manager.store_inputs(i, h) - - ip.history_manager.db_log_output = True - # Doesn't match the input, but we'll just check it's stored. - ip.history_manager.output_hist_reprs[3] = "spam" - ip.history_manager.store_output(3) - - assert ip.history_manager.input_hist_raw == [""] + hist - - # Detailed tests for _get_range_session - grs = ip.history_manager._get_range_session - assert list(grs(start=2, stop=-1)) == list(zip([0], [2], hist[1:-1])) - assert list(grs(start=-2)) == list(zip([0, 0], [2, 3], hist[-2:])) - assert list(grs(output=True)) == list( - zip([0, 0, 0], [1, 2, 3], zip(hist, [None, None, "spam"])) - ) - - # Check whether specifying a range beyond the end of the current - # session results in an error (gh-804) - ip.run_line_magic("hist", "2-500") - - # Check that we can write non-ascii characters to a file - ip.run_line_magic("hist", "-f %s" % (tmp_path / "test1")) - ip.run_line_magic("hist", "-pf %s" % (tmp_path / "test2")) - ip.run_line_magic("hist", "-nf %s" % (tmp_path / "test3")) - ip.run_line_magic("save", "%s 1-10" % (tmp_path / "test4")) - - # New session - ip.history_manager.reset() - newcmds = ["z=5", "class X(object):\n pass", "k='p'", "z=5"] - for i, cmd in enumerate(newcmds, start=1): - ip.history_manager.store_inputs(i, cmd) - gothist = ip.history_manager.get_range(start=1, stop=4) - assert list(gothist) == list(zip([0, 0, 0], [1, 2, 3], newcmds)) - # Previous session: - gothist = ip.history_manager.get_range(-1, 1, 4) - assert list(gothist) == list(zip([1, 1, 1], [1, 2, 3], hist)) - - newhist = [(2, i, c) for (i, c) in enumerate(newcmds, 1)] - - # Check get_hist_tail - gothist = ip.history_manager.get_tail(5, output=True, - include_latest=True) - expected = [(1, 3, (hist[-1], "spam"))] \ - + [(s, n, (c, None)) for (s, n, c) in newhist] - assert list(gothist) == expected - - gothist = ip.history_manager.get_tail(2) - expected = newhist[-3:-1] - assert list(gothist) == expected - - # Check get_hist_search - - gothist = ip.history_manager.search("*test*") - assert list(gothist) == [(1, 2, hist[1])] - - gothist = ip.history_manager.search("*=*") - assert list(gothist) == [ - (1, 1, hist[0]), - (1, 2, hist[1]), - (1, 3, hist[2]), - newhist[0], - newhist[2], - newhist[3], - ] - - gothist = ip.history_manager.search("*=*", n=4) - assert list(gothist) == [ - (1, 3, hist[2]), - newhist[0], - newhist[2], - newhist[3], - ] - - gothist = ip.history_manager.search("*=*", unique=True) - assert list(gothist) == [ - (1, 1, hist[0]), - (1, 2, hist[1]), - (1, 3, hist[2]), - newhist[2], - newhist[3], - ] - - gothist = ip.history_manager.search("*=*", unique=True, n=3) - assert list(gothist) == [(1, 3, hist[2]), newhist[2], newhist[3]] - - gothist = ip.history_manager.search("b*", output=True) - assert list(gothist) == [(1, 3, (hist[2], "spam"))] - - # Cross testing: check that magic %save can get previous session. - testfilename = (tmp_path / "test.py").resolve() - ip.run_line_magic("save", str(testfilename) + " ~1/1-3") - with io.open(testfilename, encoding="utf-8") as testfile: - assert testfile.read() == "# coding: utf-8\n" + "\n".join(hist) + "\n" - - # Duplicate line numbers - check that it doesn't crash, and - # gets a new session - ip.history_manager.store_inputs(1, "rogue") - ip.history_manager.writeout_cache() - assert ip.history_manager.session_number == 3 - - # Check that session and line values are not just max values - sessid, lineno, entry = newhist[-1] - assert lineno > 1 - ip.history_manager.reset() - lineno = 1 - ip.history_manager.store_inputs(lineno, entry) - gothist = ip.history_manager.search("*=*", unique=True) - hist = list(gothist)[-1] - assert sessid < hist[0] - assert hist[1:] == (lineno, entry) - finally: - # Ensure saving thread is shut down before we try to clean up the files - ip.history_manager.save_thread.stop() - # Forcibly close database rather than relying on garbage collection - ip.history_manager.db.close() - # Restore history manager - ip.history_manager = hist_manager_ori - - -def test_extract_hist_ranges(): - instr = "1 2/3 ~4/5-6 ~4/7-~4/9 ~9/2-~7/5 ~10/" - expected = [(0, 1, 2), # 0 == current session - (2, 3, 4), - (-4, 5, 7), - (-4, 7, 10), - (-9, 2, None), # None == to end - (-8, 1, None), - (-7, 1, 6), - (-10, 1, None)] - actual = list(extract_hist_ranges(instr)) - assert actual == expected - - -def test_extract_hist_ranges_empty_str(): - instr = "" - expected = [(0, 1, None)] # 0 == current session, None == to end - actual = list(extract_hist_ranges(instr)) - assert actual == expected - - -def test_magic_rerun(): - """Simple test for %rerun (no args -> rerun last line)""" - ip = get_ipython() - ip.run_cell("a = 10", store_history=True) - ip.run_cell("a += 1", store_history=True) - assert ip.user_ns["a"] == 11 - ip.run_cell("%rerun", store_history=True) - assert ip.user_ns["a"] == 12 - -def test_timestamp_type(): - ip = get_ipython() - info = ip.history_manager.get_session_info() - assert isinstance(info[1], datetime) - -def test_hist_file_config(): - cfg = Config() - tfile = tempfile.NamedTemporaryFile(delete=False) - cfg.HistoryManager.hist_file = Path(tfile.name) - try: - hm = HistoryManager(shell=get_ipython(), config=cfg) - assert hm.hist_file == cfg.HistoryManager.hist_file - finally: - try: - Path(tfile.name).unlink() - except OSError: - # same catch as in testing.tools.TempFileMixin - # On Windows, even though we close the file, we still can't - # delete it. I have no clue why - pass - -def test_histmanager_disabled(): - """Ensure that disabling the history manager doesn't create a database.""" - cfg = Config() - cfg.HistoryAccessor.enabled = False - - ip = get_ipython() - with TemporaryDirectory() as tmpdir: - hist_manager_ori = ip.history_manager - hist_file = Path(tmpdir) / "history.sqlite" - cfg.HistoryManager.hist_file = hist_file - try: - ip.history_manager = HistoryManager(shell=ip, config=cfg) - hist = ["a=1", "def f():\n test = 1\n return test", "b='€Æ¾÷ß'"] - for i, h in enumerate(hist, start=1): - ip.history_manager.store_inputs(i, h) - assert ip.history_manager.input_hist_raw == [""] + hist - ip.history_manager.reset() - ip.history_manager.end_session() - finally: - ip.history_manager = hist_manager_ori - - # hist_file should not be created - assert hist_file.exists() is False - - -def test_get_tail_session_awareness(): - """Test .get_tail() is: - - session specific in HistoryManager - - session agnostic in HistoryAccessor - same for .get_last_session_id() - """ - ip = get_ipython() - with TemporaryDirectory() as tmpdir: - tmp_path = Path(tmpdir) - hist_file = tmp_path / "history.sqlite" - get_source = lambda x: x[2] - hm1 = None - hm2 = None - ha = None - try: - # hm1 creates a new session and adds history entries, - # ha catches up - hm1 = HistoryManager(shell=ip, hist_file=hist_file) - hm1_last_sid = hm1.get_last_session_id - ha = HistoryAccessor(hist_file=hist_file) - ha_last_sid = ha.get_last_session_id - - hist1 = ["a=1", "b=1", "c=1"] - for i, h in enumerate(hist1 + [""], start=1): - hm1.store_inputs(i, h) - assert list(map(get_source, hm1.get_tail())) == hist1 - assert list(map(get_source, ha.get_tail())) == hist1 - sid1 = hm1_last_sid() - assert sid1 is not None - assert ha_last_sid() == sid1 - - # hm2 creates a new session and adds entries, - # ha catches up - hm2 = HistoryManager(shell=ip, hist_file=hist_file) - hm2_last_sid = hm2.get_last_session_id - - hist2 = ["a=2", "b=2", "c=2"] - for i, h in enumerate(hist2 + [""], start=1): - hm2.store_inputs(i, h) - tail = hm2.get_tail(n=3) - assert list(map(get_source, tail)) == hist2 - tail = ha.get_tail(n=3) - assert list(map(get_source, tail)) == hist2 - sid2 = hm2_last_sid() - assert sid2 is not None - assert ha_last_sid() == sid2 - assert sid2 != sid1 - - # but hm1 still maintains its point of reference - # and adding more entries to it doesn't change others - # immediate perspective - assert hm1_last_sid() == sid1 - tail = hm1.get_tail(n=3) - assert list(map(get_source, tail)) == hist1 - - hist3 = ["a=3", "b=3", "c=3"] - for i, h in enumerate(hist3 + [""], start=5): - hm1.store_inputs(i, h) - tail = hm1.get_tail(n=7) - assert list(map(get_source, tail)) == hist1 + [""] + hist3 - tail = hm2.get_tail(n=3) - assert list(map(get_source, tail)) == hist2 - tail = ha.get_tail(n=3) - assert list(map(get_source, tail)) == hist2 - assert hm1_last_sid() == sid1 - assert hm2_last_sid() == sid2 - assert ha_last_sid() == sid2 - finally: - if hm1: - hm1.save_thread.stop() - hm1.db.close() - if hm2: - hm2.save_thread.stop() - hm2.db.close() - if ha: - ha.db.close() diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_hooks.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_hooks.py deleted file mode 100644 index 6e0b1c1..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_hooks.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests for CommandChainDispatcher.""" - - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import pytest -from IPython.core.error import TryNext -from IPython.core.hooks import CommandChainDispatcher - -#----------------------------------------------------------------------------- -# Local utilities -#----------------------------------------------------------------------------- - -# Define two classes, one which succeeds and one which raises TryNext. Each -# sets the attribute `called` to True when it is called. -class Okay(object): - def __init__(self, message): - self.message = message - self.called = False - def __call__(self): - self.called = True - return self.message - -class Fail(object): - def __init__(self, message): - self.message = message - self.called = False - def __call__(self): - self.called = True - raise TryNext(self.message) - -#----------------------------------------------------------------------------- -# Test functions -#----------------------------------------------------------------------------- - -def test_command_chain_dispatcher_ff(): - """Test two failing hooks""" - fail1 = Fail("fail1") - fail2 = Fail("fail2") - dp = CommandChainDispatcher([(0, fail1), (10, fail2)]) - - with pytest.raises(TryNext) as e: - dp() - assert str(e.value) == "fail2" - - assert fail1.called is True - assert fail2.called is True - -def test_command_chain_dispatcher_fofo(): - """Test a mixture of failing and succeeding hooks.""" - fail1 = Fail("fail1") - fail2 = Fail("fail2") - okay1 = Okay("okay1") - okay2 = Okay("okay2") - - dp = CommandChainDispatcher([(0, fail1), - # (5, okay1), # add this later - (10, fail2), - (15, okay2)]) - dp.add(okay1, 5) - - assert dp() == "okay1" - - assert fail1.called is True - assert okay1.called is True - assert fail2.called is False - assert okay2.called is False - -def test_command_chain_dispatcher_eq_priority(): - okay1 = Okay(u'okay1') - okay2 = Okay(u'okay2') - dp = CommandChainDispatcher([(1, okay1)]) - dp.add(okay2, 1) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_imports.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_imports.py deleted file mode 100644 index 7aa278f..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_imports.py +++ /dev/null @@ -1,52 +0,0 @@ -# encoding: utf-8 - -def test_import_completer(): - from IPython.core import completer - -def test_import_crashhandler(): - from IPython.core import crashhandler - -def test_import_debugger(): - from IPython.core import debugger - -def test_import_excolors(): - from IPython.core import excolors - -def test_import_history(): - from IPython.core import history - -def test_import_hooks(): - from IPython.core import hooks - -def test_import_getipython(): - from IPython.core import getipython - -def test_import_interactiveshell(): - from IPython.core import interactiveshell - -def test_import_logger(): - from IPython.core import logger - -def test_import_macro(): - from IPython.core import macro - -def test_import_magic(): - from IPython.core import magic - -def test_import_oinspect(): - from IPython.core import oinspect - -def test_import_prefilter(): - from IPython.core import prefilter - -def test_import_prompts(): - from IPython.core import prompts - -def test_import_release(): - from IPython.core import release - -def test_import_ultratb(): - from IPython.core import ultratb - -def test_import_usage(): - from IPython.core import usage diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputsplitter.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputsplitter.py deleted file mode 100644 index 61e06df..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputsplitter.py +++ /dev/null @@ -1,643 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests for the inputsplitter module.""" - - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import unittest -import pytest -import sys - -with pytest.warns(DeprecationWarning, match="inputsplitter"): - from IPython.core import inputsplitter as isp -from IPython.core.inputtransformer import InputTransformer -from IPython.core.tests.test_inputtransformer import syntax, syntax_ml -from IPython.testing import tools as tt - -#----------------------------------------------------------------------------- -# Semi-complete examples (also used as tests) -#----------------------------------------------------------------------------- - -# Note: at the bottom, there's a slightly more complete version of this that -# can be useful during development of code here. - -def mini_interactive_loop(input_func): - """Minimal example of the logic of an interactive interpreter loop. - - This serves as an example, and it is used by the test system with a fake - raw_input that simulates interactive input.""" - - from IPython.core.inputsplitter import InputSplitter - - isp = InputSplitter() - # In practice, this input loop would be wrapped in an outside loop to read - # input indefinitely, until some exit/quit command was issued. Here we - # only illustrate the basic inner loop. - while isp.push_accepts_more(): - indent = ' '*isp.get_indent_spaces() - prompt = '>>> ' + indent - line = indent + input_func(prompt) - isp.push(line) - - # Here we just return input so we can use it in a test suite, but a real - # interpreter would instead send it for execution somewhere. - src = isp.source_reset() - # print('Input source was:\n', src) # dbg - return src - -#----------------------------------------------------------------------------- -# Test utilities, just for local use -#----------------------------------------------------------------------------- - - -def pseudo_input(lines): - """Return a function that acts like raw_input but feeds the input list.""" - ilines = iter(lines) - def raw_in(prompt): - try: - return next(ilines) - except StopIteration: - return '' - return raw_in - -#----------------------------------------------------------------------------- -# Tests -#----------------------------------------------------------------------------- -def test_spaces(): - tests = [('', 0), - (' ', 1), - ('\n', 0), - (' \n', 1), - ('x', 0), - (' x', 1), - (' x',2), - (' x',4), - # Note: tabs are counted as a single whitespace! - ('\tx', 1), - ('\t x', 2), - ] - with pytest.warns(PendingDeprecationWarning): - tt.check_pairs(isp.num_ini_spaces, tests) - - -def test_remove_comments(): - tests = [('text', 'text'), - ('text # comment', 'text '), - ('text # comment\n', 'text \n'), - ('text # comment \n', 'text \n'), - ('line # c \nline\n','line \nline\n'), - ('line # c \nline#c2 \nline\nline #c\n\n', - 'line \nline\nline\nline \n\n'), - ] - tt.check_pairs(isp.remove_comments, tests) - - -def test_get_input_encoding(): - encoding = isp.get_input_encoding() - assert isinstance(encoding, str) - # simple-minded check that at least encoding a simple string works with the - # encoding we got. - assert "test".encode(encoding) == b"test" - - -class NoInputEncodingTestCase(unittest.TestCase): - def setUp(self): - self.old_stdin = sys.stdin - class X: pass - fake_stdin = X() - sys.stdin = fake_stdin - - def test(self): - # Verify that if sys.stdin has no 'encoding' attribute we do the right - # thing - enc = isp.get_input_encoding() - self.assertEqual(enc, 'ascii') - - def tearDown(self): - sys.stdin = self.old_stdin - - -class InputSplitterTestCase(unittest.TestCase): - def setUp(self): - self.isp = isp.InputSplitter() - - def test_reset(self): - isp = self.isp - isp.push('x=1') - isp.reset() - self.assertEqual(isp._buffer, []) - self.assertEqual(isp.get_indent_spaces(), 0) - self.assertEqual(isp.source, '') - self.assertEqual(isp.code, None) - self.assertEqual(isp._is_complete, False) - - def test_source(self): - self.isp._store('1') - self.isp._store('2') - self.assertEqual(self.isp.source, '1\n2\n') - self.assertEqual(len(self.isp._buffer)>0, True) - self.assertEqual(self.isp.source_reset(), '1\n2\n') - self.assertEqual(self.isp._buffer, []) - self.assertEqual(self.isp.source, '') - - def test_indent(self): - isp = self.isp # shorthand - isp.push('x=1') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('if 1:\n x=1') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push('y=2\n') - self.assertEqual(isp.get_indent_spaces(), 0) - - def test_indent2(self): - isp = self.isp - isp.push('if 1:') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push(' x=1') - self.assertEqual(isp.get_indent_spaces(), 4) - # Blank lines shouldn't change the indent level - isp.push(' '*2) - self.assertEqual(isp.get_indent_spaces(), 4) - - def test_indent3(self): - isp = self.isp - # When a multiline statement contains parens or multiline strings, we - # shouldn't get confused. - isp.push("if 1:") - isp.push(" x = (1+\n 2)") - self.assertEqual(isp.get_indent_spaces(), 4) - - def test_indent4(self): - isp = self.isp - # whitespace after ':' should not screw up indent level - isp.push('if 1: \n x=1') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push('y=2\n') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('if 1:\t\n x=1') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push('y=2\n') - self.assertEqual(isp.get_indent_spaces(), 0) - - def test_dedent_pass(self): - isp = self.isp # shorthand - # should NOT cause dedent - isp.push('if 1:\n passes = 5') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push('if 1:\n pass') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('if 1:\n pass ') - self.assertEqual(isp.get_indent_spaces(), 0) - - def test_dedent_break(self): - isp = self.isp # shorthand - # should NOT cause dedent - isp.push('while 1:\n breaks = 5') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push('while 1:\n break') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('while 1:\n break ') - self.assertEqual(isp.get_indent_spaces(), 0) - - def test_dedent_continue(self): - isp = self.isp # shorthand - # should NOT cause dedent - isp.push('while 1:\n continues = 5') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push('while 1:\n continue') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('while 1:\n continue ') - self.assertEqual(isp.get_indent_spaces(), 0) - - def test_dedent_raise(self): - isp = self.isp # shorthand - # should NOT cause dedent - isp.push('if 1:\n raised = 4') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push('if 1:\n raise TypeError()') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('if 1:\n raise') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('if 1:\n raise ') - self.assertEqual(isp.get_indent_spaces(), 0) - - def test_dedent_return(self): - isp = self.isp # shorthand - # should NOT cause dedent - isp.push('if 1:\n returning = 4') - self.assertEqual(isp.get_indent_spaces(), 4) - isp.push('if 1:\n return 5 + 493') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('if 1:\n return') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('if 1:\n return ') - self.assertEqual(isp.get_indent_spaces(), 0) - isp.push('if 1:\n return(0)') - self.assertEqual(isp.get_indent_spaces(), 0) - - def test_push(self): - isp = self.isp - self.assertEqual(isp.push('x=1'), True) - - def test_push2(self): - isp = self.isp - self.assertEqual(isp.push('if 1:'), False) - for line in [' x=1', '# a comment', ' y=2']: - print(line) - self.assertEqual(isp.push(line), True) - - def test_push3(self): - isp = self.isp - isp.push('if True:') - isp.push(' a = 1') - self.assertEqual(isp.push('b = [1,'), False) - - def test_push_accepts_more(self): - isp = self.isp - isp.push('x=1') - self.assertEqual(isp.push_accepts_more(), False) - - def test_push_accepts_more2(self): - isp = self.isp - isp.push('if 1:') - self.assertEqual(isp.push_accepts_more(), True) - isp.push(' x=1') - self.assertEqual(isp.push_accepts_more(), True) - isp.push('') - self.assertEqual(isp.push_accepts_more(), False) - - def test_push_accepts_more3(self): - isp = self.isp - isp.push("x = (2+\n3)") - self.assertEqual(isp.push_accepts_more(), False) - - def test_push_accepts_more4(self): - isp = self.isp - # When a multiline statement contains parens or multiline strings, we - # shouldn't get confused. - # FIXME: we should be able to better handle de-dents in statements like - # multiline strings and multiline expressions (continued with \ or - # parens). Right now we aren't handling the indentation tracking quite - # correctly with this, though in practice it may not be too much of a - # problem. We'll need to see. - isp.push("if 1:") - isp.push(" x = (2+") - isp.push(" 3)") - self.assertEqual(isp.push_accepts_more(), True) - isp.push(" y = 3") - self.assertEqual(isp.push_accepts_more(), True) - isp.push('') - self.assertEqual(isp.push_accepts_more(), False) - - def test_push_accepts_more5(self): - isp = self.isp - isp.push('try:') - isp.push(' a = 5') - isp.push('except:') - isp.push(' raise') - # We want to be able to add an else: block at this point, so it should - # wait for a blank line. - self.assertEqual(isp.push_accepts_more(), True) - - def test_continuation(self): - isp = self.isp - isp.push("import os, \\") - self.assertEqual(isp.push_accepts_more(), True) - isp.push("sys") - self.assertEqual(isp.push_accepts_more(), False) - - def test_syntax_error(self): - isp = self.isp - # Syntax errors immediately produce a 'ready' block, so the invalid - # Python can be sent to the kernel for evaluation with possible ipython - # special-syntax conversion. - isp.push('run foo') - self.assertEqual(isp.push_accepts_more(), False) - - def test_unicode(self): - self.isp.push(u"Pérez") - self.isp.push(u'\xc3\xa9') - self.isp.push(u"u'\xc3\xa9'") - - @pytest.mark.xfail( - reason="Bug in python 3.9.8 – bpo 45738", - condition=sys.version_info in [(3, 11, 0, "alpha", 2)], - raises=SystemError, - strict=True, - ) - def test_line_continuation(self): - """ Test issue #2108.""" - isp = self.isp - # A blank line after a line continuation should not accept more - isp.push("1 \\\n\n") - self.assertEqual(isp.push_accepts_more(), False) - # Whitespace after a \ is a SyntaxError. The only way to test that - # here is to test that push doesn't accept more (as with - # test_syntax_error() above). - isp.push(r"1 \ ") - self.assertEqual(isp.push_accepts_more(), False) - # Even if the line is continuable (c.f. the regular Python - # interpreter) - isp.push(r"(1 \ ") - self.assertEqual(isp.push_accepts_more(), False) - - def test_check_complete(self): - isp = self.isp - self.assertEqual(isp.check_complete("a = 1"), ('complete', None)) - self.assertEqual(isp.check_complete("for a in range(5):"), ('incomplete', 4)) - self.assertEqual(isp.check_complete("raise = 2"), ('invalid', None)) - self.assertEqual(isp.check_complete("a = [1,\n2,"), ('incomplete', 0)) - self.assertEqual(isp.check_complete("def a():\n x=1\n global x"), ('invalid', None)) - -class InteractiveLoopTestCase(unittest.TestCase): - """Tests for an interactive loop like a python shell. - """ - def check_ns(self, lines, ns): - """Validate that the given input lines produce the resulting namespace. - - Note: the input lines are given exactly as they would be typed in an - auto-indenting environment, as mini_interactive_loop above already does - auto-indenting and prepends spaces to the input. - """ - src = mini_interactive_loop(pseudo_input(lines)) - test_ns = {} - exec(src, test_ns) - # We can't check that the provided ns is identical to the test_ns, - # because Python fills test_ns with extra keys (copyright, etc). But - # we can check that the given dict is *contained* in test_ns - for k,v in ns.items(): - self.assertEqual(test_ns[k], v) - - def test_simple(self): - self.check_ns(['x=1'], dict(x=1)) - - def test_simple2(self): - self.check_ns(['if 1:', 'x=2'], dict(x=2)) - - def test_xy(self): - self.check_ns(['x=1; y=2'], dict(x=1, y=2)) - - def test_abc(self): - self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3)) - - def test_multi(self): - self.check_ns(['x =(1+','1+','2)'], dict(x=4)) - - -class IPythonInputTestCase(InputSplitterTestCase): - """By just creating a new class whose .isp is a different instance, we - re-run the same test battery on the new input splitter. - - In addition, this runs the tests over the syntax and syntax_ml dicts that - were tested by individual functions, as part of the OO interface. - - It also makes some checks on the raw buffer storage. - """ - - def setUp(self): - self.isp = isp.IPythonInputSplitter() - - def test_syntax(self): - """Call all single-line syntax tests from the main object""" - isp = self.isp - for example in syntax.values(): - for raw, out_t in example: - if raw.startswith(' '): - continue - - isp.push(raw+'\n') - out_raw = isp.source_raw - out = isp.source_reset() - self.assertEqual(out.rstrip(), out_t, - tt.pair_fail_msg.format("inputsplitter",raw, out_t, out)) - self.assertEqual(out_raw.rstrip(), raw.rstrip()) - - def test_syntax_multiline(self): - isp = self.isp - for example in syntax_ml.values(): - for line_pairs in example: - out_t_parts = [] - raw_parts = [] - for lraw, out_t_part in line_pairs: - if out_t_part is not None: - out_t_parts.append(out_t_part) - - if lraw is not None: - isp.push(lraw) - raw_parts.append(lraw) - - out_raw = isp.source_raw - out = isp.source_reset() - out_t = '\n'.join(out_t_parts).rstrip() - raw = '\n'.join(raw_parts).rstrip() - self.assertEqual(out.rstrip(), out_t) - self.assertEqual(out_raw.rstrip(), raw) - - def test_syntax_multiline_cell(self): - isp = self.isp - for example in syntax_ml.values(): - - out_t_parts = [] - for line_pairs in example: - raw = '\n'.join(r for r, _ in line_pairs if r is not None) - out_t = '\n'.join(t for _,t in line_pairs if t is not None) - out = isp.transform_cell(raw) - # Match ignoring trailing whitespace - self.assertEqual(out.rstrip(), out_t.rstrip()) - - def test_cellmagic_preempt(self): - isp = self.isp - for raw, name, line, cell in [ - ("%%cellm a\nIn[1]:", u'cellm', u'a', u'In[1]:'), - ("%%cellm \nline\n>>> hi", u'cellm', u'', u'line\n>>> hi'), - (">>> %%cellm \nline\n>>> hi", u'cellm', u'', u'line\nhi'), - ("%%cellm \n>>> hi", u'cellm', u'', u'>>> hi'), - ("%%cellm \nline1\nline2", u'cellm', u'', u'line1\nline2'), - ("%%cellm \nline1\\\\\nline2", u'cellm', u'', u'line1\\\\\nline2'), - ]: - expected = "get_ipython().run_cell_magic(%r, %r, %r)" % ( - name, line, cell - ) - out = isp.transform_cell(raw) - self.assertEqual(out.rstrip(), expected.rstrip()) - - def test_multiline_passthrough(self): - isp = self.isp - class CommentTransformer(InputTransformer): - def __init__(self): - self._lines = [] - - def push(self, line): - self._lines.append(line + '#') - - def reset(self): - text = '\n'.join(self._lines) - self._lines = [] - return text - - isp.physical_line_transforms.insert(0, CommentTransformer()) - - for raw, expected in [ - ("a=5", "a=5#"), - ("%ls foo", "get_ipython().run_line_magic(%r, %r)" % (u'ls', u'foo#')), - ("!ls foo\n%ls bar", "get_ipython().system(%r)\nget_ipython().run_line_magic(%r, %r)" % ( - u'ls foo#', u'ls', u'bar#' - )), - ("1\n2\n3\n%ls foo\n4\n5", "1#\n2#\n3#\nget_ipython().run_line_magic(%r, %r)\n4#\n5#" % (u'ls', u'foo#')), - ]: - out = isp.transform_cell(raw) - self.assertEqual(out.rstrip(), expected.rstrip()) - -#----------------------------------------------------------------------------- -# Main - use as a script, mostly for developer experiments -#----------------------------------------------------------------------------- - -if __name__ == '__main__': - # A simple demo for interactive experimentation. This code will not get - # picked up by any test suite. - from IPython.core.inputsplitter import IPythonInputSplitter - - # configure here the syntax to use, prompt and whether to autoindent - #isp, start_prompt = InputSplitter(), '>>> ' - isp, start_prompt = IPythonInputSplitter(), 'In> ' - - autoindent = True - #autoindent = False - - try: - while True: - prompt = start_prompt - while isp.push_accepts_more(): - indent = ' '*isp.get_indent_spaces() - if autoindent: - line = indent + input(prompt+indent) - else: - line = input(prompt) - isp.push(line) - prompt = '... ' - - # Here we just return input so we can use it in a test suite, but a - # real interpreter would instead send it for execution somewhere. - #src = isp.source; raise EOFError # dbg - raw = isp.source_raw - src = isp.source_reset() - print('Input source was:\n', src) - print('Raw source was:\n', raw) - except EOFError: - print('Bye') - -# Tests for cell magics support - -def test_last_blank(): - assert isp.last_blank("") is False - assert isp.last_blank("abc") is False - assert isp.last_blank("abc\n") is False - assert isp.last_blank("abc\na") is False - - assert isp.last_blank("\n") is True - assert isp.last_blank("\n ") is True - assert isp.last_blank("abc\n ") is True - assert isp.last_blank("abc\n\n") is True - assert isp.last_blank("abc\nd\n\n") is True - assert isp.last_blank("abc\nd\ne\n\n") is True - assert isp.last_blank("abc \n \n \n\n") is True - - -def test_last_two_blanks(): - assert isp.last_two_blanks("") is False - assert isp.last_two_blanks("abc") is False - assert isp.last_two_blanks("abc\n") is False - assert isp.last_two_blanks("abc\n\na") is False - assert isp.last_two_blanks("abc\n \n") is False - assert isp.last_two_blanks("abc\n\n") is False - - assert isp.last_two_blanks("\n\n") is True - assert isp.last_two_blanks("\n\n ") is True - assert isp.last_two_blanks("\n \n") is True - assert isp.last_two_blanks("abc\n\n ") is True - assert isp.last_two_blanks("abc\n\n\n") is True - assert isp.last_two_blanks("abc\n\n \n") is True - assert isp.last_two_blanks("abc\n\n \n ") is True - assert isp.last_two_blanks("abc\n\n \n \n") is True - assert isp.last_two_blanks("abc\nd\n\n\n") is True - assert isp.last_two_blanks("abc\nd\ne\nf\n\n\n") is True - - -class CellMagicsCommon(object): - - def test_whole_cell(self): - src = "%%cellm line\nbody\n" - out = self.sp.transform_cell(src) - ref = "get_ipython().run_cell_magic('cellm', 'line', 'body')\n" - assert out == ref - - def test_cellmagic_help(self): - self.sp.push('%%cellm?') - assert self.sp.push_accepts_more() is False - - def tearDown(self): - self.sp.reset() - - -class CellModeCellMagics(CellMagicsCommon, unittest.TestCase): - sp = isp.IPythonInputSplitter(line_input_checker=False) - - def test_incremental(self): - sp = self.sp - sp.push("%%cellm firstline\n") - assert sp.push_accepts_more() is True # 1 - sp.push("line2\n") - assert sp.push_accepts_more() is True # 2 - sp.push("\n") - # This should accept a blank line and carry on until the cell is reset - assert sp.push_accepts_more() is True # 3 - - def test_no_strip_coding(self): - src = '\n'.join([ - '%%writefile foo.py', - '# coding: utf-8', - 'print(u"üñîçø∂é")', - ]) - out = self.sp.transform_cell(src) - assert "# coding: utf-8" in out - - -class LineModeCellMagics(CellMagicsCommon, unittest.TestCase): - sp = isp.IPythonInputSplitter(line_input_checker=True) - - def test_incremental(self): - sp = self.sp - sp.push("%%cellm line2\n") - assert sp.push_accepts_more() is True # 1 - sp.push("\n") - # In this case, a blank line should end the cell magic - assert sp.push_accepts_more() is False # 2 - - -indentation_samples = [ - ('a = 1', 0), - ('for a in b:', 4), - ('def f():', 4), - ('def f(): #comment', 4), - ('a = ":#not a comment"', 0), - ('def f():\n a = 1', 4), - ('def f():\n return 1', 0), - ('for a in b:\n' - ' if a < 0:' - ' continue', 3), - ('a = {', 4), - ('a = {\n' - ' 1,', 5), - ('b = """123', 0), - ('', 0), - ('def f():\n pass', 0), - ('class Bar:\n def f():\n pass', 4), - ('class Bar:\n def f():\n raise', 4), -] - -def test_find_next_indent(): - for code, exp in indentation_samples: - res = isp.find_next_indent(code) - msg = "{!r} != {!r} (expected)\n Code: {!r}".format(res, exp, code) - assert res == exp, msg diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer.py deleted file mode 100644 index bfc936d..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer.py +++ /dev/null @@ -1,469 +0,0 @@ -import tokenize - -from IPython.testing import tools as tt - -from IPython.core import inputtransformer as ipt - -def transform_and_reset(transformer): - transformer = transformer() - def transform(inp): - try: - return transformer.push(inp) - finally: - transformer.reset() - - return transform - -# Transformer tests -def transform_checker(tests, transformer, **kwargs): - """Utility to loop over test inputs""" - transformer = transformer(**kwargs) - try: - for inp, tr in tests: - if inp is None: - out = transformer.reset() - else: - out = transformer.push(inp) - assert out == tr - finally: - transformer.reset() - -# Data for all the syntax tests in the form of lists of pairs of -# raw/transformed input. We store it here as a global dict so that we can use -# it both within single-function tests and also to validate the behavior of the -# larger objects - -syntax = \ - dict(assign_system = - [('a =! ls', "a = get_ipython().getoutput('ls')"), - ('b = !ls', "b = get_ipython().getoutput('ls')"), - ('c= !ls', "c = get_ipython().getoutput('ls')"), - ('d == !ls', 'd == !ls'), # Invalid syntax, but we leave == alone. - ('x=1', 'x=1'), # normal input is unmodified - (' ',' '), # blank lines are kept intact - # Tuple unpacking - ("a, b = !echo 'a\\nb'", "a, b = get_ipython().getoutput(\"echo 'a\\\\nb'\")"), - ("a,= !echo 'a'", "a, = get_ipython().getoutput(\"echo 'a'\")"), - ("a, *bc = !echo 'a\\nb\\nc'", "a, *bc = get_ipython().getoutput(\"echo 'a\\\\nb\\\\nc'\")"), - # Tuple unpacking with regular Python expressions, not our syntax. - ("a, b = range(2)", "a, b = range(2)"), - ("a, = range(1)", "a, = range(1)"), - ("a, *bc = range(3)", "a, *bc = range(3)"), - ], - - assign_magic = - [('a =% who', "a = get_ipython().run_line_magic('who', '')"), - ('b = %who', "b = get_ipython().run_line_magic('who', '')"), - ('c= %ls', "c = get_ipython().run_line_magic('ls', '')"), - ('d == %ls', 'd == %ls'), # Invalid syntax, but we leave == alone. - ('x=1', 'x=1'), # normal input is unmodified - (' ',' '), # blank lines are kept intact - ("a, b = %foo", "a, b = get_ipython().run_line_magic('foo', '')"), - ], - classic_prompt=[ - (">>> x=1", "x=1"), - ("x=1", "x=1"), # normal input is unmodified - (" ", " "), # blank lines are kept intact - ], - ipy_prompt=[ - ("In [1]: x=1", "x=1"), - ("x=1", "x=1"), # normal input is unmodified - (" ", " "), # blank lines are kept intact - ], - # Tests for the escape transformer to leave normal code alone - escaped_noesc=[ - (" ", " "), - ("x=1", "x=1"), - ], - # System calls - escaped_shell=[ - ("!ls", "get_ipython().system('ls')"), - # Double-escape shell, this means to capture the output of the - # subprocess and return it - ("!!ls", "get_ipython().getoutput('ls')"), - ], - # Help/object info - escaped_help=[ - ("?", "get_ipython().show_usage()"), - ("?x1", "get_ipython().run_line_magic('pinfo', 'x1')"), - ("??x2", "get_ipython().run_line_magic('pinfo2', 'x2')"), - ("?a.*s", "get_ipython().run_line_magic('psearch', 'a.*s')"), - ("?%hist1", "get_ipython().run_line_magic('pinfo', '%hist1')"), - ("?%%hist2", "get_ipython().run_line_magic('pinfo', '%%hist2')"), - ("?abc = qwe", "get_ipython().run_line_magic('pinfo', 'abc')"), - ], - end_help=[ - ("x3?", "get_ipython().run_line_magic('pinfo', 'x3')"), - ("x4??", "get_ipython().run_line_magic('pinfo2', 'x4')"), - ("%hist1?", "get_ipython().run_line_magic('pinfo', '%hist1')"), - ("%hist2??", "get_ipython().run_line_magic('pinfo2', '%hist2')"), - ("%%hist3?", "get_ipython().run_line_magic('pinfo', '%%hist3')"), - ("%%hist4??", "get_ipython().run_line_magic('pinfo2', '%%hist4')"), - ("π.foo?", "get_ipython().run_line_magic('pinfo', 'π.foo')"), - ("f*?", "get_ipython().run_line_magic('psearch', 'f*')"), - ("ax.*aspe*?", "get_ipython().run_line_magic('psearch', 'ax.*aspe*')"), - ("a = abc?", "get_ipython().run_line_magic('pinfo', 'abc')"), - ("a = abc.qe??", "get_ipython().run_line_magic('pinfo2', 'abc.qe')"), - ("a = *.items?", "get_ipython().run_line_magic('psearch', '*.items')"), - ("plot(a?", "get_ipython().run_line_magic('pinfo', 'a')"), - ("a*2 #comment?", "a*2 #comment?"), - ], - # Explicit magic calls - escaped_magic=[ - ("%cd", "get_ipython().run_line_magic('cd', '')"), - ("%cd /home", "get_ipython().run_line_magic('cd', '/home')"), - # Backslashes need to be escaped. - ("%cd C:\\User", "get_ipython().run_line_magic('cd', 'C:\\\\User')"), - (" %magic", " get_ipython().run_line_magic('magic', '')"), - ], - # Quoting with separate arguments - escaped_quote=[ - (",f", 'f("")'), - (",f x", 'f("x")'), - (" ,f y", ' f("y")'), - (",f a b", 'f("a", "b")'), - ], - # Quoting with single argument - escaped_quote2=[ - (";f", 'f("")'), - (";f x", 'f("x")'), - (" ;f y", ' f("y")'), - (";f a b", 'f("a b")'), - ], - # Simply apply parens - escaped_paren=[ - ("/f", "f()"), - ("/f x", "f(x)"), - (" /f y", " f(y)"), - ("/f a b", "f(a, b)"), - ], - # Check that we transform prompts before other transforms - mixed=[ - ("In [1]: %lsmagic", "get_ipython().run_line_magic('lsmagic', '')"), - (">>> %lsmagic", "get_ipython().run_line_magic('lsmagic', '')"), - ("In [2]: !ls", "get_ipython().system('ls')"), - ("In [3]: abs?", "get_ipython().run_line_magic('pinfo', 'abs')"), - ("In [4]: b = %who", "b = get_ipython().run_line_magic('who', '')"), - ], -) - -# multiline syntax examples. Each of these should be a list of lists, with -# each entry itself having pairs of raw/transformed input. The union (with -# '\n'.join() of the transformed inputs is what the splitter should produce -# when fed the raw lines one at a time via push. -syntax_ml = \ - dict(classic_prompt = - [ [('>>> for i in range(10):','for i in range(10):'), - ('... print i',' print i'), - ('... ', ''), - ], - [('>>> a="""','a="""'), - ('... 123"""','123"""'), - ], - [('a="""','a="""'), - ('... 123','123'), - ('... 456"""','456"""'), - ], - [('a="""','a="""'), - ('>>> 123','123'), - ('... 456"""','456"""'), - ], - [('a="""','a="""'), - ('123','123'), - ('... 456"""','... 456"""'), - ], - [('....__class__','....__class__'), - ], - [('a=5', 'a=5'), - ('...', ''), - ], - [('>>> def f(x):', 'def f(x):'), - ('...', ''), - ('... return x', ' return x'), - ], - [('board = """....', 'board = """....'), - ('....', '....'), - ('...."""', '...."""'), - ], - ], - - ipy_prompt = - [ [('In [24]: for i in range(10):','for i in range(10):'), - (' ....: print i',' print i'), - (' ....: ', ''), - ], - [('In [24]: for i in range(10):','for i in range(10):'), - # Qt console prompts expand with spaces, not dots - (' ...: print i',' print i'), - (' ...: ', ''), - ], - [('In [24]: for i in range(10):','for i in range(10):'), - # Sometimes whitespace preceding '...' has been removed - ('...: print i',' print i'), - ('...: ', ''), - ], - [('In [24]: for i in range(10):','for i in range(10):'), - # Space after last continuation prompt has been removed (issue #6674) - ('...: print i',' print i'), - ('...:', ''), - ], - [('In [2]: a="""','a="""'), - (' ...: 123"""','123"""'), - ], - [('a="""','a="""'), - (' ...: 123','123'), - (' ...: 456"""','456"""'), - ], - [('a="""','a="""'), - ('In [1]: 123','123'), - (' ...: 456"""','456"""'), - ], - [('a="""','a="""'), - ('123','123'), - (' ...: 456"""',' ...: 456"""'), - ], - ], - - multiline_datastructure_prompt = - [ [('>>> a = [1,','a = [1,'), - ('... 2]','2]'), - ], - ], - - multiline_datastructure = - [ [('b = ("%s"', None), - ('# comment', None), - ('%foo )', 'b = ("%s"\n# comment\n%foo )'), - ], - ], - - multiline_string = - [ [("'''foo?", None), - ("bar'''", "'''foo?\nbar'''"), - ], - ], - - leading_indent = - [ [(' print "hi"','print "hi"'), - ], - [(' for a in range(5):','for a in range(5):'), - (' a*2',' a*2'), - ], - [(' a="""','a="""'), - (' 123"""','123"""'), - ], - [('a="""','a="""'), - (' 123"""',' 123"""'), - ], - ], - - cellmagic = - [ [('%%foo a', None), - (None, "get_ipython().run_cell_magic('foo', 'a', '')"), - ], - [('%%bar 123', None), - ('hello', None), - (None , "get_ipython().run_cell_magic('bar', '123', 'hello')"), - ], - [('a=5', 'a=5'), - ('%%cellmagic', '%%cellmagic'), - ], - ], - - escaped = - [ [('%abc def \\', None), - ('ghi', "get_ipython().run_line_magic('abc', 'def ghi')"), - ], - [('%abc def \\', None), - ('ghi\\', None), - (None, "get_ipython().run_line_magic('abc', 'def ghi')"), - ], - ], - - assign_magic = - [ [('a = %bc de \\', None), - ('fg', "a = get_ipython().run_line_magic('bc', 'de fg')"), - ], - [('a = %bc de \\', None), - ('fg\\', None), - (None, "a = get_ipython().run_line_magic('bc', 'de fg')"), - ], - ], - - assign_system = - [ [('a = !bc de \\', None), - ('fg', "a = get_ipython().getoutput('bc de fg')"), - ], - [('a = !bc de \\', None), - ('fg\\', None), - (None, "a = get_ipython().getoutput('bc de fg')"), - ], - ], - ) - - -def test_assign_system(): - tt.check_pairs(transform_and_reset(ipt.assign_from_system), syntax['assign_system']) - -def test_assign_magic(): - tt.check_pairs(transform_and_reset(ipt.assign_from_magic), syntax['assign_magic']) - -def test_classic_prompt(): - tt.check_pairs(transform_and_reset(ipt.classic_prompt), syntax['classic_prompt']) - for example in syntax_ml['classic_prompt']: - transform_checker(example, ipt.classic_prompt) - for example in syntax_ml['multiline_datastructure_prompt']: - transform_checker(example, ipt.classic_prompt) - - # Check that we don't transform the second line if the first is obviously - # IPython syntax - transform_checker([ - ('%foo', '%foo'), - ('>>> bar', '>>> bar'), - ], ipt.classic_prompt) - - -def test_ipy_prompt(): - tt.check_pairs(transform_and_reset(ipt.ipy_prompt), syntax['ipy_prompt']) - for example in syntax_ml['ipy_prompt']: - transform_checker(example, ipt.ipy_prompt) - - # Check that we don't transform the second line if we're inside a cell magic - transform_checker([ - ('%%foo', '%%foo'), - ('In [1]: bar', 'In [1]: bar'), - ], ipt.ipy_prompt) - -def test_assemble_logical_lines(): - tests = \ - [ [("a = \\", None), - ("123", "a = 123"), - ], - [("a = \\", None), # Test resetting when within a multi-line string - ("12 *\\", None), - (None, "a = 12 *"), - ], - [("# foo\\", "# foo\\"), # Comments can't be continued like this - ], - ] - for example in tests: - transform_checker(example, ipt.assemble_logical_lines) - -def test_assemble_python_lines(): - tests = \ - [ [("a = '''", None), - ("abc'''", "a = '''\nabc'''"), - ], - [("a = '''", None), # Test resetting when within a multi-line string - ("def", None), - (None, "a = '''\ndef"), - ], - [("a = [1,", None), - ("2]", "a = [1,\n2]"), - ], - [("a = [1,", None), # Test resetting when within a multi-line string - ("2,", None), - (None, "a = [1,\n2,"), - ], - [("a = '''", None), # Test line continuation within a multi-line string - ("abc\\", None), - ("def", None), - ("'''", "a = '''\nabc\\\ndef\n'''"), - ], - ] + syntax_ml['multiline_datastructure'] - for example in tests: - transform_checker(example, ipt.assemble_python_lines) - - -def test_help_end(): - tt.check_pairs(transform_and_reset(ipt.help_end), syntax['end_help']) - -def test_escaped_noesc(): - tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_noesc']) - - -def test_escaped_shell(): - tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_shell']) - - -def test_escaped_help(): - tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_help']) - - -def test_escaped_magic(): - tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_magic']) - - -def test_escaped_quote(): - tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote']) - - -def test_escaped_quote2(): - tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote2']) - - -def test_escaped_paren(): - tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_paren']) - - -def test_cellmagic(): - for example in syntax_ml['cellmagic']: - transform_checker(example, ipt.cellmagic) - - line_example = [('%%bar 123', None), - ('hello', None), - ('' , "get_ipython().run_cell_magic('bar', '123', 'hello')"), - ] - transform_checker(line_example, ipt.cellmagic, end_on_blank_line=True) - -def test_has_comment(): - tests = [('text', False), - ('text #comment', True), - ('text #comment\n', True), - ('#comment', True), - ('#comment\n', True), - ('a = "#string"', False), - ('a = "#string" # comment', True), - ('a #comment not "string"', True), - ] - tt.check_pairs(ipt.has_comment, tests) - -@ipt.TokenInputTransformer.wrap -def decistmt(tokens): - """Substitute Decimals for floats in a string of statements. - - Based on an example from the tokenize module docs. - """ - result = [] - for toknum, tokval, _, _, _ in tokens: - if toknum == tokenize.NUMBER and '.' in tokval: # replace NUMBER tokens - yield from [ - (tokenize.NAME, 'Decimal'), - (tokenize.OP, '('), - (tokenize.STRING, repr(tokval)), - (tokenize.OP, ')') - ] - else: - yield (toknum, tokval) - - - -def test_token_input_transformer(): - tests = [('1.2', "Decimal ('1.2')"), - ('"1.2"', '"1.2"'), - ] - tt.check_pairs(transform_and_reset(decistmt), tests) - ml_tests = \ - [ [("a = 1.2; b = '''x", None), - ("y'''", "a =Decimal ('1.2');b ='''x\ny'''"), - ], - [("a = [1.2,", None), - ("3]", "a =[Decimal ('1.2'),\n3 ]"), - ], - [("a = '''foo", None), # Test resetting when within a multi-line string - ("bar", None), - (None, "a = '''foo\nbar"), - ], - ] - for example in ml_tests: - transform_checker(example, decistmt) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer2.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer2.py deleted file mode 100644 index 0f563b7..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer2.py +++ /dev/null @@ -1,448 +0,0 @@ -"""Tests for the token-based transformers in IPython.core.inputtransformer2 - -Line-based transformers are the simpler ones; token-based transformers are -more complex. See test_inputtransformer2_line for tests for line-based -transformations. -""" - -import platform -import string -import sys -from textwrap import dedent - -import pytest - -from IPython.core import inputtransformer2 as ipt2 -from IPython.core.inputtransformer2 import _find_assign_op, make_tokens_by_line - -MULTILINE_MAGIC = ( - """\ -a = f() -%foo \\ -bar -g() -""".splitlines( - keepends=True - ), - (2, 0), - """\ -a = f() -get_ipython().run_line_magic('foo', ' bar') -g() -""".splitlines( - keepends=True - ), -) - -INDENTED_MAGIC = ( - """\ -for a in range(5): - %ls -""".splitlines( - keepends=True - ), - (2, 4), - """\ -for a in range(5): - get_ipython().run_line_magic('ls', '') -""".splitlines( - keepends=True - ), -) - -CRLF_MAGIC = ( - ["a = f()\n", "%ls\r\n", "g()\n"], - (2, 0), - ["a = f()\n", "get_ipython().run_line_magic('ls', '')\n", "g()\n"], -) - -MULTILINE_MAGIC_ASSIGN = ( - """\ -a = f() -b = %foo \\ - bar -g() -""".splitlines( - keepends=True - ), - (2, 4), - """\ -a = f() -b = get_ipython().run_line_magic('foo', ' bar') -g() -""".splitlines( - keepends=True - ), -) - -MULTILINE_SYSTEM_ASSIGN = ("""\ -a = f() -b = !foo \\ - bar -g() -""".splitlines(keepends=True), (2, 4), """\ -a = f() -b = get_ipython().getoutput('foo bar') -g() -""".splitlines(keepends=True)) - -##### - -MULTILINE_SYSTEM_ASSIGN_AFTER_DEDENT = ( - """\ -def test(): - for i in range(1): - print(i) - res =! ls -""".splitlines( - keepends=True - ), - (4, 7), - """\ -def test(): - for i in range(1): - print(i) - res =get_ipython().getoutput(\' ls\') -""".splitlines( - keepends=True - ), -) - -###### - -AUTOCALL_QUOTE = ([",f 1 2 3\n"], (1, 0), ['f("1", "2", "3")\n']) - -AUTOCALL_QUOTE2 = ([";f 1 2 3\n"], (1, 0), ['f("1 2 3")\n']) - -AUTOCALL_PAREN = (["/f 1 2 3\n"], (1, 0), ["f(1, 2, 3)\n"]) - -SIMPLE_HELP = (["foo?\n"], (1, 0), ["get_ipython().run_line_magic('pinfo', 'foo')\n"]) - -DETAILED_HELP = ( - ["foo??\n"], - (1, 0), - ["get_ipython().run_line_magic('pinfo2', 'foo')\n"], -) - -MAGIC_HELP = (["%foo?\n"], (1, 0), ["get_ipython().run_line_magic('pinfo', '%foo')\n"]) - -HELP_IN_EXPR = ( - ["a = b + c?\n"], - (1, 0), - ["get_ipython().run_line_magic('pinfo', 'c')\n"], -) - -HELP_CONTINUED_LINE = ( - """\ -a = \\ -zip? -""".splitlines( - keepends=True - ), - (1, 0), - [r"get_ipython().run_line_magic('pinfo', 'zip')" + "\n"], -) - -HELP_MULTILINE = ( - """\ -(a, -b) = zip? -""".splitlines( - keepends=True - ), - (1, 0), - [r"get_ipython().run_line_magic('pinfo', 'zip')" + "\n"], -) - -HELP_UNICODE = ( - ["π.foo?\n"], - (1, 0), - ["get_ipython().run_line_magic('pinfo', 'π.foo')\n"], -) - - -def null_cleanup_transformer(lines): - """ - A cleanup transform that returns an empty list. - """ - return [] - - -def test_check_make_token_by_line_never_ends_empty(): - """ - Check that not sequence of single or double characters ends up leading to en empty list of tokens - """ - from string import printable - - for c in printable: - assert make_tokens_by_line(c)[-1] != [] - for k in printable: - assert make_tokens_by_line(c + k)[-1] != [] - - -def check_find(transformer, case, match=True): - sample, expected_start, _ = case - tbl = make_tokens_by_line(sample) - res = transformer.find(tbl) - if match: - # start_line is stored 0-indexed, expected values are 1-indexed - assert (res.start_line + 1, res.start_col) == expected_start - return res - else: - assert res is None - - -def check_transform(transformer_cls, case): - lines, start, expected = case - transformer = transformer_cls(start) - assert transformer.transform(lines) == expected - - -def test_continued_line(): - lines = MULTILINE_MAGIC_ASSIGN[0] - assert ipt2.find_end_of_continued_line(lines, 1) == 2 - - assert ipt2.assemble_continued_line(lines, (1, 5), 2) == "foo bar" - - -def test_find_assign_magic(): - check_find(ipt2.MagicAssign, MULTILINE_MAGIC_ASSIGN) - check_find(ipt2.MagicAssign, MULTILINE_SYSTEM_ASSIGN, match=False) - check_find(ipt2.MagicAssign, MULTILINE_SYSTEM_ASSIGN_AFTER_DEDENT, match=False) - - -def test_transform_assign_magic(): - check_transform(ipt2.MagicAssign, MULTILINE_MAGIC_ASSIGN) - - -def test_find_assign_system(): - check_find(ipt2.SystemAssign, MULTILINE_SYSTEM_ASSIGN) - check_find(ipt2.SystemAssign, MULTILINE_SYSTEM_ASSIGN_AFTER_DEDENT) - check_find(ipt2.SystemAssign, (["a = !ls\n"], (1, 5), None)) - check_find(ipt2.SystemAssign, (["a=!ls\n"], (1, 2), None)) - check_find(ipt2.SystemAssign, MULTILINE_MAGIC_ASSIGN, match=False) - - -def test_transform_assign_system(): - check_transform(ipt2.SystemAssign, MULTILINE_SYSTEM_ASSIGN) - check_transform(ipt2.SystemAssign, MULTILINE_SYSTEM_ASSIGN_AFTER_DEDENT) - - -def test_find_magic_escape(): - check_find(ipt2.EscapedCommand, MULTILINE_MAGIC) - check_find(ipt2.EscapedCommand, INDENTED_MAGIC) - check_find(ipt2.EscapedCommand, MULTILINE_MAGIC_ASSIGN, match=False) - - -def test_transform_magic_escape(): - check_transform(ipt2.EscapedCommand, MULTILINE_MAGIC) - check_transform(ipt2.EscapedCommand, INDENTED_MAGIC) - check_transform(ipt2.EscapedCommand, CRLF_MAGIC) - - -def test_find_autocalls(): - for case in [AUTOCALL_QUOTE, AUTOCALL_QUOTE2, AUTOCALL_PAREN]: - print("Testing %r" % case[0]) - check_find(ipt2.EscapedCommand, case) - - -def test_transform_autocall(): - for case in [AUTOCALL_QUOTE, AUTOCALL_QUOTE2, AUTOCALL_PAREN]: - print("Testing %r" % case[0]) - check_transform(ipt2.EscapedCommand, case) - - -def test_find_help(): - for case in [SIMPLE_HELP, DETAILED_HELP, MAGIC_HELP, HELP_IN_EXPR]: - check_find(ipt2.HelpEnd, case) - - tf = check_find(ipt2.HelpEnd, HELP_CONTINUED_LINE) - assert tf.q_line == 1 - assert tf.q_col == 3 - - tf = check_find(ipt2.HelpEnd, HELP_MULTILINE) - assert tf.q_line == 1 - assert tf.q_col == 8 - - # ? in a comment does not trigger help - check_find(ipt2.HelpEnd, (["foo # bar?\n"], None, None), match=False) - # Nor in a string - check_find(ipt2.HelpEnd, (["foo = '''bar?\n"], None, None), match=False) - - -def test_transform_help(): - tf = ipt2.HelpEnd((1, 0), (1, 9)) - assert tf.transform(HELP_IN_EXPR[0]) == HELP_IN_EXPR[2] - - tf = ipt2.HelpEnd((1, 0), (2, 3)) - assert tf.transform(HELP_CONTINUED_LINE[0]) == HELP_CONTINUED_LINE[2] - - tf = ipt2.HelpEnd((1, 0), (2, 8)) - assert tf.transform(HELP_MULTILINE[0]) == HELP_MULTILINE[2] - - tf = ipt2.HelpEnd((1, 0), (1, 0)) - assert tf.transform(HELP_UNICODE[0]) == HELP_UNICODE[2] - - -def test_find_assign_op_dedent(): - """ - be careful that empty token like dedent are not counted as parens - """ - - class Tk: - def __init__(self, s): - self.string = s - - assert _find_assign_op([Tk(s) for s in ("", "a", "=", "b")]) == 2 - assert ( - _find_assign_op([Tk(s) for s in ("", "(", "a", "=", "b", ")", "=", "5")]) == 6 - ) - - -extra_closing_paren_param = ( - pytest.param("(\n))", "invalid", None) - if sys.version_info >= (3, 12) - else pytest.param("(\n))", "incomplete", 0) -) -examples = [ - pytest.param("a = 1", "complete", None), - pytest.param("for a in range(5):", "incomplete", 4), - pytest.param("for a in range(5):\n if a > 0:", "incomplete", 8), - pytest.param("raise = 2", "invalid", None), - pytest.param("a = [1,\n2,", "incomplete", 0), - extra_closing_paren_param, - pytest.param("\\\r\n", "incomplete", 0), - pytest.param("a = '''\n hi", "incomplete", 3), - pytest.param("def a():\n x=1\n global x", "invalid", None), - pytest.param( - "a \\ ", - "invalid", - None, - marks=pytest.mark.xfail( - reason="Bug in python 3.9.8 – bpo 45738", - condition=sys.version_info in [(3, 11, 0, "alpha", 2)], - raises=SystemError, - strict=True, - ), - ), # Nothing allowed after backslash, - pytest.param("1\\\n+2", "complete", None), -] - - -@pytest.mark.parametrize("code, expected, number", examples) -def test_check_complete_param(code, expected, number): - cc = ipt2.TransformerManager().check_complete - assert cc(code) == (expected, number) - - -@pytest.mark.xfail(platform.python_implementation() == "PyPy", reason="fail on pypy") -@pytest.mark.xfail( - reason="Bug in python 3.9.8 – bpo 45738", - condition=sys.version_info in [(3, 11, 0, "alpha", 2)], - raises=SystemError, - strict=True, -) -def test_check_complete(): - cc = ipt2.TransformerManager().check_complete - - example = dedent( - """ - if True: - a=1""" - ) - - assert cc(example) == ("incomplete", 4) - assert cc(example + "\n") == ("complete", None) - assert cc(example + "\n ") == ("complete", None) - - # no need to loop on all the letters/numbers. - short = "12abAB" + string.printable[62:] - for c in short: - # test does not raise: - cc(c) - for k in short: - cc(c + k) - - assert cc("def f():\n x=0\n \\\n ") == ("incomplete", 2) - - -@pytest.mark.xfail(platform.python_implementation() == "PyPy", reason="fail on pypy") -@pytest.mark.parametrize( - "value, expected", - [ - ('''def foo():\n """''', ("incomplete", 4)), - ("""async with example:\n pass""", ("incomplete", 4)), - ("""async with example:\n pass\n """, ("complete", None)), - ], -) -def test_check_complete_II(value, expected): - """ - Test that multiple line strings are properly handled. - - Separate test function for convenience - - """ - cc = ipt2.TransformerManager().check_complete - assert cc(value) == expected - - -@pytest.mark.parametrize( - "value, expected", - [ - (")", ("invalid", None)), - ("]", ("invalid", None)), - ("}", ("invalid", None)), - (")(", ("invalid", None)), - ("][", ("invalid", None)), - ("}{", ("invalid", None)), - ("]()(", ("invalid", None)), - ("())(", ("invalid", None)), - (")[](", ("invalid", None)), - ("()](", ("invalid", None)), - ], -) -def test_check_complete_invalidates_sunken_brackets(value, expected): - """ - Test that a single line with more closing brackets than the opening ones is - interpreted as invalid - """ - cc = ipt2.TransformerManager().check_complete - assert cc(value) == expected - - -def test_null_cleanup_transformer(): - manager = ipt2.TransformerManager() - manager.cleanup_transforms.insert(0, null_cleanup_transformer) - assert manager.transform_cell("") == "" - - -def test_side_effects_I(): - count = 0 - - def counter(lines): - nonlocal count - count += 1 - return lines - - counter.has_side_effects = True - - manager = ipt2.TransformerManager() - manager.cleanup_transforms.insert(0, counter) - assert manager.check_complete("a=1\n") == ("complete", None) - assert count == 0 - - -def test_side_effects_II(): - count = 0 - - def counter(lines): - nonlocal count - count += 1 - return lines - - counter.has_side_effects = True - - manager = ipt2.TransformerManager() - manager.line_transforms.insert(0, counter) - assert manager.check_complete("b=1\n") == ("complete", None) - assert count == 0 diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer2_line.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer2_line.py deleted file mode 100644 index ec7a873..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_inputtransformer2_line.py +++ /dev/null @@ -1,167 +0,0 @@ -"""Tests for the line-based transformers in IPython.core.inputtransformer2 - -Line-based transformers are the simpler ones; token-based transformers are -more complex. See test_inputtransformer2 for tests for token-based transformers. -""" - -from IPython.core import inputtransformer2 as ipt2 - -CELL_MAGIC = ("""\ -%%foo arg -body 1 -body 2 -""", """\ -get_ipython().run_cell_magic('foo', 'arg', 'body 1\\nbody 2\\n') -""") - -def test_cell_magic(): - for sample, expected in [CELL_MAGIC]: - assert ipt2.cell_magic(sample.splitlines(keepends=True)) == expected.splitlines( - keepends=True - ) - -CLASSIC_PROMPT = ("""\ ->>> for a in range(5): -... print(a) -""", """\ -for a in range(5): - print(a) -""") - -CLASSIC_PROMPT_L2 = ("""\ -for a in range(5): -... print(a) -... print(a ** 2) -""", """\ -for a in range(5): - print(a) - print(a ** 2) -""") - -def test_classic_prompt(): - for sample, expected in [CLASSIC_PROMPT, CLASSIC_PROMPT_L2]: - assert ipt2.classic_prompt( - sample.splitlines(keepends=True) - ) == expected.splitlines(keepends=True) - -IPYTHON_PROMPT = ("""\ -In [1]: for a in range(5): - ...: print(a) -""", """\ -for a in range(5): - print(a) -""") - -IPYTHON_PROMPT_L2 = ("""\ -for a in range(5): - ...: print(a) - ...: print(a ** 2) -""", """\ -for a in range(5): - print(a) - print(a ** 2) -""") - - -IPYTHON_PROMPT_VI_INS = ( - """\ -[ins] In [11]: def a(): - ...: 123 - ...: - ...: 123 -""", - """\ -def a(): - 123 - -123 -""", -) - -IPYTHON_PROMPT_VI_NAV = ( - """\ -[nav] In [11]: def a(): - ...: 123 - ...: - ...: 123 -""", - """\ -def a(): - 123 - -123 -""", -) - - -def test_ipython_prompt(): - for sample, expected in [ - IPYTHON_PROMPT, - IPYTHON_PROMPT_L2, - IPYTHON_PROMPT_VI_INS, - IPYTHON_PROMPT_VI_NAV, - ]: - assert ipt2.ipython_prompt( - sample.splitlines(keepends=True) - ) == expected.splitlines(keepends=True) - - -INDENT_SPACES = ("""\ - if True: - a = 3 -""", """\ -if True: - a = 3 -""") - -INDENT_TABS = ("""\ -\tif True: -\t\tb = 4 -""", """\ -if True: -\tb = 4 -""") - -def test_leading_indent(): - for sample, expected in [INDENT_SPACES, INDENT_TABS]: - assert ipt2.leading_indent( - sample.splitlines(keepends=True) - ) == expected.splitlines(keepends=True) - -LEADING_EMPTY_LINES = ("""\ - \t - -if True: - a = 3 - -b = 4 -""", """\ -if True: - a = 3 - -b = 4 -""") - -ONLY_EMPTY_LINES = ("""\ - \t - -""", """\ - \t - -""") - -def test_leading_empty_lines(): - for sample, expected in [LEADING_EMPTY_LINES, ONLY_EMPTY_LINES]: - assert ipt2.leading_empty_lines( - sample.splitlines(keepends=True) - ) == expected.splitlines(keepends=True) - -CRLF_MAGIC = ([ - "%%ls\r\n" -], [ - "get_ipython().run_cell_magic('ls', '', '')\n" -]) - -def test_crlf_magic(): - for sample, expected in [CRLF_MAGIC]: - assert ipt2.cell_magic(sample) == expected diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_interactiveshell.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_interactiveshell.py deleted file mode 100644 index f87d96f..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_interactiveshell.py +++ /dev/null @@ -1,1221 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests for the key interactiveshell module. - -Historically the main classes in interactiveshell have been under-tested. This -module should grow as many single-method tests as possible to trap many of the -recurring bugs we seem to encounter with high-level interaction. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import asyncio -import ast -import os -import signal -import shutil -import sys -import tempfile -import unittest -import pytest -from unittest import mock - -from os.path import join - -from IPython.core.error import InputRejected -from IPython.core.inputtransformer import InputTransformer -from IPython.core import interactiveshell -from IPython.core.oinspect import OInfo -from IPython.testing.decorators import ( - skipif, - skip_win32, - onlyif_unicode_paths, - onlyif_cmds_exist, - skip_if_not_osx, -) -from IPython.testing import tools as tt -from IPython.utils.process import find_cmd - -#----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- -# This is used by every single test, no point repeating it ad nauseam - -#----------------------------------------------------------------------------- -# Tests -#----------------------------------------------------------------------------- - -class DerivedInterrupt(KeyboardInterrupt): - pass - -class InteractiveShellTestCase(unittest.TestCase): - def test_naked_string_cells(self): - """Test that cells with only naked strings are fully executed""" - # First, single-line inputs - ip.run_cell('"a"\n') - self.assertEqual(ip.user_ns['_'], 'a') - # And also multi-line cells - ip.run_cell('"""a\nb"""\n') - self.assertEqual(ip.user_ns['_'], 'a\nb') - - def test_run_empty_cell(self): - """Just make sure we don't get a horrible error with a blank - cell of input. Yes, I did overlook that.""" - old_xc = ip.execution_count - res = ip.run_cell('') - self.assertEqual(ip.execution_count, old_xc) - self.assertEqual(res.execution_count, None) - - def test_run_cell_multiline(self): - """Multi-block, multi-line cells must execute correctly. - """ - src = '\n'.join(["x=1", - "y=2", - "if 1:", - " x += 1", - " y += 1",]) - res = ip.run_cell(src) - self.assertEqual(ip.user_ns['x'], 2) - self.assertEqual(ip.user_ns['y'], 3) - self.assertEqual(res.success, True) - self.assertEqual(res.result, None) - - def test_multiline_string_cells(self): - "Code sprinkled with multiline strings should execute (GH-306)" - ip.run_cell('tmp=0') - self.assertEqual(ip.user_ns['tmp'], 0) - res = ip.run_cell('tmp=1;"""a\nb"""\n') - self.assertEqual(ip.user_ns['tmp'], 1) - self.assertEqual(res.success, True) - self.assertEqual(res.result, "a\nb") - - def test_dont_cache_with_semicolon(self): - "Ending a line with semicolon should not cache the returned object (GH-307)" - oldlen = len(ip.user_ns['Out']) - for cell in ['1;', '1;1;']: - res = ip.run_cell(cell, store_history=True) - newlen = len(ip.user_ns['Out']) - self.assertEqual(oldlen, newlen) - self.assertIsNone(res.result) - i = 0 - #also test the default caching behavior - for cell in ['1', '1;1']: - ip.run_cell(cell, store_history=True) - newlen = len(ip.user_ns['Out']) - i += 1 - self.assertEqual(oldlen+i, newlen) - - def test_syntax_error(self): - res = ip.run_cell("raise = 3") - self.assertIsInstance(res.error_before_exec, SyntaxError) - - def test_open_standard_input_stream(self): - res = ip.run_cell("open(0)") - self.assertIsInstance(res.error_in_exec, ValueError) - - def test_open_standard_output_stream(self): - res = ip.run_cell("open(1)") - self.assertIsInstance(res.error_in_exec, ValueError) - - def test_open_standard_error_stream(self): - res = ip.run_cell("open(2)") - self.assertIsInstance(res.error_in_exec, ValueError) - - def test_In_variable(self): - "Verify that In variable grows with user input (GH-284)" - oldlen = len(ip.user_ns['In']) - ip.run_cell('1;', store_history=True) - newlen = len(ip.user_ns['In']) - self.assertEqual(oldlen+1, newlen) - self.assertEqual(ip.user_ns['In'][-1],'1;') - - def test_magic_names_in_string(self): - ip.run_cell('a = """\n%exit\n"""') - self.assertEqual(ip.user_ns['a'], '\n%exit\n') - - def test_trailing_newline(self): - """test that running !(command) does not raise a SyntaxError""" - ip.run_cell('!(true)\n', False) - ip.run_cell('!(true)\n\n\n', False) - - def test_gh_597(self): - """Pretty-printing lists of objects with non-ascii reprs may cause - problems.""" - class Spam(object): - def __repr__(self): - return "\xe9"*50 - import IPython.core.formatters - f = IPython.core.formatters.PlainTextFormatter() - f([Spam(), Spam()]) - - def test_future_flags(self): - """Check that future flags are used for parsing code (gh-777)""" - ip.run_cell('from __future__ import barry_as_FLUFL') - try: - ip.run_cell('prfunc_return_val = 1 <> 2') - assert 'prfunc_return_val' in ip.user_ns - finally: - # Reset compiler flags so we don't mess up other tests. - ip.compile.reset_compiler_flags() - - def test_can_pickle(self): - "Can we pickle objects defined interactively (GH-29)" - ip = get_ipython() - ip.reset() - ip.run_cell(("class Mylist(list):\n" - " def __init__(self,x=[]):\n" - " list.__init__(self,x)")) - ip.run_cell("w=Mylist([1,2,3])") - - from pickle import dumps - - # We need to swap in our main module - this is only necessary - # inside the test framework, because IPython puts the interactive module - # in place (but the test framework undoes this). - _main = sys.modules['__main__'] - sys.modules['__main__'] = ip.user_module - try: - res = dumps(ip.user_ns["w"]) - finally: - sys.modules['__main__'] = _main - self.assertTrue(isinstance(res, bytes)) - - def test_global_ns(self): - "Code in functions must be able to access variables outside them." - ip = get_ipython() - ip.run_cell("a = 10") - ip.run_cell(("def f(x):\n" - " return x + a")) - ip.run_cell("b = f(12)") - self.assertEqual(ip.user_ns["b"], 22) - - def test_bad_custom_tb(self): - """Check that InteractiveShell is protected from bad custom exception handlers""" - ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0) - self.assertEqual(ip.custom_exceptions, (IOError,)) - with tt.AssertPrints("Custom TB Handler failed", channel='stderr'): - ip.run_cell(u'raise IOError("foo")') - self.assertEqual(ip.custom_exceptions, ()) - - def test_bad_custom_tb_return(self): - """Check that InteractiveShell is protected from bad return types in custom exception handlers""" - ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1) - self.assertEqual(ip.custom_exceptions, (NameError,)) - with tt.AssertPrints("Custom TB Handler failed", channel='stderr'): - ip.run_cell(u'a=abracadabra') - self.assertEqual(ip.custom_exceptions, ()) - - def test_drop_by_id(self): - myvars = {"a":object(), "b":object(), "c": object()} - ip.push(myvars, interactive=False) - for name in myvars: - assert name in ip.user_ns, name - assert name in ip.user_ns_hidden, name - ip.user_ns['b'] = 12 - ip.drop_by_id(myvars) - for name in ["a", "c"]: - assert name not in ip.user_ns, name - assert name not in ip.user_ns_hidden, name - assert ip.user_ns['b'] == 12 - ip.reset() - - def test_var_expand(self): - ip.user_ns['f'] = u'Ca\xf1o' - self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o') - self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o') - self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1') - self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2') - - self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'") - - ip.user_ns['f'] = b'Ca\xc3\xb1o' - # This should not raise any exception: - ip.var_expand(u'echo $f') - - def test_var_expand_local(self): - """Test local variable expansion in !system and %magic calls""" - # !system - ip.run_cell( - "def test():\n" - ' lvar = "ttt"\n' - " ret = !echo {lvar}\n" - " return ret[0]\n" - ) - res = ip.user_ns["test"]() - self.assertIn("ttt", res) - - # %magic - ip.run_cell( - "def makemacro():\n" - ' macroname = "macro_var_expand_locals"\n' - " %macro {macroname} codestr\n" - ) - ip.user_ns["codestr"] = "str(12)" - ip.run_cell("makemacro()") - self.assertIn("macro_var_expand_locals", ip.user_ns) - - def test_var_expand_self(self): - """Test variable expansion with the name 'self', which was failing. - - See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218 - """ - ip.run_cell( - "class cTest:\n" - ' classvar="see me"\n' - " def test(self):\n" - " res = !echo Variable: {self.classvar}\n" - " return res[0]\n" - ) - self.assertIn("see me", ip.user_ns["cTest"]().test()) - - def test_bad_var_expand(self): - """var_expand on invalid formats shouldn't raise""" - # SyntaxError - self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}") - # NameError - self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}") - # ZeroDivisionError - self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}") - - def test_silent_postexec(self): - """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks""" - pre_explicit = mock.Mock() - pre_always = mock.Mock() - post_explicit = mock.Mock() - post_always = mock.Mock() - all_mocks = [pre_explicit, pre_always, post_explicit, post_always] - - ip.events.register('pre_run_cell', pre_explicit) - ip.events.register('pre_execute', pre_always) - ip.events.register('post_run_cell', post_explicit) - ip.events.register('post_execute', post_always) - - try: - ip.run_cell("1", silent=True) - assert pre_always.called - assert not pre_explicit.called - assert post_always.called - assert not post_explicit.called - # double-check that non-silent exec did what we expected - # silent to avoid - ip.run_cell("1") - assert pre_explicit.called - assert post_explicit.called - info, = pre_explicit.call_args[0] - result, = post_explicit.call_args[0] - self.assertEqual(info, result.info) - # check that post hooks are always called - [m.reset_mock() for m in all_mocks] - ip.run_cell("syntax error") - assert pre_always.called - assert pre_explicit.called - assert post_always.called - assert post_explicit.called - info, = pre_explicit.call_args[0] - result, = post_explicit.call_args[0] - self.assertEqual(info, result.info) - finally: - # remove post-exec - ip.events.unregister('pre_run_cell', pre_explicit) - ip.events.unregister('pre_execute', pre_always) - ip.events.unregister('post_run_cell', post_explicit) - ip.events.unregister('post_execute', post_always) - - def test_silent_noadvance(self): - """run_cell(silent=True) doesn't advance execution_count""" - ec = ip.execution_count - # silent should force store_history=False - ip.run_cell("1", store_history=True, silent=True) - - self.assertEqual(ec, ip.execution_count) - # double-check that non-silent exec did what we expected - # silent to avoid - ip.run_cell("1", store_history=True) - self.assertEqual(ec+1, ip.execution_count) - - def test_silent_nodisplayhook(self): - """run_cell(silent=True) doesn't trigger displayhook""" - d = dict(called=False) - - trap = ip.display_trap - save_hook = trap.hook - - def failing_hook(*args, **kwargs): - d['called'] = True - - try: - trap.hook = failing_hook - res = ip.run_cell("1", silent=True) - self.assertFalse(d['called']) - self.assertIsNone(res.result) - # double-check that non-silent exec did what we expected - # silent to avoid - ip.run_cell("1") - self.assertTrue(d['called']) - finally: - trap.hook = save_hook - - def test_ofind_line_magic(self): - from IPython.core.magic import register_line_magic - - @register_line_magic - def lmagic(line): - "A line magic" - - # Get info on line magic - lfind = ip._ofind("lmagic") - info = OInfo( - found=True, - isalias=False, - ismagic=True, - namespace="IPython internal", - obj=lmagic, - parent=None, - ) - self.assertEqual(lfind, info) - - def test_ofind_cell_magic(self): - from IPython.core.magic import register_cell_magic - - @register_cell_magic - def cmagic(line, cell): - "A cell magic" - - # Get info on cell magic - find = ip._ofind("cmagic") - info = OInfo( - found=True, - isalias=False, - ismagic=True, - namespace="IPython internal", - obj=cmagic, - parent=None, - ) - self.assertEqual(find, info) - - def test_ofind_property_with_error(self): - class A(object): - @property - def foo(self): - raise NotImplementedError() # pragma: no cover - - a = A() - - found = ip._ofind("a.foo", [("locals", locals())]) - info = OInfo( - found=True, - isalias=False, - ismagic=False, - namespace="locals", - obj=A.foo, - parent=a, - ) - self.assertEqual(found, info) - - def test_ofind_multiple_attribute_lookups(self): - class A(object): - @property - def foo(self): - raise NotImplementedError() # pragma: no cover - - a = A() - a.a = A() - a.a.a = A() - - found = ip._ofind("a.a.a.foo", [("locals", locals())]) - info = OInfo( - found=True, - isalias=False, - ismagic=False, - namespace="locals", - obj=A.foo, - parent=a.a.a, - ) - self.assertEqual(found, info) - - def test_ofind_slotted_attributes(self): - class A(object): - __slots__ = ['foo'] - def __init__(self): - self.foo = 'bar' - - a = A() - found = ip._ofind("a.foo", [("locals", locals())]) - info = OInfo( - found=True, - isalias=False, - ismagic=False, - namespace="locals", - obj=a.foo, - parent=a, - ) - self.assertEqual(found, info) - - found = ip._ofind("a.bar", [("locals", locals())]) - expected = OInfo( - found=False, - isalias=False, - ismagic=False, - namespace=None, - obj=None, - parent=a, - ) - assert found == expected - - def test_ofind_prefers_property_to_instance_level_attribute(self): - class A(object): - @property - def foo(self): - return 'bar' - a = A() - a.__dict__["foo"] = "baz" - self.assertEqual(a.foo, "bar") - found = ip._ofind("a.foo", [("locals", locals())]) - self.assertIs(found.obj, A.foo) - - def test_custom_syntaxerror_exception(self): - called = [] - def my_handler(shell, etype, value, tb, tb_offset=None): - called.append(etype) - shell.showtraceback((etype, value, tb), tb_offset=tb_offset) - - ip.set_custom_exc((SyntaxError,), my_handler) - try: - ip.run_cell("1f") - # Check that this was called, and only once. - self.assertEqual(called, [SyntaxError]) - finally: - # Reset the custom exception hook - ip.set_custom_exc((), None) - - def test_custom_exception(self): - called = [] - def my_handler(shell, etype, value, tb, tb_offset=None): - called.append(etype) - shell.showtraceback((etype, value, tb), tb_offset=tb_offset) - - ip.set_custom_exc((ValueError,), my_handler) - try: - res = ip.run_cell("raise ValueError('test')") - # Check that this was called, and only once. - self.assertEqual(called, [ValueError]) - # Check that the error is on the result object - self.assertIsInstance(res.error_in_exec, ValueError) - finally: - # Reset the custom exception hook - ip.set_custom_exc((), None) - - @mock.patch("builtins.print") - def test_showtraceback_with_surrogates(self, mocked_print): - values = [] - - def mock_print_func(value, sep=" ", end="\n", file=sys.stdout, flush=False): - values.append(value) - if value == chr(0xD8FF): - raise UnicodeEncodeError("utf-8", chr(0xD8FF), 0, 1, "") - - # mock builtins.print - mocked_print.side_effect = mock_print_func - - # ip._showtraceback() is replaced in globalipapp.py. - # Call original method to test. - interactiveshell.InteractiveShell._showtraceback(ip, None, None, chr(0xD8FF)) - - self.assertEqual(mocked_print.call_count, 2) - self.assertEqual(values, [chr(0xD8FF), "\\ud8ff"]) - - def test_mktempfile(self): - filename = ip.mktempfile() - # Check that we can open the file again on Windows - with open(filename, "w", encoding="utf-8") as f: - f.write("abc") - - filename = ip.mktempfile(data="blah") - with open(filename, "r", encoding="utf-8") as f: - self.assertEqual(f.read(), "blah") - - def test_new_main_mod(self): - # Smoketest to check that this accepts a unicode module name - name = u'jiefmw' - mod = ip.new_main_mod(u'%s.py' % name, name) - self.assertEqual(mod.__name__, name) - - def test_get_exception_only(self): - try: - raise KeyboardInterrupt - except KeyboardInterrupt: - msg = ip.get_exception_only() - self.assertEqual(msg, 'KeyboardInterrupt\n') - - try: - raise DerivedInterrupt("foo") - except KeyboardInterrupt: - msg = ip.get_exception_only() - self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n') - - def test_inspect_text(self): - ip.run_cell('a = 5') - text = ip.object_inspect_text('a') - self.assertIsInstance(text, str) - - def test_last_execution_result(self): - """ Check that last execution result gets set correctly (GH-10702) """ - result = ip.run_cell('a = 5; a') - self.assertTrue(ip.last_execution_succeeded) - self.assertEqual(ip.last_execution_result.result, 5) - - result = ip.run_cell('a = x_invalid_id_x') - self.assertFalse(ip.last_execution_succeeded) - self.assertFalse(ip.last_execution_result.success) - self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError) - - def test_reset_aliasing(self): - """ Check that standard posix aliases work after %reset. """ - if os.name != 'posix': - return - - ip.reset() - for cmd in ('clear', 'more', 'less', 'man'): - res = ip.run_cell('%' + cmd) - self.assertEqual(res.success, True) - - -@pytest.mark.skipif( - sys.implementation.name == "pypy" - and ((7, 3, 13) < sys.implementation.version < (7, 3, 16)), - reason="Unicode issues with scandir on PyPy, see https://github.com/pypy/pypy/issues/4860", -) -class TestSafeExecfileNonAsciiPath(unittest.TestCase): - @onlyif_unicode_paths - def setUp(self): - self.BASETESTDIR = tempfile.mkdtemp() - self.TESTDIR = join(self.BASETESTDIR, u"åäö") - os.mkdir(self.TESTDIR) - with open( - join(self.TESTDIR, "åäötestscript.py"), "w", encoding="utf-8" - ) as sfile: - sfile.write("pass\n") - self.oldpath = os.getcwd() - os.chdir(self.TESTDIR) - self.fname = u"åäötestscript.py" - - def tearDown(self): - os.chdir(self.oldpath) - shutil.rmtree(self.BASETESTDIR) - - @onlyif_unicode_paths - def test_1(self): - """Test safe_execfile with non-ascii path - """ - ip.safe_execfile(self.fname, {}, raise_exceptions=True) - -class ExitCodeChecks(tt.TempFileMixin): - - def setUp(self): - self.system = ip.system_raw - - def test_exit_code_ok(self): - self.system('exit 0') - self.assertEqual(ip.user_ns['_exit_code'], 0) - - def test_exit_code_error(self): - self.system('exit 1') - self.assertEqual(ip.user_ns['_exit_code'], 1) - - @skipif(not hasattr(signal, 'SIGALRM')) - def test_exit_code_signal(self): - self.mktmp("import signal, time\n" - "signal.setitimer(signal.ITIMER_REAL, 0.1)\n" - "time.sleep(1)\n") - self.system("%s %s" % (sys.executable, self.fname)) - self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM) - - @onlyif_cmds_exist("csh") - def test_exit_code_signal_csh(self): # pragma: no cover - SHELL = os.environ.get("SHELL", None) - os.environ["SHELL"] = find_cmd("csh") - try: - self.test_exit_code_signal() - finally: - if SHELL is not None: - os.environ['SHELL'] = SHELL - else: - del os.environ['SHELL'] - - -class TestSystemRaw(ExitCodeChecks): - - def setUp(self): - super().setUp() - self.system = ip.system_raw - - @onlyif_unicode_paths - def test_1(self): - """Test system_raw with non-ascii cmd - """ - cmd = u'''python -c "'åäö'" ''' - ip.system_raw(cmd) - - @mock.patch('subprocess.call', side_effect=KeyboardInterrupt) - @mock.patch('os.system', side_effect=KeyboardInterrupt) - def test_control_c(self, *mocks): - try: - self.system("sleep 1 # won't happen") - except KeyboardInterrupt: # pragma: no cove - self.fail( - "system call should intercept " - "keyboard interrupt from subprocess.call" - ) - self.assertEqual(ip.user_ns["_exit_code"], -signal.SIGINT) - - -@pytest.mark.parametrize("magic_cmd", ["pip", "conda", "cd"]) -def test_magic_warnings(magic_cmd): - if sys.platform == "win32": - to_mock = "os.system" - expected_arg, expected_kwargs = magic_cmd, dict() - else: - to_mock = "subprocess.call" - expected_arg, expected_kwargs = magic_cmd, dict( - shell=True, executable=os.environ.get("SHELL", None) - ) - - with mock.patch(to_mock, return_value=0) as mock_sub: - with pytest.warns(Warning, match=r"You executed the system command"): - ip.system_raw(magic_cmd) - mock_sub.assert_called_once_with(expected_arg, **expected_kwargs) - - -# TODO: Exit codes are currently ignored on Windows. -class TestSystemPipedExitCode(ExitCodeChecks): - - def setUp(self): - super().setUp() - self.system = ip.system_piped - - @skip_win32 - def test_exit_code_ok(self): - ExitCodeChecks.test_exit_code_ok(self) - - @skip_win32 - def test_exit_code_error(self): - ExitCodeChecks.test_exit_code_error(self) - - @skip_win32 - def test_exit_code_signal(self): - ExitCodeChecks.test_exit_code_signal(self) - -class TestModules(tt.TempFileMixin): - def test_extraneous_loads(self): - """Test we're not loading modules on startup that we shouldn't. - """ - self.mktmp("import sys\n" - "print('numpy' in sys.modules)\n" - "print('ipyparallel' in sys.modules)\n" - "print('ipykernel' in sys.modules)\n" - ) - out = "False\nFalse\nFalse\n" - tt.ipexec_validate(self.fname, out) - -class Negator(ast.NodeTransformer): - """Negates all number literals in an AST.""" - - def visit_Num(self, node): - node.value = -node.value - return node - - def visit_Constant(self, node): - if isinstance(node.value, int): - return self.visit_Num(node) - return node - -class TestAstTransform(unittest.TestCase): - def setUp(self): - self.negator = Negator() - ip.ast_transformers.append(self.negator) - - def tearDown(self): - ip.ast_transformers.remove(self.negator) - - def test_non_int_const(self): - with tt.AssertPrints("hello"): - ip.run_cell('print("hello")') - - def test_run_cell(self): - with tt.AssertPrints("-34"): - ip.run_cell("print(12 + 22)") - - # A named reference to a number shouldn't be transformed. - ip.user_ns["n"] = 55 - with tt.AssertNotPrints("-55"): - ip.run_cell("print(n)") - - def test_timeit(self): - called = set() - def f(x): - called.add(x) - ip.push({'f':f}) - - with tt.AssertPrints("std. dev. of"): - ip.run_line_magic("timeit", "-n1 f(1)") - self.assertEqual(called, {-1}) - called.clear() - - with tt.AssertPrints("std. dev. of"): - ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)") - self.assertEqual(called, {-2, -3}) - - def test_time(self): - called = [] - def f(x): - called.append(x) - ip.push({'f':f}) - - # Test with an expression - with tt.AssertPrints("Wall time: "): - ip.run_line_magic("time", "f(5+9)") - self.assertEqual(called, [-14]) - called[:] = [] - - # Test with a statement (different code path) - with tt.AssertPrints("Wall time: "): - ip.run_line_magic("time", "a = f(-3 + -2)") - self.assertEqual(called, [5]) - - def test_macro(self): - ip.push({'a':10}) - # The AST transformation makes this do a+=-1 - ip.define_macro("amacro", "a+=1\nprint(a)") - - with tt.AssertPrints("9"): - ip.run_cell("amacro") - with tt.AssertPrints("8"): - ip.run_cell("amacro") - -class TestMiscTransform(unittest.TestCase): - - - def test_transform_only_once(self): - cleanup = 0 - line_t = 0 - def count_cleanup(lines): - nonlocal cleanup - cleanup += 1 - return lines - - def count_line_t(lines): - nonlocal line_t - line_t += 1 - return lines - - ip.input_transformer_manager.cleanup_transforms.append(count_cleanup) - ip.input_transformer_manager.line_transforms.append(count_line_t) - - ip.run_cell('1') - - assert cleanup == 1 - assert line_t == 1 - -class IntegerWrapper(ast.NodeTransformer): - """Wraps all integers in a call to Integer()""" - - # for Python 3.7 and earlier - - # for Python 3.7 and earlier - def visit_Num(self, node): - if isinstance(node.n, int): - return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()), - args=[node], keywords=[]) - return node - - # For Python 3.8+ - def visit_Constant(self, node): - if isinstance(node.value, int): - return self.visit_Num(node) - return node - - -class TestAstTransform2(unittest.TestCase): - def setUp(self): - self.intwrapper = IntegerWrapper() - ip.ast_transformers.append(self.intwrapper) - - self.calls = [] - def Integer(*args): - self.calls.append(args) - return args - ip.push({"Integer": Integer}) - - def tearDown(self): - ip.ast_transformers.remove(self.intwrapper) - del ip.user_ns['Integer'] - - def test_run_cell(self): - ip.run_cell("n = 2") - self.assertEqual(self.calls, [(2,)]) - - # This shouldn't throw an error - ip.run_cell("o = 2.0") - self.assertEqual(ip.user_ns['o'], 2.0) - - def test_run_cell_non_int(self): - ip.run_cell("n = 'a'") - assert self.calls == [] - - def test_timeit(self): - called = set() - def f(x): - called.add(x) - ip.push({'f':f}) - - with tt.AssertPrints("std. dev. of"): - ip.run_line_magic("timeit", "-n1 f(1)") - self.assertEqual(called, {(1,)}) - called.clear() - - with tt.AssertPrints("std. dev. of"): - ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)") - self.assertEqual(called, {(2,), (3,)}) - -class ErrorTransformer(ast.NodeTransformer): - """Throws an error when it sees a number.""" - - def visit_Constant(self, node): - if isinstance(node.value, int): - raise ValueError("test") - return node - - -class TestAstTransformError(unittest.TestCase): - def test_unregistering(self): - err_transformer = ErrorTransformer() - ip.ast_transformers.append(err_transformer) - - with self.assertWarnsRegex(UserWarning, "It will be unregistered"): - ip.run_cell("1 + 2") - - # This should have been removed. - self.assertNotIn(err_transformer, ip.ast_transformers) - - -class StringRejector(ast.NodeTransformer): - """Throws an InputRejected when it sees a string literal. - - Used to verify that NodeTransformers can signal that a piece of code should - not be executed by throwing an InputRejected. - """ - - def visit_Constant(self, node): - if isinstance(node.value, str): - raise InputRejected("test") - return node - - -class TestAstTransformInputRejection(unittest.TestCase): - - def setUp(self): - self.transformer = StringRejector() - ip.ast_transformers.append(self.transformer) - - def tearDown(self): - ip.ast_transformers.remove(self.transformer) - - def test_input_rejection(self): - """Check that NodeTransformers can reject input.""" - - expect_exception_tb = tt.AssertPrints("InputRejected: test") - expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False) - - # Run the same check twice to verify that the transformer is not - # disabled after raising. - with expect_exception_tb, expect_no_cell_output: - ip.run_cell("'unsafe'") - - with expect_exception_tb, expect_no_cell_output: - res = ip.run_cell("'unsafe'") - - self.assertIsInstance(res.error_before_exec, InputRejected) - -def test__IPYTHON__(): - # This shouldn't raise a NameError, that's all - __IPYTHON__ - - -class DummyRepr(object): - def __repr__(self): - return "DummyRepr" - - def _repr_html_(self): - return "dummy" - - def _repr_javascript_(self): - return "console.log('hi');", {'key': 'value'} - - -def test_user_variables(): - # enable all formatters - ip.display_formatter.active_types = ip.display_formatter.format_types - - ip.user_ns['dummy'] = d = DummyRepr() - keys = {'dummy', 'doesnotexist'} - r = ip.user_expressions({ key:key for key in keys}) - - assert keys == set(r.keys()) - dummy = r["dummy"] - assert {"status", "data", "metadata"} == set(dummy.keys()) - assert dummy["status"] == "ok" - data = dummy["data"] - metadata = dummy["metadata"] - assert data.get("text/html") == d._repr_html_() - js, jsmd = d._repr_javascript_() - assert data.get("application/javascript") == js - assert metadata.get("application/javascript") == jsmd - - dne = r["doesnotexist"] - assert dne["status"] == "error" - assert dne["ename"] == "NameError" - - # back to text only - ip.display_formatter.active_types = ['text/plain'] - -def test_user_expression(): - # enable all formatters - ip.display_formatter.active_types = ip.display_formatter.format_types - query = { - 'a' : '1 + 2', - 'b' : '1/0', - } - r = ip.user_expressions(query) - import pprint - pprint.pprint(r) - assert set(r.keys()) == set(query.keys()) - a = r["a"] - assert {"status", "data", "metadata"} == set(a.keys()) - assert a["status"] == "ok" - data = a["data"] - metadata = a["metadata"] - assert data.get("text/plain") == "3" - - b = r["b"] - assert b["status"] == "error" - assert b["ename"] == "ZeroDivisionError" - - # back to text only - ip.display_formatter.active_types = ['text/plain'] - - -class TestSyntaxErrorTransformer(unittest.TestCase): - """Check that SyntaxError raised by an input transformer is handled by run_cell()""" - - @staticmethod - def transformer(lines): - for line in lines: - pos = line.find('syntaxerror') - if pos >= 0: - e = SyntaxError('input contains "syntaxerror"') - e.text = line - e.offset = pos + 1 - raise e - return lines - - def setUp(self): - ip.input_transformers_post.append(self.transformer) - - def tearDown(self): - ip.input_transformers_post.remove(self.transformer) - - def test_syntaxerror_input_transformer(self): - with tt.AssertPrints('1234'): - ip.run_cell('1234') - with tt.AssertPrints('SyntaxError: invalid syntax'): - ip.run_cell('1 2 3') # plain python syntax error - with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'): - ip.run_cell('2345 # syntaxerror') # input transformer syntax error - with tt.AssertPrints('3456'): - ip.run_cell('3456') - - -class TestWarningSuppression(unittest.TestCase): - def test_warning_suppression(self): - ip.run_cell("import warnings") - try: - with self.assertWarnsRegex(UserWarning, "asdf"): - ip.run_cell("warnings.warn('asdf')") - # Here's the real test -- if we run that again, we should get the - # warning again. Traditionally, each warning was only issued once per - # IPython session (approximately), even if the user typed in new and - # different code that should have also triggered the warning, leading - # to much confusion. - with self.assertWarnsRegex(UserWarning, "asdf"): - ip.run_cell("warnings.warn('asdf')") - finally: - ip.run_cell("del warnings") - - - def test_deprecation_warning(self): - ip.run_cell(""" -import warnings -def wrn(): - warnings.warn( - "I AM A WARNING", - DeprecationWarning - ) - """) - try: - with self.assertWarnsRegex(DeprecationWarning, "I AM A WARNING"): - ip.run_cell("wrn()") - finally: - ip.run_cell("del warnings") - ip.run_cell("del wrn") - - -class TestImportNoDeprecate(tt.TempFileMixin): - - def setUp(self): - """Make a valid python temp file.""" - self.mktmp(""" -import warnings -def wrn(): - warnings.warn( - "I AM A WARNING", - DeprecationWarning - ) -""") - super().setUp() - - def test_no_dep(self): - """ - No deprecation warning should be raised from imported functions - """ - ip.run_cell("from {} import wrn".format(self.fname)) - - with tt.AssertNotPrints("I AM A WARNING"): - ip.run_cell("wrn()") - ip.run_cell("del wrn") - - -def test_custom_exc_count(): - hook = mock.Mock(return_value=None) - ip.set_custom_exc((SyntaxError,), hook) - before = ip.execution_count - ip.run_cell("def foo()", store_history=True) - # restore default excepthook - ip.set_custom_exc((), None) - assert hook.call_count == 1 - assert ip.execution_count == before + 1 - - -def test_run_cell_async(): - ip.run_cell("import asyncio") - coro = ip.run_cell_async("await asyncio.sleep(0.01)\n5") - assert asyncio.iscoroutine(coro) - loop = asyncio.new_event_loop() - result = loop.run_until_complete(coro) - assert isinstance(result, interactiveshell.ExecutionResult) - assert result.result == 5 - - -def test_run_cell_await(): - ip.run_cell("import asyncio") - result = ip.run_cell("await asyncio.sleep(0.01); 10") - assert ip.user_ns["_"] == 10 - - -def test_run_cell_asyncio_run(): - ip.run_cell("import asyncio") - result = ip.run_cell("await asyncio.sleep(0.01); 1") - assert ip.user_ns["_"] == 1 - result = ip.run_cell("asyncio.run(asyncio.sleep(0.01)); 2") - assert ip.user_ns["_"] == 2 - result = ip.run_cell("await asyncio.sleep(0.01); 3") - assert ip.user_ns["_"] == 3 - - -def test_should_run_async(): - assert not ip.should_run_async("a = 5", transformed_cell="a = 5") - assert ip.should_run_async("await x", transformed_cell="await x") - assert ip.should_run_async( - "import asyncio; await asyncio.sleep(1)", - transformed_cell="import asyncio; await asyncio.sleep(1)", - ) - - -def test_set_custom_completer(): - num_completers = len(ip.Completer.matchers) - - def foo(*args, **kwargs): - return "I'm a completer!" - - ip.set_custom_completer(foo, 0) - - # check that we've really added a new completer - assert len(ip.Completer.matchers) == num_completers + 1 - - # check that the first completer is the function we defined - assert ip.Completer.matchers[0]() == "I'm a completer!" - - # clean up - ip.Completer.custom_matchers.pop() - - -class TestShowTracebackAttack(unittest.TestCase): - """Test that the interactive shell is resilient against the client attack of - manipulating the showtracebacks method. These attacks shouldn't result in an - unhandled exception in the kernel.""" - - def setUp(self): - self.orig_showtraceback = interactiveshell.InteractiveShell.showtraceback - - def tearDown(self): - interactiveshell.InteractiveShell.showtraceback = self.orig_showtraceback - - def test_set_show_tracebacks_none(self): - """Test the case of the client setting showtracebacks to None""" - - result = ip.run_cell( - """ - import IPython.core.interactiveshell - IPython.core.interactiveshell.InteractiveShell.showtraceback = None - - assert False, "This should not raise an exception" - """ - ) - print(result) - - assert result.result is None - assert isinstance(result.error_in_exec, TypeError) - assert str(result.error_in_exec) == "'NoneType' object is not callable" - - def test_set_show_tracebacks_noop(self): - """Test the case of the client setting showtracebacks to a no op lambda""" - - result = ip.run_cell( - """ - import IPython.core.interactiveshell - IPython.core.interactiveshell.InteractiveShell.showtraceback = lambda *args, **kwargs: None - - assert False, "This should not raise an exception" - """ - ) - print(result) - - assert result.result is None - assert isinstance(result.error_in_exec, AssertionError) - assert str(result.error_in_exec) == "This should not raise an exception" - - -@skip_if_not_osx -def test_enable_gui_osx(): - simple_prompt = ip.simple_prompt - ip.simple_prompt = False - - ip.enable_gui("osx") - assert ip.active_eventloop == "osx" - ip.enable_gui() - - # The following line fails for IPython <= 8.25.0 - ip.enable_gui("macosx") - assert ip.active_eventloop == "osx" - ip.enable_gui() - - ip.simple_prompt = simple_prompt diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_iplib.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_iplib.py deleted file mode 100644 index a5e51fb..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_iplib.py +++ /dev/null @@ -1,246 +0,0 @@ -"""Tests for the key interactiveshell module, where the main ipython class is defined. -""" - -import stack_data -import sys - -SV_VERSION = tuple([int(x) for x in stack_data.__version__.split(".")[0:2]]) - - -def test_reset(): - """reset must clear most namespaces.""" - - # Check that reset runs without error - ip.reset() - - # Once we've reset it (to clear of any junk that might have been there from - # other tests, we can count how many variables are in the user's namespace - nvars_user_ns = len(ip.user_ns) - nvars_hidden = len(ip.user_ns_hidden) - - # Now add a few variables to user_ns, and check that reset clears them - ip.user_ns['x'] = 1 - ip.user_ns['y'] = 1 - ip.reset() - - # Finally, check that all namespaces have only as many variables as we - # expect to find in them: - assert len(ip.user_ns) == nvars_user_ns - assert len(ip.user_ns_hidden) == nvars_hidden - - -# Tests for reporting of exceptions in various modes, handling of SystemExit, -# and %tb functionality. This is really a mix of testing ultraTB and interactiveshell. - -def doctest_tb_plain(): - """ - In [18]: xmode plain - Exception reporting mode: Plain - - In [19]: run simpleerr.py - Traceback (most recent call last): - File ...:... - bar(mode) - File ...:... in bar - div0() - File ...:... in div0 - x/y - ZeroDivisionError: ... - """ - - -def doctest_tb_context(): - """ - In [3]: xmode context - Exception reporting mode: Context - - In [4]: run simpleerr.py - --------------------------------------------------------------------------- - ZeroDivisionError Traceback (most recent call last) - - ... - 30 except IndexError: - 31 mode = 'div' - ---> 33 bar(mode) - - ... in bar(mode) - 15 "bar" - 16 if mode=='div': - ---> 17 div0() - 18 elif mode=='exit': - 19 try: - - ... in div0() - 6 x = 1 - 7 y = 0 - ----> 8 x/y - - ZeroDivisionError: ...""" - - -def doctest_tb_verbose(): - """ - In [5]: xmode verbose - Exception reporting mode: Verbose - - In [6]: run simpleerr.py - --------------------------------------------------------------------------- - ZeroDivisionError Traceback (most recent call last) - - ... - 30 except IndexError: - 31 mode = 'div' - ---> 33 bar(mode) - mode = 'div' - - ... in bar(mode='div') - 15 "bar" - 16 if mode=='div': - ---> 17 div0() - 18 elif mode=='exit': - 19 try: - - ... in div0() - 6 x = 1 - 7 y = 0 - ----> 8 x/y - x = 1 - y = 0 - - ZeroDivisionError: ... - """ - - -def doctest_tb_sysexit(): - """ - In [17]: %xmode plain - Exception reporting mode: Plain - - In [18]: %run simpleerr.py exit - An exception has occurred, use %tb to see the full traceback. - SystemExit: (1, 'Mode = exit') - - In [19]: %run simpleerr.py exit 2 - An exception has occurred, use %tb to see the full traceback. - SystemExit: (2, 'Mode = exit') - - In [20]: %tb - Traceback (most recent call last): - File ...:... in execfile - exec(compiler(f.read(), fname, "exec"), glob, loc) - File ...:... - bar(mode) - File ...:... in bar - sysexit(stat, mode) - File ...:... in sysexit - raise SystemExit(stat, f"Mode = {mode}") - SystemExit: (2, 'Mode = exit') - - In [21]: %xmode context - Exception reporting mode: Context - - In [22]: %tb - --------------------------------------------------------------------------- - SystemExit Traceback (most recent call last) - File ..., in execfile(fname, glob, loc, compiler) - ... with open(fname, "rb") as f: - ... compiler = compiler or compile - ---> ... exec(compiler(f.read(), fname, "exec"), glob, loc) - ... - 30 except IndexError: - 31 mode = 'div' - ---> 33 bar(mode) - - ...bar(mode) - 21 except: - 22 stat = 1 - ---> 23 sysexit(stat, mode) - 24 else: - 25 raise ValueError('Unknown mode') - - ...sysexit(stat, mode) - 10 def sysexit(stat, mode): - ---> 11 raise SystemExit(stat, f"Mode = {mode}") - - SystemExit: (2, 'Mode = exit') - """ - - -if SV_VERSION < (0, 6): - - def doctest_tb_sysexit_verbose_stack_data_05(): - """ - In [18]: %run simpleerr.py exit - An exception has occurred, use %tb to see the full traceback. - SystemExit: (1, 'Mode = exit') - - In [19]: %run simpleerr.py exit 2 - An exception has occurred, use %tb to see the full traceback. - SystemExit: (2, 'Mode = exit') - - In [23]: %xmode verbose - Exception reporting mode: Verbose - - In [24]: %tb - --------------------------------------------------------------------------- - SystemExit Traceback (most recent call last) - - ... - 30 except IndexError: - 31 mode = 'div' - ---> 33 bar(mode) - mode = 'exit' - - ... in bar(mode='exit') - ... except: - ... stat = 1 - ---> ... sysexit(stat, mode) - mode = 'exit' - stat = 2 - ... else: - ... raise ValueError('Unknown mode') - - ... in sysexit(stat=2, mode='exit') - 10 def sysexit(stat, mode): - ---> 11 raise SystemExit(stat, f"Mode = {mode}") - stat = 2 - - SystemExit: (2, 'Mode = exit') - """ - - -def test_run_cell(): - import textwrap - - ip.run_cell("a = 10\na+=1") - ip.run_cell("assert a == 11\nassert 1") - - assert ip.user_ns["a"] == 11 - complex = textwrap.dedent( - """ - if 1: - print "hello" - if 1: - print "world" - - if 2: - print "foo" - - if 3: - print "bar" - - if 4: - print "bar" - - """ - ) - # Simply verifies that this kind of input is run - ip.run_cell(complex) - - -def test_db(): - """Test the internal database used for variable persistence.""" - ip.db["__unittest_"] = 12 - assert ip.db["__unittest_"] == 12 - del ip.db["__unittest_"] - assert "__unittest_" not in ip.db diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_logger.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_logger.py deleted file mode 100644 index 003f603..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_logger.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test IPython.core.logger""" - -import os.path - -import pytest -from tempfile import TemporaryDirectory - - -def test_logstart_inaccessible_file(): - with pytest.raises(IOError): - _ip.logger.logstart(logfname="/") # Opening that filename will fail. - - try: - _ip.run_cell("a=1") # Check it doesn't try to log this - finally: - _ip.logger.log_active = False # If this fails, don't let later tests fail - -def test_logstart_unicode(): - with TemporaryDirectory() as tdir: - logfname = os.path.join(tdir, "test_unicode.log") - _ip.run_cell("'abc€'") - try: - _ip.run_line_magic("logstart", "-to %s" % logfname) - _ip.run_cell("'abc€'") - finally: - _ip.logger.logstop() diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic.py deleted file mode 100644 index 4e16700..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic.py +++ /dev/null @@ -1,1623 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests for various magic functions.""" - -import gc -import io -import os -import re -import shlex -import signal -import sys -import warnings -from importlib import invalidate_caches -from io import StringIO -from pathlib import Path -from time import sleep -from threading import Thread -from subprocess import CalledProcessError -from textwrap import dedent -from time import sleep -from threading import Thread -from unittest import TestCase, mock - -import pytest - -from IPython import get_ipython -from IPython.core import magic -from IPython.core.error import UsageError -from IPython.core.magic import ( - Magics, - cell_magic, - line_magic, - magics_class, - register_cell_magic, - register_line_magic, -) -from IPython.core.magics import code, execution, logging, osm, script -from IPython.testing import decorators as dec -from IPython.testing import tools as tt -from IPython.utils.io import capture_output -from IPython.utils.process import find_cmd -from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory -from IPython.utils.syspathcontext import prepended_to_syspath - -from .test_debugger import PdbTestInput - -from tempfile import NamedTemporaryFile - -@magic.magics_class -class DummyMagics(magic.Magics): pass - -def test_extract_code_ranges(): - instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :" - expected = [ - (0, 1), - (2, 3), - (4, 6), - (6, 9), - (9, 14), - (16, None), - (None, 9), - (9, None), - (None, 13), - (None, None), - ] - actual = list(code.extract_code_ranges(instr)) - assert actual == expected - -def test_extract_symbols(): - source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n""" - symbols_args = ["a", "b", "A", "A,b", "A,a", "z"] - expected = [([], ['a']), - (["def b():\n return 42\n"], []), - (["class A: pass\n"], []), - (["class A: pass\n", "def b():\n return 42\n"], []), - (["class A: pass\n"], ['a']), - ([], ['z'])] - for symbols, exp in zip(symbols_args, expected): - assert code.extract_symbols(source, symbols) == exp - - -def test_extract_symbols_raises_exception_with_non_python_code(): - source = ("=begin A Ruby program :)=end\n" - "def hello\n" - "puts 'Hello world'\n" - "end") - with pytest.raises(SyntaxError): - code.extract_symbols(source, "hello") - - -def test_magic_not_found(): - # magic not found raises UsageError - with pytest.raises(UsageError): - _ip.run_line_magic("doesntexist", "") - - # ensure result isn't success when a magic isn't found - result = _ip.run_cell('%doesntexist') - assert isinstance(result.error_in_exec, UsageError) - - -def test_cell_magic_not_found(): - # magic not found raises UsageError - with pytest.raises(UsageError): - _ip.run_cell_magic('doesntexist', 'line', 'cell') - - # ensure result isn't success when a magic isn't found - result = _ip.run_cell('%%doesntexist') - assert isinstance(result.error_in_exec, UsageError) - - -def test_magic_error_status(): - def fail(shell): - 1/0 - _ip.register_magic_function(fail) - result = _ip.run_cell('%fail') - assert isinstance(result.error_in_exec, ZeroDivisionError) - - -def test_config(): - """ test that config magic does not raise - can happen if Configurable init is moved too early into - Magics.__init__ as then a Config object will be registered as a - magic. - """ - ## should not raise. - _ip.run_line_magic("config", "") - - -def test_config_available_configs(): - """ test that config magic prints available configs in unique and - sorted order. """ - with capture_output() as captured: - _ip.run_line_magic("config", "") - - stdout = captured.stdout - config_classes = stdout.strip().split('\n')[1:] - assert config_classes == sorted(set(config_classes)) - -def test_config_print_class(): - """ test that config with a classname prints the class's options. """ - with capture_output() as captured: - _ip.run_line_magic("config", "TerminalInteractiveShell") - - stdout = captured.stdout - assert re.match( - "TerminalInteractiveShell.* options", stdout.splitlines()[0] - ), f"{stdout}\n\n1st line of stdout not like 'TerminalInteractiveShell.* options'" - - -def test_rehashx(): - # clear up everything - _ip.alias_manager.clear_aliases() - del _ip.db['syscmdlist'] - - _ip.run_line_magic("rehashx", "") - # Practically ALL ipython development systems will have more than 10 aliases - - assert len(_ip.alias_manager.aliases) > 10 - for name, cmd in _ip.alias_manager.aliases: - # we must strip dots from alias names - assert "." not in name - - # rehashx must fill up syscmdlist - scoms = _ip.db['syscmdlist'] - assert len(scoms) > 10 - - -def test_magic_parse_options(): - """Test that we don't mangle paths when parsing magic options.""" - ip = get_ipython() - path = 'c:\\x' - m = DummyMagics(ip) - opts = m.parse_options('-f %s' % path,'f:')[0] - # argv splitting is os-dependent - if os.name == 'posix': - expected = 'c:x' - else: - expected = path - assert opts["f"] == expected - - -def test_magic_parse_long_options(): - """Magic.parse_options can handle --foo=bar long options""" - ip = get_ipython() - m = DummyMagics(ip) - opts, _ = m.parse_options("--foo --bar=bubble", "a", "foo", "bar=") - assert "foo" in opts - assert "bar" in opts - assert opts["bar"] == "bubble" - - -def doctest_hist_f(): - """Test %hist -f with temporary filename. - - In [9]: import tempfile - - In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-') - - In [11]: %hist -nl -f $tfile 3 - - In [13]: import os; os.unlink(tfile) - """ - - -def doctest_hist_op(): - """Test %hist -op - - In [1]: class b(float): - ...: pass - ...: - - In [2]: class s(object): - ...: def __str__(self): - ...: return 's' - ...: - - In [3]: - - In [4]: class r(b): - ...: def __repr__(self): - ...: return 'r' - ...: - - In [5]: class sr(s,r): pass - ...: - - In [6]: - - In [7]: bb=b() - - In [8]: ss=s() - - In [9]: rr=r() - - In [10]: ssrr=sr() - - In [11]: 4.5 - Out[11]: 4.5 - - In [12]: str(ss) - Out[12]: 's' - - In [13]: - - In [14]: %hist -op - >>> class b: - ... pass - ... - >>> class s(b): - ... def __str__(self): - ... return 's' - ... - >>> - >>> class r(b): - ... def __repr__(self): - ... return 'r' - ... - >>> class sr(s,r): pass - >>> - >>> bb=b() - >>> ss=s() - >>> rr=r() - >>> ssrr=sr() - >>> 4.5 - 4.5 - >>> str(ss) - 's' - >>> - """ - -def test_hist_pof(): - ip = get_ipython() - ip.run_cell("1+2", store_history=True) - #raise Exception(ip.history_manager.session_number) - #raise Exception(list(ip.history_manager._get_range_session())) - with TemporaryDirectory() as td: - tf = os.path.join(td, 'hist.py') - ip.run_line_magic('history', '-pof %s' % tf) - assert os.path.isfile(tf) - - -def test_macro(): - ip = get_ipython() - ip.history_manager.reset() # Clear any existing history. - cmds = ["a=1", "def b():\n return a**2", "print(a,b())"] - for i, cmd in enumerate(cmds, start=1): - ip.history_manager.store_inputs(i, cmd) - ip.run_line_magic("macro", "test 1-3") - assert ip.user_ns["test"].value == "\n".join(cmds) + "\n" - - # List macros - assert "test" in ip.run_line_magic("macro", "") - - -def test_macro_run(): - """Test that we can run a multi-line macro successfully.""" - ip = get_ipython() - ip.history_manager.reset() - cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"] - for cmd in cmds: - ip.run_cell(cmd, store_history=True) - assert ip.user_ns["test"].value == "a+=1\nprint(a)\n" - with tt.AssertPrints("12"): - ip.run_cell("test") - with tt.AssertPrints("13"): - ip.run_cell("test") - - -def test_magic_magic(): - """Test %magic""" - ip = get_ipython() - with capture_output() as captured: - ip.run_line_magic("magic", "") - - stdout = captured.stdout - assert "%magic" in stdout - assert "IPython" in stdout - assert "Available" in stdout - - -@dec.skipif_not_numpy -def test_numpy_reset_array_undec(): - "Test '%reset array' functionality" - _ip.ex("import numpy as np") - _ip.ex("a = np.empty(2)") - assert "a" in _ip.user_ns - _ip.run_line_magic("reset", "-f array") - assert "a" not in _ip.user_ns - - -def test_reset_out(): - "Test '%reset out' magic" - _ip.run_cell("parrot = 'dead'", store_history=True) - # test '%reset -f out', make an Out prompt - _ip.run_cell("parrot", store_history=True) - assert "dead" in [_ip.user_ns[x] for x in ("_", "__", "___")] - _ip.run_line_magic("reset", "-f out") - assert "dead" not in [_ip.user_ns[x] for x in ("_", "__", "___")] - assert len(_ip.user_ns["Out"]) == 0 - - -def test_reset_in(): - "Test '%reset in' magic" - # test '%reset -f in' - _ip.run_cell("parrot", store_history=True) - assert "parrot" in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")] - _ip.run_line_magic("reset", "-f in") - assert "parrot" not in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")] - assert len(set(_ip.user_ns["In"])) == 1 - - -def test_reset_dhist(): - "Test '%reset dhist' magic" - _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing - _ip.run_line_magic("cd", os.path.dirname(pytest.__file__)) - _ip.run_line_magic("cd", "-") - assert len(_ip.user_ns["_dh"]) > 0 - _ip.run_line_magic("reset", "-f dhist") - assert len(_ip.user_ns["_dh"]) == 0 - _ip.run_cell("_dh = [d for d in tmp]") # restore - - -def test_reset_in_length(): - "Test that '%reset in' preserves In[] length" - _ip.run_cell("print 'foo'") - _ip.run_cell("reset -f in") - assert len(_ip.user_ns["In"]) == _ip.displayhook.prompt_count + 1 - - -class TestResetErrors(TestCase): - - def test_reset_redefine(self): - - @magics_class - class KernelMagics(Magics): - @line_magic - def less(self, shell): pass - - _ip.register_magics(KernelMagics) - - with self.assertLogs() as cm: - # hack, we want to just capture logs, but assertLogs fails if not - # logs get produce. - # so log one things we ignore. - import logging as log_mod - log = log_mod.getLogger() - log.info('Nothing') - # end hack. - _ip.run_cell("reset -f") - - assert len(cm.output) == 1 - for out in cm.output: - assert "Invalid alias" not in out - -def test_tb_syntaxerror(): - """test %tb after a SyntaxError""" - ip = get_ipython() - ip.run_cell("for") - - # trap and validate stdout - save_stdout = sys.stdout - try: - sys.stdout = StringIO() - ip.run_cell("%tb") - out = sys.stdout.getvalue() - finally: - sys.stdout = save_stdout - # trim output, and only check the last line - last_line = out.rstrip().splitlines()[-1].strip() - assert last_line == "SyntaxError: invalid syntax" - - -def test_time(): - ip = get_ipython() - - with tt.AssertPrints("Wall time: "): - ip.run_cell("%time None") - - ip.run_cell("def f(kmjy):\n" - " %time print (2*kmjy)") - - with tt.AssertPrints("Wall time: "): - with tt.AssertPrints("hihi", suppress=False): - ip.run_cell("f('hi')") - - -# ';' at the end of %time prevents instruction value to be printed. -# This tests fix for #13837. -def test_time_no_output_with_semicolon(): - ip = get_ipython() - - # Test %time cases - with tt.AssertPrints(" 123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%time 123000+456") - - with tt.AssertNotPrints(" 123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%time 123000+456;") - - with tt.AssertPrints(" 123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%time 123000+456 # Comment") - - with tt.AssertNotPrints(" 123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%time 123000+456; # Comment") - - with tt.AssertPrints(" 123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%time 123000+456 # ;Comment") - - # Test %%time cases - with tt.AssertPrints("123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%%time\n123000+456\n\n\n") - - with tt.AssertNotPrints("123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%%time\n123000+456;\n\n\n") - - with tt.AssertPrints("123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%%time\n123000+456 # Comment\n\n\n") - - with tt.AssertNotPrints("123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%%time\n123000+456; # Comment\n\n\n") - - with tt.AssertPrints("123456"): - with tt.AssertPrints("Wall time: ", suppress=False): - with tt.AssertPrints("CPU times: ", suppress=False): - ip.run_cell("%%time\n123000+456 # ;Comment\n\n\n") - - -def test_time_last_not_expression(): - ip.run_cell("%%time\n" - "var_1 = 1\n" - "var_2 = 2\n") - assert ip.user_ns['var_1'] == 1 - del ip.user_ns['var_1'] - assert ip.user_ns['var_2'] == 2 - del ip.user_ns['var_2'] - - -@dec.skip_win32 -def test_time2(): - ip = get_ipython() - - with tt.AssertPrints("CPU times: user "): - ip.run_cell("%time None") - -def test_time3(): - """Erroneous magic function calls, issue gh-3334""" - ip = get_ipython() - ip.user_ns.pop('run', None) - - with tt.AssertNotPrints("not found", channel='stderr'): - ip.run_cell("%%time\n" - "run = 0\n" - "run += 1") - -def test_multiline_time(): - """Make sure last statement from time return a value.""" - ip = get_ipython() - ip.user_ns.pop('run', None) - - ip.run_cell( - dedent( - """\ - %%time - a = "ho" - b = "hey" - a+b - """ - ) - ) - assert ip.user_ns_hidden["_"] == "hohey" - - -def test_time_local_ns(): - """ - Test that local_ns is actually global_ns when running a cell magic - """ - ip = get_ipython() - ip.run_cell("%%time\n" "myvar = 1") - assert ip.user_ns["myvar"] == 1 - del ip.user_ns["myvar"] - - -def test_time_microseconds_display(): - """Ensure ASCII is used when necessary""" - with mock.patch("sys.stdout", io.TextIOWrapper(StringIO(), encoding="utf-8")): - assert execution._format_time(0.000001) == "1 \u03bcs" - with mock.patch("sys.stdout", io.TextIOWrapper(StringIO(), encoding="ascii")): - assert execution._format_time(0.000001) == "1 us" - - -# Test %%capture magic. Added to test issue #13926 -def test_capture(): - ip = get_ipython() - - # Test %%capture nominal case - ip.run_cell("%%capture abc\n1+2") - with tt.AssertPrints("True", suppress=False): - ip.run_cell("'abc' in locals()") - with tt.AssertPrints("True", suppress=False): - ip.run_cell("'outputs' in dir(abc)") - with tt.AssertPrints("3", suppress=False): - ip.run_cell("abc.outputs[0]") - - # Test %%capture with ';' at end of expression - ip.run_cell("%%capture abc\n7+8;") - with tt.AssertPrints("False", suppress=False): - ip.run_cell("'abc' in locals()") - - -def test_doctest_mode(): - "Toggle doctest_mode twice, it should be a no-op and run without error" - _ip.run_line_magic("doctest_mode", "") - _ip.run_line_magic("doctest_mode", "") - - -def test_parse_options(): - """Tests for basic options parsing in magics.""" - # These are only the most minimal of tests, more should be added later. At - # the very least we check that basic text/unicode calls work OK. - m = DummyMagics(_ip) - assert m.parse_options("foo", "")[1] == "foo" - assert m.parse_options("foo", "")[1] == "foo" - - -def test_parse_options_preserve_non_option_string(): - """Test to assert preservation of non-option part of magic-block, while parsing magic options.""" - m = DummyMagics(_ip) - opts, stmt = m.parse_options( - " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True - ) - assert opts == {"n": "1", "r": "13"} - assert stmt == "_ = 314 + foo" - - -def test_run_magic_preserve_code_block(): - """Test to assert preservation of non-option part of magic-block, while running magic.""" - _ip.user_ns["spaces"] = [] - _ip.run_line_magic( - "timeit", "-n1 -r1 spaces.append([s.count(' ') for s in ['document']])" - ) - assert _ip.user_ns["spaces"] == [[0]] - - -def test_dirops(): - """Test various directory handling operations.""" - # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/') - curpath = os.getcwd - startdir = os.getcwd() - ipdir = os.path.realpath(_ip.ipython_dir) - try: - _ip.run_line_magic("cd", '"%s"' % ipdir) - assert curpath() == ipdir - _ip.run_line_magic("cd", "-") - assert curpath() == startdir - _ip.run_line_magic("pushd", '"%s"' % ipdir) - assert curpath() == ipdir - _ip.run_line_magic("popd", "") - assert curpath() == startdir - finally: - os.chdir(startdir) - - -def test_cd_force_quiet(): - """Test OSMagics.cd_force_quiet option""" - _ip.config.OSMagics.cd_force_quiet = True - osmagics = osm.OSMagics(shell=_ip) - - startdir = os.getcwd() - ipdir = os.path.realpath(_ip.ipython_dir) - - try: - with tt.AssertNotPrints(ipdir): - osmagics.cd('"%s"' % ipdir) - with tt.AssertNotPrints(startdir): - osmagics.cd('-') - finally: - os.chdir(startdir) - - -def test_xmode(): - # Calling xmode three times should be a no-op - xmode = _ip.InteractiveTB.mode - for i in range(4): - _ip.run_line_magic("xmode", "") - assert _ip.InteractiveTB.mode == xmode - -def test_reset_hard(): - monitor = [] - class A(object): - def __del__(self): - monitor.append(1) - def __repr__(self): - return "" - - _ip.user_ns["a"] = A() - _ip.run_cell("a") - - assert monitor == [] - _ip.run_line_magic("reset", "-f") - assert monitor == [1] - -class TestXdel(tt.TempFileMixin): - def test_xdel(self): - """Test that references from %run are cleared by xdel.""" - src = ("class A(object):\n" - " monitor = []\n" - " def __del__(self):\n" - " self.monitor.append(1)\n" - "a = A()\n") - self.mktmp(src) - # %run creates some hidden references... - _ip.run_line_magic("run", "%s" % self.fname) - # ... as does the displayhook. - _ip.run_cell("a") - - monitor = _ip.user_ns["A"].monitor - assert monitor == [] - - _ip.run_line_magic("xdel", "a") - - # Check that a's __del__ method has been called. - gc.collect(0) - assert monitor == [1] - -def doctest_who(): - """doctest for %who - - In [1]: %reset -sf - - In [2]: alpha = 123 - - In [3]: beta = 'beta' - - In [4]: %who int - alpha - - In [5]: %who str - beta - - In [6]: %whos - Variable Type Data/Info - ---------------------------- - alpha int 123 - beta str beta - - In [7]: %who_ls - Out[7]: ['alpha', 'beta'] - """ - -def test_whos(): - """Check that whos is protected against objects where repr() fails.""" - class A(object): - def __repr__(self): - raise Exception() - _ip.user_ns['a'] = A() - _ip.run_line_magic("whos", "") - -def doctest_precision(): - """doctest for %precision - - In [1]: f = get_ipython().display_formatter.formatters['text/plain'] - - In [2]: %precision 5 - Out[2]: '%.5f' - - In [3]: f.float_format - Out[3]: '%.5f' - - In [4]: %precision %e - Out[4]: '%e' - - In [5]: f(3.1415927) - Out[5]: '3.141593e+00' - """ - - -def test_debug_magic(): - """Test debugging a small code with %debug - - In [1]: with PdbTestInput(['c']): - ...: %debug print("a b") #doctest: +ELLIPSIS - ...: - ... - ipdb> c - a b - In [2]: - """ - - -def test_debug_magic_locals(): - """Test debugging a small code with %debug with locals - - In [1]: with PdbTestInput(['c']): - ...: def fun(): - ...: res = 1 - ...: %debug print(res) - ...: fun() - ...: - ... - ipdb> c - 1 - In [2]: - """ - -def test_psearch(): - with tt.AssertPrints("dict.fromkeys"): - _ip.run_cell("dict.fr*?") - with tt.AssertPrints("π.is_integer"): - _ip.run_cell("π = 3.14;\nπ.is_integ*?") - -def test_timeit_shlex(): - """test shlex issues with timeit (#1109)""" - _ip.ex("def f(*a,**kw): pass") - _ip.run_line_magic("timeit", '-n1 "this is a bug".count(" ")') - _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1)') - _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1, " ", 2, " ")') - _ip.run_line_magic("timeit", '-r1 -n1 ("a " + "b")') - _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b")') - _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b ")') - - -def test_timeit_special_syntax(): - "Test %%timeit with IPython special syntax" - @register_line_magic - def lmagic(line): - ip = get_ipython() - ip.user_ns['lmagic_out'] = line - - # line mode test - _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line") - assert _ip.user_ns["lmagic_out"] == "my line" - # cell mode test - _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2") - assert _ip.user_ns["lmagic_out"] == "my line2" - - -def test_timeit_return(): - """ - test whether timeit -o return object - """ - - res = _ip.run_line_magic('timeit','-n10 -r10 -o 1') - assert(res is not None) - -def test_timeit_quiet(): - """ - test quiet option of timeit magic - """ - with tt.AssertNotPrints("loops"): - _ip.run_cell("%timeit -n1 -r1 -q 1") - -def test_timeit_return_quiet(): - with tt.AssertNotPrints("loops"): - res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1') - assert (res is not None) - -def test_timeit_invalid_return(): - with pytest.raises(SyntaxError): - _ip.run_line_magic('timeit', 'return') - -@dec.skipif(execution.profile is None) -def test_prun_special_syntax(): - "Test %%prun with IPython special syntax" - @register_line_magic - def lmagic(line): - ip = get_ipython() - ip.user_ns['lmagic_out'] = line - - # line mode test - _ip.run_line_magic("prun", "-q %lmagic my line") - assert _ip.user_ns["lmagic_out"] == "my line" - # cell mode test - _ip.run_cell_magic("prun", "-q", "%lmagic my line2") - assert _ip.user_ns["lmagic_out"] == "my line2" - - -@dec.skipif(execution.profile is None) -def test_prun_quotes(): - "Test that prun does not clobber string escapes (GH #1302)" - _ip.run_line_magic("prun", r"-q x = '\t'") - assert _ip.user_ns["x"] == "\t" - - -def test_extension(): - # Debugging information for failures of this test - print('sys.path:') - for p in sys.path: - print(' ', p) - print('CWD', os.getcwd()) - - pytest.raises(ImportError, _ip.run_line_magic, "load_ext", "daft_extension") - daft_path = os.path.join(os.path.dirname(__file__), "daft_extension") - sys.path.insert(0, daft_path) - try: - _ip.user_ns.pop('arq', None) - invalidate_caches() # Clear import caches - _ip.run_line_magic("load_ext", "daft_extension") - assert _ip.user_ns["arq"] == 185 - _ip.run_line_magic("unload_ext", "daft_extension") - assert 'arq' not in _ip.user_ns - finally: - sys.path.remove(daft_path) - - -def test_notebook_export_json(): - pytest.importorskip("nbformat") - _ip = get_ipython() - _ip.history_manager.reset() # Clear any existing history. - cmds = ["a=1", "def b():\n return a**2", "print('noël, été', b())"] - for i, cmd in enumerate(cmds, start=1): - _ip.history_manager.store_inputs(i, cmd) - with TemporaryDirectory() as td: - outfile = os.path.join(td, "nb.ipynb") - _ip.run_line_magic("notebook", "%s" % outfile) - - -class TestEnv(TestCase): - - def test_env(self): - env = _ip.run_line_magic("env", "") - self.assertTrue(isinstance(env, dict)) - - def test_env_secret(self): - env = _ip.run_line_magic("env", "") - hidden = "" - with mock.patch.dict( - os.environ, - { - "API_KEY": "abc123", - "SECRET_THING": "ssshhh", - "JUPYTER_TOKEN": "", - "VAR": "abc" - } - ): - env = _ip.run_line_magic("env", "") - assert env["API_KEY"] == hidden - assert env["SECRET_THING"] == hidden - assert env["JUPYTER_TOKEN"] == hidden - assert env["VAR"] == "abc" - - def test_env_get_set_simple(self): - env = _ip.run_line_magic("env", "var val1") - self.assertEqual(env, None) - self.assertEqual(os.environ["var"], "val1") - self.assertEqual(_ip.run_line_magic("env", "var"), "val1") - env = _ip.run_line_magic("env", "var=val2") - self.assertEqual(env, None) - self.assertEqual(os.environ['var'], 'val2') - - def test_env_get_set_complex(self): - env = _ip.run_line_magic("env", "var 'val1 '' 'val2") - self.assertEqual(env, None) - self.assertEqual(os.environ['var'], "'val1 '' 'val2") - self.assertEqual(_ip.run_line_magic("env", "var"), "'val1 '' 'val2") - env = _ip.run_line_magic("env", 'var=val2 val3="val4') - self.assertEqual(env, None) - self.assertEqual(os.environ['var'], 'val2 val3="val4') - - def test_env_set_bad_input(self): - self.assertRaises(UsageError, lambda: _ip.run_line_magic("set_env", "var")) - - def test_env_set_whitespace(self): - self.assertRaises(UsageError, lambda: _ip.run_line_magic("env", "var A=B")) - - -class CellMagicTestCase(TestCase): - - def check_ident(self, magic): - # Manually called, we get the result - out = _ip.run_cell_magic(magic, "a", "b") - assert out == ("a", "b") - # Via run_cell, it goes into the user's namespace via displayhook - _ip.run_cell("%%" + magic + " c\nd\n") - assert _ip.user_ns["_"] == ("c", "d\n") - - def test_cell_magic_func_deco(self): - "Cell magic using simple decorator" - @register_cell_magic - def cellm(line, cell): - return line, cell - - self.check_ident('cellm') - - def test_cell_magic_reg(self): - "Cell magic manually registered" - def cellm(line, cell): - return line, cell - - _ip.register_magic_function(cellm, 'cell', 'cellm2') - self.check_ident('cellm2') - - def test_cell_magic_class(self): - "Cell magics declared via a class" - @magics_class - class MyMagics(Magics): - - @cell_magic - def cellm3(self, line, cell): - return line, cell - - _ip.register_magics(MyMagics) - self.check_ident('cellm3') - - def test_cell_magic_class2(self): - "Cell magics declared via a class, #2" - @magics_class - class MyMagics2(Magics): - - @cell_magic('cellm4') - def cellm33(self, line, cell): - return line, cell - - _ip.register_magics(MyMagics2) - self.check_ident('cellm4') - # Check that nothing is registered as 'cellm33' - c33 = _ip.find_cell_magic('cellm33') - assert c33 == None - -def test_file(): - """Basic %%writefile""" - ip = get_ipython() - with TemporaryDirectory() as td: - fname = os.path.join(td, "file1") - ip.run_cell_magic( - "writefile", - fname, - "\n".join( - [ - "line1", - "line2", - ] - ), - ) - s = Path(fname).read_text(encoding="utf-8") - assert "line1\n" in s - assert "line2" in s - - -@dec.skip_win32 -def test_file_single_quote(): - """Basic %%writefile with embedded single quotes""" - ip = get_ipython() - with TemporaryDirectory() as td: - fname = os.path.join(td, "'file1'") - ip.run_cell_magic( - "writefile", - fname, - "\n".join( - [ - "line1", - "line2", - ] - ), - ) - s = Path(fname).read_text(encoding="utf-8") - assert "line1\n" in s - assert "line2" in s - - -@dec.skip_win32 -def test_file_double_quote(): - """Basic %%writefile with embedded double quotes""" - ip = get_ipython() - with TemporaryDirectory() as td: - fname = os.path.join(td, '"file1"') - ip.run_cell_magic( - "writefile", - fname, - "\n".join( - [ - "line1", - "line2", - ] - ), - ) - s = Path(fname).read_text(encoding="utf-8") - assert "line1\n" in s - assert "line2" in s - - -def test_file_var_expand(): - """%%writefile $filename""" - ip = get_ipython() - with TemporaryDirectory() as td: - fname = os.path.join(td, "file1") - ip.user_ns["filename"] = fname - ip.run_cell_magic( - "writefile", - "$filename", - "\n".join( - [ - "line1", - "line2", - ] - ), - ) - s = Path(fname).read_text(encoding="utf-8") - assert "line1\n" in s - assert "line2" in s - - -def test_file_unicode(): - """%%writefile with unicode cell""" - ip = get_ipython() - with TemporaryDirectory() as td: - fname = os.path.join(td, 'file1') - ip.run_cell_magic("writefile", fname, u'\n'.join([ - u'liné1', - u'liné2', - ])) - with io.open(fname, encoding='utf-8') as f: - s = f.read() - assert "liné1\n" in s - assert "liné2" in s - - -def test_file_amend(): - """%%writefile -a amends files""" - ip = get_ipython() - with TemporaryDirectory() as td: - fname = os.path.join(td, "file2") - ip.run_cell_magic( - "writefile", - fname, - "\n".join( - [ - "line1", - "line2", - ] - ), - ) - ip.run_cell_magic( - "writefile", - "-a %s" % fname, - "\n".join( - [ - "line3", - "line4", - ] - ), - ) - s = Path(fname).read_text(encoding="utf-8") - assert "line1\n" in s - assert "line3\n" in s - - -def test_file_spaces(): - """%%file with spaces in filename""" - ip = get_ipython() - with TemporaryWorkingDirectory() as td: - fname = "file name" - ip.run_cell_magic( - "file", - '"%s"' % fname, - "\n".join( - [ - "line1", - "line2", - ] - ), - ) - s = Path(fname).read_text(encoding="utf-8") - assert "line1\n" in s - assert "line2" in s - - -def test_script_config(): - ip = get_ipython() - ip.config.ScriptMagics.script_magics = ['whoda'] - sm = script.ScriptMagics(shell=ip) - assert "whoda" in sm.magics["cell"] - - -def _interrupt_after_1s(): - sleep(1) - signal.raise_signal(signal.SIGINT) - - -def test_script_raise_on_interrupt(): - ip = get_ipython() - - with pytest.raises(CalledProcessError): - thread = Thread(target=_interrupt_after_1s) - thread.start() - ip.run_cell_magic( - "script", f"{sys.executable}", "from time import sleep; sleep(2)" - ) - thread.join() - - -def test_script_do_not_raise_on_interrupt(): - ip = get_ipython() - - thread = Thread(target=_interrupt_after_1s) - thread.start() - ip.run_cell_magic( - "script", - f"--no-raise-error {sys.executable}", - "from time import sleep; sleep(2)", - ) - thread.join() - - -def test_script_out(): - ip = get_ipython() - ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')") - assert ip.user_ns["output"].strip() == "hi" - - -def test_script_err(): - ip = get_ipython() - ip.run_cell_magic( - "script", - f"--err error {sys.executable}", - "import sys; print('hello', file=sys.stderr)", - ) - assert ip.user_ns["error"].strip() == "hello" - - -def test_script_out_err(): - ip = get_ipython() - ip.run_cell_magic( - "script", - f"--out output --err error {sys.executable}", - "\n".join( - [ - "import sys", - "print('hi')", - "print('hello', file=sys.stderr)", - ] - ), - ) - assert ip.user_ns["output"].strip() == "hi" - assert ip.user_ns["error"].strip() == "hello" - - -async def test_script_bg_out(): - ip = get_ipython() - ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')") - assert (await ip.user_ns["output"].read()).strip() == b"hi" - assert ip.user_ns["output"].at_eof() - - -async def test_script_bg_err(): - ip = get_ipython() - ip.run_cell_magic( - "script", - f"--bg --err error {sys.executable}", - "import sys; print('hello', file=sys.stderr)", - ) - assert (await ip.user_ns["error"].read()).strip() == b"hello" - assert ip.user_ns["error"].at_eof() - - -async def test_script_bg_out_err(): - ip = get_ipython() - ip.run_cell_magic( - "script", - f"--bg --out output --err error {sys.executable}", - "\n".join( - [ - "import sys", - "print('hi')", - "print('hello', file=sys.stderr)", - ] - ), - ) - assert (await ip.user_ns["output"].read()).strip() == b"hi" - assert (await ip.user_ns["error"].read()).strip() == b"hello" - assert ip.user_ns["output"].at_eof() - assert ip.user_ns["error"].at_eof() - - -async def test_script_bg_proc(): - ip = get_ipython() - ip.run_cell_magic( - "script", - f"--bg --out output --proc p {sys.executable}", - "\n".join( - [ - "import sys", - "print('hi')", - "print('hello', file=sys.stderr)", - ] - ), - ) - p = ip.user_ns["p"] - await p.wait() - assert p.returncode == 0 - assert (await p.stdout.read()).strip() == b"hi" - # not captured, so empty - assert (await p.stderr.read()) == b"" - assert p.stdout.at_eof() - assert p.stderr.at_eof() - - -def test_script_defaults(): - ip = get_ipython() - for cmd in ['sh', 'bash', 'perl', 'ruby']: - try: - find_cmd(cmd) - except Exception: - pass - else: - assert cmd in ip.magics_manager.magics["cell"] - - -async def test_script_streams_continiously(capsys): - ip = get_ipython() - # Windows is slow to start up a thread on CI - is_windows = os.name == "nt" - step = 3 if is_windows else 1 - code = dedent( - f"""\ - import time - for _ in range(3): - time.sleep({step}) - print(".", flush=True, end="") - """ - ) - - def print_numbers(): - for i in range(3): - sleep(step) - print(i, flush=True, end="") - - thread = Thread(target=print_numbers) - thread.start() - sleep(step / 2) - ip.run_cell_magic("script", f"{sys.executable}", code) - thread.join() - - captured = capsys.readouterr() - # If the streaming was line-wise or broken - # we would get `012...` - assert captured.out == "0.1.2." - - -@magics_class -class FooFoo(Magics): - """class with both %foo and %%foo magics""" - @line_magic('foo') - def line_foo(self, line): - "I am line foo" - pass - - @cell_magic("foo") - def cell_foo(self, line, cell): - "I am cell foo, not line foo" - pass - -def test_line_cell_info(): - """%%foo and %foo magics are distinguishable to inspect""" - ip = get_ipython() - ip.magics_manager.register(FooFoo) - oinfo = ip.object_inspect("foo") - assert oinfo["found"] is True - assert oinfo["ismagic"] is True - - oinfo = ip.object_inspect("%%foo") - assert oinfo["found"] is True - assert oinfo["ismagic"] is True - assert oinfo["docstring"] == FooFoo.cell_foo.__doc__ - - oinfo = ip.object_inspect("%foo") - assert oinfo["found"] is True - assert oinfo["ismagic"] is True - assert oinfo["docstring"] == FooFoo.line_foo.__doc__ - - -def test_multiple_magics(): - ip = get_ipython() - foo1 = FooFoo(ip) - foo2 = FooFoo(ip) - mm = ip.magics_manager - mm.register(foo1) - assert mm.magics["line"]["foo"].__self__ is foo1 - mm.register(foo2) - assert mm.magics["line"]["foo"].__self__ is foo2 - - -def test_alias_magic(): - """Test %alias_magic.""" - ip = get_ipython() - mm = ip.magics_manager - - # Basic operation: both cell and line magics are created, if possible. - ip.run_line_magic("alias_magic", "timeit_alias timeit") - assert "timeit_alias" in mm.magics["line"] - assert "timeit_alias" in mm.magics["cell"] - - # --cell is specified, line magic not created. - ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit") - assert "timeit_cell_alias" not in mm.magics["line"] - assert "timeit_cell_alias" in mm.magics["cell"] - - # Test that line alias is created successfully. - ip.run_line_magic("alias_magic", "--line env_alias env") - assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "") - - # Test that line alias with parameters passed in is created successfully. - ip.run_line_magic( - "alias_magic", "--line history_alias history --params " + shlex.quote("3") - ) - assert "history_alias" in mm.magics["line"] - - -def test_save(): - """Test %save.""" - ip = get_ipython() - ip.history_manager.reset() # Clear any existing history. - cmds = ["a=1", "def b():\n return a**2", "print(a, b())"] - for i, cmd in enumerate(cmds, start=1): - ip.history_manager.store_inputs(i, cmd) - with TemporaryDirectory() as tmpdir: - file = os.path.join(tmpdir, "testsave.py") - ip.run_line_magic("save", "%s 1-10" % file) - content = Path(file).read_text(encoding="utf-8") - assert content.count(cmds[0]) == 1 - assert "coding: utf-8" in content - ip.run_line_magic("save", "-a %s 1-10" % file) - content = Path(file).read_text(encoding="utf-8") - assert content.count(cmds[0]) == 2 - assert "coding: utf-8" in content - - -def test_save_with_no_args(): - ip = get_ipython() - ip.history_manager.reset() # Clear any existing history. - cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"] - for i, cmd in enumerate(cmds, start=1): - ip.history_manager.store_inputs(i, cmd) - - with TemporaryDirectory() as tmpdir: - path = os.path.join(tmpdir, "testsave.py") - ip.run_line_magic("save", path) - content = Path(path).read_text(encoding="utf-8") - expected_content = dedent( - """\ - # coding: utf-8 - a=1 - def b(): - return a**2 - print(a, b()) - """ - ) - assert content == expected_content - - -def test_store(): - """Test %store.""" - ip = get_ipython() - ip.run_line_magic('load_ext', 'storemagic') - - # make sure the storage is empty - ip.run_line_magic("store", "-z") - ip.user_ns["var"] = 42 - ip.run_line_magic("store", "var") - ip.user_ns["var"] = 39 - ip.run_line_magic("store", "-r") - assert ip.user_ns["var"] == 42 - - ip.run_line_magic("store", "-d var") - ip.user_ns["var"] = 39 - ip.run_line_magic("store", "-r") - assert ip.user_ns["var"] == 39 - - -def _run_edit_test(arg_s, exp_filename=None, - exp_lineno=-1, - exp_contents=None, - exp_is_temp=None): - ip = get_ipython() - M = code.CodeMagics(ip) - last_call = ['',''] - opts,args = M.parse_options(arg_s,'prxn:') - filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call) - - if exp_filename is not None: - assert exp_filename == filename - if exp_contents is not None: - with io.open(filename, 'r', encoding='utf-8') as f: - contents = f.read() - assert exp_contents == contents - if exp_lineno != -1: - assert exp_lineno == lineno - if exp_is_temp is not None: - assert exp_is_temp == is_temp - - -def test_edit_interactive(): - """%edit on interactively defined objects""" - ip = get_ipython() - n = ip.execution_count - ip.run_cell("def foo(): return 1", store_history=True) - - with pytest.raises(code.InteractivelyDefined) as e: - _run_edit_test("foo") - assert e.value.index == n - - -def test_edit_cell(): - """%edit [cell id]""" - ip = get_ipython() - - ip.run_cell("def foo(): return 1", store_history=True) - - # test - _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True) - -def test_edit_fname(): - """%edit file""" - # test - _run_edit_test("test file.py", exp_filename="test file.py") - -def test_bookmark(): - ip = get_ipython() - ip.run_line_magic('bookmark', 'bmname') - with tt.AssertPrints('bmname'): - ip.run_line_magic('bookmark', '-l') - ip.run_line_magic('bookmark', '-d bmname') - -def test_ls_magic(): - ip = get_ipython() - json_formatter = ip.display_formatter.formatters['application/json'] - json_formatter.enabled = True - lsmagic = ip.run_line_magic("lsmagic", "") - with warnings.catch_warnings(record=True) as w: - j = json_formatter(lsmagic) - assert sorted(j) == ["cell", "line"] - assert w == [] # no warnings - - -def test_strip_initial_indent(): - def sii(s): - lines = s.splitlines() - return '\n'.join(code.strip_initial_indent(lines)) - - assert sii(" a = 1\nb = 2") == "a = 1\nb = 2" - assert sii(" a\n b\nc") == "a\n b\nc" - assert sii("a\n b") == "a\n b" - -def test_logging_magic_quiet_from_arg(): - _ip.config.LoggingMagics.quiet = False - lm = logging.LoggingMagics(shell=_ip) - with TemporaryDirectory() as td: - try: - with tt.AssertNotPrints(re.compile("Activating.*")): - lm.logstart('-q {}'.format( - os.path.join(td, "quiet_from_arg.log"))) - finally: - _ip.logger.logstop() - -def test_logging_magic_quiet_from_config(): - _ip.config.LoggingMagics.quiet = True - lm = logging.LoggingMagics(shell=_ip) - with TemporaryDirectory() as td: - try: - with tt.AssertNotPrints(re.compile("Activating.*")): - lm.logstart(os.path.join(td, "quiet_from_config.log")) - finally: - _ip.logger.logstop() - - -def test_logging_magic_not_quiet(): - _ip.config.LoggingMagics.quiet = False - lm = logging.LoggingMagics(shell=_ip) - with TemporaryDirectory() as td: - try: - with tt.AssertPrints(re.compile("Activating.*")): - lm.logstart(os.path.join(td, "not_quiet.log")) - finally: - _ip.logger.logstop() - - -def test_time_no_var_expand(): - _ip.user_ns["a"] = 5 - _ip.user_ns["b"] = [] - _ip.run_line_magic("time", 'b.append("{a}")') - assert _ip.user_ns["b"] == ["{a}"] - - -# this is slow, put at the end for local testing. -def test_timeit_arguments(): - "Test valid timeit arguments, should not cause SyntaxError (GH #1269)" - _ip.run_line_magic("timeit", "-n1 -r1 a=('#')") - - -MINIMAL_LAZY_MAGIC = """ -from IPython.core.magic import ( - Magics, - magics_class, - line_magic, - cell_magic, -) - - -@magics_class -class LazyMagics(Magics): - @line_magic - def lazy_line(self, line): - print("Lazy Line") - - @cell_magic - def lazy_cell(self, line, cell): - print("Lazy Cell") - - -def load_ipython_extension(ipython): - ipython.register_magics(LazyMagics) -""" - - -def test_lazy_magics(): - with pytest.raises(UsageError): - ip.run_line_magic("lazy_line", "") - - startdir = os.getcwd() - - with TemporaryDirectory() as tmpdir: - with prepended_to_syspath(tmpdir): - ptempdir = Path(tmpdir) - tf = ptempdir / "lazy_magic_module.py" - tf.write_text(MINIMAL_LAZY_MAGIC) - ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3]) - with tt.AssertPrints("Lazy Line"): - ip.run_line_magic("lazy_line", "") - - -TEST_MODULE = """ -print('Loaded my_tmp') -if __name__ == "__main__": - print('I just ran a script') -""" - -def test_run_module_from_import_hook(): - "Test that a module can be loaded via an import hook" - with TemporaryDirectory() as tmpdir: - fullpath = os.path.join(tmpdir, "my_tmp.py") - Path(fullpath).write_text(TEST_MODULE, encoding="utf-8") - - import importlib.abc - import importlib.util - - class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader): - def find_spec(self, fullname, path, target=None): - if fullname == "my_tmp": - return importlib.util.spec_from_loader(fullname, self) - - def get_filename(self, fullname): - assert fullname == "my_tmp" - return fullpath - - def get_data(self, path): - assert Path(path).samefile(fullpath) - return Path(fullpath).read_text(encoding="utf-8") - - sys.meta_path.insert(0, MyTempImporter()) - - with capture_output() as captured: - _ip.run_line_magic("run", "-m my_tmp") - _ip.run_cell("import my_tmp") - - output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n" - assert output == captured.stdout - - sys.meta_path.pop(0) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic_arguments.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic_arguments.py deleted file mode 100644 index 0044163..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic_arguments.py +++ /dev/null @@ -1,142 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011, IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -import argparse -import sys - -from IPython.core.magic_arguments import (argument, argument_group, kwds, - magic_arguments, parse_argstring, real_name) - -LEADING_SPACE = "" if sys.version_info > (3, 13) else " " - - -@magic_arguments() -@argument('-f', '--foo', help="an argument") -def magic_foo1(self, args): - """ A docstring. - """ - return parse_argstring(magic_foo1, args) - - -@magic_arguments() -def magic_foo2(self, args): - """ A docstring. - """ - return parse_argstring(magic_foo2, args) - - -@magic_arguments() -@argument('-f', '--foo', help="an argument") -@argument_group('Group') -@argument('-b', '--bar', help="a grouped argument") -@argument_group('Second Group') -@argument('-z', '--baz', help="another grouped argument") -def magic_foo3(self, args): - """ A docstring. - """ - return parse_argstring(magic_foo3, args) - - -@magic_arguments() -@kwds(argument_default=argparse.SUPPRESS) -@argument('-f', '--foo', help="an argument") -def magic_foo4(self, args): - """ A docstring. - """ - return parse_argstring(magic_foo4, args) - - -@magic_arguments('frobnicate') -@argument('-f', '--foo', help="an argument") -def magic_foo5(self, args): - """ A docstring. - """ - return parse_argstring(magic_foo5, args) - - -@magic_arguments() -@argument('-f', '--foo', help="an argument") -def magic_magic_foo(self, args): - """ A docstring. - """ - return parse_argstring(magic_magic_foo, args) - - -@magic_arguments() -@argument('-f', '--foo', help="an argument") -def foo(self, args): - """ A docstring. - """ - return parse_argstring(foo, args) - - -def test_magic_arguments(): - # “optional arguments†was replaced with “options†in argparse help - # https://docs.python.org/3/whatsnew/3.10.html#argparse - # https://bugs.python.org/issue9694 - options = "optional arguments" if sys.version_info < (3, 10) else "options" - - assert ( - magic_foo1.__doc__ - == f"::\n\n %foo1 [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n" - ) - assert getattr(magic_foo1, "argcmd_name", None) == None - assert real_name(magic_foo1) == "foo1" - assert magic_foo1(None, "") == argparse.Namespace(foo=None) - assert hasattr(magic_foo1, "has_arguments") - - assert magic_foo2.__doc__ == f"::\n\n %foo2\n\n{LEADING_SPACE}A docstring.\n" - assert getattr(magic_foo2, "argcmd_name", None) == None - assert real_name(magic_foo2) == "foo2" - assert magic_foo2(None, "") == argparse.Namespace() - assert hasattr(magic_foo2, "has_arguments") - - assert ( - magic_foo3.__doc__ - == f"::\n\n %foo3 [-f FOO] [-b BAR] [-z BAZ]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n\nGroup:\n -b BAR, --bar BAR a grouped argument\n\nSecond Group:\n -z BAZ, --baz BAZ another grouped argument\n" - ) - assert getattr(magic_foo3, "argcmd_name", None) == None - assert real_name(magic_foo3) == "foo3" - assert magic_foo3(None, "") == argparse.Namespace(bar=None, baz=None, foo=None) - assert hasattr(magic_foo3, "has_arguments") - - assert ( - magic_foo4.__doc__ - == f"::\n\n %foo4 [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n" - ) - assert getattr(magic_foo4, "argcmd_name", None) == None - assert real_name(magic_foo4) == "foo4" - assert magic_foo4(None, "") == argparse.Namespace() - assert hasattr(magic_foo4, "has_arguments") - - assert ( - magic_foo5.__doc__ - == f"::\n\n %frobnicate [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n" - ) - assert getattr(magic_foo5, "argcmd_name", None) == "frobnicate" - assert real_name(magic_foo5) == "frobnicate" - assert magic_foo5(None, "") == argparse.Namespace(foo=None) - assert hasattr(magic_foo5, "has_arguments") - - assert ( - magic_magic_foo.__doc__ - == f"::\n\n %magic_foo [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n" - ) - assert getattr(magic_magic_foo, "argcmd_name", None) == None - assert real_name(magic_magic_foo) == "magic_foo" - assert magic_magic_foo(None, "") == argparse.Namespace(foo=None) - assert hasattr(magic_magic_foo, "has_arguments") - - assert ( - foo.__doc__ - == f"::\n\n %foo [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n" - ) - assert getattr(foo, "argcmd_name", None) == None - assert real_name(foo) == "foo" - assert foo(None, "") == argparse.Namespace(foo=None) - assert hasattr(foo, "has_arguments") diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic_terminal.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic_terminal.py deleted file mode 100644 index 5dfa0f0..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_magic_terminal.py +++ /dev/null @@ -1,216 +0,0 @@ -"""Tests for various magic functions specific to the terminal frontend.""" - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import sys -from io import StringIO -from unittest import TestCase - -from IPython.testing import tools as tt -#----------------------------------------------------------------------------- -# Test functions begin -#----------------------------------------------------------------------------- - - -MINIMAL_LAZY_MAGIC = """ -from IPython.core.magic import ( - Magics, - magics_class, - line_magic, - cell_magic, -) - - -@magics_class -class LazyMagics(Magics): - @line_magic - def lazy_line(self, line): - print("Lazy Line") - - @cell_magic - def lazy_cell(self, line, cell): - print("Lazy Cell") - - -def load_ipython_extension(ipython): - ipython.register_magics(LazyMagics) -""" - -def check_cpaste(code, should_fail=False): - """Execute code via 'cpaste' and ensure it was executed, unless - should_fail is set. - """ - ip.user_ns['code_ran'] = False - - src = StringIO() - src.write(code) - src.write('\n--\n') - src.seek(0) - - stdin_save = sys.stdin - sys.stdin = src - - try: - context = tt.AssertPrints if should_fail else tt.AssertNotPrints - with context("Traceback (most recent call last)"): - ip.run_line_magic("cpaste", "") - - if not should_fail: - assert ip.user_ns['code_ran'], "%r failed" % code - finally: - sys.stdin = stdin_save - -def test_cpaste(): - """Test cpaste magic""" - - def runf(): - """Marker function: sets a flag when executed. - """ - ip.user_ns['code_ran'] = True - return 'runf' # return string so '+ runf()' doesn't result in success - - tests = {'pass': ["runf()", - "In [1]: runf()", - "In [1]: if 1:\n ...: runf()", - "> > > runf()", - ">>> runf()", - " >>> runf()", - ], - - 'fail': ["1 + runf()", - "++ runf()", - ]} - - ip.user_ns['runf'] = runf - - for code in tests['pass']: - check_cpaste(code) - - for code in tests['fail']: - check_cpaste(code, should_fail=True) - - - -class PasteTestCase(TestCase): - """Multiple tests for clipboard pasting""" - - def paste(self, txt, flags='-q'): - """Paste input text, by default in quiet mode""" - ip.hooks.clipboard_get = lambda: txt - ip.run_line_magic("paste", flags) - - def setUp(self): - # Inject fake clipboard hook but save original so we can restore it later - self.original_clip = ip.hooks.clipboard_get - - def tearDown(self): - # Restore original hook - ip.hooks.clipboard_get = self.original_clip - - def test_paste(self): - ip.user_ns.pop("x", None) - self.paste("x = 1") - self.assertEqual(ip.user_ns["x"], 1) - ip.user_ns.pop("x") - - def test_paste_pyprompt(self): - ip.user_ns.pop("x", None) - self.paste(">>> x=2") - self.assertEqual(ip.user_ns["x"], 2) - ip.user_ns.pop("x") - - def test_paste_py_multi(self): - self.paste( - """ - >>> x = [1,2,3] - >>> y = [] - >>> for i in x: - ... y.append(i**2) - ... - """ - ) - self.assertEqual(ip.user_ns["x"], [1, 2, 3]) - self.assertEqual(ip.user_ns["y"], [1, 4, 9]) - - def test_paste_py_multi_r(self): - "Now, test that self.paste -r works" - self.test_paste_py_multi() - self.assertEqual(ip.user_ns.pop("x"), [1, 2, 3]) - self.assertEqual(ip.user_ns.pop("y"), [1, 4, 9]) - self.assertFalse("x" in ip.user_ns) - ip.run_line_magic("paste", "-r") - self.assertEqual(ip.user_ns["x"], [1, 2, 3]) - self.assertEqual(ip.user_ns["y"], [1, 4, 9]) - - def test_paste_email(self): - "Test pasting of email-quoted contents" - self.paste( - """\ - >> def foo(x): - >> return x + 1 - >> xx = foo(1.1)""" - ) - self.assertEqual(ip.user_ns["xx"], 2.1) - - def test_paste_email2(self): - "Email again; some programs add a space also at each quoting level" - self.paste( - """\ - > > def foo(x): - > > return x + 1 - > > yy = foo(2.1) """ - ) - self.assertEqual(ip.user_ns["yy"], 3.1) - - def test_paste_email_py(self): - "Email quoting of interactive input" - self.paste( - """\ - >> >>> def f(x): - >> ... return x+1 - >> ... - >> >>> zz = f(2.5) """ - ) - self.assertEqual(ip.user_ns["zz"], 3.5) - - def test_paste_echo(self): - "Also test self.paste echoing, by temporarily faking the writer" - w = StringIO() - old_write = sys.stdout.write - sys.stdout.write = w.write - code = """ - a = 100 - b = 200""" - try: - self.paste(code,'') - out = w.getvalue() - finally: - sys.stdout.write = old_write - self.assertEqual(ip.user_ns["a"], 100) - self.assertEqual(ip.user_ns["b"], 200) - assert out == code + "\n## -- End pasted text --\n" - - def test_paste_leading_commas(self): - "Test multiline strings with leading commas" - tm = ip.magics_manager.registry['TerminalMagics'] - s = '''\ -a = """ -,1,2,3 -"""''' - ip.user_ns.pop("foo", None) - tm.store_or_execute(s, "foo") - self.assertIn("foo", ip.user_ns) - - def test_paste_trailing_question(self): - "Test pasting sources with trailing question marks" - tm = ip.magics_manager.registry['TerminalMagics'] - s = '''\ -def funcfoo(): - if True: #am i true? - return 'fooresult' -''' - ip.user_ns.pop('funcfoo', None) - self.paste(s) - self.assertEqual(ip.user_ns["funcfoo"](), "fooresult") diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_oinspect.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_oinspect.py deleted file mode 100644 index ac7c365..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_oinspect.py +++ /dev/null @@ -1,589 +0,0 @@ -"""Tests for the object inspection functionality. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -from contextlib import contextmanager -from inspect import signature, Signature, Parameter -import inspect -import os -import pytest -import re -import sys - -from .. import oinspect - -from decorator import decorator - -from IPython.testing.tools import AssertPrints, AssertNotPrints -from IPython.utils.path import compress_user - - -#----------------------------------------------------------------------------- -# Globals and constants -#----------------------------------------------------------------------------- - -inspector = None - -def setup_module(): - global inspector - inspector = oinspect.Inspector() - - -class SourceModuleMainTest: - __module__ = "__main__" - - -#----------------------------------------------------------------------------- -# Local utilities -#----------------------------------------------------------------------------- - -# WARNING: since this test checks the line number where a function is -# defined, if any code is inserted above, the following line will need to be -# updated. Do NOT insert any whitespace between the next line and the function -# definition below. -THIS_LINE_NUMBER = 47 # Put here the actual number of this line - - -def test_find_source_lines(): - assert oinspect.find_source_lines(test_find_source_lines) == THIS_LINE_NUMBER + 3 - assert oinspect.find_source_lines(type) is None - assert oinspect.find_source_lines(SourceModuleMainTest) is None - assert oinspect.find_source_lines(SourceModuleMainTest()) is None - - -def test_getsource(): - assert oinspect.getsource(type) is None - assert oinspect.getsource(SourceModuleMainTest) is None - assert oinspect.getsource(SourceModuleMainTest()) is None - - -def test_inspect_getfile_raises_exception(): - """Check oinspect.find_file/getsource/find_source_lines expectations""" - with pytest.raises(TypeError): - inspect.getfile(type) - with pytest.raises(OSError): - inspect.getfile(SourceModuleMainTest) - - -# A couple of utilities to ensure these tests work the same from a source or a -# binary install -def pyfile(fname): - return os.path.normcase(re.sub('.py[co]$', '.py', fname)) - - -def match_pyfiles(f1, f2): - assert pyfile(f1) == pyfile(f2) - - -def test_find_file(): - match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__)) - assert oinspect.find_file(type) is None - assert oinspect.find_file(SourceModuleMainTest) is None - assert oinspect.find_file(SourceModuleMainTest()) is None - - -def test_find_file_decorated1(): - - @decorator - def noop1(f): - def wrapper(*a, **kw): - return f(*a, **kw) - return wrapper - - @noop1 - def f(x): - "My docstring" - - match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__)) - assert f.__doc__ == "My docstring" - - -def test_find_file_decorated2(): - - @decorator - def noop2(f, *a, **kw): - return f(*a, **kw) - - @noop2 - @noop2 - @noop2 - def f(x): - "My docstring 2" - - match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__)) - assert f.__doc__ == "My docstring 2" - - -def test_find_file_magic(): - run = ip.find_line_magic('run') - assert oinspect.find_file(run) is not None - - -# A few generic objects we can then inspect in the tests below - -class Call(object): - """This is the class docstring.""" - - def __init__(self, x, y=1): - """This is the constructor docstring.""" - - def __call__(self, *a, **kw): - """This is the call docstring.""" - - def method(self, x, z=2): - """Some method's docstring""" - -class HasSignature(object): - """This is the class docstring.""" - __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)]) - - def __init__(self, *args): - """This is the init docstring""" - - -class SimpleClass(object): - def method(self, x, z=2): - """Some method's docstring""" - - -class Awkward(object): - def __getattr__(self, name): - raise Exception(name) - -class NoBoolCall: - """ - callable with `__bool__` raising should still be inspect-able. - """ - - def __call__(self): - """does nothing""" - pass - - def __bool__(self): - """just raise NotImplemented""" - raise NotImplementedError('Must be implemented') - - -class SerialLiar(object): - """Attribute accesses always get another copy of the same class. - - unittest.mock.call does something similar, but it's not ideal for testing - as the failure mode is to eat all your RAM. This gives up after 10k levels. - """ - def __init__(self, max_fibbing_twig, lies_told=0): - if lies_told > 10000: - raise RuntimeError('Nose too long, honesty is the best policy') - self.max_fibbing_twig = max_fibbing_twig - self.lies_told = lies_told - max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told) - - def __getattr__(self, item): - return SerialLiar(self.max_fibbing_twig, self.lies_told + 1) - -#----------------------------------------------------------------------------- -# Tests -#----------------------------------------------------------------------------- - -def test_info(): - "Check that Inspector.info fills out various fields as expected." - i = inspector.info(Call, oname="Call") - assert i["type_name"] == "type" - expected_class = str(type(type)) # (Python 3) or - assert i["base_class"] == expected_class - assert re.search( - "", - i["string_form"], - ) - fname = __file__ - if fname.endswith(".pyc"): - fname = fname[:-1] - # case-insensitive comparison needed on some filesystems - # e.g. Windows: - assert i["file"].lower() == compress_user(fname).lower() - assert i["definition"] == None - assert i["docstring"] == Call.__doc__ - assert i["source"] == None - assert i["isclass"] is True - assert i["init_definition"] == "Call(x, y=1)" - assert i["init_docstring"] == Call.__init__.__doc__ - - i = inspector.info(Call, detail_level=1) - assert i["source"] is not None - assert i["docstring"] == None - - c = Call(1) - c.__doc__ = "Modified instance docstring" - i = inspector.info(c) - assert i["type_name"] == "Call" - assert i["docstring"] == "Modified instance docstring" - assert i["class_docstring"] == Call.__doc__ - assert i["init_docstring"] == Call.__init__.__doc__ - assert i["call_docstring"] == Call.__call__.__doc__ - - -def test_class_signature(): - info = inspector.info(HasSignature, "HasSignature") - assert info["init_definition"] == "HasSignature(test)" - assert info["init_docstring"] == HasSignature.__init__.__doc__ - - -def test_info_awkward(): - # Just test that this doesn't throw an error. - inspector.info(Awkward()) - -def test_bool_raise(): - inspector.info(NoBoolCall()) - -def test_info_serialliar(): - fib_tracker = [0] - inspector.info(SerialLiar(fib_tracker)) - - # Nested attribute access should be cut off at 100 levels deep to avoid - # infinite loops: https://github.com/ipython/ipython/issues/9122 - assert fib_tracker[0] < 9000 - -def support_function_one(x, y=2, *a, **kw): - """A simple function.""" - -def test_calldef_none(): - # We should ignore __call__ for all of these. - for obj in [support_function_one, SimpleClass().method, any, str.upper]: - i = inspector.info(obj) - assert i["call_def"] is None - - -def f_kwarg(pos, *, kwonly): - pass - -def test_definition_kwonlyargs(): - i = inspector.info(f_kwarg, oname="f_kwarg") # analysis:ignore - assert i["definition"] == "f_kwarg(pos, *, kwonly)" - - -def test_getdoc(): - class A(object): - """standard docstring""" - pass - - class B(object): - """standard docstring""" - def getdoc(self): - return "custom docstring" - - class C(object): - """standard docstring""" - def getdoc(self): - return None - - a = A() - b = B() - c = C() - - assert oinspect.getdoc(a) == "standard docstring" - assert oinspect.getdoc(b) == "custom docstring" - assert oinspect.getdoc(c) == "standard docstring" - - -def test_empty_property_has_no_source(): - i = inspector.info(property(), detail_level=1) - assert i["source"] is None - - -def test_property_sources(): - # A simple adder whose source and signature stays - # the same across Python distributions - def simple_add(a, b): - "Adds two numbers" - return a + b - - class A(object): - @property - def foo(self): - return 'bar' - - foo = foo.setter(lambda self, v: setattr(self, 'bar', v)) - - dname = property(oinspect.getdoc) - adder = property(simple_add) - - i = inspector.info(A.foo, detail_level=1) - assert "def foo(self):" in i["source"] - assert "lambda self, v:" in i["source"] - - i = inspector.info(A.dname, detail_level=1) - assert "def getdoc(obj)" in i["source"] - - i = inspector.info(A.adder, detail_level=1) - assert "def simple_add(a, b)" in i["source"] - - -def test_property_docstring_is_in_info_for_detail_level_0(): - class A(object): - @property - def foobar(self): - """This is `foobar` property.""" - pass - - ip.user_ns["a_obj"] = A() - assert ( - "This is `foobar` property." - == ip.object_inspect("a_obj.foobar", detail_level=0)["docstring"] - ) - - ip.user_ns["a_cls"] = A - assert ( - "This is `foobar` property." - == ip.object_inspect("a_cls.foobar", detail_level=0)["docstring"] - ) - - -def test_pdef(): - # See gh-1914 - def foo(): pass - inspector.pdef(foo, 'foo') - - -@contextmanager -def cleanup_user_ns(**kwargs): - """ - On exit delete all the keys that were not in user_ns before entering. - - It does not restore old values ! - - Parameters - ---------- - - **kwargs - used to update ip.user_ns - - """ - try: - known = set(ip.user_ns.keys()) - ip.user_ns.update(kwargs) - yield - finally: - added = set(ip.user_ns.keys()) - known - for k in added: - del ip.user_ns[k] - - -def test_pinfo_bool_raise(): - """ - Test that bool method is not called on parent. - """ - - class RaiseBool: - attr = None - - def __bool__(self): - raise ValueError("pinfo should not access this method") - - raise_bool = RaiseBool() - - with cleanup_user_ns(raise_bool=raise_bool): - ip._inspect("pinfo", "raise_bool.attr", detail_level=0) - - -def test_pinfo_getindex(): - def dummy(): - """ - MARKER - """ - - container = [dummy] - with cleanup_user_ns(container=container): - with AssertPrints("MARKER"): - ip._inspect("pinfo", "container[0]", detail_level=0) - assert "container" not in ip.user_ns.keys() - - -def test_qmark_getindex(): - def dummy(): - """ - MARKER 2 - """ - - container = [dummy] - with cleanup_user_ns(container=container): - with AssertPrints("MARKER 2"): - ip.run_cell("container[0]?") - assert "container" not in ip.user_ns.keys() - - -def test_qmark_getindex_negatif(): - def dummy(): - """ - MARKER 3 - """ - - container = [dummy] - with cleanup_user_ns(container=container): - with AssertPrints("MARKER 3"): - ip.run_cell("container[-1]?") - assert "container" not in ip.user_ns.keys() - - - -def test_pinfo_nonascii(): - # See gh-1177 - from . import nonascii2 - ip.user_ns['nonascii2'] = nonascii2 - ip._inspect('pinfo', 'nonascii2', detail_level=1) - -def test_pinfo_type(): - """ - type can fail in various edge case, for example `type.__subclass__()` - """ - ip._inspect('pinfo', 'type') - - -def test_pinfo_docstring_no_source(): - """Docstring should be included with detail_level=1 if there is no source""" - with AssertPrints('Docstring:'): - ip._inspect('pinfo', 'str.format', detail_level=0) - with AssertPrints('Docstring:'): - ip._inspect('pinfo', 'str.format', detail_level=1) - - -def test_pinfo_no_docstring_if_source(): - """Docstring should not be included with detail_level=1 if source is found""" - def foo(): - """foo has a docstring""" - - ip.user_ns['foo'] = foo - - with AssertPrints('Docstring:'): - ip._inspect('pinfo', 'foo', detail_level=0) - with AssertPrints('Source:'): - ip._inspect('pinfo', 'foo', detail_level=1) - with AssertNotPrints('Docstring:'): - ip._inspect('pinfo', 'foo', detail_level=1) - - -def test_pinfo_docstring_if_detail_and_no_source(): - """ Docstring should be displayed if source info not available """ - obj_def = '''class Foo(object): - """ This is a docstring for Foo """ - def bar(self): - """ This is a docstring for Foo.bar """ - pass - ''' - - ip.run_cell(obj_def) - ip.run_cell('foo = Foo()') - - with AssertNotPrints("Source:"): - with AssertPrints('Docstring:'): - ip._inspect('pinfo', 'foo', detail_level=0) - with AssertPrints('Docstring:'): - ip._inspect('pinfo', 'foo', detail_level=1) - with AssertPrints('Docstring:'): - ip._inspect('pinfo', 'foo.bar', detail_level=0) - - with AssertNotPrints('Docstring:'): - with AssertPrints('Source:'): - ip._inspect('pinfo', 'foo.bar', detail_level=1) - - -@pytest.mark.xfail( - sys.version_info.releaselevel not in ("final", "candidate"), - reason="fails on 3.13.dev", - strict=True, -) -def test_pinfo_docstring_dynamic(capsys): - obj_def = """class Bar: - __custom_documentations__ = { - "prop" : "cdoc for prop", - "non_exist" : "cdoc for non_exist", - } - @property - def prop(self): - ''' - Docstring for prop - ''' - return self._prop - - @prop.setter - def prop(self, v): - self._prop = v - """ - ip.run_cell(obj_def) - - ip.run_cell("b = Bar()") - - ip.run_line_magic("pinfo", "b.prop") - captured = capsys.readouterr() - assert re.search(r"Docstring:\s+cdoc for prop", captured.out) - - ip.run_line_magic("pinfo", "b.non_exist") - captured = capsys.readouterr() - assert re.search(r"Docstring:\s+cdoc for non_exist", captured.out) - - ip.run_cell("b.prop?") - captured = capsys.readouterr() - assert re.search(r"Docstring:\s+cdoc for prop", captured.out) - - ip.run_cell("b.non_exist?") - captured = capsys.readouterr() - assert re.search(r"Docstring:\s+cdoc for non_exist", captured.out) - - ip.run_cell("b.undefined?") - captured = capsys.readouterr() - assert re.search(r"Type:\s+NoneType", captured.out) - - -def test_pinfo_magic(): - with AssertPrints("Docstring:"): - ip._inspect("pinfo", "lsmagic", detail_level=0) - - with AssertPrints("Source:"): - ip._inspect("pinfo", "lsmagic", detail_level=1) - - -def test_init_colors(): - # ensure colors are not present in signature info - info = inspector.info(HasSignature) - init_def = info["init_definition"] - assert "[0m" not in init_def - - -def test_builtin_init(): - info = inspector.info(list) - init_def = info['init_definition'] - assert init_def is not None - - -def test_render_signature_short(): - def short_fun(a=1): pass - sig = oinspect._render_signature( - signature(short_fun), - short_fun.__name__, - ) - assert sig == "short_fun(a=1)" - - -def test_render_signature_long(): - from typing import Optional - - def long_function( - a_really_long_parameter: int, - and_another_long_one: bool = False, - let_us_make_sure_this_is_looong: Optional[str] = None, - ) -> bool: pass - - sig = oinspect._render_signature( - signature(long_function), - long_function.__name__, - ) - expected = """\ -long_function( - a_really_long_parameter: int, - and_another_long_one: bool = False, - let_us_make_sure_this_is_looong: Optional[str] = None, -) -> bool\ -""" - - assert sig == expected diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_page.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_page.py deleted file mode 100644 index 9f6a374..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_page.py +++ /dev/null @@ -1,20 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team. -# -# Distributed under the terms of the BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- -import io - -# N.B. For the test suite, page.page is overridden (see IPython.testing.globalipapp) -from IPython.core import page - -def test_detect_screen_size(): - """Simple smoketest for page._detect_screen_size.""" - try: - page._detect_screen_size(True, 25) - except (TypeError, io.UnsupportedOperation): - # This can happen in the test suite, because stdout may not have a - # fileno. - pass diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_paths.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_paths.py deleted file mode 100644 index 8e4a63f..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_paths.py +++ /dev/null @@ -1,202 +0,0 @@ -import errno -import os -import shutil -import tempfile -import warnings -from unittest.mock import patch - -from tempfile import TemporaryDirectory -from testpath import assert_isdir, assert_isfile, modified_env - -from IPython import paths -from IPython.testing.decorators import skip_win32 - -TMP_TEST_DIR = os.path.realpath(tempfile.mkdtemp()) -HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir") -XDG_TEST_DIR = os.path.join(HOME_TEST_DIR, "xdg_test_dir") -XDG_CACHE_DIR = os.path.join(HOME_TEST_DIR, "xdg_cache_dir") -IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython') - -def setup_module(): - """Setup testenvironment for the module: - - - Adds dummy home dir tree - """ - # Do not mask exceptions here. In particular, catching WindowsError is a - # problem because that exception is only defined on Windows... - os.makedirs(IP_TEST_DIR) - os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython')) - os.makedirs(os.path.join(XDG_CACHE_DIR, 'ipython')) - - -def teardown_module(): - """Teardown testenvironment for the module: - - - Remove dummy home dir tree - """ - # Note: we remove the parent test dir, which is the root of all test - # subdirs we may have created. Use shutil instead of os.removedirs, so - # that non-empty directories are all recursively removed. - shutil.rmtree(TMP_TEST_DIR) - -def patch_get_home_dir(dirpath): - return patch.object(paths, 'get_home_dir', return_value=dirpath) - - -def test_get_ipython_dir_1(): - """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions.""" - env_ipdir = os.path.join("someplace", ".ipython") - with patch.object(paths, '_writable_dir', return_value=True), \ - modified_env({'IPYTHONDIR': env_ipdir}): - ipdir = paths.get_ipython_dir() - - assert ipdir == env_ipdir - -def test_get_ipython_dir_2(): - """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions.""" - with patch_get_home_dir('someplace'), \ - patch.object(paths, 'get_xdg_dir', return_value=None), \ - patch.object(paths, '_writable_dir', return_value=True), \ - patch('os.name', "posix"), \ - modified_env({'IPYTHON_DIR': None, - 'IPYTHONDIR': None, - 'XDG_CONFIG_HOME': None - }): - ipdir = paths.get_ipython_dir() - - assert ipdir == os.path.join("someplace", ".ipython") - -def test_get_ipython_dir_3(): - """test_get_ipython_dir_3, use XDG if defined and exists, and .ipython doesn't exist.""" - tmphome = TemporaryDirectory() - try: - with patch_get_home_dir(tmphome.name), \ - patch('os.name', 'posix'), \ - modified_env({ - 'IPYTHON_DIR': None, - 'IPYTHONDIR': None, - 'XDG_CONFIG_HOME': XDG_TEST_DIR, - }), warnings.catch_warnings(record=True) as w: - ipdir = paths.get_ipython_dir() - - assert ipdir == os.path.join(tmphome.name, XDG_TEST_DIR, "ipython") - assert len(w) == 0 - finally: - tmphome.cleanup() - -def test_get_ipython_dir_4(): - """test_get_ipython_dir_4, warn if XDG and home both exist.""" - with patch_get_home_dir(HOME_TEST_DIR), \ - patch('os.name', 'posix'): - try: - os.mkdir(os.path.join(XDG_TEST_DIR, 'ipython')) - except OSError as e: - if e.errno != errno.EEXIST: - raise - - - with modified_env({ - 'IPYTHON_DIR': None, - 'IPYTHONDIR': None, - 'XDG_CONFIG_HOME': XDG_TEST_DIR, - }), warnings.catch_warnings(record=True) as w: - ipdir = paths.get_ipython_dir() - - assert len(w) == 1 - assert "Ignoring" in str(w[0]) - - -def test_get_ipython_dir_5(): - """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist.""" - with patch_get_home_dir(HOME_TEST_DIR), \ - patch('os.name', 'posix'): - try: - os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython')) - except OSError as e: - if e.errno != errno.ENOENT: - raise - - with modified_env({ - 'IPYTHON_DIR': None, - 'IPYTHONDIR': None, - 'XDG_CONFIG_HOME': XDG_TEST_DIR, - }): - ipdir = paths.get_ipython_dir() - - assert ipdir == IP_TEST_DIR - -def test_get_ipython_dir_6(): - """test_get_ipython_dir_6, use home over XDG if defined and neither exist.""" - xdg = os.path.join(HOME_TEST_DIR, 'somexdg') - os.mkdir(xdg) - shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython')) - print(paths._writable_dir) - with patch_get_home_dir(HOME_TEST_DIR), \ - patch.object(paths, 'get_xdg_dir', return_value=xdg), \ - patch('os.name', 'posix'), \ - modified_env({ - 'IPYTHON_DIR': None, - 'IPYTHONDIR': None, - 'XDG_CONFIG_HOME': None, - }), warnings.catch_warnings(record=True) as w: - ipdir = paths.get_ipython_dir() - - assert ipdir == os.path.join(HOME_TEST_DIR, ".ipython") - assert len(w) == 0 - -def test_get_ipython_dir_7(): - """test_get_ipython_dir_7, test home directory expansion on IPYTHONDIR""" - home_dir = os.path.normpath(os.path.expanduser('~')) - with modified_env({'IPYTHONDIR': os.path.join('~', 'somewhere')}), \ - patch.object(paths, '_writable_dir', return_value=True): - ipdir = paths.get_ipython_dir() - assert ipdir == os.path.join(home_dir, "somewhere") - - -@skip_win32 -def test_get_ipython_dir_8(): - """test_get_ipython_dir_8, test / home directory""" - if not os.access("/", os.W_OK): - # test only when HOME directory actually writable - return - - with ( - patch.object(paths, "_writable_dir", lambda path: bool(path)), - patch.object(paths, "get_xdg_dir", return_value=None), - modified_env( - { - "IPYTHON_DIR": None, - "IPYTHONDIR": None, - "HOME": "/", - } - ), - ): - assert paths.get_ipython_dir() == "/.ipython" - - -def test_get_ipython_cache_dir(): - with modified_env({'HOME': HOME_TEST_DIR}): - if os.name == "posix": - # test default - os.makedirs(os.path.join(HOME_TEST_DIR, ".cache")) - with modified_env({'XDG_CACHE_HOME': None}): - ipdir = paths.get_ipython_cache_dir() - assert os.path.join(HOME_TEST_DIR, ".cache", "ipython") == ipdir - assert_isdir(ipdir) - - # test env override - with modified_env({"XDG_CACHE_HOME": XDG_CACHE_DIR}): - ipdir = paths.get_ipython_cache_dir() - assert_isdir(ipdir) - assert ipdir == os.path.join(XDG_CACHE_DIR, "ipython") - else: - assert paths.get_ipython_cache_dir() == paths.get_ipython_dir() - -def test_get_ipython_package_dir(): - ipdir = paths.get_ipython_package_dir() - assert_isdir(ipdir) - - -def test_get_ipython_module_path(): - ipapp_path = paths.get_ipython_module_path('IPython.terminal.ipapp') - assert_isfile(ipapp_path) diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_prefilter.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_prefilter.py deleted file mode 100644 index 379a530..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_prefilter.py +++ /dev/null @@ -1,149 +0,0 @@ -"""Tests for input manipulation machinery.""" - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -import pytest - -from IPython.core.prefilter import AutocallChecker - -#----------------------------------------------------------------------------- -# Tests -#----------------------------------------------------------------------------- - -def test_prefilter(): - """Test user input conversions""" - - # pairs of (raw, expected correct) input - pairs = [ ('2+2','2+2'), - ] - - for raw, correct in pairs: - assert ip.prefilter(raw) == correct - -def test_prefilter_shadowed(): - def dummy_magic(line): pass - - prev_automagic_state = ip.automagic - ip.automagic = True - ip.autocall = 0 - - try: - # These should not be transformed - they are shadowed by other names - for name in ['if', 'zip', 'get_ipython']: # keyword, builtin, global - ip.register_magic_function(dummy_magic, magic_name=name) - res = ip.prefilter(name + " foo") - assert res == name + " foo" - del ip.magics_manager.magics["line"][name] - - # These should be transformed - for name in ['fi', 'piz', 'nohtypi_teg']: - ip.register_magic_function(dummy_magic, magic_name=name) - res = ip.prefilter(name + " foo") - assert res != name + " foo" - del ip.magics_manager.magics["line"][name] - - finally: - ip.automagic = prev_automagic_state - -def test_autocall_binops(): - """See https://github.com/ipython/ipython/issues/81""" - ip.run_line_magic("autocall", "2") - f = lambda x: x - ip.user_ns['f'] = f - try: - assert ip.prefilter("f 1") == "f(1)" - for t in ["f +1", "f -1"]: - assert ip.prefilter(t) == t - - # Run tests again with a more permissive exclude_regexp, which will - # allow transformation of binary operations ('f -1' -> 'f(-1)'). - pm = ip.prefilter_manager - ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm, - config=pm.config) - try: - ac.priority = 1 - ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or ' - pm.sort_checkers() - - assert ip.prefilter("f -1") == "f(-1)" - assert ip.prefilter("f +1") == "f(+1)" - finally: - pm.unregister_checker(ac) - finally: - ip.run_line_magic("autocall", "0") - del ip.user_ns["f"] - - -def test_issue_114(): - """Check that multiline string literals don't expand as magic - see http://github.com/ipython/ipython/issues/114""" - - template = '"""\n%s\n"""' - # Store the current value of multi_line_specials and turn it off before - # running test, since it could be true (case in which the test doesn't make - # sense, as multiline string literals *will* expand as magic in that case). - msp = ip.prefilter_manager.multi_line_specials - ip.prefilter_manager.multi_line_specials = False - try: - for mgk in ip.magics_manager.lsmagic()['line']: - raw = template % mgk - assert ip.prefilter(raw) == raw - finally: - ip.prefilter_manager.multi_line_specials = msp - - -def test_prefilter_attribute_errors(): - """Capture exceptions thrown by user objects on attribute access. - - See http://github.com/ipython/ipython/issues/988.""" - - class X(object): - def __getattr__(self, k): - raise ValueError('broken object') - def __call__(self, x): - return x - - # Create a callable broken object - ip.user_ns["x"] = X() - ip.run_line_magic("autocall", "2") - try: - # Even if x throws an attribute error when looking at its rewrite - # attribute, we should not crash. So the test here is simply making - # the prefilter call and not having an exception. - ip.prefilter('x 1') - finally: - del ip.user_ns["x"] - ip.run_line_magic("autocall", "0") - - -def test_autocall_type_ann(): - ip.run_cell("import collections.abc") - ip.run_line_magic("autocall", "1") - try: - assert ( - ip.prefilter("collections.abc.Callable[[int], None]") - == "collections.abc.Callable[[int], None]" - ) - finally: - ip.run_line_magic("autocall", "0") - - -def test_autocall_should_support_unicode(): - ip.run_line_magic("autocall", "2") - ip.user_ns["π"] = lambda x: x - try: - assert ip.prefilter("π 3") == "π(3)" - finally: - ip.run_line_magic("autocall", "0") - del ip.user_ns["π"] - - -def test_autocall_regression_gh_14513(): - ip.run_line_magic("autocall", "2") - ip.user_ns["foo"] = dict() - try: - assert ip.prefilter("foo") == "foo" - finally: - ip.run_line_magic("autocall", "0") - del ip.user_ns["foo"] diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_profile.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_profile.py deleted file mode 100644 index 8e03b5a..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_profile.py +++ /dev/null @@ -1,161 +0,0 @@ -# coding: utf-8 -"""Tests for profile-related functions. - -Currently only the startup-dir functionality is tested, but more tests should -be added for: - - * ipython profile create - * ipython profile list - * ipython profile create --parallel - * security dir permissions - -Authors -------- - -* MinRK - -""" - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import shutil -import sys -import tempfile -from pathlib import Path -from tempfile import TemporaryDirectory -from unittest import TestCase - -import pytest - -from IPython.core.profileapp import list_bundled_profiles, list_profiles_in -from IPython.core.profiledir import ProfileDir -from IPython.testing import decorators as dec -from IPython.testing import tools as tt -from IPython.utils.process import getoutput - -#----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- -TMP_TEST_DIR = Path(tempfile.mkdtemp()) -HOME_TEST_DIR = TMP_TEST_DIR / "home_test_dir" -IP_TEST_DIR = HOME_TEST_DIR / ".ipython" - -# -# Setup/teardown functions/decorators -# - -def setup_module(): - """Setup test environment for the module: - - - Adds dummy home dir tree - """ - # Do not mask exceptions here. In particular, catching WindowsError is a - # problem because that exception is only defined on Windows... - (Path.cwd() / IP_TEST_DIR).mkdir(parents=True) - - -def teardown_module(): - """Teardown test environment for the module: - - - Remove dummy home dir tree - """ - # Note: we remove the parent test dir, which is the root of all test - # subdirs we may have created. Use shutil instead of os.removedirs, so - # that non-empty directories are all recursively removed. - shutil.rmtree(TMP_TEST_DIR) - - -#----------------------------------------------------------------------------- -# Test functions -#----------------------------------------------------------------------------- -class ProfileStartupTest(TestCase): - def setUp(self): - # create profile dir - self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, "test") - self.options = ["--ipython-dir", IP_TEST_DIR, "--profile", "test"] - self.fname = TMP_TEST_DIR / "test.py" - - def tearDown(self): - # We must remove this profile right away so its presence doesn't - # confuse other tests. - shutil.rmtree(self.pd.location) - - def init(self, startup_file, startup, test): - # write startup python file - with open(Path(self.pd.startup_dir) / startup_file, "w", encoding="utf-8") as f: - f.write(startup) - # write simple test file, to check that the startup file was run - with open(self.fname, "w", encoding="utf-8") as f: - f.write(test) - - def validate(self, output): - tt.ipexec_validate(self.fname, output, "", options=self.options) - - def test_startup_py(self): - self.init('00-start.py', 'zzz=123\n', 'print(zzz)\n') - self.validate('123') - - def test_startup_ipy(self): - self.init('00-start.ipy', '%xmode plain\n', '') - self.validate('Exception reporting mode: Plain') - - -@pytest.mark.skipif( - sys.implementation.name == "pypy" - and ((7, 3, 13) < sys.implementation.version < (7, 3, 16)), - reason="Unicode issues with scandir on PyPy, see https://github.com/pypy/pypy/issues/4860", -) -def test_list_profiles_in(): - # No need to remove these directories and files, as they will get nuked in - # the module-level teardown. - td = Path(tempfile.mkdtemp(dir=TMP_TEST_DIR)) - for name in ("profile_foo", "profile_hello", "not_a_profile"): - Path(td / name).mkdir(parents=True) - if dec.unicode_paths: - Path(td / "profile_ünicode").mkdir(parents=True) - - with open(td / "profile_file", "w", encoding="utf-8") as f: - f.write("I am not a profile directory") - profiles = list_profiles_in(td) - - # unicode normalization can turn u'ünicode' into u'u\0308nicode', - # so only check for *nicode, and that creating a ProfileDir from the - # name remains valid - found_unicode = False - for p in list(profiles): - if p.endswith('nicode'): - pd = ProfileDir.find_profile_dir_by_name(td, p) - profiles.remove(p) - found_unicode = True - break - if dec.unicode_paths: - assert found_unicode is True - assert set(profiles) == {"foo", "hello"} - - -def test_list_bundled_profiles(): - # This variable will need to be updated when a new profile gets bundled - bundled = sorted(list_bundled_profiles()) - assert bundled == [] - - -def test_profile_create_ipython_dir(): - """ipython profile create respects --ipython-dir""" - with TemporaryDirectory() as td: - getoutput( - [ - sys.executable, - "-m", - "IPython", - "profile", - "create", - "foo", - "--ipython-dir=%s" % td, - ] - ) - profile_dir = Path(td) / "profile_foo" - assert Path(profile_dir).exists() - ipython_config = profile_dir / "ipython_config.py" - assert Path(ipython_config).exists() diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_prompts.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_prompts.py deleted file mode 100644 index 95e6163..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_prompts.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -"""Tests for prompt generation.""" - -import unittest - -from IPython.core.prompts import LazyEvaluate - -class PromptTests(unittest.TestCase): - def test_lazy_eval_unicode(self): - u = u'ünicødé' - lz = LazyEvaluate(lambda : u) - self.assertEqual(str(lz), u) - self.assertEqual(format(lz), u) - - def test_lazy_eval_nonascii_bytes(self): - u = u'ünicødé' - b = u.encode('utf8') - lz = LazyEvaluate(lambda : b) - # unicode(lz) would fail - self.assertEqual(str(lz), str(b)) - self.assertEqual(format(lz), str(b)) - - def test_lazy_eval_float(self): - f = 0.503 - lz = LazyEvaluate(lambda : f) - - self.assertEqual(str(lz), str(f)) - self.assertEqual(format(lz), str(f)) - self.assertEqual(format(lz, '.1'), '0.5') - diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_pylabtools.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_pylabtools.py deleted file mode 100644 index 31d3dbe..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_pylabtools.py +++ /dev/null @@ -1,375 +0,0 @@ -"""Tests for pylab tools module. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -from binascii import a2b_base64 -from io import BytesIO - -import pytest - -matplotlib = pytest.importorskip("matplotlib") -matplotlib.use('Agg') -from matplotlib.figure import Figure - -from matplotlib import pyplot as plt -from matplotlib_inline import backend_inline -import numpy as np - -from IPython.core.getipython import get_ipython -from IPython.core.interactiveshell import InteractiveShell -from IPython.core.display import _PNG, _JPEG -from .. import pylabtools as pt - -from IPython.testing import decorators as dec - - -def test_figure_to_svg(): - # simple empty-figure test - fig = plt.figure() - assert pt.print_figure(fig, "svg") is None - - plt.close('all') - - # simple check for at least svg-looking output - fig = plt.figure() - ax = fig.add_subplot(1,1,1) - ax.plot([1,2,3]) - plt.draw() - svg = pt.print_figure(fig, "svg")[:100].lower() - assert "doctype svg" in svg - - -def _check_pil_jpeg_bytes(): - """Skip if PIL can't write JPEGs to BytesIO objects""" - # PIL's JPEG plugin can't write to BytesIO objects - # Pillow fixes this - from PIL import Image - buf = BytesIO() - img = Image.new("RGB", (4,4)) - try: - img.save(buf, 'jpeg') - except Exception as e: - ename = e.__class__.__name__ - raise pytest.skip("PIL can't write JPEG to BytesIO: %s: %s" % (ename, e)) from e - -@dec.skip_without("PIL.Image") -def test_figure_to_jpeg(): - _check_pil_jpeg_bytes() - # simple check for at least jpeg-looking output - fig = plt.figure() - ax = fig.add_subplot(1,1,1) - ax.plot([1,2,3]) - plt.draw() - jpeg = pt.print_figure(fig, 'jpeg', pil_kwargs={'optimize': 50})[:100].lower() - assert jpeg.startswith(_JPEG) - -def test_retina_figure(): - # simple empty-figure test - fig = plt.figure() - assert pt.retina_figure(fig) == None - plt.close('all') - - fig = plt.figure() - ax = fig.add_subplot(1,1,1) - ax.plot([1,2,3]) - plt.draw() - png, md = pt.retina_figure(fig) - assert png.startswith(_PNG) - assert "width" in md - assert "height" in md - - -_fmt_mime_map = { - 'png': 'image/png', - 'jpeg': 'image/jpeg', - 'pdf': 'application/pdf', - 'retina': 'image/png', - 'svg': 'image/svg+xml', -} - -def test_select_figure_formats_str(): - ip = get_ipython() - for fmt, active_mime in _fmt_mime_map.items(): - pt.select_figure_formats(ip, fmt) - for mime, f in ip.display_formatter.formatters.items(): - if mime == active_mime: - assert Figure in f - else: - assert Figure not in f - -def test_select_figure_formats_kwargs(): - ip = get_ipython() - kwargs = dict(bbox_inches="tight") - pt.select_figure_formats(ip, "png", **kwargs) - formatter = ip.display_formatter.formatters["image/png"] - f = formatter.lookup_by_type(Figure) - cell = f.keywords - expected = kwargs - expected["base64"] = True - expected["fmt"] = "png" - assert cell == expected - - # check that the formatter doesn't raise - fig = plt.figure() - ax = fig.add_subplot(1,1,1) - ax.plot([1,2,3]) - plt.draw() - formatter.enabled = True - png = formatter(fig) - assert isinstance(png, str) - png_bytes = a2b_base64(png) - assert png_bytes.startswith(_PNG) - -def test_select_figure_formats_set(): - ip = get_ipython() - for fmts in [ - {'png', 'svg'}, - ['png'], - ('jpeg', 'pdf', 'retina'), - {'svg'}, - ]: - active_mimes = {_fmt_mime_map[fmt] for fmt in fmts} - pt.select_figure_formats(ip, fmts) - for mime, f in ip.display_formatter.formatters.items(): - if mime in active_mimes: - assert Figure in f - else: - assert Figure not in f - -def test_select_figure_formats_bad(): - ip = get_ipython() - with pytest.raises(ValueError): - pt.select_figure_formats(ip, 'foo') - with pytest.raises(ValueError): - pt.select_figure_formats(ip, {'png', 'foo'}) - with pytest.raises(ValueError): - pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad']) - -def test_import_pylab(): - ns = {} - pt.import_pylab(ns, import_all=False) - assert "plt" in ns - assert ns["np"] == np - - -class TestPylabSwitch(object): - class Shell(InteractiveShell): - def init_history(self): - """Sets up the command history, and starts regular autosaves.""" - self.config.HistoryManager.hist_file = ":memory:" - super().init_history() - - def enable_gui(self, gui): - pass - - def setup_method(self): - import matplotlib - def act_mpl(backend): - matplotlib.rcParams['backend'] = backend - - # Save rcParams since they get modified - self._saved_rcParams = matplotlib.rcParams - self._saved_rcParamsOrig = matplotlib.rcParamsOrig - matplotlib.rcParams = dict(backend="QtAgg") - matplotlib.rcParamsOrig = dict(backend="QtAgg") - - # Mock out functions - self._save_am = pt.activate_matplotlib - pt.activate_matplotlib = act_mpl - self._save_ip = pt.import_pylab - pt.import_pylab = lambda *a,**kw:None - self._save_cis = backend_inline.configure_inline_support - backend_inline.configure_inline_support = lambda *a, **kw: None - - def teardown_method(self): - pt.activate_matplotlib = self._save_am - pt.import_pylab = self._save_ip - backend_inline.configure_inline_support = self._save_cis - import matplotlib - matplotlib.rcParams = self._saved_rcParams - matplotlib.rcParamsOrig = self._saved_rcParamsOrig - - def test_qt(self): - s = self.Shell() - gui, backend = s.enable_matplotlib(None) - assert gui == "qt" - assert s.pylab_gui_select == "qt" - - gui, backend = s.enable_matplotlib("inline") - assert gui is None - assert s.pylab_gui_select == "qt" - - gui, backend = s.enable_matplotlib("qt") - assert gui == "qt" - assert s.pylab_gui_select == "qt" - - gui, backend = s.enable_matplotlib("inline") - assert gui is None - assert s.pylab_gui_select == "qt" - - gui, backend = s.enable_matplotlib() - assert gui == "qt" - assert s.pylab_gui_select == "qt" - - def test_inline(self): - s = self.Shell() - gui, backend = s.enable_matplotlib("inline") - assert gui is None - assert s.pylab_gui_select == None - - gui, backend = s.enable_matplotlib("inline") - assert gui is None - assert s.pylab_gui_select == None - - gui, backend = s.enable_matplotlib("qt") - assert gui == "qt" - assert s.pylab_gui_select == "qt" - - def test_inline_twice(self): - "Using '%matplotlib inline' twice should not reset formatters" - - ip = self.Shell() - gui, backend = ip.enable_matplotlib("inline") - assert gui is None - - fmts = {'png'} - active_mimes = {_fmt_mime_map[fmt] for fmt in fmts} - pt.select_figure_formats(ip, fmts) - - gui, backend = ip.enable_matplotlib("inline") - assert gui is None - - for mime, f in ip.display_formatter.formatters.items(): - if mime in active_mimes: - assert Figure in f - else: - assert Figure not in f - - def test_qt_gtk(self): - s = self.Shell() - gui, backend = s.enable_matplotlib("qt") - assert gui == "qt" - assert s.pylab_gui_select == "qt" - - gui, backend = s.enable_matplotlib("gtk3") - assert gui == "qt" - assert s.pylab_gui_select == "qt" - - @dec.skipif(not pt._matplotlib_manages_backends()) - def test_backend_module_name_case_sensitive(self): - # Matplotlib backend names are case insensitive unless explicitly specified using - # "module://some_module.some_name" syntax which are case sensitive for mpl >= 3.9.1 - all_lowercase = "module://matplotlib_inline.backend_inline" - some_uppercase = "module://matplotlib_inline.Backend_inline" - mpl3_9_1 = matplotlib.__version_info__ >= (3, 9, 1) - - s = self.Shell() - s.enable_matplotlib(all_lowercase) - if mpl3_9_1: - with pytest.raises(RuntimeError): - s.enable_matplotlib(some_uppercase) - else: - s.enable_matplotlib(some_uppercase) - - s.run_line_magic("matplotlib", all_lowercase) - if mpl3_9_1: - with pytest.raises(RuntimeError): - s.run_line_magic("matplotlib", some_uppercase) - else: - s.run_line_magic("matplotlib", some_uppercase) - - -def test_no_gui_backends(): - for k in ['agg', 'svg', 'pdf', 'ps']: - assert k not in pt.backend2gui - - -def test_figure_no_canvas(): - fig = Figure() - fig.canvas = None - pt.print_figure(fig) - - -@pytest.mark.parametrize( - "name, expected_gui, expected_backend", - [ - # name is gui - ("gtk3", "gtk3", "gtk3agg"), - ("gtk4", "gtk4", "gtk4agg"), - ("headless", None, "agg"), - ("osx", "osx", "macosx"), - ("qt", "qt", "qtagg"), - ("qt5", "qt5", "qt5agg"), - ("qt6", "qt6", "qtagg"), - ("tk", "tk", "tkagg"), - ("wx", "wx", "wxagg"), - # name is backend - ("agg", None, "agg"), - ("cairo", None, "cairo"), - ("pdf", None, "pdf"), - ("ps", None, "ps"), - ("svg", None, "svg"), - ("template", None, "template"), - ("gtk3agg", "gtk3", "gtk3agg"), - ("gtk3cairo", "gtk3", "gtk3cairo"), - ("gtk4agg", "gtk4", "gtk4agg"), - ("gtk4cairo", "gtk4", "gtk4cairo"), - ("macosx", "osx", "macosx"), - ("nbagg", "nbagg", "nbagg"), - ("notebook", "nbagg", "notebook"), - ("qtagg", "qt", "qtagg"), - ("qtcairo", "qt", "qtcairo"), - ("qt5agg", "qt5", "qt5agg"), - ("qt5cairo", "qt5", "qt5cairo"), - ("tkagg", "tk", "tkagg"), - ("tkcairo", "tk", "tkcairo"), - ("webagg", "webagg", "webagg"), - ("wxagg", "wx", "wxagg"), - ("wxcairo", "wx", "wxcairo"), - ], -) -def test_backend_builtin(name, expected_gui, expected_backend): - # Test correct identification of Matplotlib built-in backends without importing and using them, - # otherwise we would need to ensure all the complex dependencies such as windowing toolkits are - # installed. - - mpl_manages_backends = pt._matplotlib_manages_backends() - if not mpl_manages_backends: - # Backends not supported before _matplotlib_manages_backends or supported - # but with different expected_gui or expected_backend. - if ( - name.endswith("agg") - or name.endswith("cairo") - or name in ("headless", "macosx", "pdf", "ps", "svg", "template") - ): - pytest.skip() - elif name == "qt6": - expected_backend = "qtagg" - elif name == "notebook": - expected_backend, expected_gui = expected_gui, expected_backend - - gui, backend = pt.find_gui_and_backend(name) - if not mpl_manages_backends: - gui = gui.lower() if gui else None - backend = backend.lower() if backend else None - assert gui == expected_gui - assert backend == expected_backend - - -def test_backend_entry_point(): - gui, backend = pt.find_gui_and_backend("inline") - assert gui is None - expected_backend = ( - "inline" - if pt._matplotlib_manages_backends() - else "module://matplotlib_inline.backend_inline" - ) - assert backend == expected_backend - - -def test_backend_unknown(): - with pytest.raises(RuntimeError if pt._matplotlib_manages_backends() else KeyError): - pt.find_gui_and_backend("name-does-not-exist") diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_run.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_run.py deleted file mode 100644 index 971f8e3..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_run.py +++ /dev/null @@ -1,626 +0,0 @@ -# encoding: utf-8 -"""Tests for code execution (%run and related), which is particularly tricky. - -Because of how %run manages namespaces, and the fact that we are trying here to -verify subtle object deletion and reference counting issues, the %run tests -will be kept in this separate file. This makes it easier to aggregate in one -place the tricks needed to handle it; most other magics are much easier to test -and we do so in a common test_magic file. - -Note that any test using `run -i` should make sure to do a `reset` afterwards, -as otherwise it may influence later tests. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - - -import functools -import os -import platform -import random -import string -import sys -import textwrap -import unittest -from os.path import join as pjoin -from unittest.mock import patch - -import pytest -from tempfile import TemporaryDirectory - -from IPython.core import debugger -from IPython.testing import decorators as dec -from IPython.testing import tools as tt -from IPython.utils.io import capture_output - - -def doctest_refbug(): - """Very nasty problem with references held by multiple runs of a script. - See: https://github.com/ipython/ipython/issues/141 - - In [1]: _ip.clear_main_mod_cache() - # random - - In [2]: %run refbug - - In [3]: call_f() - lowercased: hello - - In [4]: %run refbug - - In [5]: call_f() - lowercased: hello - lowercased: hello - """ - - -def doctest_run_builtins(): - r"""Check that %run doesn't damage __builtins__. - - In [1]: import tempfile - - In [2]: bid1 = id(__builtins__) - - In [3]: fname = tempfile.mkstemp('.py')[1] - - In [3]: f = open(fname, 'w', encoding='utf-8') - - In [4]: dummy= f.write('pass\n') - - In [5]: f.flush() - - In [6]: t1 = type(__builtins__) - - In [7]: %run $fname - - In [7]: f.close() - - In [8]: bid2 = id(__builtins__) - - In [9]: t2 = type(__builtins__) - - In [10]: t1 == t2 - Out[10]: True - - In [10]: bid1 == bid2 - Out[10]: True - - In [12]: try: - ....: os.unlink(fname) - ....: except: - ....: pass - ....: - """ - - -def doctest_run_option_parser(): - r"""Test option parser in %run. - - In [1]: %run print_argv.py - [] - - In [2]: %run print_argv.py print*.py - ['print_argv.py'] - - In [3]: %run -G print_argv.py print*.py - ['print*.py'] - - """ - - -@dec.skip_win32 -def doctest_run_option_parser_for_posix(): - r"""Test option parser in %run (Linux/OSX specific). - - You need double quote to escape glob in POSIX systems: - - In [1]: %run print_argv.py print\\*.py - ['print*.py'] - - You can't use quote to escape glob in POSIX systems: - - In [2]: %run print_argv.py 'print*.py' - ['print_argv.py'] - - """ - - -doctest_run_option_parser_for_posix.__skip_doctest__ = sys.platform == "win32" - - -@dec.skip_if_not_win32 -def doctest_run_option_parser_for_windows(): - r"""Test option parser in %run (Windows specific). - - In Windows, you can't escape ``*` `by backslash: - - In [1]: %run print_argv.py print\\*.py - ['print\\\\*.py'] - - You can use quote to escape glob: - - In [2]: %run print_argv.py 'print*.py' - ["'print*.py'"] - - """ - - -doctest_run_option_parser_for_windows.__skip_doctest__ = sys.platform != "win32" - - -def doctest_reset_del(): - """Test that resetting doesn't cause errors in __del__ methods. - - In [2]: class A(object): - ...: def __del__(self): - ...: print(str("Hi")) - ...: - - In [3]: a = A() - - In [4]: get_ipython().reset(); import gc; x = gc.collect(0) - Hi - - In [5]: 1+1 - Out[5]: 2 - """ - -# For some tests, it will be handy to organize them in a class with a common -# setup that makes a temp file - -class TestMagicRunPass(tt.TempFileMixin): - - def setUp(self): - content = "a = [1,2,3]\nb = 1" - self.mktmp(content) - - def run_tmpfile(self): - _ip = get_ipython() - # This fails on Windows if self.tmpfile.name has spaces or "~" in it. - # See below and ticket https://bugs.launchpad.net/bugs/366353 - _ip.run_line_magic("run", self.fname) - - def run_tmpfile_p(self): - _ip = get_ipython() - # This fails on Windows if self.tmpfile.name has spaces or "~" in it. - # See below and ticket https://bugs.launchpad.net/bugs/366353 - _ip.run_line_magic("run", "-p %s" % self.fname) - - def test_builtins_id(self): - """Check that %run doesn't damage __builtins__ """ - _ip = get_ipython() - # Test that the id of __builtins__ is not modified by %run - bid1 = id(_ip.user_ns['__builtins__']) - self.run_tmpfile() - bid2 = id(_ip.user_ns['__builtins__']) - assert bid1 == bid2 - - def test_builtins_type(self): - """Check that the type of __builtins__ doesn't change with %run. - - However, the above could pass if __builtins__ was already modified to - be a dict (it should be a module) by a previous use of %run. So we - also check explicitly that it really is a module: - """ - _ip = get_ipython() - self.run_tmpfile() - assert type(_ip.user_ns["__builtins__"]) == type(sys) - - def test_run_profile(self): - """Test that the option -p, which invokes the profiler, do not - crash by invoking execfile""" - self.run_tmpfile_p() - - def test_run_debug_twice(self): - # https://github.com/ipython/ipython/issues/10028 - _ip = get_ipython() - with tt.fake_input(["c"]): - _ip.run_line_magic("run", "-d %s" % self.fname) - with tt.fake_input(["c"]): - _ip.run_line_magic("run", "-d %s" % self.fname) - - def test_run_debug_twice_with_breakpoint(self): - """Make a valid python temp file.""" - _ip = get_ipython() - with tt.fake_input(["b 2", "c", "c"]): - _ip.run_line_magic("run", "-d %s" % self.fname) - - with tt.fake_input(["c"]): - with tt.AssertNotPrints("KeyError"): - _ip.run_line_magic("run", "-d %s" % self.fname) - - -class TestMagicRunSimple(tt.TempFileMixin): - - def test_simpledef(self): - """Test that simple class definitions work.""" - src = ("class foo: pass\n" - "def f(): return foo()") - self.mktmp(src) - _ip.run_line_magic("run", str(self.fname)) - _ip.run_cell("t = isinstance(f(), foo)") - assert _ip.user_ns["t"] is True - - @pytest.mark.xfail( - platform.python_implementation() == "PyPy", - reason="expecting __del__ call on exit is unreliable and doesn't happen on PyPy", - ) - def test_obj_del(self): - """Test that object's __del__ methods are called on exit.""" - src = ("class A(object):\n" - " def __del__(self):\n" - " print('object A deleted')\n" - "a = A()\n") - self.mktmp(src) - err = None - tt.ipexec_validate(self.fname, 'object A deleted', err) - - def test_aggressive_namespace_cleanup(self): - """Test that namespace cleanup is not too aggressive GH-238 - - Returning from another run magic deletes the namespace""" - # see ticket https://github.com/ipython/ipython/issues/238 - - with tt.TempFileMixin() as empty: - empty.mktmp("") - # On Windows, the filename will have \users in it, so we need to use the - # repr so that the \u becomes \\u. - src = ( - "ip = get_ipython()\n" - "for i in range(5):\n" - " try:\n" - " ip.run_line_magic(%r, %r)\n" - " except NameError as e:\n" - " print(i)\n" - " break\n" % ("run", empty.fname) - ) - self.mktmp(src) - _ip.run_line_magic("run", str(self.fname)) - _ip.run_cell("ip == get_ipython()") - assert _ip.user_ns["i"] == 4 - - def test_run_second(self): - """Test that running a second file doesn't clobber the first, gh-3547""" - self.mktmp("avar = 1\n" "def afunc():\n" " return avar\n") - - with tt.TempFileMixin() as empty: - empty.mktmp("") - - _ip.run_line_magic("run", self.fname) - _ip.run_line_magic("run", empty.fname) - assert _ip.user_ns["afunc"]() == 1 - - def test_tclass(self): - mydir = os.path.dirname(__file__) - tc = os.path.join(mydir, "tclass") - src = f"""\ -import gc -%run "{tc}" C-first -gc.collect(0) -%run "{tc}" C-second -gc.collect(0) -%run "{tc}" C-third -gc.collect(0) -%reset -f -""" - self.mktmp(src, ".ipy") - out = """\ -ARGV 1-: ['C-first'] -ARGV 1-: ['C-second'] -tclass.py: deleting object: C-first -ARGV 1-: ['C-third'] -tclass.py: deleting object: C-second -tclass.py: deleting object: C-third -""" - err = None - tt.ipexec_validate(self.fname, out, err) - - def test_run_i_after_reset(self): - """Check that %run -i still works after %reset (gh-693)""" - src = "yy = zz\n" - self.mktmp(src) - _ip.run_cell("zz = 23") - try: - _ip.run_line_magic("run", "-i %s" % self.fname) - assert _ip.user_ns["yy"] == 23 - finally: - _ip.run_line_magic("reset", "-f") - - _ip.run_cell("zz = 23") - try: - _ip.run_line_magic("run", "-i %s" % self.fname) - assert _ip.user_ns["yy"] == 23 - finally: - _ip.run_line_magic("reset", "-f") - - def test_unicode(self): - """Check that files in odd encodings are accepted.""" - mydir = os.path.dirname(__file__) - na = os.path.join(mydir, "nonascii.py") - _ip.run_line_magic("run", na) - assert _ip.user_ns["u"] == "Ўт№Ф" - - def test_run_py_file_attribute(self): - """Test handling of `__file__` attribute in `%run .py`.""" - src = "t = __file__\n" - self.mktmp(src) - _missing = object() - file1 = _ip.user_ns.get("__file__", _missing) - _ip.run_line_magic("run", self.fname) - file2 = _ip.user_ns.get("__file__", _missing) - - # Check that __file__ was equal to the filename in the script's - # namespace. - assert _ip.user_ns["t"] == self.fname - - # Check that __file__ was not leaked back into user_ns. - assert file1 == file2 - - def test_run_ipy_file_attribute(self): - """Test handling of `__file__` attribute in `%run `.""" - src = "t = __file__\n" - self.mktmp(src, ext='.ipy') - _missing = object() - file1 = _ip.user_ns.get("__file__", _missing) - _ip.run_line_magic("run", self.fname) - file2 = _ip.user_ns.get("__file__", _missing) - - # Check that __file__ was equal to the filename in the script's - # namespace. - assert _ip.user_ns["t"] == self.fname - - # Check that __file__ was not leaked back into user_ns. - assert file1 == file2 - - def test_run_formatting(self): - """ Test that %run -t -N does not raise a TypeError for N > 1.""" - src = "pass" - self.mktmp(src) - _ip.run_line_magic("run", "-t -N 1 %s" % self.fname) - _ip.run_line_magic("run", "-t -N 10 %s" % self.fname) - - def test_ignore_sys_exit(self): - """Test the -e option to ignore sys.exit()""" - src = "import sys; sys.exit(1)" - self.mktmp(src) - with tt.AssertPrints("SystemExit"): - _ip.run_line_magic("run", self.fname) - - with tt.AssertNotPrints("SystemExit"): - _ip.run_line_magic("run", "-e %s" % self.fname) - - def test_run_nb(self): - """Test %run notebook.ipynb""" - pytest.importorskip("nbformat") - from nbformat import v4, writes - nb = v4.new_notebook( - cells=[ - v4.new_markdown_cell("The Ultimate Question of Everything"), - v4.new_code_cell("answer=42") - ] - ) - src = writes(nb, version=4) - self.mktmp(src, ext='.ipynb') - - _ip.run_line_magic("run", self.fname) - - assert _ip.user_ns["answer"] == 42 - - def test_run_nb_error(self): - """Test %run notebook.ipynb error""" - pytest.importorskip("nbformat") - from nbformat import v4, writes - - # %run when a file name isn't provided - pytest.raises(Exception, _ip.magic, "run") - - # %run when a file doesn't exist - pytest.raises(Exception, _ip.magic, "run foobar.ipynb") - - # %run on a notebook with an error - nb = v4.new_notebook( - cells=[ - v4.new_code_cell("0/0") - ] - ) - src = writes(nb, version=4) - self.mktmp(src, ext='.ipynb') - pytest.raises(Exception, _ip.magic, "run %s" % self.fname) - - def test_file_options(self): - src = ('import sys\n' - 'a = " ".join(sys.argv[1:])\n') - self.mktmp(src) - test_opts = "-x 3 --verbose" - _ip.run_line_magic("run", "{0} {1}".format(self.fname, test_opts)) - assert _ip.user_ns["a"] == test_opts - - -class TestMagicRunWithPackage(unittest.TestCase): - - def writefile(self, name, content): - path = os.path.join(self.tempdir.name, name) - d = os.path.dirname(path) - if not os.path.isdir(d): - os.makedirs(d) - with open(path, "w", encoding="utf-8") as f: - f.write(textwrap.dedent(content)) - - def setUp(self): - self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)])) - """Temporary (probably) valid python package name.""" - - self.value = int(random.random() * 10000) - - self.tempdir = TemporaryDirectory() - self.__orig_cwd = os.getcwd() - sys.path.insert(0, self.tempdir.name) - - self.writefile(os.path.join(package, '__init__.py'), '') - self.writefile(os.path.join(package, 'sub.py'), """ - x = {0!r} - """.format(self.value)) - self.writefile(os.path.join(package, 'relative.py'), """ - from .sub import x - """) - self.writefile(os.path.join(package, 'absolute.py'), """ - from {0}.sub import x - """.format(package)) - self.writefile(os.path.join(package, 'args.py'), """ - import sys - a = " ".join(sys.argv[1:]) - """.format(package)) - - def tearDown(self): - os.chdir(self.__orig_cwd) - sys.path[:] = [p for p in sys.path if p != self.tempdir.name] - self.tempdir.cleanup() - - def check_run_submodule(self, submodule, opts=""): - _ip.user_ns.pop("x", None) - _ip.run_line_magic( - "run", "{2} -m {0}.{1}".format(self.package, submodule, opts) - ) - self.assertEqual( - _ip.user_ns["x"], - self.value, - "Variable `x` is not loaded from module `{0}`.".format(submodule), - ) - - def test_run_submodule_with_absolute_import(self): - self.check_run_submodule('absolute') - - def test_run_submodule_with_relative_import(self): - """Run submodule that has a relative import statement (#2727).""" - self.check_run_submodule('relative') - - def test_prun_submodule_with_absolute_import(self): - self.check_run_submodule('absolute', '-p') - - def test_prun_submodule_with_relative_import(self): - self.check_run_submodule('relative', '-p') - - def with_fake_debugger(func): - @functools.wraps(func) - def wrapper(*args, **kwds): - with patch.object(debugger.Pdb, 'run', staticmethod(eval)): - return func(*args, **kwds) - return wrapper - - @with_fake_debugger - def test_debug_run_submodule_with_absolute_import(self): - self.check_run_submodule('absolute', '-d') - - @with_fake_debugger - def test_debug_run_submodule_with_relative_import(self): - self.check_run_submodule('relative', '-d') - - def test_module_options(self): - _ip.user_ns.pop("a", None) - test_opts = "-x abc -m test" - _ip.run_line_magic("run", "-m {0}.args {1}".format(self.package, test_opts)) - assert _ip.user_ns["a"] == test_opts - - def test_module_options_with_separator(self): - _ip.user_ns.pop("a", None) - test_opts = "-x abc -m test" - _ip.run_line_magic("run", "-m {0}.args -- {1}".format(self.package, test_opts)) - assert _ip.user_ns["a"] == test_opts - - -def test_run__name__(): - with TemporaryDirectory() as td: - path = pjoin(td, "foo.py") - with open(path, "w", encoding="utf-8") as f: - f.write("q = __name__") - - _ip.user_ns.pop("q", None) - _ip.run_line_magic("run", "{}".format(path)) - assert _ip.user_ns.pop("q") == "__main__" - - _ip.run_line_magic("run", "-n {}".format(path)) - assert _ip.user_ns.pop("q") == "foo" - - try: - _ip.run_line_magic("run", "-i -n {}".format(path)) - assert _ip.user_ns.pop("q") == "foo" - finally: - _ip.run_line_magic("reset", "-f") - - -def test_run_tb(): - """Test traceback offset in %run""" - with TemporaryDirectory() as td: - path = pjoin(td, "foo.py") - with open(path, "w", encoding="utf-8") as f: - f.write( - "\n".join( - [ - "def foo():", - " return bar()", - "def bar():", - " raise RuntimeError('hello!')", - "foo()", - ] - ) - ) - with capture_output() as io: - _ip.run_line_magic("run", "{}".format(path)) - out = io.stdout - assert "execfile" not in out - assert "RuntimeError" in out - assert out.count("---->") == 3 - del ip.user_ns['bar'] - del ip.user_ns['foo'] - - -def test_multiprocessing_run(): - """Set we can run mutiprocesgin without messing up up main namespace - - Note that import `nose.tools as nt` modify the values - sys.module['__mp_main__'] so we need to temporarily set it to None to test - the issue. - """ - with TemporaryDirectory() as td: - mpm = sys.modules.get('__mp_main__') - sys.modules['__mp_main__'] = None - try: - path = pjoin(td, "test.py") - with open(path, "w", encoding="utf-8") as f: - f.write("import multiprocessing\nprint('hoy')") - with capture_output() as io: - _ip.run_line_magic('run', path) - _ip.run_cell("i_m_undefined") - out = io.stdout - assert "hoy" in out - assert "AttributeError" not in out - assert "NameError" in out - assert out.count("---->") == 1 - except: - raise - finally: - sys.modules['__mp_main__'] = mpm - - -def test_script_tb(): - """Test traceback offset in `ipython script.py`""" - with TemporaryDirectory() as td: - path = pjoin(td, "foo.py") - with open(path, "w", encoding="utf-8") as f: - f.write( - "\n".join( - [ - "def foo():", - " return bar()", - "def bar():", - " raise RuntimeError('hello!')", - "foo()", - ] - ) - ) - out, err = tt.ipexec(path) - assert "execfile" not in out - assert "RuntimeError" in out - assert out.count("---->") == 3 diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_shellapp.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_shellapp.py deleted file mode 100644 index 9f4f87b..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_shellapp.py +++ /dev/null @@ -1,56 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests for shellapp module. - -Authors -------- -* Bradley Froehle -""" -#----------------------------------------------------------------------------- -# Copyright (C) 2012 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -import unittest - -from IPython.testing import decorators as dec -from IPython.testing import tools as tt - - -class TestFileToRun(tt.TempFileMixin, unittest.TestCase): - """Test the behavior of the file_to_run parameter.""" - - def test_py_script_file_attribute(self): - """Test that `__file__` is set when running `ipython file.py`""" - src = "print(__file__)\n" - self.mktmp(src) - - err = None - tt.ipexec_validate(self.fname, self.fname, err) - - def test_ipy_script_file_attribute(self): - """Test that `__file__` is set when running `ipython file.ipy`""" - src = "print(__file__)\n" - self.mktmp(src, ext='.ipy') - - err = None - tt.ipexec_validate(self.fname, self.fname, err) - - # The commands option to ipexec_validate doesn't work on Windows, and it - # doesn't seem worth fixing - @dec.skip_win32 - def test_py_script_file_attribute_interactively(self): - """Test that `__file__` is not set after `ipython -i file.py`""" - src = "True\n" - self.mktmp(src) - - out, err = tt.ipexec( - self.fname, - options=["-i"], - commands=['"__file__" in globals()', "print(123)", "exit()"], - ) - assert "False" in out, f"Subprocess stderr:\n{err}\n-----" diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_splitinput.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_splitinput.py deleted file mode 100644 index f5fc53f..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_splitinput.py +++ /dev/null @@ -1,41 +0,0 @@ -# coding: utf-8 - -from IPython.core.splitinput import split_user_input, LineInfo - -import pytest - -tests = [ - ("x=1", ("", "", "x", "=1")), - ("?", ("", "?", "", "")), - ("??", ("", "??", "", "")), - (" ?", (" ", "?", "", "")), - (" ??", (" ", "??", "", "")), - ("??x", ("", "??", "x", "")), - ("?x=1", ("", "?", "x", "=1")), - ("!ls", ("", "!", "ls", "")), - (" !ls", (" ", "!", "ls", "")), - ("!!ls", ("", "!!", "ls", "")), - (" !!ls", (" ", "!!", "ls", "")), - (",ls", ("", ",", "ls", "")), - (";ls", ("", ";", "ls", "")), - (" ;ls", (" ", ";", "ls", "")), - ("f.g(x)", ("", "", "f.g", "(x)")), - ("f.g (x)", ("", "", "f.g", " (x)")), - ("?%hist1", ("", "?", "%hist1", "")), - ("?%%hist2", ("", "?", "%%hist2", "")), - ("??%hist3", ("", "??", "%hist3", "")), - ("??%%hist4", ("", "??", "%%hist4", "")), - ("?x*", ("", "?", "x*", "")), - ("Pérez Fernando", ("", "", "Pérez", " Fernando")), -] - - -@pytest.mark.parametrize("input, output", tests) -def test_split_user_input(input, output): - assert split_user_input(input) == output - - -def test_LineInfo(): - """Simple test for LineInfo construction and str()""" - linfo = LineInfo(" %cd /home") - assert str(linfo) == "LineInfo [ |%|cd|/home]" diff --git a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_ultratb.py b/.venv/lib/python3.12/site-packages/IPython/core/tests/test_ultratb.py deleted file mode 100644 index c8f5271..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/tests/test_ultratb.py +++ /dev/null @@ -1,457 +0,0 @@ -# encoding: utf-8 -"""Tests for IPython.core.ultratb -""" -import io -import os.path -import platform -import re -import sys -import traceback -import unittest -from textwrap import dedent - -from tempfile import TemporaryDirectory - -from IPython.core.ultratb import ColorTB, VerboseTB -from IPython.testing import tools as tt -from IPython.testing.decorators import onlyif_unicode_paths, skip_without -from IPython.utils.syspathcontext import prepended_to_syspath - -file_1 = """1 -2 -3 -def f(): - 1/0 -""" - -file_2 = """def f(): - 1/0 -""" - - -def recursionlimit(frames): - """ - decorator to set the recursion limit temporarily - """ - - def inner(test_function): - def wrapper(*args, **kwargs): - rl = sys.getrecursionlimit() - sys.setrecursionlimit(frames) - try: - return test_function(*args, **kwargs) - finally: - sys.setrecursionlimit(rl) - - return wrapper - - return inner - - -class ChangedPyFileTest(unittest.TestCase): - def test_changing_py_file(self): - """Traceback produced if the line where the error occurred is missing? - - https://github.com/ipython/ipython/issues/1456 - """ - with TemporaryDirectory() as td: - fname = os.path.join(td, "foo.py") - with open(fname, "w", encoding="utf-8") as f: - f.write(file_1) - - with prepended_to_syspath(td): - ip.run_cell("import foo") - - with tt.AssertPrints("ZeroDivisionError"): - ip.run_cell("foo.f()") - - # Make the file shorter, so the line of the error is missing. - with open(fname, "w", encoding="utf-8") as f: - f.write(file_2) - - # For some reason, this was failing on the *second* call after - # changing the file, so we call f() twice. - with tt.AssertNotPrints("Internal Python error", channel='stderr'): - with tt.AssertPrints("ZeroDivisionError"): - ip.run_cell("foo.f()") - with tt.AssertPrints("ZeroDivisionError"): - ip.run_cell("foo.f()") - -iso_8859_5_file = u'''# coding: iso-8859-5 - -def fail(): - """дбИЖ""" - 1/0 # дбИЖ -''' - -class NonAsciiTest(unittest.TestCase): - @onlyif_unicode_paths - def test_nonascii_path(self): - # Non-ascii directory name as well. - with TemporaryDirectory(suffix=u'é') as td: - fname = os.path.join(td, u"fooé.py") - with open(fname, "w", encoding="utf-8") as f: - f.write(file_1) - - with prepended_to_syspath(td): - ip.run_cell("import foo") - - with tt.AssertPrints("ZeroDivisionError"): - ip.run_cell("foo.f()") - - def test_iso8859_5(self): - with TemporaryDirectory() as td: - fname = os.path.join(td, 'dfghjkl.py') - - with io.open(fname, 'w', encoding='iso-8859-5') as f: - f.write(iso_8859_5_file) - - with prepended_to_syspath(td): - ip.run_cell("from dfghjkl import fail") - - with tt.AssertPrints("ZeroDivisionError"): - with tt.AssertPrints(u'дбИЖ', suppress=False): - ip.run_cell('fail()') - - def test_nonascii_msg(self): - cell = u"raise Exception('é')" - expected = u"Exception('é')" - ip.run_cell("%xmode plain") - with tt.AssertPrints(expected): - ip.run_cell(cell) - - ip.run_cell("%xmode verbose") - with tt.AssertPrints(expected): - ip.run_cell(cell) - - ip.run_cell("%xmode context") - with tt.AssertPrints(expected): - ip.run_cell(cell) - - ip.run_cell("%xmode minimal") - with tt.AssertPrints(u"Exception: é"): - ip.run_cell(cell) - - # Put this back into Context mode for later tests. - ip.run_cell("%xmode context") - -class NestedGenExprTestCase(unittest.TestCase): - """ - Regression test for the following issues: - https://github.com/ipython/ipython/issues/8293 - https://github.com/ipython/ipython/issues/8205 - """ - def test_nested_genexpr(self): - code = dedent( - """\ - class SpecificException(Exception): - pass - - def foo(x): - raise SpecificException("Success!") - - sum(sum(foo(x) for _ in [0]) for x in [0]) - """ - ) - with tt.AssertPrints('SpecificException: Success!', suppress=False): - ip.run_cell(code) - - -indentationerror_file = """if True: -zoom() -""" - -class IndentationErrorTest(unittest.TestCase): - def test_indentationerror_shows_line(self): - # See issue gh-2398 - with tt.AssertPrints("IndentationError"): - with tt.AssertPrints("zoom()", suppress=False): - ip.run_cell(indentationerror_file) - - with TemporaryDirectory() as td: - fname = os.path.join(td, "foo.py") - with open(fname, "w", encoding="utf-8") as f: - f.write(indentationerror_file) - - with tt.AssertPrints("IndentationError"): - with tt.AssertPrints("zoom()", suppress=False): - ip.run_line_magic("run", fname) - - -@skip_without("pandas") -def test_dynamic_code(): - code = """ - import pandas - df = pandas.DataFrame([]) - - # Important: only fails inside of an "exec" call: - exec("df.foobarbaz()") - """ - - with tt.AssertPrints("Could not get source"): - ip.run_cell(code) - - -se_file_1 = """1 -2 -7/ -""" - -se_file_2 = """7/ -""" - -class SyntaxErrorTest(unittest.TestCase): - - def test_syntaxerror_no_stacktrace_at_compile_time(self): - syntax_error_at_compile_time = """ -def foo(): - .. -""" - with tt.AssertPrints("SyntaxError"): - ip.run_cell(syntax_error_at_compile_time) - - with tt.AssertNotPrints("foo()"): - ip.run_cell(syntax_error_at_compile_time) - - def test_syntaxerror_stacktrace_when_running_compiled_code(self): - syntax_error_at_runtime = """ -def foo(): - eval("..") - -def bar(): - foo() - -bar() -""" - with tt.AssertPrints("SyntaxError"): - ip.run_cell(syntax_error_at_runtime) - # Assert syntax error during runtime generate stacktrace - with tt.AssertPrints(["foo()", "bar()"]): - ip.run_cell(syntax_error_at_runtime) - del ip.user_ns['bar'] - del ip.user_ns['foo'] - - def test_changing_py_file(self): - with TemporaryDirectory() as td: - fname = os.path.join(td, "foo.py") - with open(fname, "w", encoding="utf-8") as f: - f.write(se_file_1) - - with tt.AssertPrints(["7/", "SyntaxError"]): - ip.run_line_magic("run", fname) - - # Modify the file - with open(fname, "w", encoding="utf-8") as f: - f.write(se_file_2) - - # The SyntaxError should point to the correct line - with tt.AssertPrints(["7/", "SyntaxError"]): - ip.run_line_magic("run", fname) - - def test_non_syntaxerror(self): - # SyntaxTB may be called with an error other than a SyntaxError - # See e.g. gh-4361 - try: - raise ValueError('QWERTY') - except ValueError: - with tt.AssertPrints('QWERTY'): - ip.showsyntaxerror() - -import sys - -if platform.python_implementation() != "PyPy": - """ - New 3.9 Pgen Parser does not raise Memory error, except on failed malloc. - """ - class MemoryErrorTest(unittest.TestCase): - def test_memoryerror(self): - memoryerror_code = "(" * 200 + ")" * 200 - ip.run_cell(memoryerror_code) - - -class Python3ChainedExceptionsTest(unittest.TestCase): - DIRECT_CAUSE_ERROR_CODE = """ -try: - x = 1 + 2 - print(not_defined_here) -except Exception as e: - x += 55 - x - 1 - y = {} - raise KeyError('uh') from e - """ - - EXCEPTION_DURING_HANDLING_CODE = """ -try: - x = 1 + 2 - print(not_defined_here) -except Exception as e: - x += 55 - x - 1 - y = {} - raise KeyError('uh') - """ - - SUPPRESS_CHAINING_CODE = """ -try: - 1/0 -except Exception: - raise ValueError("Yikes") from None - """ - - SYS_EXIT_WITH_CONTEXT_CODE = """ -try: - 1/0 -except Exception as e: - raise SystemExit(1) - """ - - def test_direct_cause_error(self): - with tt.AssertPrints(["KeyError", "NameError", "direct cause"]): - ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE) - - def test_exception_during_handling_error(self): - with tt.AssertPrints(["KeyError", "NameError", "During handling"]): - ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE) - - def test_sysexit_while_handling_error(self): - with tt.AssertPrints(["SystemExit", "to see the full traceback"]): - with tt.AssertNotPrints(["another exception"], suppress=False): - ip.run_cell(self.SYS_EXIT_WITH_CONTEXT_CODE) - - def test_suppress_exception_chaining(self): - with tt.AssertNotPrints("ZeroDivisionError"), \ - tt.AssertPrints("ValueError", suppress=False): - ip.run_cell(self.SUPPRESS_CHAINING_CODE) - - def test_plain_direct_cause_error(self): - with tt.AssertPrints(["KeyError", "NameError", "direct cause"]): - ip.run_cell("%xmode Plain") - ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE) - ip.run_cell("%xmode Verbose") - - def test_plain_exception_during_handling_error(self): - with tt.AssertPrints(["KeyError", "NameError", "During handling"]): - ip.run_cell("%xmode Plain") - ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE) - ip.run_cell("%xmode Verbose") - - def test_plain_suppress_exception_chaining(self): - with tt.AssertNotPrints("ZeroDivisionError"), \ - tt.AssertPrints("ValueError", suppress=False): - ip.run_cell("%xmode Plain") - ip.run_cell(self.SUPPRESS_CHAINING_CODE) - ip.run_cell("%xmode Verbose") - - -class RecursionTest(unittest.TestCase): - DEFINITIONS = """ -def non_recurs(): - 1/0 - -def r1(): - r1() - -def r3a(): - r3b() - -def r3b(): - r3c() - -def r3c(): - r3a() - -def r3o1(): - r3a() - -def r3o2(): - r3o1() -""" - def setUp(self): - ip.run_cell(self.DEFINITIONS) - - def test_no_recursion(self): - with tt.AssertNotPrints("skipping similar frames"): - ip.run_cell("non_recurs()") - - @recursionlimit(200) - def test_recursion_one_frame(self): - with tt.AssertPrints(re.compile( - r"\[\.\.\. skipping similar frames: r1 at line 5 \(\d{2,3} times\)\]") - ): - ip.run_cell("r1()") - - @recursionlimit(160) - def test_recursion_three_frames(self): - with tt.AssertPrints("[... skipping similar frames: "), \ - tt.AssertPrints(re.compile(r"r3a at line 8 \(\d{2} times\)"), suppress=False), \ - tt.AssertPrints(re.compile(r"r3b at line 11 \(\d{2} times\)"), suppress=False), \ - tt.AssertPrints(re.compile(r"r3c at line 14 \(\d{2} times\)"), suppress=False): - ip.run_cell("r3o2()") - - -class PEP678NotesReportingTest(unittest.TestCase): - ERROR_WITH_NOTE = """ -try: - raise AssertionError("Message") -except Exception as e: - try: - e.add_note("This is a PEP-678 note.") - except AttributeError: # Python <= 3.10 - e.__notes__ = ("This is a PEP-678 note.",) - raise - """ - - def test_verbose_reports_notes(self): - with tt.AssertPrints(["AssertionError", "Message", "This is a PEP-678 note."]): - ip.run_cell(self.ERROR_WITH_NOTE) - - def test_plain_reports_notes(self): - with tt.AssertPrints(["AssertionError", "Message", "This is a PEP-678 note."]): - ip.run_cell("%xmode Plain") - ip.run_cell(self.ERROR_WITH_NOTE) - ip.run_cell("%xmode Verbose") - - -#---------------------------------------------------------------------------- - -# module testing (minimal) -def test_handlers(): - def spam(c, d_e): - (d, e) = d_e - x = c + d - y = c * d - foo(x, y) - - def foo(a, b, bar=1): - eggs(a, b + bar) - - def eggs(f, g, z=globals()): - h = f + g - i = f - g - return h / i - - buff = io.StringIO() - - buff.write('') - buff.write('*** Before ***') - try: - buff.write(spam(1, (2, 3))) - except: - traceback.print_exc(file=buff) - - handler = ColorTB(ostream=buff) - buff.write('*** ColorTB ***') - try: - buff.write(spam(1, (2, 3))) - except: - handler(*sys.exc_info()) - buff.write('') - - handler = VerboseTB(ostream=buff) - buff.write('*** VerboseTB ***') - try: - buff.write(spam(1, (2, 3))) - except: - handler(*sys.exc_info()) - buff.write('') diff --git a/.venv/lib/python3.12/site-packages/IPython/core/ultratb.py b/.venv/lib/python3.12/site-packages/IPython/core/ultratb.py deleted file mode 100644 index a8a38f1..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/ultratb.py +++ /dev/null @@ -1,1547 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Verbose and colourful traceback formatting. - -**ColorTB** - -I've always found it a bit hard to visually parse tracebacks in Python. The -ColorTB class is a solution to that problem. It colors the different parts of a -traceback in a manner similar to what you would expect from a syntax-highlighting -text editor. - -Installation instructions for ColorTB:: - - import sys,ultratb - sys.excepthook = ultratb.ColorTB() - -**VerboseTB** - -I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds -of useful info when a traceback occurs. Ping originally had it spit out HTML -and intended it for CGI programmers, but why should they have all the fun? I -altered it to spit out colored text to the terminal. It's a bit overwhelming, -but kind of neat, and maybe useful for long-running programs that you believe -are bug-free. If a crash *does* occur in that type of program you want details. -Give it a shot--you'll love it or you'll hate it. - -.. note:: - - The Verbose mode prints the variables currently visible where the exception - happened (shortening their strings if too long). This can potentially be - very slow, if you happen to have a huge data structure whose string - representation is complex to compute. Your computer may appear to freeze for - a while with cpu usage at 100%. If this occurs, you can cancel the traceback - with Ctrl-C (maybe hitting it more than once). - - If you encounter this kind of situation often, you may want to use the - Verbose_novars mode instead of the regular Verbose, which avoids formatting - variables (but otherwise includes the information and context given by - Verbose). - -.. note:: - - The verbose mode print all variables in the stack, which means it can - potentially leak sensitive information like access keys, or unencrypted - password. - -Installation instructions for VerboseTB:: - - import sys,ultratb - sys.excepthook = ultratb.VerboseTB() - -Note: Much of the code in this module was lifted verbatim from the standard -library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'. - -Color schemes -------------- - -The colors are defined in the class TBTools through the use of the -ColorSchemeTable class. Currently the following exist: - - - NoColor: allows all of this module to be used in any terminal (the color - escapes are just dummy blank strings). - - - Linux: is meant to look good in a terminal like the Linux console (black - or very dark background). - - - LightBG: similar to Linux but swaps dark/light colors to be more readable - in light background terminals. - - - Neutral: a neutral color scheme that should be readable on both light and - dark background - -You can implement other color schemes easily, the syntax is fairly -self-explanatory. Please send back new schemes you develop to the author for -possible inclusion in future releases. - -Inheritance diagram: - -.. inheritance-diagram:: IPython.core.ultratb - :parts: 3 -""" - -#***************************************************************************** -# Copyright (C) 2001 Nathaniel Gray -# Copyright (C) 2001-2004 Fernando Perez -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - - -from collections.abc import Sequence -import functools -import inspect -import linecache -import pydoc -import sys -import time -import traceback -import types -from types import TracebackType -from typing import Any, List, Optional, Tuple - -import stack_data -from pygments.formatters.terminal256 import Terminal256Formatter -from pygments.styles import get_style_by_name - -import IPython.utils.colorable as colorable -# IPython's own modules -from IPython import get_ipython -from IPython.core import debugger -from IPython.core.display_trap import DisplayTrap -from IPython.core.excolors import exception_colors -from IPython.utils import PyColorize -from IPython.utils import path as util_path -from IPython.utils import py3compat -from IPython.utils.terminal import get_terminal_size - -# Globals -# amount of space to put line numbers before verbose tracebacks -INDENT_SIZE = 8 - -# Default color scheme. This is used, for example, by the traceback -# formatter. When running in an actual IPython instance, the user's rc.colors -# value is used, but having a module global makes this functionality available -# to users of ultratb who are NOT running inside ipython. -DEFAULT_SCHEME = 'NoColor' -FAST_THRESHOLD = 10_000 - -# --------------------------------------------------------------------------- -# Code begins - -# Helper function -- largely belongs to VerboseTB, but we need the same -# functionality to produce a pseudo verbose TB for SyntaxErrors, so that they -# can be recognized properly by ipython.el's py-traceback-line-re -# (SyntaxErrors have to be treated specially because they have no traceback) - - -@functools.lru_cache() -def count_lines_in_py_file(filename: str) -> int: - """ - Given a filename, returns the number of lines in the file - if it ends with the extension ".py". Otherwise, returns 0. - """ - if not filename.endswith(".py"): - return 0 - else: - try: - with open(filename, "r") as file: - s = sum(1 for line in file) - except UnicodeError: - return 0 - return s - - """ - Given a frame object, returns the total number of lines in the file - if the filename ends with the extension ".py". Otherwise, returns 0. - """ - - -def get_line_number_of_frame(frame: types.FrameType) -> int: - """ - Given a frame object, returns the total number of lines in the file - containing the frame's code object, or the number of lines in the - frame's source code if the file is not available. - - Parameters - ---------- - frame : FrameType - The frame object whose line number is to be determined. - - Returns - ------- - int - The total number of lines in the file containing the frame's - code object, or the number of lines in the frame's source code - if the file is not available. - """ - filename = frame.f_code.co_filename - if filename is None: - print("No file....") - lines, first = inspect.getsourcelines(frame) - return first + len(lines) - return count_lines_in_py_file(filename) - - -def _safe_string(value, what, func=str): - # Copied from cpython/Lib/traceback.py - try: - return func(value) - except: - return f"<{what} {func.__name__}() failed>" - - -def _format_traceback_lines(lines, Colors, has_colors: bool, lvals): - """ - Format tracebacks lines with pointing arrow, leading numbers... - - Parameters - ---------- - lines : list[Line] - Colors - ColorScheme used. - lvals : str - Values of local variables, already colored, to inject just after the error line. - """ - numbers_width = INDENT_SIZE - 1 - res = [] - - for stack_line in lines: - if stack_line is stack_data.LINE_GAP: - res.append('%s (...)%s\n' % (Colors.linenoEm, Colors.Normal)) - continue - - line = stack_line.render(pygmented=has_colors).rstrip('\n') + '\n' - lineno = stack_line.lineno - if stack_line.is_current: - # This is the line with the error - pad = numbers_width - len(str(lineno)) - num = '%s%s' % (debugger.make_arrow(pad), str(lineno)) - start_color = Colors.linenoEm - else: - num = '%*s' % (numbers_width, lineno) - start_color = Colors.lineno - - line = '%s%s%s %s' % (start_color, num, Colors.Normal, line) - - res.append(line) - if lvals and stack_line.is_current: - res.append(lvals + '\n') - return res - -def _simple_format_traceback_lines(lnum, index, lines, Colors, lvals, _line_format): - """ - Format tracebacks lines with pointing arrow, leading numbers... - - Parameters - ========== - - lnum: int - number of the target line of code. - index: int - which line in the list should be highlighted. - lines: list[string] - Colors: - ColorScheme used. - lvals: bytes - Values of local variables, already colored, to inject just after the error line. - _line_format: f (str) -> (str, bool) - return (colorized version of str, failure to do so) - """ - numbers_width = INDENT_SIZE - 1 - res = [] - for i, line in enumerate(lines, lnum - index): - # assert isinstance(line, str) - line = py3compat.cast_unicode(line) - - new_line, err = _line_format(line, "str") - if not err: - line = new_line - - if i == lnum: - # This is the line with the error - pad = numbers_width - len(str(i)) - num = "%s%s" % (debugger.make_arrow(pad), str(lnum)) - line = "%s%s%s %s%s" % ( - Colors.linenoEm, - num, - Colors.line, - line, - Colors.Normal, - ) - else: - num = "%*s" % (numbers_width, i) - line = "%s%s%s %s" % (Colors.lineno, num, Colors.Normal, line) - - res.append(line) - if lvals and i == lnum: - res.append(lvals + "\n") - return res - - -def _format_filename(file, ColorFilename, ColorNormal, *, lineno=None): - """ - Format filename lines with custom formatting from caching compiler or `File *.py` by default - - Parameters - ---------- - file : str - ColorFilename - ColorScheme's filename coloring to be used. - ColorNormal - ColorScheme's normal coloring to be used. - """ - ipinst = get_ipython() - if ( - ipinst is not None - and (data := ipinst.compile.format_code_name(file)) is not None - ): - label, name = data - if lineno is None: - tpl_link = f"{{label}} {ColorFilename}{{name}}{ColorNormal}" - else: - tpl_link = ( - f"{{label}} {ColorFilename}{{name}}, line {{lineno}}{ColorNormal}" - ) - else: - label = "File" - name = util_path.compress_user( - py3compat.cast_unicode(file, util_path.fs_encoding) - ) - if lineno is None: - tpl_link = f"{{label}} {ColorFilename}{{name}}{ColorNormal}" - else: - # can we make this the more friendly ", line {{lineno}}", or do we need to preserve the formatting with the colon? - tpl_link = f"{{label}} {ColorFilename}{{name}}:{{lineno}}{ColorNormal}" - - return tpl_link.format(label=label, name=name, lineno=lineno) - -#--------------------------------------------------------------------------- -# Module classes -class TBTools(colorable.Colorable): - """Basic tools used by all traceback printer classes.""" - - # Number of frames to skip when reporting tracebacks - tb_offset = 0 - - def __init__( - self, - color_scheme="NoColor", - call_pdb=False, - ostream=None, - parent=None, - config=None, - *, - debugger_cls=None, - ): - # Whether to call the interactive pdb debugger after printing - # tracebacks or not - super(TBTools, self).__init__(parent=parent, config=config) - self.call_pdb = call_pdb - - # Output stream to write to. Note that we store the original value in - # a private attribute and then make the public ostream a property, so - # that we can delay accessing sys.stdout until runtime. The way - # things are written now, the sys.stdout object is dynamically managed - # so a reference to it should NEVER be stored statically. This - # property approach confines this detail to a single location, and all - # subclasses can simply access self.ostream for writing. - self._ostream = ostream - - # Create color table - self.color_scheme_table = exception_colors() - - self.set_colors(color_scheme) - self.old_scheme = color_scheme # save initial value for toggles - self.debugger_cls = debugger_cls or debugger.Pdb - - if call_pdb: - self.pdb = self.debugger_cls() - else: - self.pdb = None - - def _get_ostream(self): - """Output stream that exceptions are written to. - - Valid values are: - - - None: the default, which means that IPython will dynamically resolve - to sys.stdout. This ensures compatibility with most tools, including - Windows (where plain stdout doesn't recognize ANSI escapes). - - - Any object with 'write' and 'flush' attributes. - """ - return sys.stdout if self._ostream is None else self._ostream - - def _set_ostream(self, val): - assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush')) - self._ostream = val - - ostream = property(_get_ostream, _set_ostream) - - @staticmethod - def _get_chained_exception(exception_value): - cause = getattr(exception_value, "__cause__", None) - if cause: - return cause - if getattr(exception_value, "__suppress_context__", False): - return None - return getattr(exception_value, "__context__", None) - - def get_parts_of_chained_exception( - self, evalue - ) -> Optional[Tuple[type, BaseException, TracebackType]]: - chained_evalue = self._get_chained_exception(evalue) - - if chained_evalue: - return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__ - return None - - def prepare_chained_exception_message(self, cause) -> List[Any]: - direct_cause = "\nThe above exception was the direct cause of the following exception:\n" - exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n" - - if cause: - message = [[direct_cause]] - else: - message = [[exception_during_handling]] - return message - - @property - def has_colors(self) -> bool: - return self.color_scheme_table.active_scheme_name.lower() != "nocolor" - - def set_colors(self, *args, **kw): - """Shorthand access to the color table scheme selector method.""" - - # Set own color table - self.color_scheme_table.set_active_scheme(*args, **kw) - # for convenience, set Colors to the active scheme - self.Colors = self.color_scheme_table.active_colors - # Also set colors of debugger - if hasattr(self, 'pdb') and self.pdb is not None: - self.pdb.set_colors(*args, **kw) - - def color_toggle(self): - """Toggle between the currently active color scheme and NoColor.""" - - if self.color_scheme_table.active_scheme_name == 'NoColor': - self.color_scheme_table.set_active_scheme(self.old_scheme) - self.Colors = self.color_scheme_table.active_colors - else: - self.old_scheme = self.color_scheme_table.active_scheme_name - self.color_scheme_table.set_active_scheme('NoColor') - self.Colors = self.color_scheme_table.active_colors - - def stb2text(self, stb): - """Convert a structured traceback (a list) to a string.""" - return '\n'.join(stb) - - def text(self, etype, value, tb, tb_offset: Optional[int] = None, context=5): - """Return formatted traceback. - - Subclasses may override this if they add extra arguments. - """ - tb_list = self.structured_traceback(etype, value, tb, - tb_offset, context) - return self.stb2text(tb_list) - - def structured_traceback( - self, - etype: type, - evalue: Optional[BaseException], - etb: Optional[TracebackType] = None, - tb_offset: Optional[int] = None, - number_of_lines_of_context: int = 5, - ): - """Return a list of traceback frames. - - Must be implemented by each class. - """ - raise NotImplementedError() - - -#--------------------------------------------------------------------------- -class ListTB(TBTools): - """Print traceback information from a traceback list, with optional color. - - Calling requires 3 arguments: (etype, evalue, elist) - as would be obtained by:: - - etype, evalue, tb = sys.exc_info() - if tb: - elist = traceback.extract_tb(tb) - else: - elist = None - - It can thus be used by programs which need to process the traceback before - printing (such as console replacements based on the code module from the - standard library). - - Because they are meant to be called without a full traceback (only a - list), instances of this class can't call the interactive pdb debugger.""" - - - def __call__(self, etype, value, elist): - self.ostream.flush() - self.ostream.write(self.text(etype, value, elist)) - self.ostream.write('\n') - - def _extract_tb(self, tb): - if tb: - return traceback.extract_tb(tb) - else: - return None - - def structured_traceback( - self, - etype: type, - evalue: Optional[BaseException], - etb: Optional[TracebackType] = None, - tb_offset: Optional[int] = None, - context=5, - ): - """Return a color formatted string with the traceback info. - - Parameters - ---------- - etype : exception type - Type of the exception raised. - evalue : object - Data stored in the exception - etb : list | TracebackType | None - If list: List of frames, see class docstring for details. - If Traceback: Traceback of the exception. - tb_offset : int, optional - Number of frames in the traceback to skip. If not given, the - instance evalue is used (set in constructor). - context : int, optional - Number of lines of context information to print. - - Returns - ------- - String with formatted exception. - """ - # This is a workaround to get chained_exc_ids in recursive calls - # etb should not be a tuple if structured_traceback is not recursive - if isinstance(etb, tuple): - etb, chained_exc_ids = etb - else: - chained_exc_ids = set() - - if isinstance(etb, list): - elist = etb - elif etb is not None: - elist = self._extract_tb(etb) - else: - elist = [] - tb_offset = self.tb_offset if tb_offset is None else tb_offset - assert isinstance(tb_offset, int) - Colors = self.Colors - out_list = [] - if elist: - - if tb_offset and len(elist) > tb_offset: - elist = elist[tb_offset:] - - out_list.append('Traceback %s(most recent call last)%s:' % - (Colors.normalEm, Colors.Normal) + '\n') - out_list.extend(self._format_list(elist)) - # The exception info should be a single entry in the list. - lines = ''.join(self._format_exception_only(etype, evalue)) - out_list.append(lines) - - # Find chained exceptions if we have a traceback (not for exception-only mode) - if etb is not None: - exception = self.get_parts_of_chained_exception(evalue) - - if exception and (id(exception[1]) not in chained_exc_ids): - chained_exception_message = ( - self.prepare_chained_exception_message(evalue.__cause__)[0] - if evalue is not None - else "" - ) - etype, evalue, etb = exception - # Trace exception to avoid infinite 'cause' loop - chained_exc_ids.add(id(exception[1])) - chained_exceptions_tb_offset = 0 - out_list = ( - self.structured_traceback( - etype, - evalue, - (etb, chained_exc_ids), # type: ignore - chained_exceptions_tb_offset, - context, - ) - + chained_exception_message - + out_list - ) - - return out_list - - def _format_list(self, extracted_list): - """Format a list of traceback entry tuples for printing. - - Given a list of tuples as returned by extract_tb() or - extract_stack(), return a list of strings ready for printing. - Each string in the resulting list corresponds to the item with the - same index in the argument list. Each string ends in a newline; - the strings may contain internal newlines as well, for those items - whose source text line is not None. - - Lifted almost verbatim from traceback.py - """ - - Colors = self.Colors - output_list = [] - for ind, (filename, lineno, name, line) in enumerate(extracted_list): - normalCol, nameCol, fileCol, lineCol = ( - # Emphasize the last entry - (Colors.normalEm, Colors.nameEm, Colors.filenameEm, Colors.line) - if ind == len(extracted_list) - 1 - else (Colors.Normal, Colors.name, Colors.filename, "") - ) - - fns = _format_filename(filename, fileCol, normalCol, lineno=lineno) - item = f"{normalCol} {fns}" - - if name != "": - item += f" in {nameCol}{name}{normalCol}\n" - else: - item += "\n" - if line: - item += f"{lineCol} {line.strip()}{normalCol}\n" - output_list.append(item) - - return output_list - - def _format_exception_only(self, etype, value): - """Format the exception part of a traceback. - - The arguments are the exception type and value such as given by - sys.exc_info()[:2]. The return value is a list of strings, each ending - in a newline. Normally, the list contains a single string; however, - for SyntaxError exceptions, it contains several lines that (when - printed) display detailed information about where the syntax error - occurred. The message indicating which exception occurred is the - always last string in the list. - - Also lifted nearly verbatim from traceback.py - """ - have_filedata = False - Colors = self.Colors - output_list = [] - stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal) - if value is None: - # Not sure if this can still happen in Python 2.6 and above - output_list.append(stype + "\n") - else: - if issubclass(etype, SyntaxError): - have_filedata = True - if not value.filename: value.filename = "" - if value.lineno: - lineno = value.lineno - textline = linecache.getline(value.filename, value.lineno) - else: - lineno = "unknown" - textline = "" - output_list.append( - "%s %s%s\n" - % ( - Colors.normalEm, - _format_filename( - value.filename, - Colors.filenameEm, - Colors.normalEm, - lineno=(None if lineno == "unknown" else lineno), - ), - Colors.Normal, - ) - ) - if textline == "": - textline = py3compat.cast_unicode(value.text, "utf-8") - - if textline is not None: - i = 0 - while i < len(textline) and textline[i].isspace(): - i += 1 - output_list.append( - "%s %s%s\n" % (Colors.line, textline.strip(), Colors.Normal) - ) - if value.offset is not None: - s = ' ' - for c in textline[i:value.offset - 1]: - if c.isspace(): - s += c - else: - s += " " - output_list.append( - "%s%s^%s\n" % (Colors.caret, s, Colors.Normal) - ) - - try: - s = value.msg - except Exception: - s = self._some_str(value) - if s: - output_list.append( - "%s%s:%s %s\n" % (stype, Colors.excName, Colors.Normal, s) - ) - else: - output_list.append("%s\n" % stype) - - # PEP-678 notes - output_list.extend(f"{x}\n" for x in getattr(value, "__notes__", [])) - - # sync with user hooks - if have_filedata: - ipinst = get_ipython() - if ipinst is not None: - ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0) - - return output_list - - def get_exception_only(self, etype, value): - """Only print the exception type and message, without a traceback. - - Parameters - ---------- - etype : exception type - value : exception value - """ - return ListTB.structured_traceback(self, etype, value) - - def show_exception_only(self, etype, evalue): - """Only print the exception type and message, without a traceback. - - Parameters - ---------- - etype : exception type - evalue : exception value - """ - # This method needs to use __call__ from *this* class, not the one from - # a subclass whose signature or behavior may be different - ostream = self.ostream - ostream.flush() - ostream.write('\n'.join(self.get_exception_only(etype, evalue))) - ostream.flush() - - def _some_str(self, value): - # Lifted from traceback.py - try: - return py3compat.cast_unicode(str(value)) - except: - return u'' % type(value).__name__ - - -class FrameInfo: - """ - Mirror of stack data's FrameInfo, but so that we can bypass highlighting on - really long frames. - """ - - description: Optional[str] - filename: Optional[str] - lineno: Tuple[int] - # number of context lines to use - context: Optional[int] - raw_lines: List[str] - - @classmethod - def _from_stack_data_FrameInfo(cls, frame_info): - return cls( - getattr(frame_info, "description", None), - getattr(frame_info, "filename", None), # type: ignore[arg-type] - getattr(frame_info, "lineno", None), # type: ignore[arg-type] - getattr(frame_info, "frame", None), - getattr(frame_info, "code", None), - sd=frame_info, - context=None, - ) - - def __init__( - self, - description: Optional[str], - filename: str, - lineno: Tuple[int], - frame, - code, - *, - sd=None, - context=None, - ): - self.description = description - self.filename = filename - self.lineno = lineno - self.frame = frame - self.code = code - self._sd = sd - self.context = context - - # self.lines = [] - if sd is None: - try: - # return a list of source lines and a starting line number - self.raw_lines = inspect.getsourcelines(frame)[0] - except OSError: - self.raw_lines = [ - "'Could not get source, probably due dynamically evaluated source code.'" - ] - - @property - def variables_in_executing_piece(self): - if self._sd: - return self._sd.variables_in_executing_piece - else: - return [] - - @property - def lines(self): - from executing.executing import NotOneValueFound - - try: - return self._sd.lines - except NotOneValueFound: - - class Dummy: - lineno = 0 - is_current = False - - def render(self, *, pygmented): - return "" - - return [Dummy()] - - @property - def executing(self): - if self._sd: - return self._sd.executing - else: - return None - - -# ---------------------------------------------------------------------------- -class VerboseTB(TBTools): - """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead - of HTML. Requires inspect and pydoc. Crazy, man. - - Modified version which optionally strips the topmost entries from the - traceback, to be used with alternate interpreters (because their own code - would appear in the traceback).""" - - tb_highlight = "bg:ansiyellow" - tb_highlight_style = "default" - - def __init__( - self, - color_scheme: str = "Linux", - call_pdb: bool = False, - ostream=None, - tb_offset: int = 0, - long_header: bool = False, - include_vars: bool = True, - check_cache=None, - debugger_cls=None, - parent=None, - config=None, - ): - """Specify traceback offset, headers and color scheme. - - Define how many frames to drop from the tracebacks. Calling it with - tb_offset=1 allows use of this handler in interpreters which will have - their own code at the top of the traceback (VerboseTB will first - remove that frame before printing the traceback info).""" - TBTools.__init__( - self, - color_scheme=color_scheme, - call_pdb=call_pdb, - ostream=ostream, - parent=parent, - config=config, - debugger_cls=debugger_cls, - ) - self.tb_offset = tb_offset - self.long_header = long_header - self.include_vars = include_vars - # By default we use linecache.checkcache, but the user can provide a - # different check_cache implementation. This was formerly used by the - # IPython kernel for interactive code, but is no longer necessary. - if check_cache is None: - check_cache = linecache.checkcache - self.check_cache = check_cache - - self.skip_hidden = True - - def format_record(self, frame_info: FrameInfo): - """Format a single stack frame""" - assert isinstance(frame_info, FrameInfo) - Colors = self.Colors # just a shorthand + quicker name lookup - ColorsNormal = Colors.Normal # used a lot - - if isinstance(frame_info._sd, stack_data.RepeatedFrames): - return ' %s[... skipping similar frames: %s]%s\n' % ( - Colors.excName, frame_info.description, ColorsNormal) - - indent = " " * INDENT_SIZE - em_normal = "%s\n%s%s" % (Colors.valEm, indent, ColorsNormal) - tpl_call = f"in {Colors.vName}{{file}}{Colors.valEm}{{scope}}{ColorsNormal}" - tpl_call_fail = "in %s%%s%s(***failed resolving arguments***)%s" % ( - Colors.vName, - Colors.valEm, - ColorsNormal, - ) - tpl_name_val = "%%s %s= %%s%s" % (Colors.valEm, ColorsNormal) - - link = _format_filename( - frame_info.filename, - Colors.filenameEm, - ColorsNormal, - lineno=frame_info.lineno, - ) - args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame) - if frame_info.executing is not None: - func = frame_info.executing.code_qualname() - else: - func = "?" - if func == "": - call = "" - else: - # Decide whether to include variable details or not - var_repr = eqrepr if self.include_vars else nullrepr - try: - scope = inspect.formatargvalues( - args, varargs, varkw, locals_, formatvalue=var_repr - ) - call = tpl_call.format(file=func, scope=scope) - except KeyError: - # This happens in situations like errors inside generator - # expressions, where local variables are listed in the - # line, but can't be extracted from the frame. I'm not - # 100% sure this isn't actually a bug in inspect itself, - # but since there's no info for us to compute with, the - # best we can do is report the failure and move on. Here - # we must *not* call any traceback construction again, - # because that would mess up use of %debug later on. So we - # simply report the failure and move on. The only - # limitation will be that this frame won't have locals - # listed in the call signature. Quite subtle problem... - # I can't think of a good way to validate this in a unit - # test, but running a script consisting of: - # dict( (k,v.strip()) for (k,v) in range(10) ) - # will illustrate the error, if this exception catch is - # disabled. - call = tpl_call_fail % func - - lvals = '' - lvals_list = [] - if self.include_vars: - try: - # we likely want to fix stackdata at some point, but - # still need a workaround. - fibp = frame_info.variables_in_executing_piece - for var in fibp: - lvals_list.append(tpl_name_val % (var.name, repr(var.value))) - except Exception: - lvals_list.append( - "Exception trying to inspect frame. No more locals available." - ) - if lvals_list: - lvals = '%s%s' % (indent, em_normal.join(lvals_list)) - - result = f'{link}{", " if call else ""}{call}\n' - if frame_info._sd is None: - # fast fallback if file is too long - tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal) - link = tpl_link % util_path.compress_user(frame_info.filename) - level = "%s %s\n" % (link, call) - _line_format = PyColorize.Parser( - style=self.color_scheme_table.active_scheme_name, parent=self - ).format2 - first_line = frame_info.code.co_firstlineno - current_line = frame_info.lineno[0] - raw_lines = frame_info.raw_lines - index = current_line - first_line - - if index >= frame_info.context: - start = max(index - frame_info.context, 0) - stop = index + frame_info.context - index = frame_info.context - else: - start = 0 - stop = index + frame_info.context - raw_lines = raw_lines[start:stop] - - return "%s%s" % ( - level, - "".join( - _simple_format_traceback_lines( - current_line, - index, - raw_lines, - Colors, - lvals, - _line_format, - ) - ), - ) - # result += "\n".join(frame_info.raw_lines) - else: - result += "".join( - _format_traceback_lines( - frame_info.lines, Colors, self.has_colors, lvals - ) - ) - return result - - def prepare_header(self, etype: str, long_version: bool = False): - colors = self.Colors # just a shorthand + quicker name lookup - colorsnormal = colors.Normal # used a lot - exc = '%s%s%s' % (colors.excName, etype, colorsnormal) - width = min(75, get_terminal_size()[0]) - if long_version: - # Header with the exception type, python version, and date - pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable - date = time.ctime(time.time()) - - head = "%s%s%s\n%s%s%s\n%s" % ( - colors.topline, - "-" * width, - colorsnormal, - exc, - " " * (width - len(etype) - len(pyver)), - pyver, - date.rjust(width), - ) - head += ( - "\nA problem occurred executing Python code. Here is the sequence of function" - "\ncalls leading up to the error, with the most recent (innermost) call last." - ) - else: - # Simplified header - head = "%s%s" % ( - exc, - "Traceback (most recent call last)".rjust(width - len(etype)), - ) - - return head - - def format_exception(self, etype, evalue): - colors = self.Colors # just a shorthand + quicker name lookup - colorsnormal = colors.Normal # used a lot - # Get (safely) a string form of the exception info - try: - etype_str, evalue_str = map(str, (etype, evalue)) - except: - # User exception is improperly defined. - etype, evalue = str, sys.exc_info()[:2] - etype_str, evalue_str = map(str, (etype, evalue)) - - # PEP-678 notes - notes = getattr(evalue, "__notes__", []) - if not isinstance(notes, Sequence) or isinstance(notes, (str, bytes)): - notes = [_safe_string(notes, "__notes__", func=repr)] - - # ... and format it - return [ - "{}{}{}: {}".format( - colors.excName, - etype_str, - colorsnormal, - py3compat.cast_unicode(evalue_str), - ), - *( - "{}{}".format( - colorsnormal, _safe_string(py3compat.cast_unicode(n), "note") - ) - for n in notes - ), - ] - - def format_exception_as_a_whole( - self, - etype: type, - evalue: Optional[BaseException], - etb: Optional[TracebackType], - number_of_lines_of_context, - tb_offset: Optional[int], - ): - """Formats the header, traceback and exception message for a single exception. - - This may be called multiple times by Python 3 exception chaining - (PEP 3134). - """ - # some locals - orig_etype = etype - try: - etype = etype.__name__ # type: ignore - except AttributeError: - pass - - tb_offset = self.tb_offset if tb_offset is None else tb_offset - assert isinstance(tb_offset, int) - head = self.prepare_header(str(etype), self.long_header) - records = ( - self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else [] - ) - - frames = [] - skipped = 0 - lastrecord = len(records) - 1 - for i, record in enumerate(records): - if ( - not isinstance(record._sd, stack_data.RepeatedFrames) - and self.skip_hidden - ): - if ( - record.frame.f_locals.get("__tracebackhide__", 0) - and i != lastrecord - ): - skipped += 1 - continue - if skipped: - Colors = self.Colors # just a shorthand + quicker name lookup - ColorsNormal = Colors.Normal # used a lot - frames.append( - " %s[... skipping hidden %s frame]%s\n" - % (Colors.excName, skipped, ColorsNormal) - ) - skipped = 0 - frames.append(self.format_record(record)) - if skipped: - Colors = self.Colors # just a shorthand + quicker name lookup - ColorsNormal = Colors.Normal # used a lot - frames.append( - " %s[... skipping hidden %s frame]%s\n" - % (Colors.excName, skipped, ColorsNormal) - ) - - formatted_exception = self.format_exception(etype, evalue) - if records: - frame_info = records[-1] - ipinst = get_ipython() - if ipinst is not None: - ipinst.hooks.synchronize_with_editor(frame_info.filename, frame_info.lineno, 0) - - return [[head] + frames + formatted_exception] - - def get_records( - self, etb: TracebackType, number_of_lines_of_context: int, tb_offset: int - ): - assert etb is not None - context = number_of_lines_of_context - 1 - after = context // 2 - before = context - after - if self.has_colors: - style = get_style_by_name(self.tb_highlight_style) - style = stack_data.style_with_executing_node(style, self.tb_highlight) - formatter = Terminal256Formatter(style=style) - else: - formatter = None - options = stack_data.Options( - before=before, - after=after, - pygments_formatter=formatter, - ) - - # Let's estimate the amount of code we will have to parse/highlight. - cf: Optional[TracebackType] = etb - max_len = 0 - tbs = [] - while cf is not None: - try: - mod = inspect.getmodule(cf.tb_frame) - if mod is not None: - mod_name = mod.__name__ - root_name, *_ = mod_name.split(".") - if root_name == "IPython": - cf = cf.tb_next - continue - max_len = get_line_number_of_frame(cf.tb_frame) - - except OSError: - max_len = 0 - max_len = max(max_len, max_len) - tbs.append(cf) - cf = getattr(cf, "tb_next", None) - - if max_len > FAST_THRESHOLD: - FIs = [] - for tb in tbs: - frame = tb.tb_frame # type: ignore - lineno = (frame.f_lineno,) - code = frame.f_code - filename = code.co_filename - # TODO: Here we need to use before/after/ - FIs.append( - FrameInfo( - "Raw frame", filename, lineno, frame, code, context=context - ) - ) - return FIs - res = list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:] - res = [FrameInfo._from_stack_data_FrameInfo(r) for r in res] - return res - - def structured_traceback( - self, - etype: type, - evalue: Optional[BaseException], - etb: Optional[TracebackType] = None, - tb_offset: Optional[int] = None, - number_of_lines_of_context: int = 5, - ): - """Return a nice text document describing the traceback.""" - formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context, - tb_offset) - - colors = self.Colors # just a shorthand + quicker name lookup - colorsnormal = colors.Normal # used a lot - head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal) - structured_traceback_parts = [head] - chained_exceptions_tb_offset = 0 - lines_of_context = 3 - formatted_exceptions = formatted_exception - exception = self.get_parts_of_chained_exception(evalue) - if exception: - assert evalue is not None - formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) - etype, evalue, etb = exception - else: - evalue = None - chained_exc_ids = set() - while evalue: - formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context, - chained_exceptions_tb_offset) - exception = self.get_parts_of_chained_exception(evalue) - - if exception and not id(exception[1]) in chained_exc_ids: - chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop - formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) - etype, evalue, etb = exception - else: - evalue = None - - # we want to see exceptions in a reversed order: - # the first exception should be on top - for formatted_exception in reversed(formatted_exceptions): - structured_traceback_parts += formatted_exception - - return structured_traceback_parts - - def debugger(self, force: bool = False): - """Call up the pdb debugger if desired, always clean up the tb - reference. - - Keywords: - - - force(False): by default, this routine checks the instance call_pdb - flag and does not actually invoke the debugger if the flag is false. - The 'force' option forces the debugger to activate even if the flag - is false. - - If the call_pdb flag is set, the pdb interactive debugger is - invoked. In all cases, the self.tb reference to the current traceback - is deleted to prevent lingering references which hamper memory - management. - - Note that each call to pdb() does an 'import readline', so if your app - requires a special setup for the readline completers, you'll have to - fix that by hand after invoking the exception handler.""" - - if force or self.call_pdb: - if self.pdb is None: - self.pdb = self.debugger_cls() - # the system displayhook may have changed, restore the original - # for pdb - display_trap = DisplayTrap(hook=sys.__displayhook__) - with display_trap: - self.pdb.reset() - # Find the right frame so we don't pop up inside ipython itself - if hasattr(self, "tb") and self.tb is not None: # type: ignore[has-type] - etb = self.tb # type: ignore[has-type] - else: - etb = self.tb = sys.last_traceback - while self.tb is not None and self.tb.tb_next is not None: - assert self.tb.tb_next is not None - self.tb = self.tb.tb_next - if etb and etb.tb_next: - etb = etb.tb_next - self.pdb.botframe = etb.tb_frame - # last_value should be deprecated, but last-exc sometimme not set - # please check why later and remove the getattr. - exc = sys.last_value if sys.version_info < (3, 12) else getattr(sys, "last_exc", sys.last_value) # type: ignore[attr-defined] - if exc: - self.pdb.interaction(None, exc) - else: - self.pdb.interaction(None, etb) - - if hasattr(self, 'tb'): - del self.tb - - def handler(self, info=None): - (etype, evalue, etb) = info or sys.exc_info() - self.tb = etb - ostream = self.ostream - ostream.flush() - ostream.write(self.text(etype, evalue, etb)) - ostream.write('\n') - ostream.flush() - - # Changed so an instance can just be called as VerboseTB_inst() and print - # out the right info on its own. - def __call__(self, etype=None, evalue=None, etb=None): - """This hook can replace sys.excepthook (for Python 2.1 or higher).""" - if etb is None: - self.handler() - else: - self.handler((etype, evalue, etb)) - try: - self.debugger() - except KeyboardInterrupt: - print("\nKeyboardInterrupt") - - -#---------------------------------------------------------------------------- -class FormattedTB(VerboseTB, ListTB): - """Subclass ListTB but allow calling with a traceback. - - It can thus be used as a sys.excepthook for Python > 2.1. - - Also adds 'Context' and 'Verbose' modes, not available in ListTB. - - Allows a tb_offset to be specified. This is useful for situations where - one needs to remove a number of topmost frames from the traceback (such as - occurs with python programs that themselves execute other python code, - like Python shells). """ - - mode: str - - def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False, - ostream=None, - tb_offset=0, long_header=False, include_vars=False, - check_cache=None, debugger_cls=None, - parent=None, config=None): - - # NEVER change the order of this list. Put new modes at the end: - self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal'] - self.verbose_modes = self.valid_modes[1:3] - - VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb, - ostream=ostream, tb_offset=tb_offset, - long_header=long_header, include_vars=include_vars, - check_cache=check_cache, debugger_cls=debugger_cls, - parent=parent, config=config) - - # Different types of tracebacks are joined with different separators to - # form a single string. They are taken from this dict - self._join_chars = dict(Plain='', Context='\n', Verbose='\n', - Minimal='') - # set_mode also sets the tb_join_char attribute - self.set_mode(mode) - - def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5): - tb_offset = self.tb_offset if tb_offset is None else tb_offset - mode = self.mode - if mode in self.verbose_modes: - # Verbose modes need a full traceback - return VerboseTB.structured_traceback( - self, etype, value, tb, tb_offset, number_of_lines_of_context - ) - elif mode == 'Minimal': - return ListTB.get_exception_only(self, etype, value) - else: - # We must check the source cache because otherwise we can print - # out-of-date source code. - self.check_cache() - # Now we can extract and format the exception - return ListTB.structured_traceback( - self, etype, value, tb, tb_offset, number_of_lines_of_context - ) - - def stb2text(self, stb): - """Convert a structured traceback (a list) to a string.""" - return self.tb_join_char.join(stb) - - def set_mode(self, mode: Optional[str] = None): - """Switch to the desired mode. - - If mode is not specified, cycles through the available modes.""" - - if not mode: - new_idx = (self.valid_modes.index(self.mode) + 1 ) % \ - len(self.valid_modes) - self.mode = self.valid_modes[new_idx] - elif mode not in self.valid_modes: - raise ValueError( - "Unrecognized mode in FormattedTB: <" + mode + ">\n" - "Valid modes: " + str(self.valid_modes) - ) - else: - assert isinstance(mode, str) - self.mode = mode - # include variable details only in 'Verbose' mode - self.include_vars = (self.mode == self.valid_modes[2]) - # Set the join character for generating text tracebacks - self.tb_join_char = self._join_chars[self.mode] - - # some convenient shortcuts - def plain(self): - self.set_mode(self.valid_modes[0]) - - def context(self): - self.set_mode(self.valid_modes[1]) - - def verbose(self): - self.set_mode(self.valid_modes[2]) - - def minimal(self): - self.set_mode(self.valid_modes[3]) - - -#---------------------------------------------------------------------------- -class AutoFormattedTB(FormattedTB): - """A traceback printer which can be called on the fly. - - It will find out about exceptions by itself. - - A brief example:: - - AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux') - try: - ... - except: - AutoTB() # or AutoTB(out=logfile) where logfile is an open file object - """ - - def __call__(self, etype=None, evalue=None, etb=None, - out=None, tb_offset=None): - """Print out a formatted exception traceback. - - Optional arguments: - - out: an open file-like object to direct output to. - - - tb_offset: the number of frames to skip over in the stack, on a - per-call basis (this overrides temporarily the instance's tb_offset - given at initialization time.""" - - if out is None: - out = self.ostream - out.flush() - out.write(self.text(etype, evalue, etb, tb_offset)) - out.write('\n') - out.flush() - # FIXME: we should remove the auto pdb behavior from here and leave - # that to the clients. - try: - self.debugger() - except KeyboardInterrupt: - print("\nKeyboardInterrupt") - - def structured_traceback( - self, - etype: type, - evalue: Optional[BaseException], - etb: Optional[TracebackType] = None, - tb_offset: Optional[int] = None, - number_of_lines_of_context: int = 5, - ): - # tb: TracebackType or tupleof tb types ? - if etype is None: - etype, evalue, etb = sys.exc_info() - if isinstance(etb, tuple): - # tb is a tuple if this is a chained exception. - self.tb = etb[0] - else: - self.tb = etb - return FormattedTB.structured_traceback( - self, etype, evalue, etb, tb_offset, number_of_lines_of_context - ) - - -#--------------------------------------------------------------------------- - -# A simple class to preserve Nathan's original functionality. -class ColorTB(FormattedTB): - """Shorthand to initialize a FormattedTB in Linux colors mode.""" - - def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs): - FormattedTB.__init__(self, color_scheme=color_scheme, - call_pdb=call_pdb, **kwargs) - - -class SyntaxTB(ListTB): - """Extension which holds some state: the last exception value""" - - def __init__(self, color_scheme='NoColor', parent=None, config=None): - ListTB.__init__(self, color_scheme, parent=parent, config=config) - self.last_syntax_error = None - - def __call__(self, etype, value, elist): - self.last_syntax_error = value - - ListTB.__call__(self, etype, value, elist) - - def structured_traceback(self, etype, value, elist, tb_offset=None, - context=5): - # If the source file has been edited, the line in the syntax error can - # be wrong (retrieved from an outdated cache). This replaces it with - # the current value. - if isinstance(value, SyntaxError) \ - and isinstance(value.filename, str) \ - and isinstance(value.lineno, int): - linecache.checkcache(value.filename) - newtext = linecache.getline(value.filename, value.lineno) - if newtext: - value.text = newtext - self.last_syntax_error = value - return super(SyntaxTB, self).structured_traceback(etype, value, elist, - tb_offset=tb_offset, context=context) - - def clear_err_state(self): - """Return the current error state and clear it""" - e = self.last_syntax_error - self.last_syntax_error = None - return e - - def stb2text(self, stb): - """Convert a structured traceback (a list) to a string.""" - return ''.join(stb) - - -# some internal-use functions -def text_repr(value): - """Hopefully pretty robust repr equivalent.""" - # this is pretty horrible but should always return *something* - try: - return pydoc.text.repr(value) # type: ignore[call-arg] - except KeyboardInterrupt: - raise - except: - try: - return repr(value) - except KeyboardInterrupt: - raise - except: - try: - # all still in an except block so we catch - # getattr raising - name = getattr(value, '__name__', None) - if name: - # ick, recursion - return text_repr(name) - klass = getattr(value, '__class__', None) - if klass: - return '%s instance' % text_repr(klass) - except KeyboardInterrupt: - raise - except: - return 'UNRECOVERABLE REPR FAILURE' - - -def eqrepr(value, repr=text_repr): - return '=%s' % repr(value) - - -def nullrepr(value, repr=text_repr): - return '' diff --git a/.venv/lib/python3.12/site-packages/IPython/core/usage.py b/.venv/lib/python3.12/site-packages/IPython/core/usage.py deleted file mode 100644 index 53219bc..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/core/usage.py +++ /dev/null @@ -1,341 +0,0 @@ -# -*- coding: utf-8 -*- -"""Usage information for the main IPython applications. -""" -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# Copyright (C) 2001-2007 Fernando Perez. -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -import sys -from IPython.core import release - -cl_usage = """\ -========= - IPython -========= - -Tools for Interactive Computing in Python -========================================= - - A Python shell with automatic history (input and output), dynamic object - introspection, easier configuration, command completion, access to the - system shell and more. IPython can also be embedded in running programs. - - -Usage - - ipython [subcommand] [options] [-c cmd | -m mod | file] [--] [arg] ... - - If invoked with no options, it executes the file and exits, passing the - remaining arguments to the script, just as if you had specified the same - command with python. You may need to specify `--` before args to be passed - to the script, to prevent IPython from attempting to parse them. If you - specify the option `-i` before the filename, it will enter an interactive - IPython session after running the script, rather than exiting. Files ending - in .py will be treated as normal Python, but files ending in .ipy can - contain special IPython syntax (magic commands, shell expansions, etc.). - - Almost all configuration in IPython is available via the command-line. Do - `ipython --help-all` to see all available options. For persistent - configuration, look into your `ipython_config.py` configuration file for - details. - - This file is typically installed in the `IPYTHONDIR` directory, and there - is a separate configuration directory for each profile. The default profile - directory will be located in $IPYTHONDIR/profile_default. IPYTHONDIR - defaults to to `$HOME/.ipython`. For Windows users, $HOME resolves to - C:\\Users\\YourUserName in most instances. - - To initialize a profile with the default configuration file, do:: - - $> ipython profile create - - and start editing `IPYTHONDIR/profile_default/ipython_config.py` - - In IPython's documentation, we will refer to this directory as - `IPYTHONDIR`, you can change its default location by creating an - environment variable with this name and setting it to the desired path. - - For more information, see the manual available in HTML and PDF in your - installation, or online at https://ipython.org/documentation.html. -""" - -interactive_usage = """ -IPython -- An enhanced Interactive Python -========================================= - -IPython offers a fully compatible replacement for the standard Python -interpreter, with convenient shell features, special commands, command -history mechanism and output results caching. - -At your system command line, type 'ipython -h' to see the command line -options available. This document only describes interactive features. - -GETTING HELP ------------- - -Within IPython you have various way to access help: - - ? -> Introduction and overview of IPython's features (this screen). - object? -> Details about 'object'. - object?? -> More detailed, verbose information about 'object'. - %quickref -> Quick reference of all IPython specific syntax and magics. - help -> Access Python's own help system. - -If you are in terminal IPython you can quit this screen by pressing `q`. - - -MAIN FEATURES -------------- - -* Access to the standard Python help with object docstrings and the Python - manuals. Simply type 'help' (no quotes) to invoke it. - -* Magic commands: type %magic for information on the magic subsystem. - -* System command aliases, via the %alias command or the configuration file(s). - -* Dynamic object information: - - Typing ?word or word? prints detailed information about an object. Certain - long strings (code, etc.) get snipped in the center for brevity. - - Typing ??word or word?? gives access to the full information without - snipping long strings. Strings that are longer than the screen are printed - through the less pager. - - The ?/?? system gives access to the full source code for any object (if - available), shows function prototypes and other useful information. - - If you just want to see an object's docstring, type '%pdoc object' (without - quotes, and without % if you have automagic on). - -* Tab completion in the local namespace: - - At any time, hitting tab will complete any available python commands or - variable names, and show you a list of the possible completions if there's - no unambiguous one. It will also complete filenames in the current directory. - -* Search previous command history in multiple ways: - - - Start typing, and then use arrow keys up/down or (Ctrl-p/Ctrl-n) to search - through the history items that match what you've typed so far. - - - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches - your history for lines that match what you've typed so far, completing as - much as it can. - - - %hist: search history by index. - -* Persistent command history across sessions. - -* Logging of input with the ability to save and restore a working session. - -* System shell with !. Typing !ls will run 'ls' in the current directory. - -* The reload command does a 'deep' reload of a module: changes made to the - module since you imported will actually be available without having to exit. - -* Verbose and colored exception traceback printouts. See the magic xmode and - xcolor functions for details (just type %magic). - -* Input caching system: - - IPython offers numbered prompts (In/Out) with input and output caching. All - input is saved and can be retrieved as variables (besides the usual arrow - key recall). - - The following GLOBAL variables always exist (so don't overwrite them!): - _i: stores previous input. - _ii: next previous. - _iii: next-next previous. - _ih : a list of all input _ih[n] is the input from line n. - - Additionally, global variables named _i are dynamically created ( - being the prompt counter), such that _i == _ih[] - - For example, what you typed at prompt 14 is available as _i14 and _ih[14]. - - You can create macros which contain multiple input lines from this history, - for later re-execution, with the %macro function. - - The history function %hist allows you to see any part of your input history - by printing a range of the _i variables. Note that inputs which contain - magic functions (%) appear in the history with a prepended comment. This is - because they aren't really valid Python code, so you can't exec them. - -* Output caching system: - - For output that is returned from actions, a system similar to the input - cache exists but using _ instead of _i. Only actions that produce a result - (NOT assignments, for example) are cached. If you are familiar with - Mathematica, IPython's _ variables behave exactly like Mathematica's % - variables. - - The following GLOBAL variables always exist (so don't overwrite them!): - _ (one underscore): previous output. - __ (two underscores): next previous. - ___ (three underscores): next-next previous. - - Global variables named _ are dynamically created ( being the prompt - counter), such that the result of output is always available as _. - - Finally, a global dictionary named _oh exists with entries for all lines - which generated output. - -* Directory history: - - Your history of visited directories is kept in the global list _dh, and the - magic %cd command can be used to go to any entry in that list. - -* Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython) - - 1. Auto-parentheses - - Callable objects (i.e. functions, methods, etc) can be invoked like - this (notice the commas between the arguments):: - - In [1]: callable_ob arg1, arg2, arg3 - - and the input will be translated to this:: - - callable_ob(arg1, arg2, arg3) - - This feature is off by default (in rare cases it can produce - undesirable side-effects), but you can activate it at the command-line - by starting IPython with `--autocall 1`, set it permanently in your - configuration file, or turn on at runtime with `%autocall 1`. - - You can force auto-parentheses by using '/' as the first character - of a line. For example:: - - In [1]: /globals # becomes 'globals()' - - Note that the '/' MUST be the first character on the line! This - won't work:: - - In [2]: print /globals # syntax error - - In most cases the automatic algorithm should work, so you should - rarely need to explicitly invoke /. One notable exception is if you - are trying to call a function with a list of tuples as arguments (the - parenthesis will confuse IPython):: - - In [1]: zip (1,2,3),(4,5,6) # won't work - - but this will work:: - - In [2]: /zip (1,2,3),(4,5,6) - ------> zip ((1,2,3),(4,5,6)) - Out[2]= [(1, 4), (2, 5), (3, 6)] - - IPython tells you that it has altered your command line by - displaying the new command line preceded by -->. e.g.:: - - In [18]: callable list - -------> callable (list) - - 2. Auto-Quoting - - You can force auto-quoting of a function's arguments by using ',' as - the first character of a line. For example:: - - In [1]: ,my_function /home/me # becomes my_function("/home/me") - - If you use ';' instead, the whole argument is quoted as a single - string (while ',' splits on whitespace):: - - In [2]: ,my_function a b c # becomes my_function("a","b","c") - In [3]: ;my_function a b c # becomes my_function("a b c") - - Note that the ',' MUST be the first character on the line! This - won't work:: - - In [4]: x = ,my_function /home/me # syntax error -""" - -interactive_usage_min = """\ -An enhanced console for Python. -Some of its features are: -- Tab completion in the local namespace. -- Logging of input, see command-line options. -- System shell escape via ! , eg !ls. -- Magic commands, starting with a % (like %ls, %pwd, %cd, etc.) -- Keeps track of locally defined variables via %who, %whos. -- Show object information with a ? eg ?x or x? (use ?? for more info). -""" - -quick_reference = r""" -IPython -- An enhanced Interactive Python - Quick Reference Card -================================================================ - -obj?, obj?? : Get help, or more help for object (also works as - ?obj, ??obj). -?foo.*abc* : List names in 'foo' containing 'abc' in them. -%magic : Information about IPython's 'magic' % functions. - -Magic functions are prefixed by % or %%, and typically take their arguments -without parentheses, quotes or even commas for convenience. Line magics take a -single % and cell magics are prefixed with two %%. - -Example magic function calls: - -%alias d ls -F : 'd' is now an alias for 'ls -F' -alias d ls -F : Works if 'alias' not a python name -alist = %alias : Get list of aliases to 'alist' -cd /usr/share : Obvious. cd - to choose from visited dirs. -%cd?? : See help AND source for magic %cd -%timeit x=10 : time the 'x=10' statement with high precision. -%%timeit x=2**100 -x**100 : time 'x**100' with a setup of 'x=2**100'; setup code is not - counted. This is an example of a cell magic. - -System commands: - -!cp a.txt b/ : System command escape, calls os.system() -cp a.txt b/ : after %rehashx, most system commands work without ! -cp ${f}.txt $bar : Variable expansion in magics and system commands -files = !ls /usr : Capture system command output -files.s, files.l, files.n: "a b c", ['a','b','c'], 'a\nb\nc' - -History: - -_i, _ii, _iii : Previous, next previous, next next previous input -_i4, _ih[2:5] : Input history line 4, lines 2-4 -exec(_i81) : Execute input history line #81 again -%rep 81 : Edit input history line #81 -_, __, ___ : previous, next previous, next next previous output -_dh : Directory history -_oh : Output history -%hist : Command history of current session. -%hist -g foo : Search command history of (almost) all sessions for 'foo'. -%hist -g : Command history of (almost) all sessions. -%hist 1/2-8 : Command history containing lines 2-8 of session 1. -%hist 1/ ~2/ : Command history of session 1 and 2 sessions before current. -%hist ~8/1-~6/5 : Command history from line 1 of 8 sessions ago to - line 5 of 6 sessions ago. -%edit 0/ : Open editor to execute code with history of current session. - -Autocall: - -f 1,2 : f(1,2) # Off by default, enable with %autocall magic. -/f 1,2 : f(1,2) (forced autoparen) -,f 1 2 : f("1","2") -;f 1 2 : f("1 2") - -Remember: TAB completion works in many contexts, not just file names -or python names. - -The following magic functions are currently available: - -""" - -default_banner_parts = ["Python %s\n"%sys.version.split("\n")[0], - "Type 'copyright', 'credits' or 'license' for more information\n" , - "IPython {version} -- An enhanced Interactive Python. Type '?' for help.\n".format(version=release.version), -] - -default_banner = ''.join(default_banner_parts) diff --git a/.venv/lib/python3.12/site-packages/IPython/display.py b/.venv/lib/python3.12/site-packages/IPython/display.py deleted file mode 100644 index 3ccbc48..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/display.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Public API for display tools in IPython. -""" - -# ----------------------------------------------------------------------------- -# Copyright (C) 2012 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -# ----------------------------------------------------------------------------- - -# ----------------------------------------------------------------------------- -# Imports -# ----------------------------------------------------------------------------- - -from IPython.core.display_functions import * -from IPython.core.display import ( - display_pretty as display_pretty, - display_html as display_html, - display_markdown as display_markdown, - display_svg as display_svg, - display_png as display_png, - display_jpeg as display_jpeg, - display_latex as display_latex, - display_json as display_json, - display_javascript as display_javascript, - display_pdf as display_pdf, - DisplayObject as DisplayObject, - TextDisplayObject as TextDisplayObject, - Pretty as Pretty, - HTML as HTML, - Markdown as Markdown, - Math as Math, - Latex as Latex, - SVG as SVG, - ProgressBar as ProgressBar, - JSON as JSON, - GeoJSON as GeoJSON, - Javascript as Javascript, - Image as Image, - set_matplotlib_formats as set_matplotlib_formats, - set_matplotlib_close as set_matplotlib_close, - Video as Video, -) -from IPython.lib.display import * diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/__init__.py b/.venv/lib/python3.12/site-packages/IPython/extensions/__init__.py deleted file mode 100644 index db7f79f..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/extensions/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -"""This directory is meant for IPython extensions.""" diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 7e5e21f..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/autoreload.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/autoreload.cpython-312.pyc deleted file mode 100644 index 1147d04..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/autoreload.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/storemagic.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/storemagic.cpython-312.pyc deleted file mode 100644 index 3ec9959..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/extensions/__pycache__/storemagic.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/autoreload.py b/.venv/lib/python3.12/site-packages/IPython/extensions/autoreload.py deleted file mode 100644 index 98c9a0d..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/extensions/autoreload.py +++ /dev/null @@ -1,727 +0,0 @@ -"""IPython extension to reload modules before executing user code. - -``autoreload`` reloads modules automatically before entering the execution of -code typed at the IPython prompt. - -This makes for example the following workflow possible: - -.. sourcecode:: ipython - - In [1]: %load_ext autoreload - - In [2]: %autoreload 2 - - In [3]: from foo import some_function - - In [4]: some_function() - Out[4]: 42 - - In [5]: # open foo.py in an editor and change some_function to return 43 - - In [6]: some_function() - Out[6]: 43 - -The module was reloaded without reloading it explicitly, and the object -imported with ``from foo import ...`` was also updated. - -Usage -===== - -The following magic commands are provided: - -``%autoreload``, ``%autoreload now`` - - Reload all modules (except those excluded by ``%aimport``) - automatically now. - -``%autoreload 0``, ``%autoreload off`` - - Disable automatic reloading. - -``%autoreload 1``, ``%autoreload explicit`` - - Reload all modules imported with ``%aimport`` every time before - executing the Python code typed. - -``%autoreload 2``, ``%autoreload all`` - - Reload all modules (except those excluded by ``%aimport``) every - time before executing the Python code typed. - -``%autoreload 3``, ``%autoreload complete`` - - Same as 2/all, but also adds any new objects in the module. See - unit test at IPython/extensions/tests/test_autoreload.py::test_autoload_newly_added_objects - - Adding ``--print`` or ``-p`` to the ``%autoreload`` line will print autoreload activity to - standard out. ``--log`` or ``-l`` will do it to the log at INFO level; both can be used - simultaneously. - -``%aimport`` - - List modules which are to be automatically imported or not to be imported. - -``%aimport foo`` - - Import module 'foo' and mark it to be autoreloaded for ``%autoreload 1`` - -``%aimport foo, bar`` - - Import modules 'foo', 'bar' and mark them to be autoreloaded for ``%autoreload 1`` - -``%aimport -foo`` - - Mark module 'foo' to not be autoreloaded. - -Caveats -======= - -Reloading Python modules in a reliable way is in general difficult, -and unexpected things may occur. ``%autoreload`` tries to work around -common pitfalls by replacing function code objects and parts of -classes previously in the module with new versions. This makes the -following things to work: - -- Functions and classes imported via 'from xxx import foo' are upgraded - to new versions when 'xxx' is reloaded. - -- Methods and properties of classes are upgraded on reload, so that - calling 'c.foo()' on an object 'c' created before the reload causes - the new code for 'foo' to be executed. - -Some of the known remaining caveats are: - -- Replacing code objects does not always succeed: changing a @property - in a class to an ordinary method or a method to a member variable - can cause problems (but in old objects only). - -- Functions that are removed (eg. via monkey-patching) from a module - before it is reloaded are not upgraded. - -- C extension modules cannot be reloaded, and so cannot be autoreloaded. - -- While comparing Enum and Flag, the 'is' Identity Operator is used (even in the case '==' has been used (Similar to the 'None' keyword)). - -- Reloading a module, or importing the same module by a different name, creates new Enums. These may look the same, but are not. -""" - -from IPython.core import magic_arguments -from IPython.core.magic import Magics, magics_class, line_magic - -__skip_doctest__ = True - -# ----------------------------------------------------------------------------- -# Copyright (C) 2000 Thomas Heller -# Copyright (C) 2008 Pauli Virtanen -# Copyright (C) 2012 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -# ----------------------------------------------------------------------------- -# -# This IPython module is written by Pauli Virtanen, based on the autoreload -# code by Thomas Heller. - -# ----------------------------------------------------------------------------- -# Imports -# ----------------------------------------------------------------------------- - -import os -import sys -import traceback -import types -import weakref -import gc -import logging -from importlib import import_module, reload -from importlib.util import source_from_cache - -# ------------------------------------------------------------------------------ -# Autoreload functionality -# ------------------------------------------------------------------------------ - - -class ModuleReloader: - enabled = False - """Whether this reloader is enabled""" - - check_all = True - """Autoreload all modules, not just those listed in 'modules'""" - - autoload_obj = False - """Autoreload all modules AND autoload all new objects""" - - def __init__(self, shell=None): - # Modules that failed to reload: {module: mtime-on-failed-reload, ...} - self.failed = {} - # Modules specially marked as autoreloadable. - self.modules = {} - # Modules specially marked as not autoreloadable. - self.skip_modules = {} - # (module-name, name) -> weakref, for replacing old code objects - self.old_objects = {} - # Module modification timestamps - self.modules_mtimes = {} - self.shell = shell - - # Reporting callable for verbosity - self._report = lambda msg: None # by default, be quiet. - - # Cache module modification times - self.check(check_all=True, do_reload=False) - - # To hide autoreload errors - self.hide_errors = False - - def mark_module_skipped(self, module_name): - """Skip reloading the named module in the future""" - try: - del self.modules[module_name] - except KeyError: - pass - self.skip_modules[module_name] = True - - def mark_module_reloadable(self, module_name): - """Reload the named module in the future (if it is imported)""" - try: - del self.skip_modules[module_name] - except KeyError: - pass - self.modules[module_name] = True - - def aimport_module(self, module_name): - """Import a module, and mark it reloadable - - Returns - ------- - top_module : module - The imported module if it is top-level, or the top-level - top_name : module - Name of top_module - - """ - self.mark_module_reloadable(module_name) - - import_module(module_name) - top_name = module_name.split(".")[0] - top_module = sys.modules[top_name] - return top_module, top_name - - def filename_and_mtime(self, module): - if not hasattr(module, "__file__") or module.__file__ is None: - return None, None - - if getattr(module, "__name__", None) in [None, "__mp_main__", "__main__"]: - # we cannot reload(__main__) or reload(__mp_main__) - return None, None - - filename = module.__file__ - path, ext = os.path.splitext(filename) - - if ext.lower() == ".py": - py_filename = filename - else: - try: - py_filename = source_from_cache(filename) - except ValueError: - return None, None - - try: - pymtime = os.stat(py_filename).st_mtime - except OSError: - return None, None - - return py_filename, pymtime - - def check(self, check_all=False, do_reload=True): - """Check whether some modules need to be reloaded.""" - - if not self.enabled and not check_all: - return - - if check_all or self.check_all: - modules = list(sys.modules.keys()) - else: - modules = list(self.modules.keys()) - - for modname in modules: - m = sys.modules.get(modname, None) - - if modname in self.skip_modules: - continue - - py_filename, pymtime = self.filename_and_mtime(m) - if py_filename is None: - continue - - try: - if pymtime <= self.modules_mtimes[modname]: - continue - except KeyError: - self.modules_mtimes[modname] = pymtime - continue - else: - if self.failed.get(py_filename, None) == pymtime: - continue - - self.modules_mtimes[modname] = pymtime - - # If we've reached this point, we should try to reload the module - if do_reload: - self._report(f"Reloading '{modname}'.") - try: - if self.autoload_obj: - superreload(m, reload, self.old_objects, self.shell) - else: - superreload(m, reload, self.old_objects) - if py_filename in self.failed: - del self.failed[py_filename] - except: - if not self.hide_errors: - print( - "[autoreload of {} failed: {}]".format( - modname, traceback.format_exc(10) - ), - file=sys.stderr, - ) - self.failed[py_filename] = pymtime - - -# ------------------------------------------------------------------------------ -# superreload -# ------------------------------------------------------------------------------ - - -func_attrs = [ - "__code__", - "__defaults__", - "__doc__", - "__closure__", - "__globals__", - "__dict__", -] - - -def update_function(old, new): - """Upgrade the code object of a function""" - for name in func_attrs: - try: - setattr(old, name, getattr(new, name)) - except (AttributeError, TypeError): - pass - - -def update_instances(old, new): - """Use garbage collector to find all instances that refer to the old - class definition and update their __class__ to point to the new class - definition""" - - refs = gc.get_referrers(old) - - for ref in refs: - if type(ref) is old: - object.__setattr__(ref, "__class__", new) - - -def update_class(old, new): - """Replace stuff in the __dict__ of a class, and upgrade - method code objects, and add new methods, if any""" - for key in list(old.__dict__.keys()): - old_obj = getattr(old, key) - try: - new_obj = getattr(new, key) - # explicitly checking that comparison returns True to handle - # cases where `==` doesn't return a boolean. - if (old_obj == new_obj) is True: - continue - except AttributeError: - # obsolete attribute: remove it - try: - delattr(old, key) - except (AttributeError, TypeError): - pass - continue - except ValueError: - # can't compare nested structures containing - # numpy arrays using `==` - pass - - if update_generic(old_obj, new_obj): - continue - - try: - setattr(old, key, getattr(new, key)) - except (AttributeError, TypeError): - pass # skip non-writable attributes - - for key in list(new.__dict__.keys()): - if key not in list(old.__dict__.keys()): - try: - setattr(old, key, getattr(new, key)) - except (AttributeError, TypeError): - pass # skip non-writable attributes - - # update all instances of class - update_instances(old, new) - - -def update_property(old, new): - """Replace get/set/del functions of a property""" - update_generic(old.fdel, new.fdel) - update_generic(old.fget, new.fget) - update_generic(old.fset, new.fset) - - -def isinstance2(a, b, typ): - return isinstance(a, typ) and isinstance(b, typ) - - -UPDATE_RULES = [ - (lambda a, b: isinstance2(a, b, type), update_class), - (lambda a, b: isinstance2(a, b, types.FunctionType), update_function), - (lambda a, b: isinstance2(a, b, property), update_property), -] -UPDATE_RULES.extend( - [ - ( - lambda a, b: isinstance2(a, b, types.MethodType), - lambda a, b: update_function(a.__func__, b.__func__), - ), - ] -) - - -def update_generic(a, b): - for type_check, update in UPDATE_RULES: - if type_check(a, b): - update(a, b) - return True - return False - - -class StrongRef: - def __init__(self, obj): - self.obj = obj - - def __call__(self): - return self.obj - - -mod_attrs = [ - "__name__", - "__doc__", - "__package__", - "__loader__", - "__spec__", - "__file__", - "__cached__", - "__builtins__", -] - - -def append_obj(module, d, name, obj, autoload=False): - in_module = hasattr(obj, "__module__") and obj.__module__ == module.__name__ - if autoload: - # check needed for module global built-ins - if not in_module and name in mod_attrs: - return False - else: - if not in_module: - return False - - key = (module.__name__, name) - try: - d.setdefault(key, []).append(weakref.ref(obj)) - except TypeError: - pass - return True - - -def superreload(module, reload=reload, old_objects=None, shell=None): - """Enhanced version of the builtin reload function. - - superreload remembers objects previously in the module, and - - - upgrades the class dictionary of every old class in the module - - upgrades the code object of every old function and method - - clears the module's namespace before reloading - - """ - if old_objects is None: - old_objects = {} - - # collect old objects in the module - for name, obj in list(module.__dict__.items()): - if not append_obj(module, old_objects, name, obj): - continue - key = (module.__name__, name) - try: - old_objects.setdefault(key, []).append(weakref.ref(obj)) - except TypeError: - pass - - # reload module - try: - # clear namespace first from old cruft - old_dict = module.__dict__.copy() - old_name = module.__name__ - module.__dict__.clear() - module.__dict__["__name__"] = old_name - module.__dict__["__loader__"] = old_dict["__loader__"] - except (TypeError, AttributeError, KeyError): - pass - - try: - module = reload(module) - except: - # restore module dictionary on failed reload - module.__dict__.update(old_dict) - raise - - # iterate over all objects and update functions & classes - for name, new_obj in list(module.__dict__.items()): - key = (module.__name__, name) - if key not in old_objects: - # here 'shell' acts both as a flag and as an output var - if ( - shell is None - or name == "Enum" - or not append_obj(module, old_objects, name, new_obj, True) - ): - continue - shell.user_ns[name] = new_obj - - new_refs = [] - for old_ref in old_objects[key]: - old_obj = old_ref() - if old_obj is None: - continue - new_refs.append(old_ref) - update_generic(old_obj, new_obj) - - if new_refs: - old_objects[key] = new_refs - else: - del old_objects[key] - - return module - - -# ------------------------------------------------------------------------------ -# IPython connectivity -# ------------------------------------------------------------------------------ - - -@magics_class -class AutoreloadMagics(Magics): - def __init__(self, *a, **kw): - super().__init__(*a, **kw) - self._reloader = ModuleReloader(self.shell) - self._reloader.check_all = False - self._reloader.autoload_obj = False - self.loaded_modules = set(sys.modules) - - @line_magic - @magic_arguments.magic_arguments() - @magic_arguments.argument( - "mode", - type=str, - default="now", - nargs="?", - help="""blank or 'now' - Reload all modules (except those excluded by %%aimport) - automatically now. - - '0' or 'off' - Disable automatic reloading. - - '1' or 'explicit' - Reload only modules imported with %%aimport every - time before executing the Python code typed. - - '2' or 'all' - Reload all modules (except those excluded by %%aimport) - every time before executing the Python code typed. - - '3' or 'complete' - Same as 2/all, but also but also adds any new - objects in the module. - """, - ) - @magic_arguments.argument( - "-p", - "--print", - action="store_true", - default=False, - help="Show autoreload activity using `print` statements", - ) - @magic_arguments.argument( - "-l", - "--log", - action="store_true", - default=False, - help="Show autoreload activity using the logger", - ) - @magic_arguments.argument( - "--hide-errors", - action="store_true", - default=False, - help="Hide autoreload errors", - ) - def autoreload(self, line=""): - r"""%autoreload => Reload modules automatically - - %autoreload or %autoreload now - Reload all modules (except those excluded by %aimport) automatically - now. - - %autoreload 0 or %autoreload off - Disable automatic reloading. - - %autoreload 1 or %autoreload explicit - Reload only modules imported with %aimport every time before executing - the Python code typed. - - %autoreload 2 or %autoreload all - Reload all modules (except those excluded by %aimport) every time - before executing the Python code typed. - - %autoreload 3 or %autoreload complete - Same as 2/all, but also but also adds any new objects in the module. See - unit test at IPython/extensions/tests/test_autoreload.py::test_autoload_newly_added_objects - - The optional arguments --print and --log control display of autoreload activity. The default - is to act silently; --print (or -p) will print out the names of modules that are being - reloaded, and --log (or -l) outputs them to the log at INFO level. - - The optional argument --hide-errors hides any errors that can happen when trying to - reload code. - - Reloading Python modules in a reliable way is in general - difficult, and unexpected things may occur. %autoreload tries to - work around common pitfalls by replacing function code objects and - parts of classes previously in the module with new versions. This - makes the following things to work: - - - Functions and classes imported via 'from xxx import foo' are upgraded - to new versions when 'xxx' is reloaded. - - - Methods and properties of classes are upgraded on reload, so that - calling 'c.foo()' on an object 'c' created before the reload causes - the new code for 'foo' to be executed. - - Some of the known remaining caveats are: - - - Replacing code objects does not always succeed: changing a @property - in a class to an ordinary method or a method to a member variable - can cause problems (but in old objects only). - - - Functions that are removed (eg. via monkey-patching) from a module - before it is reloaded are not upgraded. - - - C extension modules cannot be reloaded, and so cannot be - autoreloaded. - - """ - args = magic_arguments.parse_argstring(self.autoreload, line) - mode = args.mode.lower() - - p = print - - logger = logging.getLogger("autoreload") - - l = logger.info - - def pl(msg): - p(msg) - l(msg) - - if args.print is False and args.log is False: - self._reloader._report = lambda msg: None - elif args.print is True: - if args.log is True: - self._reloader._report = pl - else: - self._reloader._report = p - elif args.log is True: - self._reloader._report = l - - self._reloader.hide_errors = args.hide_errors - - if mode == "" or mode == "now": - self._reloader.check(True) - elif mode == "0" or mode == "off": - self._reloader.enabled = False - elif mode == "1" or mode == "explicit": - self._reloader.enabled = True - self._reloader.check_all = False - self._reloader.autoload_obj = False - elif mode == "2" or mode == "all": - self._reloader.enabled = True - self._reloader.check_all = True - self._reloader.autoload_obj = False - elif mode == "3" or mode == "complete": - self._reloader.enabled = True - self._reloader.check_all = True - self._reloader.autoload_obj = True - else: - raise ValueError(f'Unrecognized autoreload mode "{mode}".') - - @line_magic - def aimport(self, parameter_s="", stream=None): - """%aimport => Import modules for automatic reloading. - - %aimport - List modules to automatically import and not to import. - - %aimport foo - Import module 'foo' and mark it to be autoreloaded for %autoreload explicit - - %aimport foo, bar - Import modules 'foo', 'bar' and mark them to be autoreloaded for %autoreload explicit - - %aimport -foo, bar - Mark module 'foo' to not be autoreloaded for %autoreload explicit, all, or complete, and 'bar' - to be autoreloaded for mode explicit. - """ - modname = parameter_s - if not modname: - to_reload = sorted(self._reloader.modules.keys()) - to_skip = sorted(self._reloader.skip_modules.keys()) - if stream is None: - stream = sys.stdout - if self._reloader.check_all: - stream.write("Modules to reload:\nall-except-skipped\n") - else: - stream.write("Modules to reload:\n%s\n" % " ".join(to_reload)) - stream.write("\nModules to skip:\n%s\n" % " ".join(to_skip)) - else: - for _module in [_.strip() for _ in modname.split(",")]: - if _module.startswith("-"): - _module = _module[1:].strip() - self._reloader.mark_module_skipped(_module) - else: - top_module, top_name = self._reloader.aimport_module(_module) - - # Inject module to user namespace - self.shell.push({top_name: top_module}) - - def pre_run_cell(self, info): - if self._reloader.enabled: - try: - self._reloader.check() - except: - pass - - def post_execute_hook(self): - """Cache the modification times of any modules imported in this execution""" - newly_loaded_modules = set(sys.modules) - self.loaded_modules - for modname in newly_loaded_modules: - _, pymtime = self._reloader.filename_and_mtime(sys.modules[modname]) - if pymtime is not None: - self._reloader.modules_mtimes[modname] = pymtime - - self.loaded_modules.update(newly_loaded_modules) - - -def load_ipython_extension(ip): - """Load the extension in IPython.""" - auto_reload = AutoreloadMagics(ip) - ip.register_magics(auto_reload) - ip.events.register("pre_run_cell", auto_reload.pre_run_cell) - ip.events.register("post_execute", auto_reload.post_execute_hook) diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/storemagic.py b/.venv/lib/python3.12/site-packages/IPython/extensions/storemagic.py deleted file mode 100644 index 1ab56f7..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/extensions/storemagic.py +++ /dev/null @@ -1,236 +0,0 @@ -# -*- coding: utf-8 -*- -""" -%store magic for lightweight persistence. - -Stores variables, aliases and macros in IPython's database. - -To automatically restore stored variables at startup, add this to your -:file:`ipython_config.py` file:: - - c.StoreMagics.autorestore = True -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import inspect, os, sys, textwrap - -from IPython.core.error import UsageError -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.testing.skipdoctest import skip_doctest -from traitlets import Bool - - -def restore_aliases(ip, alias=None): - staliases = ip.db.get('stored_aliases', {}) - if alias is None: - for k,v in staliases.items(): - # print("restore alias",k,v) # dbg - #self.alias_table[k] = v - ip.alias_manager.define_alias(k,v) - else: - ip.alias_manager.define_alias(alias, staliases[alias]) - - -def refresh_variables(ip): - db = ip.db - for key in db.keys('autorestore/*'): - # strip autorestore - justkey = os.path.basename(key) - try: - obj = db[key] - except KeyError: - print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey) - print("The error was:", sys.exc_info()[0]) - else: - # print("restored",justkey,"=",obj) # dbg - ip.user_ns[justkey] = obj - - -def restore_dhist(ip): - ip.user_ns['_dh'] = ip.db.get('dhist',[]) - - -def restore_data(ip): - refresh_variables(ip) - restore_aliases(ip) - restore_dhist(ip) - - -@magics_class -class StoreMagics(Magics): - """Lightweight persistence for python variables. - - Provides the %store magic.""" - - autorestore = Bool(False, help= - """If True, any %store-d variables will be automatically restored - when IPython starts. - """ - ).tag(config=True) - - def __init__(self, shell): - super(StoreMagics, self).__init__(shell=shell) - self.shell.configurables.append(self) - if self.autorestore: - restore_data(self.shell) - - @skip_doctest - @line_magic - def store(self, parameter_s=''): - """Lightweight persistence for python variables. - - Example:: - - In [1]: l = ['hello',10,'world'] - In [2]: %store l - Stored 'l' (list) - In [3]: exit - - (IPython session is closed and started again...) - - ville@badger:~$ ipython - In [1]: l - NameError: name 'l' is not defined - In [2]: %store -r - In [3]: l - Out[3]: ['hello', 10, 'world'] - - Usage: - - * ``%store`` - Show list of all variables and their current - values - * ``%store spam bar`` - Store the *current* value of the variables spam - and bar to disk - * ``%store -d spam`` - Remove the variable and its value from storage - * ``%store -z`` - Remove all variables from storage - * ``%store -r`` - Refresh all variables, aliases and directory history - from store (overwrite current vals) - * ``%store -r spam bar`` - Refresh specified variables and aliases from store - (delete current val) - * ``%store foo >a.txt`` - Store value of foo to new file a.txt - * ``%store foo >>a.txt`` - Append value of foo to file a.txt - - It should be noted that if you change the value of a variable, you - need to %store it again if you want to persist the new value. - - Note also that the variables will need to be pickleable; most basic - python types can be safely %store'd. - - Also aliases can be %store'd across sessions. - To remove an alias from the storage, use the %unalias magic. - """ - - opts,argsl = self.parse_options(parameter_s,'drz',mode='string') - args = argsl.split() - ip = self.shell - db = ip.db - # delete - if 'd' in opts: - try: - todel = args[0] - except IndexError as e: - raise UsageError('You must provide the variable to forget') from e - else: - try: - del db['autorestore/' + todel] - except BaseException as e: - raise UsageError("Can't delete variable '%s'" % todel) from e - # reset - elif 'z' in opts: - for k in db.keys('autorestore/*'): - del db[k] - - elif 'r' in opts: - if args: - for arg in args: - try: - obj = db["autorestore/" + arg] - except KeyError: - try: - restore_aliases(ip, alias=arg) - except KeyError: - print("no stored variable or alias %s" % arg) - else: - ip.user_ns[arg] = obj - else: - restore_data(ip) - - # run without arguments -> list variables & values - elif not args: - vars = db.keys('autorestore/*') - vars.sort() - if vars: - size = max(map(len, vars)) - else: - size = 0 - - print('Stored variables and their in-db values:') - fmt = '%-'+str(size)+'s -> %s' - get = db.get - for var in vars: - justkey = os.path.basename(var) - # print 30 first characters from every var - print(fmt % (justkey, repr(get(var, ''))[:50])) - - # default action - store the variable - else: - # %store foo >file.txt or >>file.txt - if len(args) > 1 and args[1].startswith(">"): - fnam = os.path.expanduser(args[1].lstrip(">").lstrip()) - if args[1].startswith(">>"): - fil = open(fnam, "a", encoding="utf-8") - else: - fil = open(fnam, "w", encoding="utf-8") - with fil: - obj = ip.ev(args[0]) - print("Writing '%s' (%s) to file '%s'." % (args[0], - obj.__class__.__name__, fnam)) - - if not isinstance (obj, str): - from pprint import pprint - pprint(obj, fil) - else: - fil.write(obj) - if not obj.endswith('\n'): - fil.write('\n') - - return - - # %store foo - for arg in args: - try: - obj = ip.user_ns[arg] - except KeyError: - # it might be an alias - name = arg - try: - cmd = ip.alias_manager.retrieve_alias(name) - except ValueError as e: - raise UsageError("Unknown variable '%s'" % name) from e - - staliases = db.get('stored_aliases',{}) - staliases[name] = cmd - db['stored_aliases'] = staliases - print("Alias stored: %s (%s)" % (name, cmd)) - return - - else: - modname = getattr(inspect.getmodule(obj), '__name__', '') - if modname == '__main__': - print(textwrap.dedent("""\ - Warning:%s is %s - Proper storage of interactively declared classes (or instances - of those classes) is not possible! Only instances - of classes in real modules on file system can be %%store'd. - """ % (arg, obj) )) - return - #pickled = pickle.dumps(obj) - db[ 'autorestore/' + arg ] = obj - print("Stored '%s' (%s)" % (arg, obj.__class__.__name__)) - - -def load_ipython_extension(ip): - """Load the extension in IPython.""" - ip.register_magics(StoreMagics) - diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__init__.py b/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index c633bcf..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/test_autoreload.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/test_autoreload.cpython-312.pyc deleted file mode 100644 index 7221771..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/test_autoreload.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/test_storemagic.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/test_storemagic.cpython-312.pyc deleted file mode 100644 index bc28ed8..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/__pycache__/test_storemagic.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/test_autoreload.py b/.venv/lib/python3.12/site-packages/IPython/extensions/tests/test_autoreload.py deleted file mode 100644 index 47f3e2d..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/test_autoreload.py +++ /dev/null @@ -1,712 +0,0 @@ -"""Tests for autoreload extension. -""" - -# ----------------------------------------------------------------------------- -# Copyright (c) 2012 IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -# ----------------------------------------------------------------------------- - -# ----------------------------------------------------------------------------- -# Imports -# ----------------------------------------------------------------------------- - -import os -import platform -import pytest -import sys -import tempfile -import textwrap -import shutil -import random -import time -import traceback -from io import StringIO -from dataclasses import dataclass - -import IPython.testing.tools as tt - -from unittest import TestCase - -from IPython.extensions.autoreload import AutoreloadMagics -from IPython.core.events import EventManager, pre_run_cell -from IPython.testing.decorators import skipif_not_numpy -from IPython.core.interactiveshell import ExecutionInfo - -if platform.python_implementation() == "PyPy": - pytest.skip( - "Current autoreload implementation is extremely slow on PyPy", - allow_module_level=True, - ) - -# ----------------------------------------------------------------------------- -# Test fixture -# ----------------------------------------------------------------------------- - -noop = lambda *a, **kw: None - - -class FakeShell: - def __init__(self): - self.ns = {} - self.user_ns = self.ns - self.user_ns_hidden = {} - self.events = EventManager(self, {"pre_run_cell", pre_run_cell}) - self.auto_magics = AutoreloadMagics(shell=self) - self.events.register("pre_run_cell", self.auto_magics.pre_run_cell) - - register_magics = set_hook = noop - - def showtraceback( - self, - exc_tuple=None, - filename=None, - tb_offset=None, - exception_only=False, - running_compiled_code=False, - ): - traceback.print_exc() - - def run_code(self, code): - self.events.trigger( - "pre_run_cell", - ExecutionInfo( - raw_cell="", - store_history=False, - silent=False, - shell_futures=False, - cell_id=None, - ), - ) - exec(code, self.user_ns) - self.auto_magics.post_execute_hook() - - def push(self, items): - self.ns.update(items) - - def magic_autoreload(self, parameter): - self.auto_magics.autoreload(parameter) - - def magic_aimport(self, parameter, stream=None): - self.auto_magics.aimport(parameter, stream=stream) - self.auto_magics.post_execute_hook() - - -class Fixture(TestCase): - """Fixture for creating test module files""" - - test_dir = None - old_sys_path = None - filename_chars = "abcdefghijklmopqrstuvwxyz0123456789" - - def setUp(self): - self.test_dir = tempfile.mkdtemp() - self.old_sys_path = list(sys.path) - sys.path.insert(0, self.test_dir) - self.shell = FakeShell() - - def tearDown(self): - shutil.rmtree(self.test_dir) - sys.path = self.old_sys_path - - self.test_dir = None - self.old_sys_path = None - self.shell = None - - def get_module(self): - module_name = "tmpmod_" + "".join(random.sample(self.filename_chars, 20)) - if module_name in sys.modules: - del sys.modules[module_name] - file_name = os.path.join(self.test_dir, module_name + ".py") - return module_name, file_name - - def write_file(self, filename, content): - """ - Write a file, and force a timestamp difference of at least one second - - Notes - ----- - Python's .pyc files record the timestamp of their compilation - with a time resolution of one second. - - Therefore, we need to force a timestamp difference between .py - and .pyc, without having the .py file be timestamped in the - future, and without changing the timestamp of the .pyc file - (because that is stored in the file). The only reliable way - to achieve this seems to be to sleep. - """ - content = textwrap.dedent(content) - # Sleep one second + eps - time.sleep(1.05) - - # Write - with open(filename, "w", encoding="utf-8") as f: - f.write(content) - - def new_module(self, code): - code = textwrap.dedent(code) - mod_name, mod_fn = self.get_module() - with open(mod_fn, "w", encoding="utf-8") as f: - f.write(code) - return mod_name, mod_fn - - -# ----------------------------------------------------------------------------- -# Test automatic reloading -# ----------------------------------------------------------------------------- - - -def pickle_get_current_class(obj): - """ - Original issue comes from pickle; hence the name. - """ - name = obj.__class__.__name__ - module_name = getattr(obj, "__module__", None) - obj2 = sys.modules[module_name] - for subpath in name.split("."): - obj2 = getattr(obj2, subpath) - return obj2 - - -class TestAutoreload(Fixture): - def test_reload_enums(self): - mod_name, mod_fn = self.new_module( - textwrap.dedent( - """ - from enum import Enum - class MyEnum(Enum): - A = 'A' - B = 'B' - """ - ) - ) - self.shell.magic_autoreload("2") - self.shell.magic_aimport(mod_name) - self.write_file( - mod_fn, - textwrap.dedent( - """ - from enum import Enum - class MyEnum(Enum): - A = 'A' - B = 'B' - C = 'C' - """ - ), - ) - with tt.AssertNotPrints( - ("[autoreload of %s failed:" % mod_name), channel="stderr" - ): - self.shell.run_code("pass") # trigger another reload - - def test_reload_class_type(self): - self.shell.magic_autoreload("2") - mod_name, mod_fn = self.new_module( - """ - class Test(): - def meth(self): - return "old" - """ - ) - assert "test" not in self.shell.ns - assert "result" not in self.shell.ns - - self.shell.run_code("from %s import Test" % mod_name) - self.shell.run_code("test = Test()") - - self.write_file( - mod_fn, - """ - class Test(): - def meth(self): - return "new" - """, - ) - - test_object = self.shell.ns["test"] - - # important to trigger autoreload logic ! - self.shell.run_code("pass") - - test_class = pickle_get_current_class(test_object) - assert isinstance(test_object, test_class) - - # extra check. - self.shell.run_code("import pickle") - self.shell.run_code("p = pickle.dumps(test)") - - def test_reload_class_attributes(self): - self.shell.magic_autoreload("2") - mod_name, mod_fn = self.new_module( - textwrap.dedent( - """ - class MyClass: - - def __init__(self, a=10): - self.a = a - self.b = 22 - # self.toto = 33 - - def square(self): - print('compute square') - return self.a*self.a - """ - ) - ) - self.shell.run_code("from %s import MyClass" % mod_name) - self.shell.run_code("first = MyClass(5)") - self.shell.run_code("first.square()") - with self.assertRaises(AttributeError): - self.shell.run_code("first.cube()") - with self.assertRaises(AttributeError): - self.shell.run_code("first.power(5)") - self.shell.run_code("first.b") - with self.assertRaises(AttributeError): - self.shell.run_code("first.toto") - - # remove square, add power - - self.write_file( - mod_fn, - textwrap.dedent( - """ - class MyClass: - - def __init__(self, a=10): - self.a = a - self.b = 11 - - def power(self, p): - print('compute power '+str(p)) - return self.a**p - """ - ), - ) - - self.shell.run_code("second = MyClass(5)") - - for object_name in {"first", "second"}: - self.shell.run_code(f"{object_name}.power(5)") - with self.assertRaises(AttributeError): - self.shell.run_code(f"{object_name}.cube()") - with self.assertRaises(AttributeError): - self.shell.run_code(f"{object_name}.square()") - self.shell.run_code(f"{object_name}.b") - self.shell.run_code(f"{object_name}.a") - with self.assertRaises(AttributeError): - self.shell.run_code(f"{object_name}.toto") - - @skipif_not_numpy - def test_comparing_numpy_structures(self): - self.shell.magic_autoreload("2") - self.shell.run_code("1+1") - mod_name, mod_fn = self.new_module( - textwrap.dedent( - """ - import numpy as np - class MyClass: - a = (np.array((.1, .2)), - np.array((.2, .3))) - """ - ) - ) - self.shell.run_code("from %s import MyClass" % mod_name) - self.shell.run_code("first = MyClass()") - - # change property `a` - self.write_file( - mod_fn, - textwrap.dedent( - """ - import numpy as np - class MyClass: - a = (np.array((.3, .4)), - np.array((.5, .6))) - """ - ), - ) - - with tt.AssertNotPrints( - ("[autoreload of %s failed:" % mod_name), channel="stderr" - ): - self.shell.run_code("pass") # trigger another reload - - def test_autoload_newly_added_objects(self): - # All of these fail with %autoreload 2 - self.shell.magic_autoreload("3") - mod_code = """ - def func1(): pass - """ - mod_name, mod_fn = self.new_module(textwrap.dedent(mod_code)) - self.shell.run_code(f"from {mod_name} import *") - self.shell.run_code("func1()") - with self.assertRaises(NameError): - self.shell.run_code("func2()") - with self.assertRaises(NameError): - self.shell.run_code("t = Test()") - with self.assertRaises(NameError): - self.shell.run_code("number") - - # ----------- TEST NEW OBJ LOADED -------------------------- - - new_code = """ - def func1(): pass - def func2(): pass - class Test: pass - number = 0 - from enum import Enum - class TestEnum(Enum): - A = 'a' - """ - self.write_file(mod_fn, textwrap.dedent(new_code)) - - # test function now exists in shell's namespace namespace - self.shell.run_code("func2()") - # test function now exists in module's dict - self.shell.run_code(f"import sys; sys.modules['{mod_name}'].func2()") - # test class now exists - self.shell.run_code("t = Test()") - # test global built-in var now exists - self.shell.run_code("number") - # test the enumerations gets loaded successfully - self.shell.run_code("TestEnum.A") - - # ----------- TEST NEW OBJ CAN BE CHANGED -------------------- - - new_code = """ - def func1(): return 'changed' - def func2(): return 'changed' - class Test: - def new_func(self): - return 'changed' - number = 1 - from enum import Enum - class TestEnum(Enum): - A = 'a' - B = 'added' - """ - self.write_file(mod_fn, textwrap.dedent(new_code)) - self.shell.run_code("assert func1() == 'changed'") - self.shell.run_code("assert func2() == 'changed'") - self.shell.run_code("t = Test(); assert t.new_func() == 'changed'") - self.shell.run_code("assert number == 1") - if sys.version_info < (3, 12): - self.shell.run_code("assert TestEnum.B.value == 'added'") - - # ----------- TEST IMPORT FROM MODULE -------------------------- - - new_mod_code = """ - from enum import Enum - class Ext(Enum): - A = 'ext' - def ext_func(): - return 'ext' - class ExtTest: - def meth(self): - return 'ext' - ext_int = 2 - """ - new_mod_name, new_mod_fn = self.new_module(textwrap.dedent(new_mod_code)) - current_mod_code = f""" - from {new_mod_name} import * - """ - self.write_file(mod_fn, textwrap.dedent(current_mod_code)) - self.shell.run_code("assert Ext.A.value == 'ext'") - self.shell.run_code("assert ext_func() == 'ext'") - self.shell.run_code("t = ExtTest(); assert t.meth() == 'ext'") - self.shell.run_code("assert ext_int == 2") - - def test_verbose_names(self): - # Asserts correspondense between original mode names and their verbose equivalents. - @dataclass - class AutoreloadSettings: - check_all: bool - enabled: bool - autoload_obj: bool - - def gather_settings(mode): - self.shell.magic_autoreload(mode) - module_reloader = self.shell.auto_magics._reloader - return AutoreloadSettings( - module_reloader.check_all, - module_reloader.enabled, - module_reloader.autoload_obj, - ) - - assert gather_settings("0") == gather_settings("off") - assert gather_settings("0") == gather_settings("OFF") # Case insensitive - assert gather_settings("1") == gather_settings("explicit") - assert gather_settings("2") == gather_settings("all") - assert gather_settings("3") == gather_settings("complete") - - # And an invalid mode name raises an exception. - with self.assertRaises(ValueError): - self.shell.magic_autoreload("4") - - def test_aimport_parsing(self): - # Modules can be included or excluded all in one line. - module_reloader = self.shell.auto_magics._reloader - self.shell.magic_aimport("os") # import and mark `os` for auto-reload. - assert module_reloader.modules["os"] is True - assert "os" not in module_reloader.skip_modules.keys() - - self.shell.magic_aimport("-math") # forbid autoreloading of `math` - assert module_reloader.skip_modules["math"] is True - assert "math" not in module_reloader.modules.keys() - - self.shell.magic_aimport( - "-os, math" - ) # Can do this all in one line; wasn't possible before. - assert module_reloader.modules["math"] is True - assert "math" not in module_reloader.skip_modules.keys() - assert module_reloader.skip_modules["os"] is True - assert "os" not in module_reloader.modules.keys() - - def test_autoreload_output(self): - self.shell.magic_autoreload("complete") - mod_code = """ - def func1(): pass - """ - mod_name, mod_fn = self.new_module(mod_code) - self.shell.run_code(f"import {mod_name}") - with tt.AssertPrints("", channel="stdout"): # no output; this is default - self.shell.run_code("pass") - - self.shell.magic_autoreload("complete --print") - self.write_file(mod_fn, mod_code) # "modify" the module - with tt.AssertPrints( - f"Reloading '{mod_name}'.", channel="stdout" - ): # see something printed out - self.shell.run_code("pass") - - self.shell.magic_autoreload("complete -p") - self.write_file(mod_fn, mod_code) # "modify" the module - with tt.AssertPrints( - f"Reloading '{mod_name}'.", channel="stdout" - ): # see something printed out - self.shell.run_code("pass") - - self.shell.magic_autoreload("complete --print --log") - self.write_file(mod_fn, mod_code) # "modify" the module - with tt.AssertPrints( - f"Reloading '{mod_name}'.", channel="stdout" - ): # see something printed out - self.shell.run_code("pass") - - self.shell.magic_autoreload("complete --print --log") - self.write_file(mod_fn, mod_code) # "modify" the module - with self.assertLogs(logger="autoreload") as lo: # see something printed out - self.shell.run_code("pass") - assert lo.output == [f"INFO:autoreload:Reloading '{mod_name}'."] - - self.shell.magic_autoreload("complete -l") - self.write_file(mod_fn, mod_code) # "modify" the module - with self.assertLogs(logger="autoreload") as lo: # see something printed out - self.shell.run_code("pass") - assert lo.output == [f"INFO:autoreload:Reloading '{mod_name}'."] - - def _check_smoketest(self, use_aimport=True): - """ - Functional test for the automatic reloader using either - '%autoreload 1' or '%autoreload 2' - """ - - mod_name, mod_fn = self.new_module( - """ -x = 9 - -z = 123 # this item will be deleted - -def foo(y): - return y + 3 - -class Baz(object): - def __init__(self, x): - self.x = x - def bar(self, y): - return self.x + y - @property - def quux(self): - return 42 - def zzz(self): - '''This method will be deleted below''' - return 99 - -class Bar: # old-style class: weakref doesn't work for it on Python < 2.7 - def foo(self): - return 1 -""" - ) - - # - # Import module, and mark for reloading - # - if use_aimport: - self.shell.magic_autoreload("1") - self.shell.magic_aimport(mod_name) - stream = StringIO() - self.shell.magic_aimport("", stream=stream) - self.assertIn(("Modules to reload:\n%s" % mod_name), stream.getvalue()) - - with self.assertRaises(ImportError): - self.shell.magic_aimport("tmpmod_as318989e89ds") - else: - self.shell.magic_autoreload("2") - self.shell.run_code("import %s" % mod_name) - stream = StringIO() - self.shell.magic_aimport("", stream=stream) - self.assertTrue( - "Modules to reload:\nall-except-skipped" in stream.getvalue() - ) - self.assertIn(mod_name, self.shell.ns) - - mod = sys.modules[mod_name] - - # - # Test module contents - # - old_foo = mod.foo - old_obj = mod.Baz(9) - old_obj2 = mod.Bar() - - def check_module_contents(): - self.assertEqual(mod.x, 9) - self.assertEqual(mod.z, 123) - - self.assertEqual(old_foo(0), 3) - self.assertEqual(mod.foo(0), 3) - - obj = mod.Baz(9) - self.assertEqual(old_obj.bar(1), 10) - self.assertEqual(obj.bar(1), 10) - self.assertEqual(obj.quux, 42) - self.assertEqual(obj.zzz(), 99) - - obj2 = mod.Bar() - self.assertEqual(old_obj2.foo(), 1) - self.assertEqual(obj2.foo(), 1) - - check_module_contents() - - # - # Simulate a failed reload: no reload should occur and exactly - # one error message should be printed - # - self.write_file( - mod_fn, - """ -a syntax error -""", - ) - - with tt.AssertPrints( - ("[autoreload of %s failed:" % mod_name), channel="stderr" - ): - self.shell.run_code("pass") # trigger reload - with tt.AssertNotPrints( - ("[autoreload of %s failed:" % mod_name), channel="stderr" - ): - self.shell.run_code("pass") # trigger another reload - check_module_contents() - - # - # Rewrite module (this time reload should succeed) - # - self.write_file( - mod_fn, - """ -x = 10 - -def foo(y): - return y + 4 - -class Baz(object): - def __init__(self, x): - self.x = x - def bar(self, y): - return self.x + y + 1 - @property - def quux(self): - return 43 - -class Bar: # old-style class - def foo(self): - return 2 -""", - ) - - def check_module_contents(): - self.assertEqual(mod.x, 10) - self.assertFalse(hasattr(mod, "z")) - - self.assertEqual(old_foo(0), 4) # superreload magic! - self.assertEqual(mod.foo(0), 4) - - obj = mod.Baz(9) - self.assertEqual(old_obj.bar(1), 11) # superreload magic! - self.assertEqual(obj.bar(1), 11) - - self.assertEqual(old_obj.quux, 43) - self.assertEqual(obj.quux, 43) - - self.assertFalse(hasattr(old_obj, "zzz")) - self.assertFalse(hasattr(obj, "zzz")) - - obj2 = mod.Bar() - self.assertEqual(old_obj2.foo(), 2) - self.assertEqual(obj2.foo(), 2) - - self.shell.run_code("pass") # trigger reload - check_module_contents() - - # - # Another failure case: deleted file (shouldn't reload) - # - os.unlink(mod_fn) - - self.shell.run_code("pass") # trigger reload - check_module_contents() - - # - # Disable autoreload and rewrite module: no reload should occur - # - if use_aimport: - self.shell.magic_aimport("-" + mod_name) - stream = StringIO() - self.shell.magic_aimport("", stream=stream) - self.assertTrue(("Modules to skip:\n%s" % mod_name) in stream.getvalue()) - - # This should succeed, although no such module exists - self.shell.magic_aimport("-tmpmod_as318989e89ds") - else: - self.shell.magic_autoreload("0") - - self.write_file( - mod_fn, - """ -x = -99 -""", - ) - - self.shell.run_code("pass") # trigger reload - self.shell.run_code("pass") - check_module_contents() - - # - # Re-enable autoreload: reload should now occur - # - if use_aimport: - self.shell.magic_aimport(mod_name) - else: - self.shell.magic_autoreload("") - - self.shell.run_code("pass") # trigger reload - self.assertEqual(mod.x, -99) - - def test_smoketest_aimport(self): - self._check_smoketest(use_aimport=True) - - def test_smoketest_autoreload(self): - self._check_smoketest(use_aimport=False) diff --git a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/test_storemagic.py b/.venv/lib/python3.12/site-packages/IPython/extensions/tests/test_storemagic.py deleted file mode 100644 index 66122ab..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/extensions/tests/test_storemagic.py +++ /dev/null @@ -1,71 +0,0 @@ -import tempfile, os -from pathlib import Path - -from traitlets.config.loader import Config - - -def setup_module(): - ip.run_line_magic("load_ext", "storemagic") - - -def test_store_restore(): - assert "bar" not in ip.user_ns, "Error: some other test leaked `bar` in user_ns" - assert "foo" not in ip.user_ns, "Error: some other test leaked `foo` in user_ns" - assert ( - "foobar" not in ip.user_ns - ), "Error: some other test leaked `foobar` in user_ns" - assert ( - "foobaz" not in ip.user_ns - ), "Error: some other test leaked `foobaz` in user_ns" - ip.user_ns["foo"] = 78 - ip.run_line_magic("alias", 'bar echo "hello"') - ip.user_ns["foobar"] = 79 - ip.user_ns["foobaz"] = "80" - tmpd = tempfile.mkdtemp() - ip.run_line_magic("cd", tmpd) - ip.run_line_magic("store", "foo") - ip.run_line_magic("store", "bar") - ip.run_line_magic("store", "foobar foobaz") - - # Check storing - assert ip.db["autorestore/foo"] == 78 - assert "bar" in ip.db["stored_aliases"] - assert ip.db["autorestore/foobar"] == 79 - assert ip.db["autorestore/foobaz"] == "80" - - # Remove those items - ip.user_ns.pop("foo", None) - ip.user_ns.pop("foobar", None) - ip.user_ns.pop("foobaz", None) - ip.alias_manager.undefine_alias("bar") - ip.run_line_magic("cd", "-") - ip.user_ns["_dh"][:] = [] - - # Check restoring - ip.run_line_magic("store", "-r foo bar foobar foobaz") - assert ip.user_ns["foo"] == 78 - assert ip.alias_manager.is_alias("bar") - assert ip.user_ns["foobar"] == 79 - assert ip.user_ns["foobaz"] == "80" - - ip.run_line_magic("store", "-r") # restores _dh too - assert any(Path(tmpd).samefile(p) for p in ip.user_ns["_dh"]) - - os.rmdir(tmpd) - -def test_autorestore(): - ip.user_ns["foo"] = 95 - ip.run_line_magic("store", "foo") - del ip.user_ns["foo"] - c = Config() - c.StoreMagics.autorestore = False - orig_config = ip.config - try: - ip.config = c - ip.extension_manager.reload_extension("storemagic") - assert "foo" not in ip.user_ns - c.StoreMagics.autorestore = True - ip.extension_manager.reload_extension("storemagic") - assert ip.user_ns["foo"] == 95 - finally: - ip.config = orig_config diff --git a/.venv/lib/python3.12/site-packages/IPython/external/__init__.py b/.venv/lib/python3.12/site-packages/IPython/external/__init__.py deleted file mode 100644 index eedc338..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/external/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -""" -This package contains all third-party modules bundled with IPython. -""" - -from typing import List - -__all__: List[str] = [] diff --git a/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index c149db2..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/qt_for_kernel.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/qt_for_kernel.cpython-312.pyc deleted file mode 100644 index 59dcea1..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/qt_for_kernel.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/qt_loaders.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/qt_loaders.cpython-312.pyc deleted file mode 100644 index 55ddf27..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/external/__pycache__/qt_loaders.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/external/qt_for_kernel.py b/.venv/lib/python3.12/site-packages/IPython/external/qt_for_kernel.py deleted file mode 100644 index 11e8862..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/external/qt_for_kernel.py +++ /dev/null @@ -1,124 +0,0 @@ -""" Import Qt in a manner suitable for an IPython kernel. - -This is the import used for the `gui=qt` or `matplotlib=qt` initialization. - -Import Priority: - -if Qt has been imported anywhere else: - use that - -if matplotlib has been imported and doesn't support v2 (<= 1.0.1): - use PyQt4 @v1 - -Next, ask QT_API env variable - -if QT_API not set: - ask matplotlib what it's using. If Qt4Agg or Qt5Agg, then use the - version matplotlib is configured with - - else: (matplotlib said nothing) - # this is the default path - nobody told us anything - try in this order: - PyQt default version, PySide, PyQt5 -else: - use what QT_API says - - Note that %gui's implementation will always set a `QT_API`, see - `IPython.terminal.pt_inputhooks.get_inputhook_name_and_func` - -""" -# NOTE: This is no longer an external, third-party module, and should be -# considered part of IPython. For compatibility however, it is being kept in -# IPython/external. - -import os -import sys - -from IPython.external.qt_loaders import ( - load_qt, - loaded_api, - enum_factory, - # QT6 - QT_API_PYQT6, - QT_API_PYSIDE6, - # QT5 - QT_API_PYQT5, - QT_API_PYSIDE2, - # QT4 - QT_API_PYQT, - QT_API_PYSIDE, - # default - QT_API_PYQT_DEFAULT, -) - -_qt_apis = ( - # QT6 - QT_API_PYQT6, - QT_API_PYSIDE6, - # QT5 - QT_API_PYQT5, - QT_API_PYSIDE2, - # default - QT_API_PYQT_DEFAULT, -) - - -def matplotlib_options(mpl): - """Constraints placed on an imported matplotlib.""" - if mpl is None: - return - backend = mpl.rcParams.get('backend', None) - if backend == 'Qt4Agg': - mpqt = mpl.rcParams.get('backend.qt4', None) - if mpqt is None: - return None - if mpqt.lower() == 'pyside': - return [QT_API_PYSIDE] - elif mpqt.lower() == 'pyqt4': - return [QT_API_PYQT_DEFAULT] - elif mpqt.lower() == 'pyqt4v2': - return [QT_API_PYQT] - raise ImportError("unhandled value for backend.qt4 from matplotlib: %r" % - mpqt) - elif backend == 'Qt5Agg': - mpqt = mpl.rcParams.get('backend.qt5', None) - if mpqt is None: - return None - if mpqt.lower() == 'pyqt5': - return [QT_API_PYQT5] - raise ImportError("unhandled value for backend.qt5 from matplotlib: %r" % - mpqt) - -def get_options(): - """Return a list of acceptable QT APIs, in decreasing order of preference.""" - #already imported Qt somewhere. Use that - loaded = loaded_api() - if loaded is not None: - return [loaded] - - mpl = sys.modules.get("matplotlib", None) - - if mpl is not None and tuple(mpl.__version__.split(".")) < ("1", "0", "2"): - # 1.0.1 only supports PyQt4 v1 - return [QT_API_PYQT_DEFAULT] - - qt_api = os.environ.get('QT_API', None) - if qt_api is None: - #no ETS variable. Ask mpl, then use default fallback path - return matplotlib_options(mpl) or [ - QT_API_PYQT_DEFAULT, - QT_API_PYQT6, - QT_API_PYSIDE6, - QT_API_PYQT5, - QT_API_PYSIDE2, - ] - elif qt_api not in _qt_apis: - raise RuntimeError("Invalid Qt API %r, valid values are: %r" % - (qt_api, ', '.join(_qt_apis))) - else: - return [qt_api] - - -api_opts = get_options() -QtCore, QtGui, QtSvg, QT_API = load_qt(api_opts) -enum_helper = enum_factory(QT_API, QtCore) diff --git a/.venv/lib/python3.12/site-packages/IPython/external/qt_loaders.py b/.venv/lib/python3.12/site-packages/IPython/external/qt_loaders.py deleted file mode 100644 index 87b7165..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/external/qt_loaders.py +++ /dev/null @@ -1,423 +0,0 @@ -""" -This module contains factory functions that attempt -to return Qt submodules from the various python Qt bindings. - -It also protects against double-importing Qt with different -bindings, which is unstable and likely to crash - -This is used primarily by qt and qt_for_kernel, and shouldn't -be accessed directly from the outside -""" - -import importlib.abc -import sys -import os -import types -from functools import partial, lru_cache -import operator - -# ### Available APIs. -# Qt6 -QT_API_PYQT6 = "pyqt6" -QT_API_PYSIDE6 = "pyside6" - -# Qt5 -QT_API_PYQT5 = 'pyqt5' -QT_API_PYSIDE2 = 'pyside2' - -# Qt4 -# NOTE: Here for legacy matplotlib compatibility, but not really supported on the IPython side. -QT_API_PYQT = "pyqt" # Force version 2 -QT_API_PYQTv1 = "pyqtv1" # Force version 2 -QT_API_PYSIDE = "pyside" - -QT_API_PYQT_DEFAULT = "pyqtdefault" # use system default for version 1 vs. 2 - -api_to_module = { - # Qt6 - QT_API_PYQT6: "PyQt6", - QT_API_PYSIDE6: "PySide6", - # Qt5 - QT_API_PYQT5: "PyQt5", - QT_API_PYSIDE2: "PySide2", - # Qt4 - QT_API_PYSIDE: "PySide", - QT_API_PYQT: "PyQt4", - QT_API_PYQTv1: "PyQt4", - # default - QT_API_PYQT_DEFAULT: "PyQt6", -} - - -class ImportDenier(importlib.abc.MetaPathFinder): - """Import Hook that will guard against bad Qt imports - once IPython commits to a specific binding - """ - - def __init__(self): - self.__forbidden = set() - - def forbid(self, module_name): - sys.modules.pop(module_name, None) - self.__forbidden.add(module_name) - - def find_spec(self, fullname, path, target=None): - if path: - return - if fullname in self.__forbidden: - raise ImportError( - """ - Importing %s disabled by IPython, which has - already imported an Incompatible QT Binding: %s - """ - % (fullname, loaded_api()) - ) - - -ID = ImportDenier() -sys.meta_path.insert(0, ID) - - -def commit_api(api): - """Commit to a particular API, and trigger ImportErrors on subsequent - dangerous imports""" - modules = set(api_to_module.values()) - - modules.remove(api_to_module[api]) - for mod in modules: - ID.forbid(mod) - - -def loaded_api(): - """Return which API is loaded, if any - - If this returns anything besides None, - importing any other Qt binding is unsafe. - - Returns - ------- - None, 'pyside6', 'pyqt6', 'pyside2', 'pyside', 'pyqt', 'pyqt5', 'pyqtv1' - """ - if sys.modules.get("PyQt6.QtCore"): - return QT_API_PYQT6 - elif sys.modules.get("PySide6.QtCore"): - return QT_API_PYSIDE6 - elif sys.modules.get("PyQt5.QtCore"): - return QT_API_PYQT5 - elif sys.modules.get("PySide2.QtCore"): - return QT_API_PYSIDE2 - elif sys.modules.get("PyQt4.QtCore"): - if qtapi_version() == 2: - return QT_API_PYQT - else: - return QT_API_PYQTv1 - elif sys.modules.get("PySide.QtCore"): - return QT_API_PYSIDE - - return None - - -def has_binding(api): - """Safely check for PyQt4/5, PySide or PySide2, without importing submodules - - Parameters - ---------- - api : str [ 'pyqtv1' | 'pyqt' | 'pyqt5' | 'pyside' | 'pyside2' | 'pyqtdefault'] - Which module to check for - - Returns - ------- - True if the relevant module appears to be importable - """ - module_name = api_to_module[api] - from importlib.util import find_spec - - required = ['QtCore', 'QtGui', 'QtSvg'] - if api in (QT_API_PYQT5, QT_API_PYSIDE2, QT_API_PYQT6, QT_API_PYSIDE6): - # QT5 requires QtWidgets too - required.append('QtWidgets') - - for submod in required: - try: - spec = find_spec('%s.%s' % (module_name, submod)) - except ImportError: - # Package (e.g. PyQt5) not found - return False - else: - if spec is None: - # Submodule (e.g. PyQt5.QtCore) not found - return False - - if api == QT_API_PYSIDE: - # We can also safely check PySide version - import PySide - - return PySide.__version_info__ >= (1, 0, 3) - - return True - - -def qtapi_version(): - """Return which QString API has been set, if any - - Returns - ------- - The QString API version (1 or 2), or None if not set - """ - try: - import sip - except ImportError: - # as of PyQt5 5.11, sip is no longer available as a top-level - # module and needs to be imported from the PyQt5 namespace - try: - from PyQt5 import sip - except ImportError: - return - try: - return sip.getapi('QString') - except ValueError: - return - - -def can_import(api): - """Safely query whether an API is importable, without importing it""" - if not has_binding(api): - return False - - current = loaded_api() - if api == QT_API_PYQT_DEFAULT: - return current in [QT_API_PYQT6, None] - else: - return current in [api, None] - - -def import_pyqt4(version=2): - """ - Import PyQt4 - - Parameters - ---------- - version : 1, 2, or None - Which QString/QVariant API to use. Set to None to use the system - default - ImportErrors raised within this function are non-recoverable - """ - # The new-style string API (version=2) automatically - # converts QStrings to Unicode Python strings. Also, automatically unpacks - # QVariants to their underlying objects. - import sip - - if version is not None: - sip.setapi('QString', version) - sip.setapi('QVariant', version) - - from PyQt4 import QtGui, QtCore, QtSvg - - if QtCore.PYQT_VERSION < 0x040700: - raise ImportError("IPython requires PyQt4 >= 4.7, found %s" % - QtCore.PYQT_VERSION_STR) - - # Alias PyQt-specific functions for PySide compatibility. - QtCore.Signal = QtCore.pyqtSignal - QtCore.Slot = QtCore.pyqtSlot - - # query for the API version (in case version == None) - version = sip.getapi('QString') - api = QT_API_PYQTv1 if version == 1 else QT_API_PYQT - return QtCore, QtGui, QtSvg, api - - -def import_pyqt5(): - """ - Import PyQt5 - - ImportErrors raised within this function are non-recoverable - """ - - from PyQt5 import QtCore, QtSvg, QtWidgets, QtGui - - # Alias PyQt-specific functions for PySide compatibility. - QtCore.Signal = QtCore.pyqtSignal - QtCore.Slot = QtCore.pyqtSlot - - # Join QtGui and QtWidgets for Qt4 compatibility. - QtGuiCompat = types.ModuleType('QtGuiCompat') - QtGuiCompat.__dict__.update(QtGui.__dict__) - QtGuiCompat.__dict__.update(QtWidgets.__dict__) - - api = QT_API_PYQT5 - return QtCore, QtGuiCompat, QtSvg, api - - -def import_pyqt6(): - """ - Import PyQt6 - - ImportErrors raised within this function are non-recoverable - """ - - from PyQt6 import QtCore, QtSvg, QtWidgets, QtGui - - # Alias PyQt-specific functions for PySide compatibility. - QtCore.Signal = QtCore.pyqtSignal - QtCore.Slot = QtCore.pyqtSlot - - # Join QtGui and QtWidgets for Qt4 compatibility. - QtGuiCompat = types.ModuleType("QtGuiCompat") - QtGuiCompat.__dict__.update(QtGui.__dict__) - QtGuiCompat.__dict__.update(QtWidgets.__dict__) - - api = QT_API_PYQT6 - return QtCore, QtGuiCompat, QtSvg, api - - -def import_pyside(): - """ - Import PySide - - ImportErrors raised within this function are non-recoverable - """ - from PySide import QtGui, QtCore, QtSvg - return QtCore, QtGui, QtSvg, QT_API_PYSIDE - -def import_pyside2(): - """ - Import PySide2 - - ImportErrors raised within this function are non-recoverable - """ - from PySide2 import QtGui, QtCore, QtSvg, QtWidgets, QtPrintSupport - - # Join QtGui and QtWidgets for Qt4 compatibility. - QtGuiCompat = types.ModuleType('QtGuiCompat') - QtGuiCompat.__dict__.update(QtGui.__dict__) - QtGuiCompat.__dict__.update(QtWidgets.__dict__) - QtGuiCompat.__dict__.update(QtPrintSupport.__dict__) - - return QtCore, QtGuiCompat, QtSvg, QT_API_PYSIDE2 - - -def import_pyside6(): - """ - Import PySide6 - - ImportErrors raised within this function are non-recoverable - """ - - def get_attrs(module): - return { - name: getattr(module, name) - for name in dir(module) - if not name.startswith("_") - } - - from PySide6 import QtGui, QtCore, QtSvg, QtWidgets, QtPrintSupport - - # Join QtGui and QtWidgets for Qt4 compatibility. - QtGuiCompat = types.ModuleType("QtGuiCompat") - QtGuiCompat.__dict__.update(QtGui.__dict__) - if QtCore.__version_info__ < (6, 7): - QtGuiCompat.__dict__.update(QtWidgets.__dict__) - QtGuiCompat.__dict__.update(QtPrintSupport.__dict__) - else: - QtGuiCompat.__dict__.update(get_attrs(QtWidgets)) - QtGuiCompat.__dict__.update(get_attrs(QtPrintSupport)) - - return QtCore, QtGuiCompat, QtSvg, QT_API_PYSIDE6 - - -def load_qt(api_options): - """ - Attempt to import Qt, given a preference list - of permissible bindings - - It is safe to call this function multiple times. - - Parameters - ---------- - api_options : List of strings - The order of APIs to try. Valid items are 'pyside', 'pyside2', - 'pyqt', 'pyqt5', 'pyqtv1' and 'pyqtdefault' - - Returns - ------- - A tuple of QtCore, QtGui, QtSvg, QT_API - The first three are the Qt modules. The last is the - string indicating which module was loaded. - - Raises - ------ - ImportError, if it isn't possible to import any requested - bindings (either because they aren't installed, or because - an incompatible library has already been installed) - """ - loaders = { - # Qt6 - QT_API_PYQT6: import_pyqt6, - QT_API_PYSIDE6: import_pyside6, - # Qt5 - QT_API_PYQT5: import_pyqt5, - QT_API_PYSIDE2: import_pyside2, - # Qt4 - QT_API_PYSIDE: import_pyside, - QT_API_PYQT: import_pyqt4, - QT_API_PYQTv1: partial(import_pyqt4, version=1), - # default - QT_API_PYQT_DEFAULT: import_pyqt6, - } - - for api in api_options: - - if api not in loaders: - raise RuntimeError( - "Invalid Qt API %r, valid values are: %s" % - (api, ", ".join(["%r" % k for k in loaders.keys()]))) - - if not can_import(api): - continue - - #cannot safely recover from an ImportError during this - result = loaders[api]() - api = result[-1] # changed if api = QT_API_PYQT_DEFAULT - commit_api(api) - return result - else: - # Clear the environment variable since it doesn't work. - if "QT_API" in os.environ: - del os.environ["QT_API"] - - raise ImportError( - """ - Could not load requested Qt binding. Please ensure that - PyQt4 >= 4.7, PyQt5, PyQt6, PySide >= 1.0.3, PySide2, or - PySide6 is available, and only one is imported per session. - - Currently-imported Qt library: %r - PyQt5 available (requires QtCore, QtGui, QtSvg, QtWidgets): %s - PyQt6 available (requires QtCore, QtGui, QtSvg, QtWidgets): %s - PySide2 installed: %s - PySide6 installed: %s - Tried to load: %r - """ - % ( - loaded_api(), - has_binding(QT_API_PYQT5), - has_binding(QT_API_PYQT6), - has_binding(QT_API_PYSIDE2), - has_binding(QT_API_PYSIDE6), - api_options, - ) - ) - - -def enum_factory(QT_API, QtCore): - """Construct an enum helper to account for PyQt5 <-> PyQt6 changes.""" - - @lru_cache(None) - def _enum(name): - # foo.bar.Enum.Entry (PyQt6) <=> foo.bar.Entry (non-PyQt6). - return operator.attrgetter( - name if QT_API == QT_API_PYQT6 else name.rpartition(".")[0] - )(sys.modules[QtCore.__package__]) - - return _enum diff --git a/.venv/lib/python3.12/site-packages/IPython/external/tests/__init__.py b/.venv/lib/python3.12/site-packages/IPython/external/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.venv/lib/python3.12/site-packages/IPython/external/tests/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/external/tests/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 21b1bf2..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/external/tests/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/external/tests/__pycache__/test_qt_loaders.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/external/tests/__pycache__/test_qt_loaders.cpython-312.pyc deleted file mode 100644 index c735599..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/external/tests/__pycache__/test_qt_loaders.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/external/tests/test_qt_loaders.py b/.venv/lib/python3.12/site-packages/IPython/external/tests/test_qt_loaders.py deleted file mode 100644 index 7bc9ccf..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/external/tests/test_qt_loaders.py +++ /dev/null @@ -1,11 +0,0 @@ -import importlib -import pytest -from IPython.external.qt_loaders import ID - - -def test_import_denier(): - ID.forbid("ipython_denied_module") - with pytest.raises(ImportError, match="disabled by IPython"): - import ipython_denied_module - with pytest.raises(ImportError, match="disabled by IPython"): - importlib.import_module("ipython_denied_module") diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__init__.py b/.venv/lib/python3.12/site-packages/IPython/lib/__init__.py deleted file mode 100644 index cf8ccb0..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# encoding: utf-8 -""" -Extra capabilities for IPython -""" - -# ----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -# ----------------------------------------------------------------------------- diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f669c71..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/backgroundjobs.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/backgroundjobs.cpython-312.pyc deleted file mode 100644 index 91ecd6a..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/backgroundjobs.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/clipboard.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/clipboard.cpython-312.pyc deleted file mode 100644 index 000ceff..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/clipboard.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/deepreload.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/deepreload.cpython-312.pyc deleted file mode 100644 index c6d92d1..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/deepreload.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/demo.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/demo.cpython-312.pyc deleted file mode 100644 index 49ac77d..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/demo.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/display.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/display.cpython-312.pyc deleted file mode 100644 index 60dd2c9..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/display.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/editorhooks.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/editorhooks.cpython-312.pyc deleted file mode 100644 index 8bfaf65..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/editorhooks.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/guisupport.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/guisupport.cpython-312.pyc deleted file mode 100644 index 03a9aef..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/guisupport.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/latextools.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/latextools.cpython-312.pyc deleted file mode 100644 index 1df5f76..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/latextools.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/lexers.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/lexers.cpython-312.pyc deleted file mode 100644 index 3de0f15..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/lexers.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/pretty.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/pretty.cpython-312.pyc deleted file mode 100644 index ddcbcca..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/__pycache__/pretty.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/backgroundjobs.py b/.venv/lib/python3.12/site-packages/IPython/lib/backgroundjobs.py deleted file mode 100644 index e7ad51e..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/backgroundjobs.py +++ /dev/null @@ -1,491 +0,0 @@ -# -*- coding: utf-8 -*- -"""Manage background (threaded) jobs conveniently from an interactive shell. - -This module provides a BackgroundJobManager class. This is the main class -meant for public usage, it implements an object which can create and manage -new background jobs. - -It also provides the actual job classes managed by these BackgroundJobManager -objects, see their docstrings below. - - -This system was inspired by discussions with B. Granger and the -BackgroundCommand class described in the book Python Scripting for -Computational Science, by H. P. Langtangen: - -http://folk.uio.no/hpl/scripting - -(although ultimately no code from this text was used, as IPython's system is a -separate implementation). - -An example notebook is provided in our documentation illustrating interactive -use of the system. -""" - -#***************************************************************************** -# Copyright (C) 2005-2006 Fernando Perez -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -# Code begins -import sys -import threading - -from IPython import get_ipython -from IPython.core.ultratb import AutoFormattedTB -from logging import error, debug - - -class BackgroundJobManager(object): - """Class to manage a pool of backgrounded threaded jobs. - - Below, we assume that 'jobs' is a BackgroundJobManager instance. - - Usage summary (see the method docstrings for details): - - jobs.new(...) -> start a new job - - jobs() or jobs.status() -> print status summary of all jobs - - jobs[N] -> returns job number N. - - foo = jobs[N].result -> assign to variable foo the result of job N - - jobs[N].traceback() -> print the traceback of dead job N - - jobs.remove(N) -> remove (finished) job N - - jobs.flush() -> remove all finished jobs - - As a convenience feature, BackgroundJobManager instances provide the - utility result and traceback methods which retrieve the corresponding - information from the jobs list: - - jobs.result(N) <--> jobs[N].result - jobs.traceback(N) <--> jobs[N].traceback() - - While this appears minor, it allows you to use tab completion - interactively on the job manager instance. - """ - - def __init__(self): - # Lists for job management, accessed via a property to ensure they're - # up to date.x - self._running = [] - self._completed = [] - self._dead = [] - # A dict of all jobs, so users can easily access any of them - self.all = {} - # For reporting - self._comp_report = [] - self._dead_report = [] - # Store status codes locally for fast lookups - self._s_created = BackgroundJobBase.stat_created_c - self._s_running = BackgroundJobBase.stat_running_c - self._s_completed = BackgroundJobBase.stat_completed_c - self._s_dead = BackgroundJobBase.stat_dead_c - self._current_job_id = 0 - - @property - def running(self): - self._update_status() - return self._running - - @property - def dead(self): - self._update_status() - return self._dead - - @property - def completed(self): - self._update_status() - return self._completed - - def new(self, func_or_exp, *args, **kwargs): - """Add a new background job and start it in a separate thread. - - There are two types of jobs which can be created: - - 1. Jobs based on expressions which can be passed to an eval() call. - The expression must be given as a string. For example: - - job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]]) - - The given expression is passed to eval(), along with the optional - global/local dicts provided. If no dicts are given, they are - extracted automatically from the caller's frame. - - A Python statement is NOT a valid eval() expression. Basically, you - can only use as an eval() argument something which can go on the right - of an '=' sign and be assigned to a variable. - - For example,"print 'hello'" is not valid, but '2+3' is. - - 2. Jobs given a function object, optionally passing additional - positional arguments: - - job_manager.new(myfunc, x, y) - - The function is called with the given arguments. - - If you need to pass keyword arguments to your function, you must - supply them as a dict named kw: - - job_manager.new(myfunc, x, y, kw=dict(z=1)) - - The reason for this asymmetry is that the new() method needs to - maintain access to its own keywords, and this prevents name collisions - between arguments to new() and arguments to your own functions. - - In both cases, the result is stored in the job.result field of the - background job object. - - You can set `daemon` attribute of the thread by giving the keyword - argument `daemon`. - - Notes and caveats: - - 1. All threads running share the same standard output. Thus, if your - background jobs generate output, it will come out on top of whatever - you are currently writing. For this reason, background jobs are best - used with silent functions which simply return their output. - - 2. Threads also all work within the same global namespace, and this - system does not lock interactive variables. So if you send job to the - background which operates on a mutable object for a long time, and - start modifying that same mutable object interactively (or in another - backgrounded job), all sorts of bizarre behaviour will occur. - - 3. If a background job is spending a lot of time inside a C extension - module which does not release the Python Global Interpreter Lock - (GIL), this will block the IPython prompt. This is simply because the - Python interpreter can only switch between threads at Python - bytecodes. While the execution is inside C code, the interpreter must - simply wait unless the extension module releases the GIL. - - 4. There is no way, due to limitations in the Python threads library, - to kill a thread once it has started.""" - - if callable(func_or_exp): - kw = kwargs.get('kw',{}) - job = BackgroundJobFunc(func_or_exp,*args,**kw) - elif isinstance(func_or_exp, str): - if not args: - frame = sys._getframe(1) - glob, loc = frame.f_globals, frame.f_locals - elif len(args)==1: - glob = loc = args[0] - elif len(args)==2: - glob,loc = args - else: - raise ValueError( - 'Expression jobs take at most 2 args (globals,locals)') - job = BackgroundJobExpr(func_or_exp, glob, loc) - else: - raise TypeError('invalid args for new job') - - if kwargs.get('daemon', False): - job.daemon = True - job.num = self._current_job_id - self._current_job_id += 1 - self.running.append(job) - self.all[job.num] = job - debug('Starting job # %s in a separate thread.' % job.num) - job.start() - return job - - def __getitem__(self, job_key): - num = job_key if isinstance(job_key, int) else job_key.num - return self.all[num] - - def __call__(self): - """An alias to self.status(), - - This allows you to simply call a job manager instance much like the - Unix `jobs` shell command.""" - - return self.status() - - def _update_status(self): - """Update the status of the job lists. - - This method moves finished jobs to one of two lists: - - self.completed: jobs which completed successfully - - self.dead: jobs which finished but died. - - It also copies those jobs to corresponding _report lists. These lists - are used to report jobs completed/dead since the last update, and are - then cleared by the reporting function after each call.""" - - # Status codes - srun, scomp, sdead = self._s_running, self._s_completed, self._s_dead - # State lists, use the actual lists b/c the public names are properties - # that call this very function on access - running, completed, dead = self._running, self._completed, self._dead - - # Now, update all state lists - for num, job in enumerate(running): - stat = job.stat_code - if stat == srun: - continue - elif stat == scomp: - completed.append(job) - self._comp_report.append(job) - running[num] = False - elif stat == sdead: - dead.append(job) - self._dead_report.append(job) - running[num] = False - # Remove dead/completed jobs from running list - running[:] = filter(None, running) - - def _group_report(self,group,name): - """Report summary for a given job group. - - Return True if the group had any elements.""" - - if group: - print('%s jobs:' % name) - for job in group: - print('%s : %s' % (job.num,job)) - print() - return True - - def _group_flush(self,group,name): - """Flush a given job group - - Return True if the group had any elements.""" - - njobs = len(group) - if njobs: - plural = {1:''}.setdefault(njobs,'s') - print('Flushing %s %s job%s.' % (njobs,name,plural)) - group[:] = [] - return True - - def _status_new(self): - """Print the status of newly finished jobs. - - Return True if any new jobs are reported. - - This call resets its own state every time, so it only reports jobs - which have finished since the last time it was called.""" - - self._update_status() - new_comp = self._group_report(self._comp_report, 'Completed') - new_dead = self._group_report(self._dead_report, - 'Dead, call jobs.traceback() for details') - self._comp_report[:] = [] - self._dead_report[:] = [] - return new_comp or new_dead - - def status(self,verbose=0): - """Print a status of all jobs currently being managed.""" - - self._update_status() - self._group_report(self.running,'Running') - self._group_report(self.completed,'Completed') - self._group_report(self.dead,'Dead') - # Also flush the report queues - self._comp_report[:] = [] - self._dead_report[:] = [] - - def remove(self,num): - """Remove a finished (completed or dead) job.""" - - try: - job = self.all[num] - except KeyError: - error('Job #%s not found' % num) - else: - stat_code = job.stat_code - if stat_code == self._s_running: - error('Job #%s is still running, it can not be removed.' % num) - return - elif stat_code == self._s_completed: - self.completed.remove(job) - elif stat_code == self._s_dead: - self.dead.remove(job) - - def flush(self): - """Flush all finished jobs (completed and dead) from lists. - - Running jobs are never flushed. - - It first calls _status_new(), to update info. If any jobs have - completed since the last _status_new() call, the flush operation - aborts.""" - - # Remove the finished jobs from the master dict - alljobs = self.all - for job in self.completed+self.dead: - del(alljobs[job.num]) - - # Now flush these lists completely - fl_comp = self._group_flush(self.completed, 'Completed') - fl_dead = self._group_flush(self.dead, 'Dead') - if not (fl_comp or fl_dead): - print('No jobs to flush.') - - def result(self,num): - """result(N) -> return the result of job N.""" - try: - return self.all[num].result - except KeyError: - error('Job #%s not found' % num) - - def _traceback(self, job): - num = job if isinstance(job, int) else job.num - try: - self.all[num].traceback() - except KeyError: - error('Job #%s not found' % num) - - def traceback(self, job=None): - if job is None: - self._update_status() - for deadjob in self.dead: - print("Traceback for: %r" % deadjob) - self._traceback(deadjob) - print() - else: - self._traceback(job) - - -class BackgroundJobBase(threading.Thread): - """Base class to build BackgroundJob classes. - - The derived classes must implement: - - - Their own __init__, since the one here raises NotImplementedError. The - derived constructor must call self._init() at the end, to provide common - initialization. - - - A strform attribute used in calls to __str__. - - - A call() method, which will make the actual execution call and must - return a value to be held in the 'result' field of the job object. - """ - - # Class constants for status, in string and as numerical codes (when - # updating jobs lists, we don't want to do string comparisons). This will - # be done at every user prompt, so it has to be as fast as possible - stat_created = 'Created'; stat_created_c = 0 - stat_running = 'Running'; stat_running_c = 1 - stat_completed = 'Completed'; stat_completed_c = 2 - stat_dead = 'Dead (Exception), call jobs.traceback() for details' - stat_dead_c = -1 - - def __init__(self): - """Must be implemented in subclasses. - - Subclasses must call :meth:`_init` for standard initialisation. - """ - raise NotImplementedError("This class can not be instantiated directly.") - - def _init(self): - """Common initialization for all BackgroundJob objects""" - - for attr in ['call','strform']: - assert hasattr(self,attr), "Missing attribute <%s>" % attr - - # The num tag can be set by an external job manager - self.num = None - - self.status = BackgroundJobBase.stat_created - self.stat_code = BackgroundJobBase.stat_created_c - self.finished = False - self.result = '' - - # reuse the ipython traceback handler if we can get to it, otherwise - # make a new one - try: - make_tb = get_ipython().InteractiveTB.text - except: - make_tb = AutoFormattedTB(mode = 'Context', - color_scheme='NoColor', - tb_offset = 1).text - # Note that the actual API for text() requires the three args to be - # passed in, so we wrap it in a simple lambda. - self._make_tb = lambda : make_tb(None, None, None) - - # Hold a formatted traceback if one is generated. - self._tb = None - - threading.Thread.__init__(self) - - def __str__(self): - return self.strform - - def __repr__(self): - return '' % (self.num, self.strform) - - def traceback(self): - print(self._tb) - - def run(self): - try: - self.status = BackgroundJobBase.stat_running - self.stat_code = BackgroundJobBase.stat_running_c - self.result = self.call() - except: - self.status = BackgroundJobBase.stat_dead - self.stat_code = BackgroundJobBase.stat_dead_c - self.finished = None - self.result = ('') - self._tb = self._make_tb() - else: - self.status = BackgroundJobBase.stat_completed - self.stat_code = BackgroundJobBase.stat_completed_c - self.finished = True - - -class BackgroundJobExpr(BackgroundJobBase): - """Evaluate an expression as a background job (uses a separate thread).""" - - def __init__(self, expression, glob=None, loc=None): - """Create a new job from a string which can be fed to eval(). - - global/locals dicts can be provided, which will be passed to the eval - call.""" - - # fail immediately if the given expression can't be compiled - self.code = compile(expression,'','eval') - - glob = {} if glob is None else glob - loc = {} if loc is None else loc - self.expression = self.strform = expression - self.glob = glob - self.loc = loc - self._init() - - def call(self): - return eval(self.code,self.glob,self.loc) - - -class BackgroundJobFunc(BackgroundJobBase): - """Run a function call as a background job (uses a separate thread).""" - - def __init__(self, func, *args, **kwargs): - """Create a new job from a callable object. - - Any positional arguments and keyword args given to this constructor - after the initial callable are passed directly to it.""" - - if not callable(func): - raise TypeError( - 'first argument to BackgroundJobFunc must be callable') - - self.func = func - self.args = args - self.kwargs = kwargs - # The string form will only include the function passed, because - # generating string representations of the arguments is a potentially - # _very_ expensive operation (e.g. with large arrays). - self.strform = str(func) - self._init() - - def call(self): - return self.func(*self.args, **self.kwargs) diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/clipboard.py b/.venv/lib/python3.12/site-packages/IPython/lib/clipboard.py deleted file mode 100644 index e0bf80b..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/clipboard.py +++ /dev/null @@ -1,102 +0,0 @@ -""" Utilities for accessing the platform's clipboard. -""" - -import os -import subprocess - -from IPython.core.error import TryNext -import IPython.utils.py3compat as py3compat - - -class ClipboardEmpty(ValueError): - pass - - -def win32_clipboard_get(): - """ Get the current clipboard's text on Windows. - - Requires Mark Hammond's pywin32 extensions. - """ - try: - import win32clipboard - except ImportError as e: - raise TryNext("Getting text from the clipboard requires the pywin32 " - "extensions: http://sourceforge.net/projects/pywin32/") from e - win32clipboard.OpenClipboard() - try: - text = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT) - except (TypeError, win32clipboard.error): - try: - text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT) - text = py3compat.cast_unicode(text, py3compat.DEFAULT_ENCODING) - except (TypeError, win32clipboard.error) as e: - raise ClipboardEmpty from e - finally: - win32clipboard.CloseClipboard() - return text - - -def osx_clipboard_get() -> str: - """ Get the clipboard's text on OS X. - """ - p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'], - stdout=subprocess.PIPE) - bytes_, stderr = p.communicate() - # Text comes in with old Mac \r line endings. Change them to \n. - bytes_ = bytes_.replace(b'\r', b'\n') - text = py3compat.decode(bytes_) - return text - - -def tkinter_clipboard_get(): - """ Get the clipboard's text using Tkinter. - - This is the default on systems that are not Windows or OS X. It may - interfere with other UI toolkits and should be replaced with an - implementation that uses that toolkit. - """ - try: - from tkinter import Tk, TclError - except ImportError as e: - raise TryNext("Getting text from the clipboard on this platform requires tkinter.") from e - - root = Tk() - root.withdraw() - try: - text = root.clipboard_get() - except TclError as e: - raise ClipboardEmpty from e - finally: - root.destroy() - text = py3compat.cast_unicode(text, py3compat.DEFAULT_ENCODING) - return text - - -def wayland_clipboard_get(): - """Get the clipboard's text under Wayland using wl-paste command. - - This requires Wayland and wl-clipboard installed and running. - """ - if os.environ.get("XDG_SESSION_TYPE") != "wayland": - raise TryNext("wayland is not detected") - - try: - with subprocess.Popen(["wl-paste"], stdout=subprocess.PIPE) as p: - raw, err = p.communicate() - if p.wait(): - raise TryNext(err) - except FileNotFoundError as e: - raise TryNext( - "Getting text from the clipboard under Wayland requires the wl-clipboard " - "extension: https://github.com/bugaevc/wl-clipboard" - ) from e - - if not raw: - raise ClipboardEmpty - - try: - text = py3compat.decode(raw) - except UnicodeDecodeError as e: - raise ClipboardEmpty from e - - return text diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/deepreload.py b/.venv/lib/python3.12/site-packages/IPython/lib/deepreload.py deleted file mode 100644 index aaedab2..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/deepreload.py +++ /dev/null @@ -1,310 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Provides a reload() function that acts recursively. - -Python's normal :func:`python:reload` function only reloads the module that it's -passed. The :func:`reload` function in this module also reloads everything -imported from that module, which is useful when you're changing files deep -inside a package. - -To use this as your default reload function, type this:: - - import builtins - from IPython.lib import deepreload - builtins.reload = deepreload.reload - -A reference to the original :func:`python:reload` is stored in this module as -:data:`original_reload`, so you can restore it later. - -This code is almost entirely based on knee.py, which is a Python -re-implementation of hierarchical module import. -""" -#***************************************************************************** -# Copyright (C) 2001 Nathaniel Gray -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -import builtins as builtin_mod -from contextlib import contextmanager -import importlib -import sys - -from types import ModuleType -from warnings import warn -import types - -original_import = builtin_mod.__import__ - -@contextmanager -def replace_import_hook(new_import): - saved_import = builtin_mod.__import__ - builtin_mod.__import__ = new_import - try: - yield - finally: - builtin_mod.__import__ = saved_import - -def get_parent(globals, level): - """ - parent, name = get_parent(globals, level) - - Return the package that an import is being performed in. If globals comes - from the module foo.bar.bat (not itself a package), this returns the - sys.modules entry for foo.bar. If globals is from a package's __init__.py, - the package's entry in sys.modules is returned. - - If globals doesn't come from a package or a module in a package, or a - corresponding entry is not found in sys.modules, None is returned. - """ - orig_level = level - - if not level or not isinstance(globals, dict): - return None, '' - - pkgname = globals.get('__package__', None) - - if pkgname is not None: - # __package__ is set, so use it - if not hasattr(pkgname, 'rindex'): - raise ValueError('__package__ set to non-string') - if len(pkgname) == 0: - if level > 0: - raise ValueError('Attempted relative import in non-package') - return None, '' - name = pkgname - else: - # __package__ not set, so figure it out and set it - if '__name__' not in globals: - return None, '' - modname = globals['__name__'] - - if '__path__' in globals: - # __path__ is set, so modname is already the package name - globals['__package__'] = name = modname - else: - # Normal module, so work out the package name if any - lastdot = modname.rfind('.') - if lastdot < 0 < level: - raise ValueError("Attempted relative import in non-package") - if lastdot < 0: - globals['__package__'] = None - return None, '' - globals['__package__'] = name = modname[:lastdot] - - dot = len(name) - for x in range(level, 1, -1): - try: - dot = name.rindex('.', 0, dot) - except ValueError as e: - raise ValueError("attempted relative import beyond top-level " - "package") from e - name = name[:dot] - - try: - parent = sys.modules[name] - except BaseException as e: - if orig_level < 1: - warn("Parent module '%.200s' not found while handling absolute " - "import" % name) - parent = None - else: - raise SystemError("Parent module '%.200s' not loaded, cannot " - "perform relative import" % name) from e - - # We expect, but can't guarantee, if parent != None, that: - # - parent.__name__ == name - # - parent.__dict__ is globals - # If this is violated... Who cares? - return parent, name - -def load_next(mod, altmod, name, buf): - """ - mod, name, buf = load_next(mod, altmod, name, buf) - - altmod is either None or same as mod - """ - - if len(name) == 0: - # completely empty module name should only happen in - # 'from . import' (or '__import__("")') - return mod, None, buf - - dot = name.find('.') - if dot == 0: - raise ValueError('Empty module name') - - if dot < 0: - subname = name - next = None - else: - subname = name[:dot] - next = name[dot+1:] - - if buf != '': - buf += '.' - buf += subname - - result = import_submodule(mod, subname, buf) - if result is None and mod != altmod: - result = import_submodule(altmod, subname, subname) - if result is not None: - buf = subname - - if result is None: - raise ImportError("No module named %.200s" % name) - - return result, next, buf - - -# Need to keep track of what we've already reloaded to prevent cyclic evil -found_now = {} - -def import_submodule(mod, subname, fullname): - """m = import_submodule(mod, subname, fullname)""" - # Require: - # if mod == None: subname == fullname - # else: mod.__name__ + "." + subname == fullname - - global found_now - if fullname in found_now and fullname in sys.modules: - m = sys.modules[fullname] - else: - print('Reloading', fullname) - found_now[fullname] = 1 - oldm = sys.modules.get(fullname, None) - try: - if oldm is not None: - m = importlib.reload(oldm) - else: - m = importlib.import_module(subname, mod) - except: - # load_module probably removed name from modules because of - # the error. Put back the original module object. - if oldm: - sys.modules[fullname] = oldm - raise - - add_submodule(mod, m, fullname, subname) - - return m - -def add_submodule(mod, submod, fullname, subname): - """mod.{subname} = submod""" - if mod is None: - return #Nothing to do here. - - if submod is None: - submod = sys.modules[fullname] - - setattr(mod, subname, submod) - - return - -def ensure_fromlist(mod, fromlist, buf, recursive): - """Handle 'from module import a, b, c' imports.""" - if not hasattr(mod, '__path__'): - return - for item in fromlist: - if not hasattr(item, 'rindex'): - raise TypeError("Item in ``from list'' not a string") - if item == '*': - if recursive: - continue # avoid endless recursion - try: - all = mod.__all__ - except AttributeError: - pass - else: - ret = ensure_fromlist(mod, all, buf, 1) - if not ret: - return 0 - elif not hasattr(mod, item): - import_submodule(mod, item, buf + '.' + item) - -def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1): - """Replacement for __import__()""" - parent, buf = get_parent(globals, level) - - head, name, buf = load_next(parent, None if level < 0 else parent, name, buf) - - tail = head - while name: - tail, name, buf = load_next(tail, tail, name, buf) - - # If tail is None, both get_parent and load_next found - # an empty module name: someone called __import__("") or - # doctored faulty bytecode - if tail is None: - raise ValueError('Empty module name') - - if not fromlist: - return head - - ensure_fromlist(tail, fromlist, buf, 0) - return tail - -modules_reloading = {} - -def deep_reload_hook(m): - """Replacement for reload().""" - # Hardcode this one as it would raise a NotImplementedError from the - # bowels of Python and screw up the import machinery after. - # unlike other imports the `exclude` list already in place is not enough. - - if m is types: - return m - if not isinstance(m, ModuleType): - raise TypeError("reload() argument must be module") - - name = m.__name__ - - if name not in sys.modules: - raise ImportError("reload(): module %.200s not in sys.modules" % name) - - global modules_reloading - try: - return modules_reloading[name] - except: - modules_reloading[name] = m - - try: - newm = importlib.reload(m) - except: - sys.modules[name] = m - raise - finally: - modules_reloading.clear() - return newm - -# Save the original hooks -original_reload = importlib.reload - -# Replacement for reload() -def reload( - module, - exclude=( - *sys.builtin_module_names, - "sys", - "os.path", - "builtins", - "__main__", - "numpy", - "numpy._globals", - ), -): - """Recursively reload all modules used in the given module. Optionally - takes a list of modules to exclude from reloading. The default exclude - list contains modules listed in sys.builtin_module_names with additional - sys, os.path, builtins and __main__, to prevent, e.g., resetting - display, exception, and io hooks. - """ - global found_now - for i in exclude: - found_now[i] = 1 - try: - with replace_import_hook(deep_import_hook): - return deep_reload_hook(module) - finally: - found_now = {} diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/demo.py b/.venv/lib/python3.12/site-packages/IPython/lib/demo.py deleted file mode 100644 index ebffd54..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/demo.py +++ /dev/null @@ -1,672 +0,0 @@ -"""Module for interactive demos using IPython. - -This module implements a few classes for running Python scripts interactively -in IPython for demonstrations. With very simple markup (a few tags in -comments), you can control points where the script stops executing and returns -control to IPython. - - -Provided classes ----------------- - -The classes are (see their docstrings for further details): - - - Demo: pure python demos - - - IPythonDemo: demos with input to be processed by IPython as if it had been - typed interactively (so magics work, as well as any other special syntax you - may have added via input prefilters). - - - LineDemo: single-line version of the Demo class. These demos are executed - one line at a time, and require no markup. - - - IPythonLineDemo: IPython version of the LineDemo class (the demo is - executed a line at a time, but processed via IPython). - - - ClearMixin: mixin to make Demo classes with less visual clutter. It - declares an empty marquee and a pre_cmd that clears the screen before each - block (see Subclassing below). - - - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo - classes. - -Inheritance diagram: - -.. inheritance-diagram:: IPython.lib.demo - :parts: 3 - -Subclassing ------------ - -The classes here all include a few methods meant to make customization by -subclassing more convenient. Their docstrings below have some more details: - - - highlight(): format every block and optionally highlight comments and - docstring content. - - - marquee(): generates a marquee to provide visible on-screen markers at each - block start and end. - - - pre_cmd(): run right before the execution of each block. - - - post_cmd(): run right after the execution of each block. If the block - raises an exception, this is NOT called. - - -Operation ---------- - -The file is run in its own empty namespace (though you can pass it a string of -arguments as if in a command line environment, and it will see those as -sys.argv). But at each stop, the global IPython namespace is updated with the -current internal demo namespace, so you can work interactively with the data -accumulated so far. - -By default, each block of code is printed (with syntax highlighting) before -executing it and you have to confirm execution. This is intended to show the -code to an audience first so you can discuss it, and only proceed with -execution once you agree. There are a few tags which allow you to modify this -behavior. - -The supported tags are: - -# stop - - Defines block boundaries, the points where IPython stops execution of the - file and returns to the interactive prompt. - - You can optionally mark the stop tag with extra dashes before and after the - word 'stop', to help visually distinguish the blocks in a text editor: - - # --- stop --- - - -# silent - - Make a block execute silently (and hence automatically). Typically used in - cases where you have some boilerplate or initialization code which you need - executed but do not want to be seen in the demo. - -# auto - - Make a block execute automatically, but still being printed. Useful for - simple code which does not warrant discussion, since it avoids the extra - manual confirmation. - -# auto_all - - This tag can _only_ be in the first block, and if given it overrides the - individual auto tags to make the whole demo fully automatic (no block asks - for confirmation). It can also be given at creation time (or the attribute - set later) to override what's in the file. - -While _any_ python file can be run as a Demo instance, if there are no stop -tags the whole file will run in a single block (no different that calling -first %pycat and then %run). The minimal markup to make this useful is to -place a set of stop tags; the other tags are only there to let you fine-tune -the execution. - -This is probably best explained with the simple example file below. You can -copy this into a file named ex_demo.py, and try running it via:: - - from IPython.lib.demo import Demo - d = Demo('ex_demo.py') - d() - -Each time you call the demo object, it runs the next block. The demo object -has a few useful methods for navigation, like again(), edit(), jump(), seek() -and back(). It can be reset for a new run via reset() or reloaded from disk -(in case you've edited the source) via reload(). See their docstrings below. - -Note: To make this simpler to explore, a file called "demo-exercizer.py" has -been added to the "docs/examples/core" directory. Just cd to this directory in -an IPython session, and type:: - - %run demo-exercizer.py - -and then follow the directions. - -Example -------- - -The following is a very simple example of a valid demo file. - -:: - - #################### EXAMPLE DEMO ############################### - '''A simple interactive demo to illustrate the use of IPython's Demo class.''' - - print('Hello, welcome to an interactive IPython demo.') - - # The mark below defines a block boundary, which is a point where IPython will - # stop execution and return to the interactive prompt. The dashes are actually - # optional and used only as a visual aid to clearly separate blocks while - # editing the demo code. - # stop - - x = 1 - y = 2 - - # stop - - # the mark below makes this block as silent - # silent - - print('This is a silent block, which gets executed but not printed.') - - # stop - # auto - print('This is an automatic block.') - print('It is executed without asking for confirmation, but printed.') - z = x + y - - print('z =', x) - - # stop - # This is just another normal block. - print('z is now:', z) - - print('bye!') - ################### END EXAMPLE DEMO ############################ -""" - - -#***************************************************************************** -# Copyright (C) 2005-2006 Fernando Perez. -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -# -#***************************************************************************** - -import os -import re -import shlex -import sys -import pygments -from pathlib import Path - -from IPython.utils.text import marquee -from IPython.utils import openpy -from IPython.utils import py3compat -__all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] - -class DemoError(Exception): pass - -def re_mark(mark): - return re.compile(r'^\s*#\s+\s+%s\s*$' % mark,re.MULTILINE) - -class Demo(object): - - re_stop = re_mark(r'-*\s?stop\s?-*') - re_silent = re_mark('silent') - re_auto = re_mark('auto') - re_auto_all = re_mark('auto_all') - - def __init__(self,src,title='',arg_str='',auto_all=None, format_rst=False, - formatter='terminal', style='default'): - """Make a new demo object. To run the demo, simply call the object. - - See the module docstring for full details and an example (you can use - IPython.Demo? in IPython to see it). - - Inputs: - - - src is either a file, or file-like object, or a - string that can be resolved to a filename. - - Optional inputs: - - - title: a string to use as the demo name. Of most use when the demo - you are making comes from an object that has no filename, or if you - want an alternate denotation distinct from the filename. - - - arg_str(''): a string of arguments, internally converted to a list - just like sys.argv, so the demo script can see a similar - environment. - - - auto_all(None): global flag to run all blocks automatically without - confirmation. This attribute overrides the block-level tags and - applies to the whole demo. It is an attribute of the object, and - can be changed at runtime simply by reassigning it to a boolean - value. - - - format_rst(False): a bool to enable comments and doc strings - formatting with pygments rst lexer - - - formatter('terminal'): a string of pygments formatter name to be - used. Useful values for terminals: terminal, terminal256, - terminal16m - - - style('default'): a string of pygments style name to be used. - """ - if hasattr(src, "read"): - # It seems to be a file or a file-like object - self.fname = "from a file-like object" - if title == '': - self.title = "from a file-like object" - else: - self.title = title - else: - # Assume it's a string or something that can be converted to one - self.fname = src - if title == '': - (filepath, filename) = os.path.split(src) - self.title = filename - else: - self.title = title - self.sys_argv = [src] + shlex.split(arg_str) - self.auto_all = auto_all - self.src = src - - try: - ip = get_ipython() # this is in builtins whenever IPython is running - self.inside_ipython = True - except NameError: - self.inside_ipython = False - - if self.inside_ipython: - # get a few things from ipython. While it's a bit ugly design-wise, - # it ensures that things like color scheme and the like are always in - # sync with the ipython mode being used. This class is only meant to - # be used inside ipython anyways, so it's OK. - self.ip_ns = ip.user_ns - self.ip_colorize = ip.pycolorize - self.ip_showtb = ip.showtraceback - self.ip_run_cell = ip.run_cell - self.shell = ip - - self.formatter = pygments.formatters.get_formatter_by_name(formatter, - style=style) - self.python_lexer = pygments.lexers.get_lexer_by_name("py3") - self.format_rst = format_rst - if format_rst: - self.rst_lexer = pygments.lexers.get_lexer_by_name("rst") - - # load user data and initialize data structures - self.reload() - - def fload(self): - """Load file object.""" - # read data and parse into blocks - if hasattr(self, 'fobj') and self.fobj is not None: - self.fobj.close() - if hasattr(self.src, "read"): - # It seems to be a file or a file-like object - self.fobj = self.src - else: - # Assume it's a string or something that can be converted to one - self.fobj = openpy.open(self.fname) - - def reload(self): - """Reload source from disk and initialize state.""" - self.fload() - - self.src = "".join(openpy.strip_encoding_cookie(self.fobj)) - src_b = [b.strip() for b in self.re_stop.split(self.src) if b] - self._silent = [bool(self.re_silent.findall(b)) for b in src_b] - self._auto = [bool(self.re_auto.findall(b)) for b in src_b] - - # if auto_all is not given (def. None), we read it from the file - if self.auto_all is None: - self.auto_all = bool(self.re_auto_all.findall(src_b[0])) - else: - self.auto_all = bool(self.auto_all) - - # Clean the sources from all markup so it doesn't get displayed when - # running the demo - src_blocks = [] - auto_strip = lambda s: self.re_auto.sub('',s) - for i,b in enumerate(src_b): - if self._auto[i]: - src_blocks.append(auto_strip(b)) - else: - src_blocks.append(b) - # remove the auto_all marker - src_blocks[0] = self.re_auto_all.sub('',src_blocks[0]) - - self.nblocks = len(src_blocks) - self.src_blocks = src_blocks - - # also build syntax-highlighted source - self.src_blocks_colored = list(map(self.highlight,self.src_blocks)) - - # ensure clean namespace and seek offset - self.reset() - - def reset(self): - """Reset the namespace and seek pointer to restart the demo""" - self.user_ns = {} - self.finished = False - self.block_index = 0 - - def _validate_index(self,index): - if index<0 or index>=self.nblocks: - raise ValueError('invalid block index %s' % index) - - def _get_index(self,index): - """Get the current block index, validating and checking status. - - Returns None if the demo is finished""" - - if index is None: - if self.finished: - print('Demo finished. Use .reset() if you want to rerun it.') - return None - index = self.block_index - else: - self._validate_index(index) - return index - - def seek(self,index): - """Move the current seek pointer to the given block. - - You can use negative indices to seek from the end, with identical - semantics to those of Python lists.""" - if index<0: - index = self.nblocks + index - self._validate_index(index) - self.block_index = index - self.finished = False - - def back(self,num=1): - """Move the seek pointer back num blocks (default is 1).""" - self.seek(self.block_index-num) - - def jump(self,num=1): - """Jump a given number of blocks relative to the current one. - - The offset can be positive or negative, defaults to 1.""" - self.seek(self.block_index+num) - - def again(self): - """Move the seek pointer back one block and re-execute.""" - self.back(1) - self() - - def edit(self,index=None): - """Edit a block. - - If no number is given, use the last block executed. - - This edits the in-memory copy of the demo, it does NOT modify the - original source file. If you want to do that, simply open the file in - an editor and use reload() when you make changes to the file. This - method is meant to let you change a block during a demonstration for - explanatory purposes, without damaging your original script.""" - - index = self._get_index(index) - if index is None: - return - # decrease the index by one (unless we're at the very beginning), so - # that the default demo.edit() call opens up the sblock we've last run - if index>0: - index -= 1 - - filename = self.shell.mktempfile(self.src_blocks[index]) - self.shell.hooks.editor(filename, 1) - with open(Path(filename), "r", encoding="utf-8") as f: - new_block = f.read() - # update the source and colored block - self.src_blocks[index] = new_block - self.src_blocks_colored[index] = self.highlight(new_block) - self.block_index = index - # call to run with the newly edited index - self() - - def show(self,index=None): - """Show a single block on screen""" - - index = self._get_index(index) - if index is None: - return - - print(self.marquee('<%s> block # %s (%s remaining)' % - (self.title,index,self.nblocks-index-1))) - print(self.src_blocks_colored[index]) - sys.stdout.flush() - - def show_all(self): - """Show entire demo on screen, block by block""" - - fname = self.title - title = self.title - nblocks = self.nblocks - silent = self._silent - marquee = self.marquee - for index,block in enumerate(self.src_blocks_colored): - if silent[index]: - print(marquee('<%s> SILENT block # %s (%s remaining)' % - (title,index,nblocks-index-1))) - else: - print(marquee('<%s> block # %s (%s remaining)' % - (title,index,nblocks-index-1))) - print(block, end=' ') - sys.stdout.flush() - - def run_cell(self,source): - """Execute a string with one or more lines of code""" - - exec(source, self.user_ns) - - def __call__(self,index=None): - """run a block of the demo. - - If index is given, it should be an integer >=1 and <= nblocks. This - means that the calling convention is one off from typical Python - lists. The reason for the inconsistency is that the demo always - prints 'Block n/N, and N is the total, so it would be very odd to use - zero-indexing here.""" - - index = self._get_index(index) - if index is None: - return - try: - marquee = self.marquee - next_block = self.src_blocks[index] - self.block_index += 1 - if self._silent[index]: - print(marquee('Executing silent block # %s (%s remaining)' % - (index,self.nblocks-index-1))) - else: - self.pre_cmd() - self.show(index) - if self.auto_all or self._auto[index]: - print(marquee('output:')) - else: - print(marquee('Press to quit, to execute...'), end=' ') - ans = py3compat.input().strip() - if ans: - print(marquee('Block NOT executed')) - return - try: - save_argv = sys.argv - sys.argv = self.sys_argv - self.run_cell(next_block) - self.post_cmd() - finally: - sys.argv = save_argv - - except: - if self.inside_ipython: - self.ip_showtb(filename=self.fname) - else: - if self.inside_ipython: - self.ip_ns.update(self.user_ns) - - if self.block_index == self.nblocks: - mq1 = self.marquee('END OF DEMO') - if mq1: - # avoid spurious print if empty marquees are used - print() - print(mq1) - print(self.marquee('Use .reset() if you want to rerun it.')) - self.finished = True - - # These methods are meant to be overridden by subclasses who may wish to - # customize the behavior of of their demos. - def marquee(self,txt='',width=78,mark='*'): - """Return the input string centered in a 'marquee'.""" - return marquee(txt,width,mark) - - def pre_cmd(self): - """Method called before executing each block.""" - pass - - def post_cmd(self): - """Method called after executing each block.""" - pass - - def highlight(self, block): - """Method called on each block to highlight it content""" - tokens = pygments.lex(block, self.python_lexer) - if self.format_rst: - from pygments.token import Token - toks = [] - for token in tokens: - if token[0] == Token.String.Doc and len(token[1]) > 6: - toks += pygments.lex(token[1][:3], self.python_lexer) - # parse doc string content by rst lexer - toks += pygments.lex(token[1][3:-3], self.rst_lexer) - toks += pygments.lex(token[1][-3:], self.python_lexer) - elif token[0] == Token.Comment.Single: - toks.append((Token.Comment.Single, token[1][0])) - # parse comment content by rst lexer - # remove the extra newline added by rst lexer - toks += list(pygments.lex(token[1][1:], self.rst_lexer))[:-1] - else: - toks.append(token) - tokens = toks - return pygments.format(tokens, self.formatter) - - -class IPythonDemo(Demo): - """Class for interactive demos with IPython's input processing applied. - - This subclasses Demo, but instead of executing each block by the Python - interpreter (via exec), it actually calls IPython on it, so that any input - filters which may be in place are applied to the input block. - - If you have an interactive environment which exposes special input - processing, you can use this class instead to write demo scripts which - operate exactly as if you had typed them interactively. The default Demo - class requires the input to be valid, pure Python code. - """ - - def run_cell(self,source): - """Execute a string with one or more lines of code""" - - self.shell.run_cell(source) - -class LineDemo(Demo): - """Demo where each line is executed as a separate block. - - The input script should be valid Python code. - - This class doesn't require any markup at all, and it's meant for simple - scripts (with no nesting or any kind of indentation) which consist of - multiple lines of input to be executed, one at a time, as if they had been - typed in the interactive prompt. - - Note: the input can not have *any* indentation, which means that only - single-lines of input are accepted, not even function definitions are - valid.""" - - def reload(self): - """Reload source from disk and initialize state.""" - # read data and parse into blocks - self.fload() - lines = self.fobj.readlines() - src_b = [l for l in lines if l.strip()] - nblocks = len(src_b) - self.src = ''.join(lines) - self._silent = [False]*nblocks - self._auto = [True]*nblocks - self.auto_all = True - self.nblocks = nblocks - self.src_blocks = src_b - - # also build syntax-highlighted source - self.src_blocks_colored = list(map(self.highlight,self.src_blocks)) - - # ensure clean namespace and seek offset - self.reset() - - -class IPythonLineDemo(IPythonDemo,LineDemo): - """Variant of the LineDemo class whose input is processed by IPython.""" - pass - - -class ClearMixin(object): - """Use this mixin to make Demo classes with less visual clutter. - - Demos using this mixin will clear the screen before every block and use - blank marquees. - - Note that in order for the methods defined here to actually override those - of the classes it's mixed with, it must go /first/ in the inheritance - tree. For example: - - class ClearIPDemo(ClearMixin,IPythonDemo): pass - - will provide an IPythonDemo class with the mixin's features. - """ - - def marquee(self,txt='',width=78,mark='*'): - """Blank marquee that returns '' no matter what the input.""" - return '' - - def pre_cmd(self): - """Method called before executing each block. - - This one simply clears the screen.""" - from IPython.utils.terminal import _term_clear - _term_clear() - -class ClearDemo(ClearMixin,Demo): - pass - - -class ClearIPDemo(ClearMixin,IPythonDemo): - pass - - -def slide(file_path, noclear=False, format_rst=True, formatter="terminal", - style="native", auto_all=False, delimiter='...'): - if noclear: - demo_class = Demo - else: - demo_class = ClearDemo - demo = demo_class(file_path, format_rst=format_rst, formatter=formatter, - style=style, auto_all=auto_all) - while not demo.finished: - demo() - try: - py3compat.input('\n' + delimiter) - except KeyboardInterrupt: - exit(1) - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser(description='Run python demos') - parser.add_argument('--noclear', '-C', action='store_true', - help='Do not clear terminal on each slide') - parser.add_argument('--rst', '-r', action='store_true', - help='Highlight comments and dostrings as rst') - parser.add_argument('--formatter', '-f', default='terminal', - help='pygments formatter name could be: terminal, ' - 'terminal256, terminal16m') - parser.add_argument('--style', '-s', default='default', - help='pygments style name') - parser.add_argument('--auto', '-a', action='store_true', - help='Run all blocks automatically without' - 'confirmation') - parser.add_argument('--delimiter', '-d', default='...', - help='slides delimiter added after each slide run') - parser.add_argument('file', nargs=1, - help='python demo file') - args = parser.parse_args() - slide(args.file[0], noclear=args.noclear, format_rst=args.rst, - formatter=args.formatter, style=args.style, auto_all=args.auto, - delimiter=args.delimiter) diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/display.py b/.venv/lib/python3.12/site-packages/IPython/lib/display.py deleted file mode 100644 index f39f389..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/display.py +++ /dev/null @@ -1,677 +0,0 @@ -"""Various display related classes. - -Authors : MinRK, gregcaporaso, dannystaple -""" -from html import escape as html_escape -from os.path import exists, isfile, splitext, abspath, join, isdir -from os import walk, sep, fsdecode - -from IPython.core.display import DisplayObject, TextDisplayObject - -from typing import Tuple, Iterable, Optional - -__all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument', - 'FileLink', 'FileLinks', 'Code'] - - -class Audio(DisplayObject): - """Create an audio object. - - When this object is returned by an input cell or passed to the - display function, it will result in Audio controls being displayed - in the frontend (only works in the notebook). - - Parameters - ---------- - data : numpy array, list, unicode, str or bytes - Can be one of - - * Numpy 1d array containing the desired waveform (mono) - * Numpy 2d array containing waveforms for each channel. - Shape=(NCHAN, NSAMPLES). For the standard channel order, see - http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx - * List of float or integer representing the waveform (mono) - * String containing the filename - * Bytestring containing raw PCM data or - * URL pointing to a file on the web. - - If the array option is used, the waveform will be normalized. - - If a filename or url is used, the format support will be browser - dependent. - url : unicode - A URL to download the data from. - filename : unicode - Path to a local file to load the data from. - embed : boolean - Should the audio data be embedded using a data URI (True) or should - the original source be referenced. Set this to True if you want the - audio to playable later with no internet connection in the notebook. - - Default is `True`, unless the keyword argument `url` is set, then - default value is `False`. - rate : integer - The sampling rate of the raw data. - Only required when data parameter is being used as an array - autoplay : bool - Set to True if the audio should immediately start playing. - Default is `False`. - normalize : bool - Whether audio should be normalized (rescaled) to the maximum possible - range. Default is `True`. When set to `False`, `data` must be between - -1 and 1 (inclusive), otherwise an error is raised. - Applies only when `data` is a list or array of samples; other types of - audio are never normalized. - - Examples - -------- - - >>> import pytest - >>> np = pytest.importorskip("numpy") - - Generate a sound - - >>> import numpy as np - >>> framerate = 44100 - >>> t = np.linspace(0,5,framerate*5) - >>> data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t) - >>> Audio(data, rate=framerate) - - - Can also do stereo or more channels - - >>> dataleft = np.sin(2*np.pi*220*t) - >>> dataright = np.sin(2*np.pi*224*t) - >>> Audio([dataleft, dataright], rate=framerate) - - - From URL: - - >>> Audio("http://www.nch.com.au/acm/8k16bitpcm.wav") # doctest: +SKIP - >>> Audio(url="http://www.w3schools.com/html/horse.ogg") # doctest: +SKIP - - From a File: - - >>> Audio('IPython/lib/tests/test.wav') # doctest: +SKIP - >>> Audio(filename='IPython/lib/tests/test.wav') # doctest: +SKIP - - From Bytes: - - >>> Audio(b'RAW_WAV_DATA..') # doctest: +SKIP - >>> Audio(data=b'RAW_WAV_DATA..') # doctest: +SKIP - - See Also - -------- - ipywidgets.Audio - - Audio widget with more more flexibility and options. - - """ - _read_flags = 'rb' - - def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False, normalize=True, *, - element_id=None): - if filename is None and url is None and data is None: - raise ValueError("No audio data found. Expecting filename, url, or data.") - if embed is False and url is None: - raise ValueError("No url found. Expecting url when embed=False") - - if url is not None and embed is not True: - self.embed = False - else: - self.embed = True - self.autoplay = autoplay - self.element_id = element_id - super(Audio, self).__init__(data=data, url=url, filename=filename) - - if self.data is not None and not isinstance(self.data, bytes): - if rate is None: - raise ValueError("rate must be specified when data is a numpy array or list of audio samples.") - self.data = Audio._make_wav(data, rate, normalize) - - def reload(self): - """Reload the raw data from file or URL.""" - import mimetypes - if self.embed: - super(Audio, self).reload() - - if self.filename is not None: - self.mimetype = mimetypes.guess_type(self.filename)[0] - elif self.url is not None: - self.mimetype = mimetypes.guess_type(self.url)[0] - else: - self.mimetype = "audio/wav" - - @staticmethod - def _make_wav(data, rate, normalize): - """ Transform a numpy array to a PCM bytestring """ - from io import BytesIO - import wave - - try: - scaled, nchan = Audio._validate_and_normalize_with_numpy(data, normalize) - except ImportError: - scaled, nchan = Audio._validate_and_normalize_without_numpy(data, normalize) - - fp = BytesIO() - waveobj = wave.open(fp,mode='wb') - waveobj.setnchannels(nchan) - waveobj.setframerate(rate) - waveobj.setsampwidth(2) - waveobj.setcomptype('NONE','NONE') - waveobj.writeframes(scaled) - val = fp.getvalue() - waveobj.close() - - return val - - @staticmethod - def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]: - import numpy as np - - data = np.array(data, dtype=float) - if len(data.shape) == 1: - nchan = 1 - elif len(data.shape) == 2: - # In wave files,channels are interleaved. E.g., - # "L1R1L2R2..." for stereo. See - # http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx - # for channel ordering - nchan = data.shape[0] - data = data.T.ravel() - else: - raise ValueError('Array audio input must be a 1D or 2D array') - - max_abs_value = np.max(np.abs(data)) - normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize) - scaled = data / normalization_factor * 32767 - return scaled.astype(" 1: - raise ValueError('Audio data must be between -1 and 1 when normalize=False.') - return max_abs_value if normalize else 1 - - def _data_and_metadata(self): - """shortcut for returning metadata with url information, if defined""" - md = {} - if self.url: - md['url'] = self.url - if md: - return self.data, md - else: - return self.data - - def _repr_html_(self): - src = """ - - """ - return src.format(src=self.src_attr(), type=self.mimetype, autoplay=self.autoplay_attr(), - element_id=self.element_id_attr()) - - def src_attr(self): - import base64 - if self.embed and (self.data is not None): - data = base64=base64.b64encode(self.data).decode('ascii') - return """data:{type};base64,{base64}""".format(type=self.mimetype, - base64=data) - elif self.url is not None: - return self.url - else: - return "" - - def autoplay_attr(self): - if(self.autoplay): - return 'autoplay="autoplay"' - else: - return '' - - def element_id_attr(self): - if (self.element_id): - return 'id="{element_id}"'.format(element_id=self.element_id) - else: - return '' - -class IFrame(object): - """ - Generic class to embed an iframe in an IPython notebook - """ - - iframe = """ - - """ - - def __init__( - self, src, width, height, extras: Optional[Iterable[str]] = None, **kwargs - ): - if extras is None: - extras = [] - - self.src = src - self.width = width - self.height = height - self.extras = extras - self.params = kwargs - - def _repr_html_(self): - """return the embed iframe""" - if self.params: - from urllib.parse import urlencode - params = "?" + urlencode(self.params) - else: - params = "" - return self.iframe.format( - src=self.src, - width=self.width, - height=self.height, - params=params, - extras=" ".join(self.extras), - ) - - -class YouTubeVideo(IFrame): - """Class for embedding a YouTube Video in an IPython session, based on its video id. - - e.g. to embed the video from https://www.youtube.com/watch?v=foo , you would - do:: - - vid = YouTubeVideo("foo") - display(vid) - - To start from 30 seconds:: - - vid = YouTubeVideo("abc", start=30) - display(vid) - - To calculate seconds from time as hours, minutes, seconds use - :class:`datetime.timedelta`:: - - start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds()) - - Other parameters can be provided as documented at - https://developers.google.com/youtube/player_parameters#Parameters - - When converting the notebook using nbconvert, a jpeg representation of the video - will be inserted in the document. - """ - - def __init__(self, id, width=400, height=300, allow_autoplay=False, **kwargs): - self.id=id - src = "https://www.youtube.com/embed/{0}".format(id) - if allow_autoplay: - extras = list(kwargs.get("extras", [])) + ['allow="autoplay"'] - kwargs.update(autoplay=1, extras=extras) - super(YouTubeVideo, self).__init__(src, width, height, **kwargs) - - def _repr_jpeg_(self): - # Deferred import - from urllib.request import urlopen - - try: - return urlopen("https://img.youtube.com/vi/{id}/hqdefault.jpg".format(id=self.id)).read() - except IOError: - return None - -class VimeoVideo(IFrame): - """ - Class for embedding a Vimeo video in an IPython session, based on its video id. - """ - - def __init__(self, id, width=400, height=300, **kwargs): - src="https://player.vimeo.com/video/{0}".format(id) - super(VimeoVideo, self).__init__(src, width, height, **kwargs) - -class ScribdDocument(IFrame): - """ - Class for embedding a Scribd document in an IPython session - - Use the start_page params to specify a starting point in the document - Use the view_mode params to specify display type one off scroll | slideshow | book - - e.g to Display Wes' foundational paper about PANDAS in book mode from page 3 - - ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book") - """ - - def __init__(self, id, width=400, height=300, **kwargs): - src="https://www.scribd.com/embeds/{0}/content".format(id) - super(ScribdDocument, self).__init__(src, width, height, **kwargs) - -class FileLink(object): - """Class for embedding a local file link in an IPython session, based on path - - e.g. to embed a link that was generated in the IPython notebook as my/data.txt - - you would do:: - - local_file = FileLink("my/data.txt") - display(local_file) - - or in the HTML notebook, just:: - - FileLink("my/data.txt") - """ - - html_link_str = "%s" - - def __init__(self, - path, - url_prefix='', - result_html_prefix='', - result_html_suffix='
'): - """ - Parameters - ---------- - path : str - path to the file or directory that should be formatted - url_prefix : str - prefix to be prepended to all files to form a working link [default: - ''] - result_html_prefix : str - text to append to beginning to link [default: ''] - result_html_suffix : str - text to append at the end of link [default: '
'] - """ - if isdir(path): - raise ValueError("Cannot display a directory using FileLink. " - "Use FileLinks to display '%s'." % path) - self.path = fsdecode(path) - self.url_prefix = url_prefix - self.result_html_prefix = result_html_prefix - self.result_html_suffix = result_html_suffix - - def _format_path(self): - fp = ''.join([self.url_prefix, html_escape(self.path)]) - return ''.join([self.result_html_prefix, - self.html_link_str % \ - (fp, html_escape(self.path, quote=False)), - self.result_html_suffix]) - - def _repr_html_(self): - """return html link to file - """ - if not exists(self.path): - return ("Path (%s) doesn't exist. " - "It may still be in the process of " - "being generated, or you may have the " - "incorrect path." % self.path) - - return self._format_path() - - def __repr__(self): - """return absolute path to file - """ - return abspath(self.path) - -class FileLinks(FileLink): - """Class for embedding local file links in an IPython session, based on path - - e.g. to embed links to files that were generated in the IPython notebook - under ``my/data``, you would do:: - - local_files = FileLinks("my/data") - display(local_files) - - or in the HTML notebook, just:: - - FileLinks("my/data") - """ - def __init__(self, - path, - url_prefix='', - included_suffixes=None, - result_html_prefix='', - result_html_suffix='
', - notebook_display_formatter=None, - terminal_display_formatter=None, - recursive=True): - """ - See :class:`FileLink` for the ``path``, ``url_prefix``, - ``result_html_prefix`` and ``result_html_suffix`` parameters. - - included_suffixes : list - Filename suffixes to include when formatting output [default: include - all files] - - notebook_display_formatter : function - Used to format links for display in the notebook. See discussion of - formatter functions below. - - terminal_display_formatter : function - Used to format links for display in the terminal. See discussion of - formatter functions below. - - Formatter functions must be of the form:: - - f(dirname, fnames, included_suffixes) - - dirname : str - The name of a directory - fnames : list - The files in that directory - included_suffixes : list - The file suffixes that should be included in the output (passing None - meansto include all suffixes in the output in the built-in formatters) - recursive : boolean - Whether to recurse into subdirectories. Default is True. - - The function should return a list of lines that will be printed in the - notebook (if passing notebook_display_formatter) or the terminal (if - passing terminal_display_formatter). This function is iterated over for - each directory in self.path. Default formatters are in place, can be - passed here to support alternative formatting. - - """ - if isfile(path): - raise ValueError("Cannot display a file using FileLinks. " - "Use FileLink to display '%s'." % path) - self.included_suffixes = included_suffixes - # remove trailing slashes for more consistent output formatting - path = path.rstrip('/') - - self.path = path - self.url_prefix = url_prefix - self.result_html_prefix = result_html_prefix - self.result_html_suffix = result_html_suffix - - self.notebook_display_formatter = \ - notebook_display_formatter or self._get_notebook_display_formatter() - self.terminal_display_formatter = \ - terminal_display_formatter or self._get_terminal_display_formatter() - - self.recursive = recursive - - def _get_display_formatter( - self, dirname_output_format, fname_output_format, fp_format, fp_cleaner=None - ): - """generate built-in formatter function - - this is used to define both the notebook and terminal built-in - formatters as they only differ by some wrapper text for each entry - - dirname_output_format: string to use for formatting directory - names, dirname will be substituted for a single "%s" which - must appear in this string - fname_output_format: string to use for formatting file names, - if a single "%s" appears in the string, fname will be substituted - if two "%s" appear in the string, the path to fname will be - substituted for the first and fname will be substituted for the - second - fp_format: string to use for formatting filepaths, must contain - exactly two "%s" and the dirname will be substituted for the first - and fname will be substituted for the second - """ - def f(dirname, fnames, included_suffixes=None): - result = [] - # begin by figuring out which filenames, if any, - # are going to be displayed - display_fnames = [] - for fname in fnames: - if (isfile(join(dirname,fname)) and - (included_suffixes is None or - splitext(fname)[1] in included_suffixes)): - display_fnames.append(fname) - - if len(display_fnames) == 0: - # if there are no filenames to display, don't print anything - # (not even the directory name) - pass - else: - # otherwise print the formatted directory name followed by - # the formatted filenames - dirname_output_line = dirname_output_format % dirname - result.append(dirname_output_line) - for fname in display_fnames: - fp = fp_format % (dirname,fname) - if fp_cleaner is not None: - fp = fp_cleaner(fp) - try: - # output can include both a filepath and a filename... - fname_output_line = fname_output_format % (fp, fname) - except TypeError: - # ... or just a single filepath - fname_output_line = fname_output_format % fname - result.append(fname_output_line) - return result - return f - - def _get_notebook_display_formatter(self, - spacer="  "): - """ generate function to use for notebook formatting - """ - dirname_output_format = \ - self.result_html_prefix + "%s/" + self.result_html_suffix - fname_output_format = \ - self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix - fp_format = self.url_prefix + '%s/%s' - if sep == "\\": - # Working on a platform where the path separator is "\", so - # must convert these to "/" for generating a URI - def fp_cleaner(fp): - # Replace all occurrences of backslash ("\") with a forward - # slash ("/") - this is necessary on windows when a path is - # provided as input, but we must link to a URI - return fp.replace('\\','/') - else: - fp_cleaner = None - - return self._get_display_formatter(dirname_output_format, - fname_output_format, - fp_format, - fp_cleaner) - - def _get_terminal_display_formatter(self, - spacer=" "): - """ generate function to use for terminal formatting - """ - dirname_output_format = "%s/" - fname_output_format = spacer + "%s" - fp_format = '%s/%s' - - return self._get_display_formatter(dirname_output_format, - fname_output_format, - fp_format) - - def _format_path(self): - result_lines = [] - if self.recursive: - walked_dir = list(walk(self.path)) - else: - walked_dir = [next(walk(self.path))] - walked_dir.sort() - for dirname, subdirs, fnames in walked_dir: - result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes) - return '\n'.join(result_lines) - - def __repr__(self): - """return newline-separated absolute paths - """ - result_lines = [] - if self.recursive: - walked_dir = list(walk(self.path)) - else: - walked_dir = [next(walk(self.path))] - walked_dir.sort() - for dirname, subdirs, fnames in walked_dir: - result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes) - return '\n'.join(result_lines) - - -class Code(TextDisplayObject): - """Display syntax-highlighted source code. - - This uses Pygments to highlight the code for HTML and Latex output. - - Parameters - ---------- - data : str - The code as a string - url : str - A URL to fetch the code from - filename : str - A local filename to load the code from - language : str - The short name of a Pygments lexer to use for highlighting. - If not specified, it will guess the lexer based on the filename - or the code. Available lexers: http://pygments.org/docs/lexers/ - """ - def __init__(self, data=None, url=None, filename=None, language=None): - self.language = language - super().__init__(data=data, url=url, filename=filename) - - def _get_lexer(self): - if self.language: - from pygments.lexers import get_lexer_by_name - return get_lexer_by_name(self.language) - elif self.filename: - from pygments.lexers import get_lexer_for_filename - return get_lexer_for_filename(self.filename) - else: - from pygments.lexers import guess_lexer - return guess_lexer(self.data) - - def __repr__(self): - return self.data - - def _repr_html_(self): - from pygments import highlight - from pygments.formatters import HtmlFormatter - fmt = HtmlFormatter() - style = ''.format(fmt.get_style_defs('.output_html')) - return style + highlight(self.data, self._get_lexer(), fmt) - - def _repr_latex_(self): - from pygments import highlight - from pygments.formatters import LatexFormatter - return highlight(self.data, self._get_lexer(), LatexFormatter()) diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/editorhooks.py b/.venv/lib/python3.12/site-packages/IPython/lib/editorhooks.py deleted file mode 100644 index d8bd6ac..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/editorhooks.py +++ /dev/null @@ -1,127 +0,0 @@ -""" 'editor' hooks for common editors that work well with ipython - -They should honor the line number argument, at least. - -Contributions are *very* welcome. -""" - -import os -import shlex -import subprocess -import sys - -from IPython import get_ipython -from IPython.core.error import TryNext -from IPython.utils import py3compat - - -def install_editor(template, wait=False): - """Installs the editor that is called by IPython for the %edit magic. - - This overrides the default editor, which is generally set by your EDITOR - environment variable or is notepad (windows) or vi (linux). By supplying a - template string `run_template`, you can control how the editor is invoked - by IPython -- (e.g. the format in which it accepts command line options) - - Parameters - ---------- - template : basestring - run_template acts as a template for how your editor is invoked by - the shell. It should contain '{filename}', which will be replaced on - invocation with the file name, and '{line}', $line by line number - (or 0) to invoke the file with. - wait : bool - If `wait` is true, wait until the user presses enter before returning, - to facilitate non-blocking editors that exit immediately after - the call. - """ - - # not all editors support $line, so we'll leave out this check - # for substitution in ['$file', '$line']: - # if not substitution in run_template: - # raise ValueError(('run_template should contain %s' - # ' for string substitution. You supplied "%s"' % (substitution, - # run_template))) - - def call_editor(self, filename, line=0): - if line is None: - line = 0 - cmd = template.format(filename=shlex.quote(filename), line=line) - print(">", cmd) - # shlex.quote doesn't work right on Windows, but it does after splitting - if sys.platform.startswith('win'): - cmd = shlex.split(cmd) - proc = subprocess.Popen(cmd, shell=True) - if proc.wait() != 0: - raise TryNext() - if wait: - py3compat.input("Press Enter when done editing:") - - get_ipython().set_hook('editor', call_editor) - get_ipython().editor = template - - -# in these, exe is always the path/name of the executable. Useful -# if you don't have the editor directory in your path -def komodo(exe=u'komodo'): - """ Activestate Komodo [Edit] """ - install_editor(exe + u' -l {line} {filename}', wait=True) - - -def scite(exe=u"scite"): - """ SciTE or Sc1 """ - install_editor(exe + u' {filename} -goto:{line}') - - -def notepadplusplus(exe=u'notepad++'): - """ Notepad++ http://notepad-plus.sourceforge.net """ - install_editor(exe + u' -n{line} {filename}') - - -def jed(exe=u'jed'): - """ JED, the lightweight emacsish editor """ - install_editor(exe + u' +{line} {filename}') - - -def idle(exe=u'idle'): - """ Idle, the editor bundled with python - - Parameters - ---------- - exe : str, None - If none, should be pretty smart about finding the executable. - """ - if exe is None: - import idlelib - p = os.path.dirname(idlelib.__filename__) - # i'm not sure if this actually works. Is this idle.py script - # guaranteed to be executable? - exe = os.path.join(p, 'idle.py') - install_editor(exe + u' {filename}') - - -def mate(exe=u'mate'): - """ TextMate, the missing editor""" - # wait=True is not required since we're using the -w flag to mate - install_editor(exe + u' -w -l {line} {filename}') - - -# ########################################## -# these are untested, report any problems -# ########################################## - - -def emacs(exe=u'emacs'): - install_editor(exe + u' +{line} {filename}') - - -def gnuclient(exe=u'gnuclient'): - install_editor(exe + u' -nw +{line} {filename}') - - -def crimson_editor(exe=u'cedt.exe'): - install_editor(exe + u' /L:{line} {filename}') - - -def kate(exe=u'kate'): - install_editor(exe + u' -u -l {line} {filename}') diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/guisupport.py b/.venv/lib/python3.12/site-packages/IPython/lib/guisupport.py deleted file mode 100644 index 4d532d0..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/guisupport.py +++ /dev/null @@ -1,155 +0,0 @@ -# coding: utf-8 -""" -Support for creating GUI apps and starting event loops. - -IPython's GUI integration allows interactive plotting and GUI usage in IPython -session. IPython has two different types of GUI integration: - -1. The terminal based IPython supports GUI event loops through Python's - PyOS_InputHook. PyOS_InputHook is a hook that Python calls periodically - whenever raw_input is waiting for a user to type code. We implement GUI - support in the terminal by setting PyOS_InputHook to a function that - iterates the event loop for a short while. It is important to note that - in this situation, the real GUI event loop is NOT run in the normal - manner, so you can't use the normal means to detect that it is running. -2. In the two process IPython kernel/frontend, the GUI event loop is run in - the kernel. In this case, the event loop is run in the normal manner by - calling the function or method of the GUI toolkit that starts the event - loop. - -In addition to starting the GUI event loops in one of these two ways, IPython -will *always* create an appropriate GUI application object when GUi -integration is enabled. - -If you want your GUI apps to run in IPython you need to do two things: - -1. Test to see if there is already an existing main application object. If - there is, you should use it. If there is not an existing application object - you should create one. -2. Test to see if the GUI event loop is running. If it is, you should not - start it. If the event loop is not running you may start it. - -This module contains functions for each toolkit that perform these things -in a consistent manner. Because of how PyOS_InputHook runs the event loop -you cannot detect if the event loop is running using the traditional calls -(such as ``wx.GetApp.IsMainLoopRunning()`` in wxPython). If PyOS_InputHook is -set These methods will return a false negative. That is, they will say the -event loop is not running, when is actually is. To work around this limitation -we proposed the following informal protocol: - -* Whenever someone starts the event loop, they *must* set the ``_in_event_loop`` - attribute of the main application object to ``True``. This should be done - regardless of how the event loop is actually run. -* Whenever someone stops the event loop, they *must* set the ``_in_event_loop`` - attribute of the main application object to ``False``. -* If you want to see if the event loop is running, you *must* use ``hasattr`` - to see if ``_in_event_loop`` attribute has been set. If it is set, you - *must* use its value. If it has not been set, you can query the toolkit - in the normal manner. -* If you want GUI support and no one else has created an application or - started the event loop you *must* do this. We don't want projects to - attempt to defer these things to someone else if they themselves need it. - -The functions below implement this logic for each GUI toolkit. If you need -to create custom application subclasses, you will likely have to modify this -code for your own purposes. This code can be copied into your own project -so you don't have to depend on IPython. - -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from IPython.core.getipython import get_ipython - -#----------------------------------------------------------------------------- -# wx -#----------------------------------------------------------------------------- - -def get_app_wx(*args, **kwargs): - """Create a new wx app or return an exiting one.""" - import wx - app = wx.GetApp() - if app is None: - if 'redirect' not in kwargs: - kwargs['redirect'] = False - app = wx.PySimpleApp(*args, **kwargs) - return app - -def is_event_loop_running_wx(app=None): - """Is the wx event loop running.""" - # New way: check attribute on shell instance - ip = get_ipython() - if ip is not None: - if ip.active_eventloop and ip.active_eventloop == 'wx': - return True - # Fall through to checking the application, because Wx has a native way - # to check if the event loop is running, unlike Qt. - - # Old way: check Wx application - if app is None: - app = get_app_wx() - if hasattr(app, '_in_event_loop'): - return app._in_event_loop - else: - return app.IsMainLoopRunning() - -def start_event_loop_wx(app=None): - """Start the wx event loop in a consistent manner.""" - if app is None: - app = get_app_wx() - if not is_event_loop_running_wx(app): - app._in_event_loop = True - app.MainLoop() - app._in_event_loop = False - else: - app._in_event_loop = True - -#----------------------------------------------------------------------------- -# Qt -#----------------------------------------------------------------------------- - -def get_app_qt4(*args, **kwargs): - """Create a new Qt app or return an existing one.""" - from IPython.external.qt_for_kernel import QtGui - app = QtGui.QApplication.instance() - if app is None: - if not args: - args = ([""],) - app = QtGui.QApplication(*args, **kwargs) - return app - -def is_event_loop_running_qt4(app=None): - """Is the qt event loop running.""" - # New way: check attribute on shell instance - ip = get_ipython() - if ip is not None: - return ip.active_eventloop and ip.active_eventloop.startswith('qt') - - # Old way: check attribute on QApplication singleton - if app is None: - app = get_app_qt4([""]) - if hasattr(app, '_in_event_loop'): - return app._in_event_loop - else: - # Does qt provide a other way to detect this? - return False - -def start_event_loop_qt4(app=None): - """Start the qt event loop in a consistent manner.""" - if app is None: - app = get_app_qt4([""]) - if not is_event_loop_running_qt4(app): - app._in_event_loop = True - app.exec_() - app._in_event_loop = False - else: - app._in_event_loop = True - -#----------------------------------------------------------------------------- -# Tk -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# gtk -#----------------------------------------------------------------------------- diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/latextools.py b/.venv/lib/python3.12/site-packages/IPython/lib/latextools.py deleted file mode 100644 index 7bea589..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/latextools.py +++ /dev/null @@ -1,257 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tools for handling LaTeX.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from io import BytesIO, open -import os -import tempfile -import shutil -import subprocess -from base64 import encodebytes -import textwrap - -from pathlib import Path - -from IPython.utils.process import find_cmd, FindCmdError -from traitlets.config import get_config -from traitlets.config.configurable import SingletonConfigurable -from traitlets import List, Bool, Unicode - - -class LaTeXTool(SingletonConfigurable): - """An object to store configuration of the LaTeX tool.""" - def _config_default(self): - return get_config() - - backends = List( - Unicode(), ["matplotlib", "dvipng"], - help="Preferred backend to draw LaTeX math equations. " - "Backends in the list are checked one by one and the first " - "usable one is used. Note that `matplotlib` backend " - "is usable only for inline style equations. To draw " - "display style equations, `dvipng` backend must be specified. ", - # It is a List instead of Enum, to make configuration more - # flexible. For example, to use matplotlib mainly but dvipng - # for display style, the default ["matplotlib", "dvipng"] can - # be used. To NOT use dvipng so that other repr such as - # unicode pretty printing is used, you can use ["matplotlib"]. - ).tag(config=True) - - use_breqn = Bool( - True, - help="Use breqn.sty to automatically break long equations. " - "This configuration takes effect only for dvipng backend.", - ).tag(config=True) - - packages = List( - ['amsmath', 'amsthm', 'amssymb', 'bm'], - help="A list of packages to use for dvipng backend. " - "'breqn' will be automatically appended when use_breqn=True.", - ).tag(config=True) - - preamble = Unicode( - help="Additional preamble to use when generating LaTeX source " - "for dvipng backend.", - ).tag(config=True) - - -def latex_to_png( - s: str, encode=False, backend=None, wrap=False, color="Black", scale=1.0 -): - """Render a LaTeX string to PNG. - - Parameters - ---------- - s : str - The raw string containing valid inline LaTeX. - encode : bool, optional - Should the PNG data base64 encoded to make it JSON'able. - backend : {matplotlib, dvipng} - Backend for producing PNG data. - wrap : bool - If true, Automatically wrap `s` as a LaTeX equation. - color : string - Foreground color name among dvipsnames, e.g. 'Maroon' or on hex RGB - format, e.g. '#AA20FA'. - scale : float - Scale factor for the resulting PNG. - None is returned when the backend cannot be used. - - """ - assert isinstance(s, str) - allowed_backends = LaTeXTool.instance().backends - if backend is None: - backend = allowed_backends[0] - if backend not in allowed_backends: - return None - if backend == 'matplotlib': - f = latex_to_png_mpl - elif backend == 'dvipng': - f = latex_to_png_dvipng - if color.startswith('#'): - # Convert hex RGB color to LaTeX RGB color. - if len(color) == 7: - try: - color = "RGB {}".format(" ".join([str(int(x, 16)) for x in - textwrap.wrap(color[1:], 2)])) - except ValueError as e: - raise ValueError('Invalid color specification {}.'.format(color)) from e - else: - raise ValueError('Invalid color specification {}.'.format(color)) - else: - raise ValueError('No such backend {0}'.format(backend)) - bin_data = f(s, wrap, color, scale) - if encode and bin_data: - bin_data = encodebytes(bin_data) - return bin_data - - -def latex_to_png_mpl(s, wrap, color='Black', scale=1.0): - try: - from matplotlib import figure, font_manager, mathtext - from matplotlib.backends import backend_agg - from pyparsing import ParseFatalException - except ImportError: - return None - - # mpl mathtext doesn't support display math, force inline - s = s.replace('$$', '$') - if wrap: - s = u'${0}$'.format(s) - - try: - prop = font_manager.FontProperties(size=12) - dpi = 120 * scale - buffer = BytesIO() - - # Adapted from mathtext.math_to_image - parser = mathtext.MathTextParser("path") - width, height, depth, _, _ = parser.parse(s, dpi=72, prop=prop) - fig = figure.Figure(figsize=(width / 72, height / 72)) - fig.text(0, depth / height, s, fontproperties=prop, color=color) - backend_agg.FigureCanvasAgg(fig) - fig.savefig(buffer, dpi=dpi, format="png", transparent=True) - return buffer.getvalue() - except (ValueError, RuntimeError, ParseFatalException): - return None - - -def latex_to_png_dvipng(s, wrap, color='Black', scale=1.0): - try: - find_cmd('latex') - find_cmd('dvipng') - except FindCmdError: - return None - - startupinfo = None - if os.name == "nt": - # prevent popup-windows - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - - try: - workdir = Path(tempfile.mkdtemp()) - tmpfile = "tmp.tex" - dvifile = "tmp.dvi" - outfile = "tmp.png" - - with workdir.joinpath(tmpfile).open("w", encoding="utf8") as f: - f.writelines(genelatex(s, wrap)) - - subprocess.check_call( - ["latex", "-halt-on-error", "-interaction", "batchmode", tmpfile], - cwd=workdir, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - startupinfo=startupinfo, - ) - - resolution = round(150 * scale) - subprocess.check_call( - [ - "dvipng", - "-T", - "tight", - "-D", - str(resolution), - "-z", - "9", - "-bg", - "Transparent", - "-o", - outfile, - dvifile, - "-fg", - color, - ], - cwd=workdir, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - startupinfo=startupinfo, - ) - - with workdir.joinpath(outfile).open("rb") as f: - return f.read() - except subprocess.CalledProcessError: - return None - finally: - shutil.rmtree(workdir) - - -def kpsewhich(filename): - """Invoke kpsewhich command with an argument `filename`.""" - try: - find_cmd("kpsewhich") - proc = subprocess.Popen( - ["kpsewhich", filename], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (stdout, stderr) = proc.communicate() - return stdout.strip().decode('utf8', 'replace') - except FindCmdError: - pass - - -def genelatex(body, wrap): - """Generate LaTeX document for dvipng backend.""" - lt = LaTeXTool.instance() - breqn = wrap and lt.use_breqn and kpsewhich("breqn.sty") - yield r'\documentclass{article}' - packages = lt.packages - if breqn: - packages = packages + ['breqn'] - for pack in packages: - yield r'\usepackage{{{0}}}'.format(pack) - yield r'\pagestyle{empty}' - if lt.preamble: - yield lt.preamble - yield r'\begin{document}' - if breqn: - yield r'\begin{dmath*}' - yield body - yield r'\end{dmath*}' - elif wrap: - yield u'$${0}$$'.format(body) - else: - yield body - yield u'\\end{document}' - - -_data_uri_template_png = u"""%s""" - -def latex_to_html(s, alt='image'): - """Render LaTeX to HTML with embedded PNG data using data URIs. - - Parameters - ---------- - s : str - The raw string containing valid inline LateX. - alt : str - The alt text to use for the HTML. - """ - base64_data = latex_to_png(s, encode=True).decode('ascii') - if base64_data: - return _data_uri_template_png % (base64_data, alt) - - diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/lexers.py b/.venv/lib/python3.12/site-packages/IPython/lib/lexers.py deleted file mode 100644 index 9aa3433..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/lexers.py +++ /dev/null @@ -1,540 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Defines a variety of Pygments lexers for highlighting IPython code. - -This includes: - - IPythonLexer, IPython3Lexer - Lexers for pure IPython (python + magic/shell commands) - - IPythonPartialTracebackLexer, IPythonTracebackLexer - Supports 2.x and 3.x via keyword `python3`. The partial traceback - lexer reads everything but the Python code appearing in a traceback. - The full lexer combines the partial lexer with an IPython lexer. - - IPythonConsoleLexer - A lexer for IPython console sessions, with support for tracebacks. - - IPyLexer - A friendly lexer which examines the first line of text and from it, - decides whether to use an IPython lexer or an IPython console lexer. - This is probably the only lexer that needs to be explicitly added - to Pygments. - -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2013, the IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -# Standard library -import re - -# Third party -from pygments.lexers import ( - BashLexer, HtmlLexer, JavascriptLexer, RubyLexer, PerlLexer, PythonLexer, - Python3Lexer, TexLexer) -from pygments.lexer import ( - Lexer, DelegatingLexer, RegexLexer, do_insertions, bygroups, using, -) -from pygments.token import ( - Generic, Keyword, Literal, Name, Operator, Other, Text, Error, -) -from pygments.util import get_bool_opt - -# Local - -line_re = re.compile('.*?\n') - -__all__ = ['build_ipy_lexer', 'IPython3Lexer', 'IPythonLexer', - 'IPythonPartialTracebackLexer', 'IPythonTracebackLexer', - 'IPythonConsoleLexer', 'IPyLexer'] - - -def build_ipy_lexer(python3): - """Builds IPython lexers depending on the value of `python3`. - - The lexer inherits from an appropriate Python lexer and then adds - information about IPython specific keywords (i.e. magic commands, - shell commands, etc.) - - Parameters - ---------- - python3 : bool - If `True`, then build an IPython lexer from a Python 3 lexer. - - """ - # It would be nice to have a single IPython lexer class which takes - # a boolean `python3`. But since there are two Python lexer classes, - # we will also have two IPython lexer classes. - if python3: - PyLexer = Python3Lexer - name = 'IPython3' - aliases = ['ipython3'] - doc = """IPython3 Lexer""" - else: - PyLexer = PythonLexer - name = 'IPython' - aliases = ['ipython2', 'ipython'] - doc = """IPython Lexer""" - - ipython_tokens = [ - (r'(?s)(\s*)(%%capture)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%debug)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?is)(\s*)(%%html)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(HtmlLexer))), - (r'(?s)(\s*)(%%javascript)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(JavascriptLexer))), - (r'(?s)(\s*)(%%js)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(JavascriptLexer))), - (r'(?s)(\s*)(%%latex)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(TexLexer))), - (r'(?s)(\s*)(%%perl)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PerlLexer))), - (r'(?s)(\s*)(%%prun)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%pypy)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%python)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%python2)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PythonLexer))), - (r'(?s)(\s*)(%%python3)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(Python3Lexer))), - (r'(?s)(\s*)(%%ruby)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(RubyLexer))), - (r'(?s)(\s*)(%%time)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%timeit)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%writefile)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%file)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r"(?s)(\s*)(%%)(\w+)(.*)", bygroups(Text, Operator, Keyword, Text)), - (r'(?s)(^\s*)(%%!)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(BashLexer))), - (r"(%%?)(\w+)(\?\??)$", bygroups(Operator, Keyword, Operator)), - (r"\b(\?\??)(\s*)$", bygroups(Operator, Text)), - (r'(%)(sx|sc|system)(.*)(\n)', bygroups(Operator, Keyword, - using(BashLexer), Text)), - (r'(%)(\w+)(.*\n)', bygroups(Operator, Keyword, Text)), - (r'^(!!)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)), - (r'(!)(?!=)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)), - (r'^(\s*)(\?\??)(\s*%{0,2}[\w\.\*]*)', bygroups(Text, Operator, Text)), - (r'(\s*%{0,2}[\w\.\*]*)(\?\??)(\s*)$', bygroups(Text, Operator, Text)), - ] - - tokens = PyLexer.tokens.copy() - tokens['root'] = ipython_tokens + tokens['root'] - - attrs = {'name': name, 'aliases': aliases, 'filenames': [], - '__doc__': doc, 'tokens': tokens} - - return type(name, (PyLexer,), attrs) - - -IPython3Lexer = build_ipy_lexer(python3=True) -IPythonLexer = build_ipy_lexer(python3=False) - - -class IPythonPartialTracebackLexer(RegexLexer): - """ - Partial lexer for IPython tracebacks. - - Handles all the non-python output. - - """ - name = 'IPython Partial Traceback' - - tokens = { - 'root': [ - # Tracebacks for syntax errors have a different style. - # For both types of tracebacks, we mark the first line with - # Generic.Traceback. For syntax errors, we mark the filename - # as we mark the filenames for non-syntax tracebacks. - # - # These two regexps define how IPythonConsoleLexer finds a - # traceback. - # - ## Non-syntax traceback - (r'^(\^C)?(-+\n)', bygroups(Error, Generic.Traceback)), - ## Syntax traceback - (r'^( File)(.*)(, line )(\d+\n)', - bygroups(Generic.Traceback, Name.Namespace, - Generic.Traceback, Literal.Number.Integer)), - - # (Exception Identifier)(Whitespace)(Traceback Message) - (r'(?u)(^[^\d\W]\w*)(\s*)(Traceback.*?\n)', - bygroups(Name.Exception, Generic.Whitespace, Text)), - # (Module/Filename)(Text)(Callee)(Function Signature) - # Better options for callee and function signature? - (r'(.*)( in )(.*)(\(.*\)\n)', - bygroups(Name.Namespace, Text, Name.Entity, Name.Tag)), - # Regular line: (Whitespace)(Line Number)(Python Code) - (r'(\s*?)(\d+)(.*?\n)', - bygroups(Generic.Whitespace, Literal.Number.Integer, Other)), - # Emphasized line: (Arrow)(Line Number)(Python Code) - # Using Exception token so arrow color matches the Exception. - (r'(-*>?\s?)(\d+)(.*?\n)', - bygroups(Name.Exception, Literal.Number.Integer, Other)), - # (Exception Identifier)(Message) - (r'(?u)(^[^\d\W]\w*)(:.*?\n)', - bygroups(Name.Exception, Text)), - # Tag everything else as Other, will be handled later. - (r'.*\n', Other), - ], - } - - -class IPythonTracebackLexer(DelegatingLexer): - """ - IPython traceback lexer. - - For doctests, the tracebacks can be snipped as much as desired with the - exception to the lines that designate a traceback. For non-syntax error - tracebacks, this is the line of hyphens. For syntax error tracebacks, - this is the line which lists the File and line number. - - """ - # The lexer inherits from DelegatingLexer. The "root" lexer is an - # appropriate IPython lexer, which depends on the value of the boolean - # `python3`. First, we parse with the partial IPython traceback lexer. - # Then, any code marked with the "Other" token is delegated to the root - # lexer. - # - name = 'IPython Traceback' - aliases = ['ipythontb'] - - def __init__(self, **options): - """ - A subclass of `DelegatingLexer` which delegates to the appropriate to either IPyLexer, - IPythonPartialTracebackLexer. - """ - # note we need a __init__ doc, as otherwise it inherits the doc from the super class - # which will fail the documentation build as it references section of the pygments docs that - # do not exists when building IPython's docs. - self.python3 = get_bool_opt(options, 'python3', False) - if self.python3: - self.aliases = ['ipython3tb'] - else: - self.aliases = ['ipython2tb', 'ipythontb'] - - if self.python3: - IPyLexer = IPython3Lexer - else: - IPyLexer = IPythonLexer - - DelegatingLexer.__init__(self, IPyLexer, - IPythonPartialTracebackLexer, **options) - -class IPythonConsoleLexer(Lexer): - """ - An IPython console lexer for IPython code-blocks and doctests, such as: - - .. code-block:: rst - - .. code-block:: ipythonconsole - - In [1]: a = 'foo' - - In [2]: a - Out[2]: 'foo' - - In [3]: print(a) - foo - - - Support is also provided for IPython exceptions: - - .. code-block:: rst - - .. code-block:: ipythonconsole - - In [1]: raise Exception - Traceback (most recent call last): - ... - Exception - - """ - name = 'IPython console session' - aliases = ['ipythonconsole'] - mimetypes = ['text/x-ipython-console'] - - # The regexps used to determine what is input and what is output. - # The default prompts for IPython are: - # - # in = 'In [#]: ' - # continuation = ' .D.: ' - # template = 'Out[#]: ' - # - # Where '#' is the 'prompt number' or 'execution count' and 'D' - # D is a number of dots matching the width of the execution count - # - in1_regex = r'In \[[0-9]+\]: ' - in2_regex = r' \.\.+\.: ' - out_regex = r'Out\[[0-9]+\]: ' - - #: The regex to determine when a traceback starts. - ipytb_start = re.compile(r'^(\^C)?(-+\n)|^( File)(.*)(, line )(\d+\n)') - - def __init__(self, **options): - """Initialize the IPython console lexer. - - Parameters - ---------- - python3 : bool - If `True`, then the console inputs are parsed using a Python 3 - lexer. Otherwise, they are parsed using a Python 2 lexer. - in1_regex : RegexObject - The compiled regular expression used to detect the start - of inputs. Although the IPython configuration setting may have a - trailing whitespace, do not include it in the regex. If `None`, - then the default input prompt is assumed. - in2_regex : RegexObject - The compiled regular expression used to detect the continuation - of inputs. Although the IPython configuration setting may have a - trailing whitespace, do not include it in the regex. If `None`, - then the default input prompt is assumed. - out_regex : RegexObject - The compiled regular expression used to detect outputs. If `None`, - then the default output prompt is assumed. - - """ - self.python3 = get_bool_opt(options, 'python3', False) - if self.python3: - self.aliases = ['ipython3console'] - else: - self.aliases = ['ipython2console', 'ipythonconsole'] - - in1_regex = options.get('in1_regex', self.in1_regex) - in2_regex = options.get('in2_regex', self.in2_regex) - out_regex = options.get('out_regex', self.out_regex) - - # So that we can work with input and output prompts which have been - # rstrip'd (possibly by editors) we also need rstrip'd variants. If - # we do not do this, then such prompts will be tagged as 'output'. - # The reason can't just use the rstrip'd variants instead is because - # we want any whitespace associated with the prompt to be inserted - # with the token. This allows formatted code to be modified so as hide - # the appearance of prompts, with the whitespace included. One example - # use of this is in copybutton.js from the standard lib Python docs. - in1_regex_rstrip = in1_regex.rstrip() + '\n' - in2_regex_rstrip = in2_regex.rstrip() + '\n' - out_regex_rstrip = out_regex.rstrip() + '\n' - - # Compile and save them all. - attrs = ['in1_regex', 'in2_regex', 'out_regex', - 'in1_regex_rstrip', 'in2_regex_rstrip', 'out_regex_rstrip'] - for attr in attrs: - self.__setattr__(attr, re.compile(locals()[attr])) - - Lexer.__init__(self, **options) - - if self.python3: - pylexer = IPython3Lexer - tblexer = IPythonTracebackLexer - else: - pylexer = IPythonLexer - tblexer = IPythonTracebackLexer - - self.pylexer = pylexer(**options) - self.tblexer = tblexer(**options) - - self.reset() - - def reset(self): - self.mode = 'output' - self.index = 0 - self.buffer = u'' - self.insertions = [] - - def buffered_tokens(self): - """ - Generator of unprocessed tokens after doing insertions and before - changing to a new state. - - """ - if self.mode == 'output': - tokens = [(0, Generic.Output, self.buffer)] - elif self.mode == 'input': - tokens = self.pylexer.get_tokens_unprocessed(self.buffer) - else: # traceback - tokens = self.tblexer.get_tokens_unprocessed(self.buffer) - - for i, t, v in do_insertions(self.insertions, tokens): - # All token indexes are relative to the buffer. - yield self.index + i, t, v - - # Clear it all - self.index += len(self.buffer) - self.buffer = u'' - self.insertions = [] - - def get_mci(self, line): - """ - Parses the line and returns a 3-tuple: (mode, code, insertion). - - `mode` is the next mode (or state) of the lexer, and is always equal - to 'input', 'output', or 'tb'. - - `code` is a portion of the line that should be added to the buffer - corresponding to the next mode and eventually lexed by another lexer. - For example, `code` could be Python code if `mode` were 'input'. - - `insertion` is a 3-tuple (index, token, text) representing an - unprocessed "token" that will be inserted into the stream of tokens - that are created from the buffer once we change modes. This is usually - the input or output prompt. - - In general, the next mode depends on current mode and on the contents - of `line`. - - """ - # To reduce the number of regex match checks, we have multiple - # 'if' blocks instead of 'if-elif' blocks. - - # Check for possible end of input - in2_match = self.in2_regex.match(line) - in2_match_rstrip = self.in2_regex_rstrip.match(line) - if (in2_match and in2_match.group().rstrip() == line.rstrip()) or \ - in2_match_rstrip: - end_input = True - else: - end_input = False - if end_input and self.mode != 'tb': - # Only look for an end of input when not in tb mode. - # An ellipsis could appear within the traceback. - mode = 'output' - code = u'' - insertion = (0, Generic.Prompt, line) - return mode, code, insertion - - # Check for output prompt - out_match = self.out_regex.match(line) - out_match_rstrip = self.out_regex_rstrip.match(line) - if out_match or out_match_rstrip: - mode = 'output' - if out_match: - idx = out_match.end() - else: - idx = out_match_rstrip.end() - code = line[idx:] - # Use the 'heading' token for output. We cannot use Generic.Error - # since it would conflict with exceptions. - insertion = (0, Generic.Heading, line[:idx]) - return mode, code, insertion - - - # Check for input or continuation prompt (non stripped version) - in1_match = self.in1_regex.match(line) - if in1_match or (in2_match and self.mode != 'tb'): - # New input or when not in tb, continued input. - # We do not check for continued input when in tb since it is - # allowable to replace a long stack with an ellipsis. - mode = 'input' - if in1_match: - idx = in1_match.end() - else: # in2_match - idx = in2_match.end() - code = line[idx:] - insertion = (0, Generic.Prompt, line[:idx]) - return mode, code, insertion - - # Check for input or continuation prompt (stripped version) - in1_match_rstrip = self.in1_regex_rstrip.match(line) - if in1_match_rstrip or (in2_match_rstrip and self.mode != 'tb'): - # New input or when not in tb, continued input. - # We do not check for continued input when in tb since it is - # allowable to replace a long stack with an ellipsis. - mode = 'input' - if in1_match_rstrip: - idx = in1_match_rstrip.end() - else: # in2_match - idx = in2_match_rstrip.end() - code = line[idx:] - insertion = (0, Generic.Prompt, line[:idx]) - return mode, code, insertion - - # Check for traceback - if self.ipytb_start.match(line): - mode = 'tb' - code = line - insertion = None - return mode, code, insertion - - # All other stuff... - if self.mode in ('input', 'output'): - # We assume all other text is output. Multiline input that - # does not use the continuation marker cannot be detected. - # For example, the 3 in the following is clearly output: - # - # In [1]: print(3) - # 3 - # - # But the following second line is part of the input: - # - # In [2]: while True: - # print(True) - # - # In both cases, the 2nd line will be 'output'. - # - mode = 'output' - else: - mode = 'tb' - - code = line - insertion = None - - return mode, code, insertion - - def get_tokens_unprocessed(self, text): - self.reset() - for match in line_re.finditer(text): - line = match.group() - mode, code, insertion = self.get_mci(line) - - if mode != self.mode: - # Yield buffered tokens before transitioning to new mode. - for token in self.buffered_tokens(): - yield token - self.mode = mode - - if insertion: - self.insertions.append((len(self.buffer), [insertion])) - self.buffer += code - - for token in self.buffered_tokens(): - yield token - -class IPyLexer(Lexer): - r""" - Primary lexer for all IPython-like code. - - This is a simple helper lexer. If the first line of the text begins with - "In \[[0-9]+\]:", then the entire text is parsed with an IPython console - lexer. If not, then the entire text is parsed with an IPython lexer. - - The goal is to reduce the number of lexers that are registered - with Pygments. - - """ - name = 'IPy session' - aliases = ['ipy'] - - def __init__(self, **options): - """ - Create a new IPyLexer instance which dispatch to either an - IPythonCOnsoleLexer (if In prompts are present) or and IPythonLexer (if - In prompts are not present). - """ - # init docstring is necessary for docs not to fail to build do to parent - # docs referenceing a section in pygments docs. - self.python3 = get_bool_opt(options, 'python3', False) - if self.python3: - self.aliases = ['ipy3'] - else: - self.aliases = ['ipy2', 'ipy'] - - Lexer.__init__(self, **options) - - self.IPythonLexer = IPythonLexer(**options) - self.IPythonConsoleLexer = IPythonConsoleLexer(**options) - - def get_tokens_unprocessed(self, text): - # Search for the input prompt anywhere...this allows code blocks to - # begin with comments as well. - if re.match(r'.*(In \[[0-9]+\]:)', text.strip(), re.DOTALL): - lex = self.IPythonConsoleLexer - else: - lex = self.IPythonLexer - for token in lex.get_tokens_unprocessed(text): - yield token - diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/pretty.py b/.venv/lib/python3.12/site-packages/IPython/lib/pretty.py deleted file mode 100644 index a232e4e..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/pretty.py +++ /dev/null @@ -1,961 +0,0 @@ -""" -Python advanced pretty printer. This pretty printer is intended to -replace the old `pprint` python module which does not allow developers -to provide their own pretty print callbacks. - -This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`. - - -Example Usage -------------- - -To directly print the representation of an object use `pprint`:: - - from pretty import pprint - pprint(complex_object) - -To get a string of the output use `pretty`:: - - from pretty import pretty - string = pretty(complex_object) - - -Extending ---------- - -The pretty library allows developers to add pretty printing rules for their -own objects. This process is straightforward. All you have to do is to -add a `_repr_pretty_` method to your object and call the methods on the -pretty printer passed:: - - class MyObject(object): - - def _repr_pretty_(self, p, cycle): - ... - -Here's an example for a class with a simple constructor:: - - class MySimpleObject: - - def __init__(self, a, b, *, c=None): - self.a = a - self.b = b - self.c = c - - def _repr_pretty_(self, p, cycle): - ctor = CallExpression.factory(self.__class__.__name__) - if self.c is None: - p.pretty(ctor(a, b)) - else: - p.pretty(ctor(a, b, c=c)) - -Here is an example implementation of a `_repr_pretty_` method for a list -subclass:: - - class MyList(list): - - def _repr_pretty_(self, p, cycle): - if cycle: - p.text('MyList(...)') - else: - with p.group(8, 'MyList([', '])'): - for idx, item in enumerate(self): - if idx: - p.text(',') - p.breakable() - p.pretty(item) - -The `cycle` parameter is `True` if pretty detected a cycle. You *have* to -react to that or the result is an infinite loop. `p.text()` just adds -non breaking text to the output, `p.breakable()` either adds a whitespace -or breaks here. If you pass it an argument it's used instead of the -default space. `p.pretty` prettyprints another object using the pretty print -method. - -The first parameter to the `group` function specifies the extra indentation -of the next line. In this example the next item will either be on the same -line (if the items are short enough) or aligned with the right edge of the -opening bracket of `MyList`. - -If you just want to indent something you can use the group function -without open / close parameters. You can also use this code:: - - with p.indent(2): - ... - -Inheritance diagram: - -.. inheritance-diagram:: IPython.lib.pretty - :parts: 3 - -:copyright: 2007 by Armin Ronacher. - Portions (c) 2009 by Robert Kern. -:license: BSD License. -""" - -from contextlib import contextmanager -import datetime -import os -import re -import sys -import types -from collections import deque -from inspect import signature -from io import StringIO -from warnings import warn - -from IPython.utils.decorators import undoc -from IPython.utils.py3compat import PYPY - -from typing import Dict - -__all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter', - 'for_type', 'for_type_by_name', 'RawText', 'RawStringLiteral', 'CallExpression'] - - -MAX_SEQ_LENGTH = 1000 -_re_pattern_type = type(re.compile('')) - -def _safe_getattr(obj, attr, default=None): - """Safe version of getattr. - - Same as getattr, but will return ``default`` on any Exception, - rather than raising. - """ - try: - return getattr(obj, attr, default) - except Exception: - return default - -@undoc -class CUnicodeIO(StringIO): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - warn(("CUnicodeIO is deprecated since IPython 6.0. " - "Please use io.StringIO instead."), - DeprecationWarning, stacklevel=2) - -def _sorted_for_pprint(items): - """ - Sort the given items for pretty printing. Since some predictable - sorting is better than no sorting at all, we sort on the string - representation if normal sorting fails. - """ - items = list(items) - try: - return sorted(items) - except Exception: - try: - return sorted(items, key=str) - except Exception: - return items - -def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH): - """ - Pretty print the object's representation. - """ - stream = StringIO() - printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length) - printer.pretty(obj) - printer.flush() - return stream.getvalue() - - -def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH): - """ - Like `pretty` but print to stdout. - """ - printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length) - printer.pretty(obj) - printer.flush() - sys.stdout.write(newline) - sys.stdout.flush() - -class _PrettyPrinterBase(object): - - @contextmanager - def indent(self, indent): - """with statement support for indenting/dedenting.""" - self.indentation += indent - try: - yield - finally: - self.indentation -= indent - - @contextmanager - def group(self, indent=0, open='', close=''): - """like begin_group / end_group but for the with statement.""" - self.begin_group(indent, open) - try: - yield - finally: - self.end_group(indent, close) - -class PrettyPrinter(_PrettyPrinterBase): - """ - Baseclass for the `RepresentationPrinter` prettyprinter that is used to - generate pretty reprs of objects. Contrary to the `RepresentationPrinter` - this printer knows nothing about the default pprinters or the `_repr_pretty_` - callback method. - """ - - def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH): - self.output = output - self.max_width = max_width - self.newline = newline - self.max_seq_length = max_seq_length - self.output_width = 0 - self.buffer_width = 0 - self.buffer = deque() - - root_group = Group(0) - self.group_stack = [root_group] - self.group_queue = GroupQueue(root_group) - self.indentation = 0 - - def _break_one_group(self, group): - while group.breakables: - x = self.buffer.popleft() - self.output_width = x.output(self.output, self.output_width) - self.buffer_width -= x.width - while self.buffer and isinstance(self.buffer[0], Text): - x = self.buffer.popleft() - self.output_width = x.output(self.output, self.output_width) - self.buffer_width -= x.width - - def _break_outer_groups(self): - while self.max_width < self.output_width + self.buffer_width: - group = self.group_queue.deq() - if not group: - return - self._break_one_group(group) - - def text(self, obj): - """Add literal text to the output.""" - width = len(obj) - if self.buffer: - text = self.buffer[-1] - if not isinstance(text, Text): - text = Text() - self.buffer.append(text) - text.add(obj, width) - self.buffer_width += width - self._break_outer_groups() - else: - self.output.write(obj) - self.output_width += width - - def breakable(self, sep=' '): - """ - Add a breakable separator to the output. This does not mean that it - will automatically break here. If no breaking on this position takes - place the `sep` is inserted which default to one space. - """ - width = len(sep) - group = self.group_stack[-1] - if group.want_break: - self.flush() - self.output.write(self.newline) - self.output.write(' ' * self.indentation) - self.output_width = self.indentation - self.buffer_width = 0 - else: - self.buffer.append(Breakable(sep, width, self)) - self.buffer_width += width - self._break_outer_groups() - - def break_(self): - """ - Explicitly insert a newline into the output, maintaining correct indentation. - """ - group = self.group_queue.deq() - if group: - self._break_one_group(group) - self.flush() - self.output.write(self.newline) - self.output.write(' ' * self.indentation) - self.output_width = self.indentation - self.buffer_width = 0 - - - def begin_group(self, indent=0, open=''): - """ - Begin a group. - The first parameter specifies the indentation for the next line (usually - the width of the opening text), the second the opening text. All - parameters are optional. - """ - if open: - self.text(open) - group = Group(self.group_stack[-1].depth + 1) - self.group_stack.append(group) - self.group_queue.enq(group) - self.indentation += indent - - def _enumerate(self, seq): - """like enumerate, but with an upper limit on the number of items""" - for idx, x in enumerate(seq): - if self.max_seq_length and idx >= self.max_seq_length: - self.text(',') - self.breakable() - self.text('...') - return - yield idx, x - - def end_group(self, dedent=0, close=''): - """End a group. See `begin_group` for more details.""" - self.indentation -= dedent - group = self.group_stack.pop() - if not group.breakables: - self.group_queue.remove(group) - if close: - self.text(close) - - def flush(self): - """Flush data that is left in the buffer.""" - for data in self.buffer: - self.output_width += data.output(self.output, self.output_width) - self.buffer.clear() - self.buffer_width = 0 - - -def _get_mro(obj_class): - """ Get a reasonable method resolution order of a class and its superclasses - for both old-style and new-style classes. - """ - if not hasattr(obj_class, '__mro__'): - # Old-style class. Mix in object to make a fake new-style class. - try: - obj_class = type(obj_class.__name__, (obj_class, object), {}) - except TypeError: - # Old-style extension type that does not descend from object. - # FIXME: try to construct a more thorough MRO. - mro = [obj_class] - else: - mro = obj_class.__mro__[1:-1] - else: - mro = obj_class.__mro__ - return mro - - -class RepresentationPrinter(PrettyPrinter): - """ - Special pretty printer that has a `pretty` method that calls the pretty - printer for a python object. - - This class stores processing data on `self` so you must *never* use - this class in a threaded environment. Always lock it or reinstanciate - it. - - Instances also have a verbose flag callbacks can access to control their - output. For example the default instance repr prints all attributes and - methods that are not prefixed by an underscore if the printer is in - verbose mode. - """ - - def __init__(self, output, verbose=False, max_width=79, newline='\n', - singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None, - max_seq_length=MAX_SEQ_LENGTH): - - PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length) - self.verbose = verbose - self.stack = [] - if singleton_pprinters is None: - singleton_pprinters = _singleton_pprinters.copy() - self.singleton_pprinters = singleton_pprinters - if type_pprinters is None: - type_pprinters = _type_pprinters.copy() - self.type_pprinters = type_pprinters - if deferred_pprinters is None: - deferred_pprinters = _deferred_type_pprinters.copy() - self.deferred_pprinters = deferred_pprinters - - def pretty(self, obj): - """Pretty print the given object.""" - obj_id = id(obj) - cycle = obj_id in self.stack - self.stack.append(obj_id) - self.begin_group() - try: - obj_class = _safe_getattr(obj, '__class__', None) or type(obj) - # First try to find registered singleton printers for the type. - try: - printer = self.singleton_pprinters[obj_id] - except (TypeError, KeyError): - pass - else: - return printer(obj, self, cycle) - # Next walk the mro and check for either: - # 1) a registered printer - # 2) a _repr_pretty_ method - for cls in _get_mro(obj_class): - if cls in self.type_pprinters: - # printer registered in self.type_pprinters - return self.type_pprinters[cls](obj, self, cycle) - else: - # deferred printer - printer = self._in_deferred_types(cls) - if printer is not None: - return printer(obj, self, cycle) - else: - # Finally look for special method names. - # Some objects automatically create any requested - # attribute. Try to ignore most of them by checking for - # callability. - if '_repr_pretty_' in cls.__dict__: - meth = cls._repr_pretty_ - if callable(meth): - return meth(obj, self, cycle) - if ( - cls is not object - # check if cls defines __repr__ - and "__repr__" in cls.__dict__ - # check if __repr__ is callable. - # Note: we need to test getattr(cls, '__repr__') - # instead of cls.__dict__['__repr__'] - # in order to work with descriptors like partialmethod, - and callable(_safe_getattr(cls, "__repr__", None)) - ): - return _repr_pprint(obj, self, cycle) - - return _default_pprint(obj, self, cycle) - finally: - self.end_group() - self.stack.pop() - - def _in_deferred_types(self, cls): - """ - Check if the given class is specified in the deferred type registry. - - Returns the printer from the registry if it exists, and None if the - class is not in the registry. Successful matches will be moved to the - regular type registry for future use. - """ - mod = _safe_getattr(cls, '__module__', None) - name = _safe_getattr(cls, '__name__', None) - key = (mod, name) - printer = None - if key in self.deferred_pprinters: - # Move the printer over to the regular registry. - printer = self.deferred_pprinters.pop(key) - self.type_pprinters[cls] = printer - return printer - - -class Printable(object): - - def output(self, stream, output_width): - return output_width - - -class Text(Printable): - - def __init__(self): - self.objs = [] - self.width = 0 - - def output(self, stream, output_width): - for obj in self.objs: - stream.write(obj) - return output_width + self.width - - def add(self, obj, width): - self.objs.append(obj) - self.width += width - - -class Breakable(Printable): - - def __init__(self, seq, width, pretty): - self.obj = seq - self.width = width - self.pretty = pretty - self.indentation = pretty.indentation - self.group = pretty.group_stack[-1] - self.group.breakables.append(self) - - def output(self, stream, output_width): - self.group.breakables.popleft() - if self.group.want_break: - stream.write(self.pretty.newline) - stream.write(' ' * self.indentation) - return self.indentation - if not self.group.breakables: - self.pretty.group_queue.remove(self.group) - stream.write(self.obj) - return output_width + self.width - - -class Group(Printable): - - def __init__(self, depth): - self.depth = depth - self.breakables = deque() - self.want_break = False - - -class GroupQueue(object): - - def __init__(self, *groups): - self.queue = [] - for group in groups: - self.enq(group) - - def enq(self, group): - depth = group.depth - while depth > len(self.queue) - 1: - self.queue.append([]) - self.queue[depth].append(group) - - def deq(self): - for stack in self.queue: - for idx, group in enumerate(reversed(stack)): - if group.breakables: - del stack[idx] - group.want_break = True - return group - for group in stack: - group.want_break = True - del stack[:] - - def remove(self, group): - try: - self.queue[group.depth].remove(group) - except ValueError: - pass - - -class RawText: - """ Object such that ``p.pretty(RawText(value))`` is the same as ``p.text(value)``. - - An example usage of this would be to show a list as binary numbers, using - ``p.pretty([RawText(bin(i)) for i in integers])``. - """ - def __init__(self, value): - self.value = value - - def _repr_pretty_(self, p, cycle): - p.text(self.value) - - -class CallExpression: - """ Object which emits a line-wrapped call expression in the form `__name(*args, **kwargs)` """ - def __init__(__self, __name, *args, **kwargs): - # dunders are to avoid clashes with kwargs, as python's name managing - # will kick in. - self = __self - self.name = __name - self.args = args - self.kwargs = kwargs - - @classmethod - def factory(cls, name): - def inner(*args, **kwargs): - return cls(name, *args, **kwargs) - return inner - - def _repr_pretty_(self, p, cycle): - # dunders are to avoid clashes with kwargs, as python's name managing - # will kick in. - - started = False - def new_item(): - nonlocal started - if started: - p.text(",") - p.breakable() - started = True - - prefix = self.name + "(" - with p.group(len(prefix), prefix, ")"): - for arg in self.args: - new_item() - p.pretty(arg) - for arg_name, arg in self.kwargs.items(): - new_item() - arg_prefix = arg_name + "=" - with p.group(len(arg_prefix), arg_prefix): - p.pretty(arg) - - -class RawStringLiteral: - """ Wrapper that shows a string with a `r` prefix """ - def __init__(self, value): - self.value = value - - def _repr_pretty_(self, p, cycle): - base_repr = repr(self.value) - if base_repr[:1] in 'uU': - base_repr = base_repr[1:] - prefix = 'ur' - else: - prefix = 'r' - base_repr = prefix + base_repr.replace('\\\\', '\\') - p.text(base_repr) - - -def _default_pprint(obj, p, cycle): - """ - The default print function. Used if an object does not provide one and - it's none of the builtin objects. - """ - klass = _safe_getattr(obj, '__class__', None) or type(obj) - if _safe_getattr(klass, '__repr__', None) is not object.__repr__: - # A user-provided repr. Find newlines and replace them with p.break_() - _repr_pprint(obj, p, cycle) - return - p.begin_group(1, '<') - p.pretty(klass) - p.text(' at 0x%x' % id(obj)) - if cycle: - p.text(' ...') - elif p.verbose: - first = True - for key in dir(obj): - if not key.startswith('_'): - try: - value = getattr(obj, key) - except AttributeError: - continue - if isinstance(value, types.MethodType): - continue - if not first: - p.text(',') - p.breakable() - p.text(key) - p.text('=') - step = len(key) + 1 - p.indentation += step - p.pretty(value) - p.indentation -= step - first = False - p.end_group(1, '>') - - -def _seq_pprinter_factory(start, end): - """ - Factory that returns a pprint function useful for sequences. Used by - the default pprint for tuples and lists. - """ - def inner(obj, p, cycle): - if cycle: - return p.text(start + '...' + end) - step = len(start) - p.begin_group(step, start) - for idx, x in p._enumerate(obj): - if idx: - p.text(',') - p.breakable() - p.pretty(x) - if len(obj) == 1 and isinstance(obj, tuple): - # Special case for 1-item tuples. - p.text(',') - p.end_group(step, end) - return inner - - -def _set_pprinter_factory(start, end): - """ - Factory that returns a pprint function useful for sets and frozensets. - """ - def inner(obj, p, cycle): - if cycle: - return p.text(start + '...' + end) - if len(obj) == 0: - # Special case. - p.text(type(obj).__name__ + '()') - else: - step = len(start) - p.begin_group(step, start) - # Like dictionary keys, we will try to sort the items if there aren't too many - if not (p.max_seq_length and len(obj) >= p.max_seq_length): - items = _sorted_for_pprint(obj) - else: - items = obj - for idx, x in p._enumerate(items): - if idx: - p.text(',') - p.breakable() - p.pretty(x) - p.end_group(step, end) - return inner - - -def _dict_pprinter_factory(start, end): - """ - Factory that returns a pprint function used by the default pprint of - dicts and dict proxies. - """ - def inner(obj, p, cycle): - if cycle: - return p.text('{...}') - step = len(start) - p.begin_group(step, start) - keys = obj.keys() - for idx, key in p._enumerate(keys): - if idx: - p.text(',') - p.breakable() - p.pretty(key) - p.text(': ') - p.pretty(obj[key]) - p.end_group(step, end) - return inner - - -def _super_pprint(obj, p, cycle): - """The pprint for the super type.""" - p.begin_group(8, '') - - - -class _ReFlags: - def __init__(self, value): - self.value = value - - def _repr_pretty_(self, p, cycle): - done_one = False - for flag in ( - "IGNORECASE", - "LOCALE", - "MULTILINE", - "DOTALL", - "UNICODE", - "VERBOSE", - "DEBUG", - ): - if self.value & getattr(re, flag): - if done_one: - p.text('|') - p.text('re.' + flag) - done_one = True - - -def _re_pattern_pprint(obj, p, cycle): - """The pprint function for regular expression patterns.""" - re_compile = CallExpression.factory('re.compile') - if obj.flags: - p.pretty(re_compile(RawStringLiteral(obj.pattern), _ReFlags(obj.flags))) - else: - p.pretty(re_compile(RawStringLiteral(obj.pattern))) - - -def _types_simplenamespace_pprint(obj, p, cycle): - """The pprint function for types.SimpleNamespace.""" - namespace = CallExpression.factory('namespace') - if cycle: - p.pretty(namespace(RawText("..."))) - else: - p.pretty(namespace(**obj.__dict__)) - - -def _type_pprint(obj, p, cycle): - """The pprint for classes and types.""" - # Heap allocated types might not have the module attribute, - # and others may set it to None. - - # Checks for a __repr__ override in the metaclass. Can't compare the - # type(obj).__repr__ directly because in PyPy the representation function - # inherited from type isn't the same type.__repr__ - if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]: - _repr_pprint(obj, p, cycle) - return - - mod = _safe_getattr(obj, '__module__', None) - try: - name = obj.__qualname__ - if not isinstance(name, str): - # This can happen if the type implements __qualname__ as a property - # or other descriptor in Python 2. - raise Exception("Try __name__") - except Exception: - name = obj.__name__ - if not isinstance(name, str): - name = '' - - if mod in (None, '__builtin__', 'builtins', 'exceptions'): - p.text(name) - else: - p.text(mod + '.' + name) - - -def _repr_pprint(obj, p, cycle): - """A pprint that just redirects to the normal repr function.""" - # Find newlines and replace them with p.break_() - output = repr(obj) - lines = output.splitlines() - with p.group(): - for idx, output_line in enumerate(lines): - if idx: - p.break_() - p.text(output_line) - - -def _function_pprint(obj, p, cycle): - """Base pprint for all functions and builtin functions.""" - name = _safe_getattr(obj, '__qualname__', obj.__name__) - mod = obj.__module__ - if mod and mod not in ('__builtin__', 'builtins', 'exceptions'): - name = mod + '.' + name - try: - func_def = name + str(signature(obj)) - except ValueError: - func_def = name - p.text('' % func_def) - - -def _exception_pprint(obj, p, cycle): - """Base pprint for all exceptions.""" - name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__) - if obj.__class__.__module__ not in ('exceptions', 'builtins'): - name = '%s.%s' % (obj.__class__.__module__, name) - - p.pretty(CallExpression(name, *getattr(obj, 'args', ()))) - - -#: the exception base -_exception_base: type -try: - _exception_base = BaseException -except NameError: - _exception_base = Exception - - -#: printers for builtin types -_type_pprinters = { - int: _repr_pprint, - float: _repr_pprint, - str: _repr_pprint, - tuple: _seq_pprinter_factory('(', ')'), - list: _seq_pprinter_factory('[', ']'), - dict: _dict_pprinter_factory('{', '}'), - set: _set_pprinter_factory('{', '}'), - frozenset: _set_pprinter_factory('frozenset({', '})'), - super: _super_pprint, - _re_pattern_type: _re_pattern_pprint, - type: _type_pprint, - types.FunctionType: _function_pprint, - types.BuiltinFunctionType: _function_pprint, - types.MethodType: _repr_pprint, - types.SimpleNamespace: _types_simplenamespace_pprint, - datetime.datetime: _repr_pprint, - datetime.timedelta: _repr_pprint, - _exception_base: _exception_pprint -} - -# render os.environ like a dict -_env_type = type(os.environ) -# future-proof in case os.environ becomes a plain dict? -if _env_type is not dict: - _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}') - -_type_pprinters[types.MappingProxyType] = _dict_pprinter_factory("mappingproxy({", "})") -_type_pprinters[slice] = _repr_pprint - -_type_pprinters[range] = _repr_pprint -_type_pprinters[bytes] = _repr_pprint - -#: printers for types specified by name -_deferred_type_pprinters: Dict = {} - - -def for_type(typ, func): - """ - Add a pretty printer for a given type. - """ - oldfunc = _type_pprinters.get(typ, None) - if func is not None: - # To support easy restoration of old pprinters, we need to ignore Nones. - _type_pprinters[typ] = func - return oldfunc - -def for_type_by_name(type_module, type_name, func): - """ - Add a pretty printer for a type specified by the module and name of a type - rather than the type object itself. - """ - key = (type_module, type_name) - oldfunc = _deferred_type_pprinters.get(key, None) - if func is not None: - # To support easy restoration of old pprinters, we need to ignore Nones. - _deferred_type_pprinters[key] = func - return oldfunc - - -#: printers for the default singletons -_singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis, - NotImplemented]), _repr_pprint) - - -def _defaultdict_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - else: - p.pretty(cls_ctor(obj.default_factory, dict(obj))) - -def _ordereddict_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - elif len(obj): - p.pretty(cls_ctor(list(obj.items()))) - else: - p.pretty(cls_ctor()) - -def _deque_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - elif obj.maxlen is not None: - p.pretty(cls_ctor(list(obj), maxlen=obj.maxlen)) - else: - p.pretty(cls_ctor(list(obj))) - -def _counter_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - elif len(obj): - p.pretty(cls_ctor(dict(obj.most_common()))) - else: - p.pretty(cls_ctor()) - - -def _userlist_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - else: - p.pretty(cls_ctor(obj.data)) - - -for_type_by_name('collections', 'defaultdict', _defaultdict_pprint) -for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint) -for_type_by_name('collections', 'deque', _deque_pprint) -for_type_by_name('collections', 'Counter', _counter_pprint) -for_type_by_name("collections", "UserList", _userlist_pprint) - -if __name__ == '__main__': - from random import randrange - class Foo(object): - def __init__(self): - self.foo = 1 - self.bar = re.compile(r'\s+') - self.blub = dict.fromkeys(range(30), randrange(1, 40)) - self.hehe = 23424.234234 - self.list = ["blub", "blah", self] - - def get_foo(self): - print("foo") - - pprint(Foo(), verbose=True) diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__init__.py b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index bc4e2e8..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_backgroundjobs.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_backgroundjobs.cpython-312.pyc deleted file mode 100644 index f504911..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_backgroundjobs.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_clipboard.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_clipboard.cpython-312.pyc deleted file mode 100644 index fc41f12..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_clipboard.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_deepreload.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_deepreload.cpython-312.pyc deleted file mode 100644 index f012ae7..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_deepreload.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_display.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_display.cpython-312.pyc deleted file mode 100644 index fd90e33..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_display.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_editorhooks.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_editorhooks.cpython-312.pyc deleted file mode 100644 index 041ae88..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_editorhooks.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_imports.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_imports.cpython-312.pyc deleted file mode 100644 index 3e82011..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_imports.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_latextools.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_latextools.cpython-312.pyc deleted file mode 100644 index b2ce7b6..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_latextools.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_lexers.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_lexers.cpython-312.pyc deleted file mode 100644 index 1da9973..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_lexers.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_pretty.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_pretty.cpython-312.pyc deleted file mode 100644 index cda3ab7..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_pretty.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_pygments.cpython-312.pyc b/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_pygments.cpython-312.pyc deleted file mode 100644 index ae09256..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/__pycache__/test_pygments.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test.wav b/.venv/lib/python3.12/site-packages/IPython/lib/tests/test.wav deleted file mode 100644 index aa74fc5..0000000 Binary files a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test.wav and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_backgroundjobs.py b/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_backgroundjobs.py deleted file mode 100644 index fc76ff1..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_backgroundjobs.py +++ /dev/null @@ -1,85 +0,0 @@ -"""Tests for pylab tools module. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2011, the IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib imports -import time - -# Our own imports -from IPython.lib import backgroundjobs as bg - -#----------------------------------------------------------------------------- -# Globals and constants -#----------------------------------------------------------------------------- -t_short = 0.0001 # very short interval to wait on jobs - -#----------------------------------------------------------------------------- -# Local utilities -#----------------------------------------------------------------------------- -def sleeper(interval=t_short, *a, **kw): - args = dict(interval=interval, - other_args=a, - kw_args=kw) - time.sleep(interval) - return args - -def crasher(interval=t_short, *a, **kw): - time.sleep(interval) - raise Exception("Dead job with interval %s" % interval) - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -def test_result(): - """Test job submission and result retrieval""" - jobs = bg.BackgroundJobManager() - j = jobs.new(sleeper) - j.join() - assert j.result["interval"] == t_short - - -def test_flush(): - """Test job control""" - jobs = bg.BackgroundJobManager() - j = jobs.new(sleeper) - j.join() - assert len(jobs.completed) == 1 - assert len(jobs.dead) == 0 - jobs.flush() - assert len(jobs.completed) == 0 - - -def test_dead(): - """Test control of dead jobs""" - jobs = bg.BackgroundJobManager() - j = jobs.new(crasher) - j.join() - assert len(jobs.completed) == 0 - assert len(jobs.dead) == 1 - jobs.flush() - assert len(jobs.dead) == 0 - - -def test_longer(): - """Test control of longer-running jobs""" - jobs = bg.BackgroundJobManager() - # Sleep for long enough for the following two checks to still report the - # job as running, but not so long that it makes the test suite noticeably - # slower. - j = jobs.new(sleeper, 0.1) - assert len(jobs.running) == 1 - assert len(jobs.completed) == 0 - j.join() - assert len(jobs.running) == 0 - assert len(jobs.completed) == 1 diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_clipboard.py b/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_clipboard.py deleted file mode 100644 index 6597c94..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_clipboard.py +++ /dev/null @@ -1,20 +0,0 @@ -from IPython.core.error import TryNext -from IPython.lib.clipboard import ClipboardEmpty -from IPython.testing.decorators import skip_if_no_x11 - - -@skip_if_no_x11 -def test_clipboard_get(): - # Smoketest for clipboard access - we can't easily guarantee that the - # clipboard is accessible and has something on it, but this tries to - # exercise the relevant code anyway. - try: - a = get_ipython().hooks.clipboard_get() - except ClipboardEmpty: - # Nothing in clipboard to get - pass - except TryNext: - # No clipboard access API available - pass - else: - assert isinstance(a, str) diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_deepreload.py b/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_deepreload.py deleted file mode 100644 index 5da606c..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_deepreload.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test suite for the deepreload module.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import types -from pathlib import Path - -import pytest -from tempfile import TemporaryDirectory - -from IPython.lib.deepreload import modules_reloading -from IPython.lib.deepreload import reload as dreload -from IPython.utils.syspathcontext import prepended_to_syspath - - -def test_deepreload(): - "Test that dreload does deep reloads and skips excluded modules." - with TemporaryDirectory() as tmpdir: - with prepended_to_syspath(tmpdir): - tmpdirpath = Path(tmpdir) - with open(tmpdirpath / "A.py", "w", encoding="utf-8") as f: - f.write("class Object:\n pass\nok = True\n") - with open(tmpdirpath / "B.py", "w", encoding="utf-8") as f: - f.write("import A\nassert A.ok, 'we are fine'\n") - import A - import B - - # Test that A is not reloaded. - obj = A.Object() - dreload(B, exclude=["A"]) - assert isinstance(obj, A.Object) is True - - # Test that an import failure will not blow-up us. - A.ok = False - with pytest.raises(AssertionError, match="we are fine"): - dreload(B, exclude=["A"]) - assert len(modules_reloading) == 0 - assert not A.ok - - # Test that A is reloaded. - obj = A.Object() - A.ok = False - dreload(B) - assert A.ok - assert isinstance(obj, A.Object) is False - - -def test_not_module(): - pytest.raises(TypeError, dreload, "modulename") - - -def test_not_in_sys_modules(): - fake_module = types.ModuleType("fake_module") - with pytest.raises(ImportError, match="not in sys.modules"): - dreload(fake_module) diff --git a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_display.py b/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_display.py deleted file mode 100644 index f5ed34c..0000000 --- a/.venv/lib/python3.12/site-packages/IPython/lib/tests/test_display.py +++ /dev/null @@ -1,272 +0,0 @@ -"""Tests for IPython.lib.display. - -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012, the IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -from tempfile import NamedTemporaryFile, mkdtemp -from os.path import split, join as pjoin, dirname -import pathlib -from unittest import TestCase, mock -import struct -import wave -from io import BytesIO - -# Third-party imports -import pytest - -try: - import numpy -except ImportError: - pass - -# Our own imports -from IPython.lib import display - -from IPython.testing.decorators import skipif_not_numpy - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -#-------------------------- -# FileLink tests -#-------------------------- - -def test_instantiation_FileLink(): - """FileLink: Test class can be instantiated""" - fl = display.FileLink('example.txt') - # TODO: remove if when only Python >= 3.6 is supported - fl = display.FileLink(pathlib.PurePath('example.txt')) - -def test_warning_on_non_existent_path_FileLink(): - """FileLink: Calling _repr_html_ on non-existent files returns a warning""" - fl = display.FileLink("example.txt") - assert fl._repr_html_().startswith("Path (example.txt)") - - -def test_existing_path_FileLink(): - """FileLink: Calling _repr_html_ functions as expected on existing filepath - """ - tf = NamedTemporaryFile() - fl = display.FileLink(tf.name) - actual = fl._repr_html_() - expected = "%s
" % (tf.name, tf.name) - assert actual == expected - - -def test_existing_path_FileLink_repr(): - """FileLink: Calling repr() functions as expected on existing filepath - """ - tf = NamedTemporaryFile() - fl = display.FileLink(tf.name) - actual = repr(fl) - expected = tf.name - assert actual == expected - - -def test_error_on_directory_to_FileLink(): - """FileLink: Raises error when passed directory - """ - td = mkdtemp() - pytest.raises(ValueError, display.FileLink, td) - -#-------------------------- -# FileLinks tests -#-------------------------- - -def test_instantiation_FileLinks(): - """FileLinks: Test class can be instantiated - """ - fls = display.FileLinks('example') - -def test_warning_on_non_existent_path_FileLinks(): - """FileLinks: Calling _repr_html_ on non-existent files returns a warning""" - fls = display.FileLinks("example") - assert fls._repr_html_().startswith("Path (example)") - - -def test_existing_path_FileLinks(): - """FileLinks: Calling _repr_html_ functions as expected on existing dir - """ - td = mkdtemp() - tf1 = NamedTemporaryFile(dir=td) - tf2 = NamedTemporaryFile(dir=td) - fl = display.FileLinks(td) - actual = fl._repr_html_() - actual = actual.split('\n') - actual.sort() - # the links should always have forward slashes, even on windows, so replace - # backslashes with forward slashes here - expected = ["%s/
" % td, - "  %s
" %\ - (tf2.name.replace("\\","/"),split(tf2.name)[1]), - "  %s
" %\ - (tf1.name.replace("\\","/"),split(tf1.name)[1])] - expected.sort() - # We compare the sorted list of links here as that's more reliable - assert actual == expected - - -def test_existing_path_FileLinks_alt_formatter(): - """FileLinks: Calling _repr_html_ functions as expected w/ an alt formatter - """ - td = mkdtemp() - tf1 = NamedTemporaryFile(dir=td) - tf2 = NamedTemporaryFile(dir=td) - def fake_formatter(dirname,fnames,included_suffixes): - return ["hello","world"] - fl = display.FileLinks(td,notebook_display_formatter=fake_formatter) - actual = fl._repr_html_() - actual = actual.split('\n') - actual.sort() - expected = ["hello","world"] - expected.sort() - # We compare the sorted list of links here as that's more reliable - assert actual == expected - - -def test_existing_path_FileLinks_repr(): - """FileLinks: Calling repr() functions as expected on existing directory """ - td = mkdtemp() - tf1 = NamedTemporaryFile(dir=td) - tf2 = NamedTemporaryFile(dir=td) - fl = display.FileLinks(td) - actual = repr(fl) - actual = actual.split('\n') - actual.sort() - expected = ['%s/' % td, ' %s' % split(tf1.name)[1],' %s' % split(tf2.name)[1]] - expected.sort() - # We compare the sorted list of links here as that's more reliable - assert actual == expected - - -def test_existing_path_FileLinks_repr_alt_formatter(): - """FileLinks: Calling repr() functions as expected w/ alt formatter - """ - td = mkdtemp() - tf1 = NamedTemporaryFile(dir=td) - tf2 = NamedTemporaryFile(dir=td) - def fake_formatter(dirname,fnames,included_suffixes): - return ["hello","world"] - fl = display.FileLinks(td,terminal_display_formatter=fake_formatter) - actual = repr(fl) - actual = actual.split('\n') - actual.sort() - expected = ["hello","world"] - expected.sort() - # We compare the sorted list of links here as that's more reliable - assert actual == expected - - -def test_error_on_file_to_FileLinks(): - """FileLinks: Raises error when passed file - """ - td = mkdtemp() - tf1 = NamedTemporaryFile(dir=td) - pytest.raises(ValueError, display.FileLinks, tf1.name) - - -def test_recursive_FileLinks(): - """FileLinks: Does not recurse when recursive=False - """ - td = mkdtemp() - tf = NamedTemporaryFile(dir=td) - subtd = mkdtemp(dir=td) - subtf = NamedTemporaryFile(dir=subtd) - fl = display.FileLinks(td) - actual = str(fl) - actual = actual.split('\n') - assert len(actual) == 4, actual - fl = display.FileLinks(td, recursive=False) - actual = str(fl) - actual = actual.split('\n') - assert len(actual) == 2, actual - -def test_audio_from_file(): - path = pjoin(dirname(__file__), 'test.wav') - display.Audio(filename=path) - -class TestAudioDataWithNumpy(TestCase): - - @skipif_not_numpy - def test_audio_from_numpy_array(self): - test_tone = get_test_tone() - audio = display.Audio(test_tone, rate=44100) - assert len(read_wav(audio.data)) == len(test_tone) - - @skipif_not_numpy - def test_audio_from_list(self): - test_tone = get_test_tone() - audio = display.Audio(list(test_tone), rate=44100) - assert len(read_wav(audio.data)) == len(test_tone) - - @skipif_not_numpy - def test_audio_from_numpy_array_without_rate_raises(self): - self.assertRaises(ValueError, display.Audio, get_test_tone()) - - @skipif_not_numpy - def test_audio_data_normalization(self): - expected_max_value = numpy.iinfo(numpy.int16).max - for scale in [1, 0.5, 2]: - audio = display.Audio(get_test_tone(scale), rate=44100) - actual_max_value = numpy.max(numpy.abs(read_wav(audio.data))) - assert actual_max_value == expected_max_value - - @skipif_not_numpy - def test_audio_data_without_normalization(self): - max_int16 = numpy.iinfo(numpy.int16).max - for scale in [1, 0.5, 0.2]: - test_tone = get_test_tone(scale) - test_tone_max_abs = numpy.max(numpy.abs(test_tone)) - expected_max_value = int(max_int16 * test_tone_max_abs) - audio = display.Audio(test_tone, rate=44100, normalize=False) - actual_max_value = numpy.max(numpy.abs(read_wav(audio.data))) - assert actual_max_value == expected_max_value - - def test_audio_data_without_normalization_raises_for_invalid_data(self): - self.assertRaises( - ValueError, - lambda: display.Audio([1.001], rate=44100, normalize=False)) - self.assertRaises( - ValueError, - lambda: display.Audio([-1.001], rate=44100, normalize=False)) - -def simulate_numpy_not_installed(): - try: - import numpy - return mock.patch('numpy.array', mock.MagicMock(side_effect=ImportError)) - except ModuleNotFoundError: - return lambda x:x - -@simulate_numpy_not_installed() -class TestAudioDataWithoutNumpy(TestAudioDataWithNumpy): - # All tests from `TestAudioDataWithNumpy` are inherited. - - @skipif_not_numpy - def test_audio_raises_for_nested_list(self): - stereo_signal = [list(get_test_tone())] * 2 - self.assertRaises(TypeError, lambda: display.Audio(stereo_signal, rate=44100)) - - -@skipif_not_numpy -def get_test_tone(scale=1): - return numpy.sin(2 * numpy.pi * 440 * numpy.linspace(0, 1, 44100)) * scale - -def read_wav(data): - with wave.open(BytesIO(data)) as wave_file: - wave_data = wave_file.readframes(wave_file.getnframes()) - num_samples = wave_file.getnframes() * wave_file.getnchannels() - return struct.unpack('<%sh' % num_samples, wave_data) - -def test_code_from_file(): - c = display.Code(filename=__file__) - assert c._repr_html_().startswith(' - - -

%(title)s

- -''' - -DOC_HEADER_EXTERNALCSS = '''\ - - - - - %(title)s - - - - -

%(title)s

- -''' - -DOC_FOOTER = '''\ - - -''' - - -class HtmlFormatter(Formatter): - r""" - Format tokens as HTML 4 ```` tags. By default, the content is enclosed - in a ``
`` tag, itself wrapped in a ``
`` tag (but see the `nowrap` option). - The ``
``'s CSS class can be set by the `cssclass` option. - - If the `linenos` option is set to ``"table"``, the ``
`` is
-    additionally wrapped inside a ```` which has one row and two
-    cells: one containing the line numbers and one containing the code.
-    Example:
-
-    .. sourcecode:: html
-
-        
-
- - -
-
1
-            2
-
-
def foo(bar):
-              pass
-            
-
- - (whitespace added to improve clarity). - - A list of lines can be specified using the `hl_lines` option to make these - lines highlighted (as of Pygments 0.11). - - With the `full` option, a complete HTML 4 document is output, including - the style definitions inside a `` - {% else %} - {{ head | safe }} - {% endif %} -{% if not embed %} - - -{% endif %} -{{ body | safe }} -{% for diagram in diagrams %} -
-

{{ diagram.title }}

-
{{ diagram.text }}
-
- {{ diagram.svg }} -
-
-{% endfor %} -{% if not embed %} - - -{% endif %} -""" - -template = Template(jinja2_template_source) - -# Note: ideally this would be a dataclass, but we're supporting Python 3.5+ so we can't do this yet -NamedDiagram = NamedTuple( - "NamedDiagram", - [("name", str), ("diagram", typing.Optional[railroad.DiagramItem]), ("index", int)], -) -""" -A simple structure for associating a name with a railroad diagram -""" - -T = TypeVar("T") - - -class EachItem(railroad.Group): - """ - Custom railroad item to compose a: - - Group containing a - - OneOrMore containing a - - Choice of the elements in the Each - with the group label indicating that all must be matched - """ - - all_label = "[ALL]" - - def __init__(self, *items): - choice_item = railroad.Choice(len(items) - 1, *items) - one_or_more_item = railroad.OneOrMore(item=choice_item) - super().__init__(one_or_more_item, label=self.all_label) - - -class AnnotatedItem(railroad.Group): - """ - Simple subclass of Group that creates an annotation label - """ - - def __init__(self, label: str, item): - super().__init__(item=item, label="[{}]".format(label) if label else label) - - -class EditablePartial(Generic[T]): - """ - Acts like a functools.partial, but can be edited. In other words, it represents a type that hasn't yet been - constructed. - """ - - # We need this here because the railroad constructors actually transform the data, so can't be called until the - # entire tree is assembled - - def __init__(self, func: Callable[..., T], args: list, kwargs: dict): - self.func = func - self.args = args - self.kwargs = kwargs - - @classmethod - def from_call(cls, func: Callable[..., T], *args, **kwargs) -> "EditablePartial[T]": - """ - If you call this function in the same way that you would call the constructor, it will store the arguments - as you expect. For example EditablePartial.from_call(Fraction, 1, 3)() == Fraction(1, 3) - """ - return EditablePartial(func=func, args=list(args), kwargs=kwargs) - - @property - def name(self): - return self.kwargs["name"] - - def __call__(self) -> T: - """ - Evaluate the partial and return the result - """ - args = self.args.copy() - kwargs = self.kwargs.copy() - - # This is a helpful hack to allow you to specify varargs parameters (e.g. *args) as keyword args (e.g. - # args=['list', 'of', 'things']) - arg_spec = inspect.getfullargspec(self.func) - if arg_spec.varargs in self.kwargs: - args += kwargs.pop(arg_spec.varargs) - - return self.func(*args, **kwargs) - - -def railroad_to_html(diagrams: List[NamedDiagram], embed=False, **kwargs) -> str: - """ - Given a list of NamedDiagram, produce a single HTML string that visualises those diagrams - :params kwargs: kwargs to be passed in to the template - """ - data = [] - for diagram in diagrams: - if diagram.diagram is None: - continue - io = StringIO() - try: - css = kwargs.get('css') - diagram.diagram.writeStandalone(io.write, css=css) - except AttributeError: - diagram.diagram.writeSvg(io.write) - title = diagram.name - if diagram.index == 0: - title += " (root)" - data.append({"title": title, "text": "", "svg": io.getvalue()}) - - return template.render(diagrams=data, embed=embed, **kwargs) - - -def resolve_partial(partial: "EditablePartial[T]") -> T: - """ - Recursively resolves a collection of Partials into whatever type they are - """ - if isinstance(partial, EditablePartial): - partial.args = resolve_partial(partial.args) - partial.kwargs = resolve_partial(partial.kwargs) - return partial() - elif isinstance(partial, list): - return [resolve_partial(x) for x in partial] - elif isinstance(partial, dict): - return {key: resolve_partial(x) for key, x in partial.items()} - else: - return partial - - -def to_railroad( - element: pyparsing.ParserElement, - diagram_kwargs: typing.Optional[dict] = None, - vertical: int = 3, - show_results_names: bool = False, - show_groups: bool = False, -) -> List[NamedDiagram]: - """ - Convert a pyparsing element tree into a list of diagrams. This is the recommended entrypoint to diagram - creation if you want to access the Railroad tree before it is converted to HTML - :param element: base element of the parser being diagrammed - :param diagram_kwargs: kwargs to pass to the Diagram() constructor - :param vertical: (optional) - int - limit at which number of alternatives should be - shown vertically instead of horizontally - :param show_results_names - bool to indicate whether results name annotations should be - included in the diagram - :param show_groups - bool to indicate whether groups should be highlighted with an unlabeled - surrounding box - """ - # Convert the whole tree underneath the root - lookup = ConverterState(diagram_kwargs=diagram_kwargs or {}) - _to_diagram_element( - element, - lookup=lookup, - parent=None, - vertical=vertical, - show_results_names=show_results_names, - show_groups=show_groups, - ) - - root_id = id(element) - # Convert the root if it hasn't been already - if root_id in lookup: - if not element.customName: - lookup[root_id].name = "" - lookup[root_id].mark_for_extraction(root_id, lookup, force=True) - - # Now that we're finished, we can convert from intermediate structures into Railroad elements - diags = list(lookup.diagrams.values()) - if len(diags) > 1: - # collapse out duplicate diags with the same name - seen = set() - deduped_diags = [] - for d in diags: - # don't extract SkipTo elements, they are uninformative as subdiagrams - if d.name == "...": - continue - if d.name is not None and d.name not in seen: - seen.add(d.name) - deduped_diags.append(d) - resolved = [resolve_partial(partial) for partial in deduped_diags] - else: - # special case - if just one diagram, always display it, even if - # it has no name - resolved = [resolve_partial(partial) for partial in diags] - return sorted(resolved, key=lambda diag: diag.index) - - -def _should_vertical( - specification: int, exprs: Iterable[pyparsing.ParserElement] -) -> bool: - """ - Returns true if we should return a vertical list of elements - """ - if specification is None: - return False - else: - return len(_visible_exprs(exprs)) >= specification - - -class ElementState: - """ - State recorded for an individual pyparsing Element - """ - - # Note: this should be a dataclass, but we have to support Python 3.5 - def __init__( - self, - element: pyparsing.ParserElement, - converted: EditablePartial, - parent: EditablePartial, - number: int, - name: str = None, - parent_index: typing.Optional[int] = None, - ): - #: The pyparsing element that this represents - self.element: pyparsing.ParserElement = element - #: The name of the element - self.name: typing.Optional[str] = name - #: The output Railroad element in an unconverted state - self.converted: EditablePartial = converted - #: The parent Railroad element, which we store so that we can extract this if it's duplicated - self.parent: EditablePartial = parent - #: The order in which we found this element, used for sorting diagrams if this is extracted into a diagram - self.number: int = number - #: The index of this inside its parent - self.parent_index: typing.Optional[int] = parent_index - #: If true, we should extract this out into a subdiagram - self.extract: bool = False - #: If true, all of this element's children have been filled out - self.complete: bool = False - - def mark_for_extraction( - self, el_id: int, state: "ConverterState", name: str = None, force: bool = False - ): - """ - Called when this instance has been seen twice, and thus should eventually be extracted into a sub-diagram - :param el_id: id of the element - :param state: element/diagram state tracker - :param name: name to use for this element's text - :param force: If true, force extraction now, regardless of the state of this. Only useful for extracting the - root element when we know we're finished - """ - self.extract = True - - # Set the name - if not self.name: - if name: - # Allow forcing a custom name - self.name = name - elif self.element.customName: - self.name = self.element.customName - else: - self.name = "" - - # Just because this is marked for extraction doesn't mean we can do it yet. We may have to wait for children - # to be added - # Also, if this is just a string literal etc, don't bother extracting it - if force or (self.complete and _worth_extracting(self.element)): - state.extract_into_diagram(el_id) - - -class ConverterState: - """ - Stores some state that persists between recursions into the element tree - """ - - def __init__(self, diagram_kwargs: typing.Optional[dict] = None): - #: A dictionary mapping ParserElements to state relating to them - self._element_diagram_states: Dict[int, ElementState] = {} - #: A dictionary mapping ParserElement IDs to subdiagrams generated from them - self.diagrams: Dict[int, EditablePartial[NamedDiagram]] = {} - #: The index of the next unnamed element - self.unnamed_index: int = 1 - #: The index of the next element. This is used for sorting - self.index: int = 0 - #: Shared kwargs that are used to customize the construction of diagrams - self.diagram_kwargs: dict = diagram_kwargs or {} - self.extracted_diagram_names: Set[str] = set() - - def __setitem__(self, key: int, value: ElementState): - self._element_diagram_states[key] = value - - def __getitem__(self, key: int) -> ElementState: - return self._element_diagram_states[key] - - def __delitem__(self, key: int): - del self._element_diagram_states[key] - - def __contains__(self, key: int): - return key in self._element_diagram_states - - def generate_unnamed(self) -> int: - """ - Generate a number used in the name of an otherwise unnamed diagram - """ - self.unnamed_index += 1 - return self.unnamed_index - - def generate_index(self) -> int: - """ - Generate a number used to index a diagram - """ - self.index += 1 - return self.index - - def extract_into_diagram(self, el_id: int): - """ - Used when we encounter the same token twice in the same tree. When this - happens, we replace all instances of that token with a terminal, and - create a new subdiagram for the token - """ - position = self[el_id] - - # Replace the original definition of this element with a regular block - if position.parent: - ret = EditablePartial.from_call(railroad.NonTerminal, text=position.name) - if "item" in position.parent.kwargs: - position.parent.kwargs["item"] = ret - elif "items" in position.parent.kwargs: - position.parent.kwargs["items"][position.parent_index] = ret - - # If the element we're extracting is a group, skip to its content but keep the title - if position.converted.func == railroad.Group: - content = position.converted.kwargs["item"] - else: - content = position.converted - - self.diagrams[el_id] = EditablePartial.from_call( - NamedDiagram, - name=position.name, - diagram=EditablePartial.from_call( - railroad.Diagram, content, **self.diagram_kwargs - ), - index=position.number, - ) - - del self[el_id] - - -def _worth_extracting(element: pyparsing.ParserElement) -> bool: - """ - Returns true if this element is worth having its own sub-diagram. Simply, if any of its children - themselves have children, then its complex enough to extract - """ - children = element.recurse() - return any(child.recurse() for child in children) - - -def _apply_diagram_item_enhancements(fn): - """ - decorator to ensure enhancements to a diagram item (such as results name annotations) - get applied on return from _to_diagram_element (we do this since there are several - returns in _to_diagram_element) - """ - - def _inner( - element: pyparsing.ParserElement, - parent: typing.Optional[EditablePartial], - lookup: ConverterState = None, - vertical: int = None, - index: int = 0, - name_hint: str = None, - show_results_names: bool = False, - show_groups: bool = False, - ) -> typing.Optional[EditablePartial]: - ret = fn( - element, - parent, - lookup, - vertical, - index, - name_hint, - show_results_names, - show_groups, - ) - - # apply annotation for results name, if present - if show_results_names and ret is not None: - element_results_name = element.resultsName - if element_results_name: - # add "*" to indicate if this is a "list all results" name - element_results_name += "" if element.modalResults else "*" - ret = EditablePartial.from_call( - railroad.Group, item=ret, label=element_results_name - ) - - return ret - - return _inner - - -def _visible_exprs(exprs: Iterable[pyparsing.ParserElement]): - non_diagramming_exprs = ( - pyparsing.ParseElementEnhance, - pyparsing.PositionToken, - pyparsing.And._ErrorStop, - ) - return [ - e - for e in exprs - if not (e.customName or e.resultsName or isinstance(e, non_diagramming_exprs)) - ] - - -@_apply_diagram_item_enhancements -def _to_diagram_element( - element: pyparsing.ParserElement, - parent: typing.Optional[EditablePartial], - lookup: ConverterState = None, - vertical: int = None, - index: int = 0, - name_hint: str = None, - show_results_names: bool = False, - show_groups: bool = False, -) -> typing.Optional[EditablePartial]: - """ - Recursively converts a PyParsing Element to a railroad Element - :param lookup: The shared converter state that keeps track of useful things - :param index: The index of this element within the parent - :param parent: The parent of this element in the output tree - :param vertical: Controls at what point we make a list of elements vertical. If this is an integer (the default), - it sets the threshold of the number of items before we go vertical. If True, always go vertical, if False, never - do so - :param name_hint: If provided, this will override the generated name - :param show_results_names: bool flag indicating whether to add annotations for results names - :returns: The converted version of the input element, but as a Partial that hasn't yet been constructed - :param show_groups: bool flag indicating whether to show groups using bounding box - """ - exprs = element.recurse() - name = name_hint or element.customName or element.__class__.__name__ - - # Python's id() is used to provide a unique identifier for elements - el_id = id(element) - - element_results_name = element.resultsName - - # Here we basically bypass processing certain wrapper elements if they contribute nothing to the diagram - if not element.customName: - if isinstance( - element, - ( - # pyparsing.TokenConverter, - # pyparsing.Forward, - pyparsing.Located, - ), - ): - # However, if this element has a useful custom name, and its child does not, we can pass it on to the child - if exprs: - if not exprs[0].customName: - propagated_name = name - else: - propagated_name = None - - return _to_diagram_element( - element.expr, - parent=parent, - lookup=lookup, - vertical=vertical, - index=index, - name_hint=propagated_name, - show_results_names=show_results_names, - show_groups=show_groups, - ) - - # If the element isn't worth extracting, we always treat it as the first time we say it - if _worth_extracting(element): - if el_id in lookup: - # If we've seen this element exactly once before, we are only just now finding out that it's a duplicate, - # so we have to extract it into a new diagram. - looked_up = lookup[el_id] - looked_up.mark_for_extraction(el_id, lookup, name=name_hint) - ret = EditablePartial.from_call(railroad.NonTerminal, text=looked_up.name) - return ret - - elif el_id in lookup.diagrams: - # If we have seen the element at least twice before, and have already extracted it into a subdiagram, we - # just put in a marker element that refers to the sub-diagram - ret = EditablePartial.from_call( - railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] - ) - return ret - - # Recursively convert child elements - # Here we find the most relevant Railroad element for matching pyparsing Element - # We use ``items=[]`` here to hold the place for where the child elements will go once created - if isinstance(element, pyparsing.And): - # detect And's created with ``expr*N`` notation - for these use a OneOrMore with a repeat - # (all will have the same name, and resultsName) - if not exprs: - return None - if len(set((e.name, e.resultsName) for e in exprs)) == 1: - ret = EditablePartial.from_call( - railroad.OneOrMore, item="", repeat=str(len(exprs)) - ) - elif _should_vertical(vertical, exprs): - ret = EditablePartial.from_call(railroad.Stack, items=[]) - else: - ret = EditablePartial.from_call(railroad.Sequence, items=[]) - elif isinstance(element, (pyparsing.Or, pyparsing.MatchFirst)): - if not exprs: - return None - if _should_vertical(vertical, exprs): - ret = EditablePartial.from_call(railroad.Choice, 0, items=[]) - else: - ret = EditablePartial.from_call(railroad.HorizontalChoice, items=[]) - elif isinstance(element, pyparsing.Each): - if not exprs: - return None - ret = EditablePartial.from_call(EachItem, items=[]) - elif isinstance(element, pyparsing.NotAny): - ret = EditablePartial.from_call(AnnotatedItem, label="NOT", item="") - elif isinstance(element, pyparsing.FollowedBy): - ret = EditablePartial.from_call(AnnotatedItem, label="LOOKAHEAD", item="") - elif isinstance(element, pyparsing.PrecededBy): - ret = EditablePartial.from_call(AnnotatedItem, label="LOOKBEHIND", item="") - elif isinstance(element, pyparsing.Group): - if show_groups: - ret = EditablePartial.from_call(AnnotatedItem, label="", item="") - else: - ret = EditablePartial.from_call(railroad.Group, label="", item="") - elif isinstance(element, pyparsing.TokenConverter): - label = type(element).__name__.lower() - if label == "tokenconverter": - ret = EditablePartial.from_call(railroad.Sequence, items=[]) - else: - ret = EditablePartial.from_call(AnnotatedItem, label=label, item="") - elif isinstance(element, pyparsing.Opt): - ret = EditablePartial.from_call(railroad.Optional, item="") - elif isinstance(element, pyparsing.OneOrMore): - ret = EditablePartial.from_call(railroad.OneOrMore, item="") - elif isinstance(element, pyparsing.ZeroOrMore): - ret = EditablePartial.from_call(railroad.ZeroOrMore, item="") - elif isinstance(element, pyparsing.Group): - ret = EditablePartial.from_call( - railroad.Group, item=None, label=element_results_name - ) - elif isinstance(element, pyparsing.Empty) and not element.customName: - # Skip unnamed "Empty" elements - ret = None - elif isinstance(element, pyparsing.ParseElementEnhance): - ret = EditablePartial.from_call(railroad.Sequence, items=[]) - elif len(exprs) > 0 and not element_results_name: - ret = EditablePartial.from_call(railroad.Group, item="", label=name) - elif len(exprs) > 0: - ret = EditablePartial.from_call(railroad.Sequence, items=[]) - else: - terminal = EditablePartial.from_call(railroad.Terminal, element.defaultName) - ret = terminal - - if ret is None: - return - - # Indicate this element's position in the tree so we can extract it if necessary - lookup[el_id] = ElementState( - element=element, - converted=ret, - parent=parent, - parent_index=index, - number=lookup.generate_index(), - ) - if element.customName: - lookup[el_id].mark_for_extraction(el_id, lookup, element.customName) - - i = 0 - for expr in exprs: - # Add a placeholder index in case we have to extract the child before we even add it to the parent - if "items" in ret.kwargs: - ret.kwargs["items"].insert(i, None) - - item = _to_diagram_element( - expr, - parent=ret, - lookup=lookup, - vertical=vertical, - index=i, - show_results_names=show_results_names, - show_groups=show_groups, - ) - - # Some elements don't need to be shown in the diagram - if item is not None: - if "item" in ret.kwargs: - ret.kwargs["item"] = item - elif "items" in ret.kwargs: - # If we've already extracted the child, don't touch this index, since it's occupied by a nonterminal - ret.kwargs["items"][i] = item - i += 1 - elif "items" in ret.kwargs: - # If we're supposed to skip this element, remove it from the parent - del ret.kwargs["items"][i] - - # If all this items children are none, skip this item - if ret and ( - ("items" in ret.kwargs and len(ret.kwargs["items"]) == 0) - or ("item" in ret.kwargs and ret.kwargs["item"] is None) - ): - ret = EditablePartial.from_call(railroad.Terminal, name) - - # Mark this element as "complete", ie it has all of its children - if el_id in lookup: - lookup[el_id].complete = True - - if el_id in lookup and lookup[el_id].extract and lookup[el_id].complete: - lookup.extract_into_diagram(el_id) - if ret is not None: - ret = EditablePartial.from_call( - railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] - ) - - return ret diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 795bf96..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/exceptions.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/exceptions.py deleted file mode 100644 index 12219f1..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/exceptions.py +++ /dev/null @@ -1,299 +0,0 @@ -# exceptions.py - -import re -import sys -import typing - -from .util import ( - col, - line, - lineno, - _collapse_string_to_ranges, - replaced_by_pep8, -) -from .unicode import pyparsing_unicode as ppu - - -class ExceptionWordUnicode(ppu.Latin1, ppu.LatinA, ppu.LatinB, ppu.Greek, ppu.Cyrillic): - pass - - -_extract_alphanums = _collapse_string_to_ranges(ExceptionWordUnicode.alphanums) -_exception_word_extractor = re.compile("([" + _extract_alphanums + "]{1,16})|.") - - -class ParseBaseException(Exception): - """base exception class for all parsing runtime exceptions""" - - loc: int - msg: str - pstr: str - parser_element: typing.Any # "ParserElement" - args: typing.Tuple[str, int, typing.Optional[str]] - - __slots__ = ( - "loc", - "msg", - "pstr", - "parser_element", - "args", - ) - - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( - self, - pstr: str, - loc: int = 0, - msg: typing.Optional[str] = None, - elem=None, - ): - self.loc = loc - if msg is None: - self.msg = pstr - self.pstr = "" - else: - self.msg = msg - self.pstr = pstr - self.parser_element = elem - self.args = (pstr, loc, msg) - - @staticmethod - def explain_exception(exc, depth=16): - """ - Method to take an exception and translate the Python internal traceback into a list - of the pyparsing expressions that caused the exception to be raised. - - Parameters: - - - exc - exception raised during parsing (need not be a ParseException, in support - of Python exceptions that might be raised in a parse action) - - depth (default=16) - number of levels back in the stack trace to list expression - and function names; if None, the full stack trace names will be listed; if 0, only - the failing input line, marker, and exception string will be shown - - Returns a multi-line string listing the ParserElements and/or function names in the - exception's stack trace. - """ - import inspect - from .core import ParserElement - - if depth is None: - depth = sys.getrecursionlimit() - ret = [] - if isinstance(exc, ParseBaseException): - ret.append(exc.line) - ret.append(" " * (exc.column - 1) + "^") - ret.append(f"{type(exc).__name__}: {exc}") - - if depth > 0: - callers = inspect.getinnerframes(exc.__traceback__, context=depth) - seen = set() - for i, ff in enumerate(callers[-depth:]): - frm = ff[0] - - f_self = frm.f_locals.get("self", None) - if isinstance(f_self, ParserElement): - if not frm.f_code.co_name.startswith( - ("parseImpl", "_parseNoCache") - ): - continue - if id(f_self) in seen: - continue - seen.add(id(f_self)) - - self_type = type(f_self) - ret.append( - f"{self_type.__module__}.{self_type.__name__} - {f_self}" - ) - - elif f_self is not None: - self_type = type(f_self) - ret.append(f"{self_type.__module__}.{self_type.__name__}") - - else: - code = frm.f_code - if code.co_name in ("wrapper", ""): - continue - - ret.append(code.co_name) - - depth -= 1 - if not depth: - break - - return "\n".join(ret) - - @classmethod - def _from_exception(cls, pe): - """ - internal factory method to simplify creating one type of ParseException - from another - avoids having __init__ signature conflicts among subclasses - """ - return cls(pe.pstr, pe.loc, pe.msg, pe.parser_element) - - @property - def line(self) -> str: - """ - Return the line of text where the exception occurred. - """ - return line(self.loc, self.pstr) - - @property - def lineno(self) -> int: - """ - Return the 1-based line number of text where the exception occurred. - """ - return lineno(self.loc, self.pstr) - - @property - def col(self) -> int: - """ - Return the 1-based column on the line of text where the exception occurred. - """ - return col(self.loc, self.pstr) - - @property - def column(self) -> int: - """ - Return the 1-based column on the line of text where the exception occurred. - """ - return col(self.loc, self.pstr) - - # pre-PEP8 compatibility - @property - def parserElement(self): - return self.parser_element - - @parserElement.setter - def parserElement(self, elem): - self.parser_element = elem - - def __str__(self) -> str: - if self.pstr: - if self.loc >= len(self.pstr): - foundstr = ", found end of text" - else: - # pull out next word at error location - found_match = _exception_word_extractor.match(self.pstr, self.loc) - if found_match is not None: - found = found_match.group(0) - else: - found = self.pstr[self.loc : self.loc + 1] - foundstr = (", found %r" % found).replace(r"\\", "\\") - else: - foundstr = "" - return f"{self.msg}{foundstr} (at char {self.loc}), (line:{self.lineno}, col:{self.column})" - - def __repr__(self): - return str(self) - - def mark_input_line( - self, marker_string: typing.Optional[str] = None, *, markerString: str = ">!<" - ) -> str: - """ - Extracts the exception line from the input string, and marks - the location of the exception with a special symbol. - """ - markerString = marker_string if marker_string is not None else markerString - line_str = self.line - line_column = self.column - 1 - if markerString: - line_str = "".join( - (line_str[:line_column], markerString, line_str[line_column:]) - ) - return line_str.strip() - - def explain(self, depth=16) -> str: - """ - Method to translate the Python internal traceback into a list - of the pyparsing expressions that caused the exception to be raised. - - Parameters: - - - depth (default=16) - number of levels back in the stack trace to list expression - and function names; if None, the full stack trace names will be listed; if 0, only - the failing input line, marker, and exception string will be shown - - Returns a multi-line string listing the ParserElements and/or function names in the - exception's stack trace. - - Example:: - - expr = pp.Word(pp.nums) * 3 - try: - expr.parse_string("123 456 A789") - except pp.ParseException as pe: - print(pe.explain(depth=0)) - - prints:: - - 123 456 A789 - ^ - ParseException: Expected W:(0-9), found 'A' (at char 8), (line:1, col:9) - - Note: the diagnostic output will include string representations of the expressions - that failed to parse. These representations will be more helpful if you use `set_name` to - give identifiable names to your expressions. Otherwise they will use the default string - forms, which may be cryptic to read. - - Note: pyparsing's default truncation of exception tracebacks may also truncate the - stack of expressions that are displayed in the ``explain`` output. To get the full listing - of parser expressions, you may have to set ``ParserElement.verbose_stacktrace = True`` - """ - return self.explain_exception(self, depth) - - # fmt: off - @replaced_by_pep8(mark_input_line) - def markInputline(self): ... - # fmt: on - - -class ParseException(ParseBaseException): - """ - Exception thrown when a parse expression doesn't match the input string - - Example:: - - try: - Word(nums).set_name("integer").parse_string("ABC") - except ParseException as pe: - print(pe) - print("column: {}".format(pe.column)) - - prints:: - - Expected integer (at char 0), (line:1, col:1) - column: 1 - - """ - - -class ParseFatalException(ParseBaseException): - """ - User-throwable exception thrown when inconsistent parse content - is found; stops all parsing immediately - """ - - -class ParseSyntaxException(ParseFatalException): - """ - Just like :class:`ParseFatalException`, but thrown internally - when an :class:`ErrorStop` ('-' operator) indicates - that parsing is to stop immediately because an unbacktrackable - syntax error has been found. - """ - - -class RecursiveGrammarException(Exception): - """ - Exception thrown by :class:`ParserElement.validate` if the - grammar could be left-recursive; parser may need to enable - left recursion using :class:`ParserElement.enable_left_recursion` - """ - - def __init__(self, parseElementList): - self.parseElementTrace = parseElementList - - def __str__(self) -> str: - return f"RecursiveGrammarException: {self.parseElementTrace}" diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/helpers.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/helpers.py deleted file mode 100644 index 018f0d6..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/helpers.py +++ /dev/null @@ -1,1100 +0,0 @@ -# helpers.py -import html.entities -import re -import sys -import typing - -from . import __diag__ -from .core import * -from .util import ( - _bslash, - _flatten, - _escape_regex_range_chars, - replaced_by_pep8, -) - - -# -# global helpers -# -def counted_array( - expr: ParserElement, - int_expr: typing.Optional[ParserElement] = None, - *, - intExpr: typing.Optional[ParserElement] = None, -) -> ParserElement: - """Helper to define a counted list of expressions. - - This helper defines a pattern of the form:: - - integer expr expr expr... - - where the leading integer tells how many expr expressions follow. - The matched tokens returns the array of expr tokens as a list - the - leading count token is suppressed. - - If ``int_expr`` is specified, it should be a pyparsing expression - that produces an integer value. - - Example:: - - counted_array(Word(alphas)).parse_string('2 ab cd ef') # -> ['ab', 'cd'] - - # in this parser, the leading integer value is given in binary, - # '10' indicating that 2 values are in the array - binary_constant = Word('01').set_parse_action(lambda t: int(t[0], 2)) - counted_array(Word(alphas), int_expr=binary_constant).parse_string('10 ab cd ef') # -> ['ab', 'cd'] - - # if other fields must be parsed after the count but before the - # list items, give the fields results names and they will - # be preserved in the returned ParseResults: - count_with_metadata = integer + Word(alphas)("type") - typed_array = counted_array(Word(alphanums), int_expr=count_with_metadata)("items") - result = typed_array.parse_string("3 bool True True False") - print(result.dump()) - - # prints - # ['True', 'True', 'False'] - # - items: ['True', 'True', 'False'] - # - type: 'bool' - """ - intExpr = intExpr or int_expr - array_expr = Forward() - - def count_field_parse_action(s, l, t): - nonlocal array_expr - n = t[0] - array_expr <<= (expr * n) if n else Empty() - # clear list contents, but keep any named results - del t[:] - - if intExpr is None: - intExpr = Word(nums).set_parse_action(lambda t: int(t[0])) - else: - intExpr = intExpr.copy() - intExpr.set_name("arrayLen") - intExpr.add_parse_action(count_field_parse_action, call_during_try=True) - return (intExpr + array_expr).set_name("(len) " + str(expr) + "...") - - -def match_previous_literal(expr: ParserElement) -> ParserElement: - """Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks for - a 'repeat' of a previous expression. For example:: - - first = Word(nums) - second = match_previous_literal(first) - match_expr = first + ":" + second - - will match ``"1:1"``, but not ``"1:2"``. Because this - matches a previous literal, will also match the leading - ``"1:1"`` in ``"1:10"``. If this is not desired, use - :class:`match_previous_expr`. Do *not* use with packrat parsing - enabled. - """ - rep = Forward() - - def copy_token_to_repeater(s, l, t): - if t: - if len(t) == 1: - rep << t[0] - else: - # flatten t tokens - tflat = _flatten(t.as_list()) - rep << And(Literal(tt) for tt in tflat) - else: - rep << Empty() - - expr.add_parse_action(copy_token_to_repeater, callDuringTry=True) - rep.set_name("(prev) " + str(expr)) - return rep - - -def match_previous_expr(expr: ParserElement) -> ParserElement: - """Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks for - a 'repeat' of a previous expression. For example:: - - first = Word(nums) - second = match_previous_expr(first) - match_expr = first + ":" + second - - will match ``"1:1"``, but not ``"1:2"``. Because this - matches by expressions, will *not* match the leading ``"1:1"`` - in ``"1:10"``; the expressions are evaluated first, and then - compared, so ``"1"`` is compared with ``"10"``. Do *not* use - with packrat parsing enabled. - """ - rep = Forward() - e2 = expr.copy() - rep <<= e2 - - def copy_token_to_repeater(s, l, t): - matchTokens = _flatten(t.as_list()) - - def must_match_these_tokens(s, l, t): - theseTokens = _flatten(t.as_list()) - if theseTokens != matchTokens: - raise ParseException( - s, l, f"Expected {matchTokens}, found{theseTokens}" - ) - - rep.set_parse_action(must_match_these_tokens, callDuringTry=True) - - expr.add_parse_action(copy_token_to_repeater, callDuringTry=True) - rep.set_name("(prev) " + str(expr)) - return rep - - -def one_of( - strs: Union[typing.Iterable[str], str], - caseless: bool = False, - use_regex: bool = True, - as_keyword: bool = False, - *, - useRegex: bool = True, - asKeyword: bool = False, -) -> ParserElement: - """Helper to quickly define a set of alternative :class:`Literal` s, - and makes sure to do longest-first testing when there is a conflict, - regardless of the input order, but returns - a :class:`MatchFirst` for best performance. - - Parameters: - - - ``strs`` - a string of space-delimited literals, or a collection of - string literals - - ``caseless`` - treat all literals as caseless - (default= ``False``) - - ``use_regex`` - as an optimization, will - generate a :class:`Regex` object; otherwise, will generate - a :class:`MatchFirst` object (if ``caseless=True`` or ``as_keyword=True``, or if - creating a :class:`Regex` raises an exception) - (default= ``True``) - - ``as_keyword`` - enforce :class:`Keyword`-style matching on the - generated expressions - (default= ``False``) - - ``asKeyword`` and ``useRegex`` are retained for pre-PEP8 compatibility, - but will be removed in a future release - - Example:: - - comp_oper = one_of("< = > <= >= !=") - var = Word(alphas) - number = Word(nums) - term = var | number - comparison_expr = term + comp_oper + term - print(comparison_expr.search_string("B = 12 AA=23 B<=AA AA>12")) - - prints:: - - [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] - """ - asKeyword = asKeyword or as_keyword - useRegex = useRegex and use_regex - - if ( - isinstance(caseless, str_type) - and __diag__.warn_on_multiple_string_args_to_oneof - ): - warnings.warn( - "More than one string argument passed to one_of, pass" - " choices as a list or space-delimited string", - stacklevel=2, - ) - - if caseless: - isequal = lambda a, b: a.upper() == b.upper() - masks = lambda a, b: b.upper().startswith(a.upper()) - parseElementClass = CaselessKeyword if asKeyword else CaselessLiteral - else: - isequal = lambda a, b: a == b - masks = lambda a, b: b.startswith(a) - parseElementClass = Keyword if asKeyword else Literal - - symbols: List[str] = [] - if isinstance(strs, str_type): - strs = typing.cast(str, strs) - symbols = strs.split() - elif isinstance(strs, Iterable): - symbols = list(strs) - else: - raise TypeError("Invalid argument to one_of, expected string or iterable") - if not symbols: - return NoMatch() - - # reorder given symbols to take care to avoid masking longer choices with shorter ones - # (but only if the given symbols are not just single characters) - if any(len(sym) > 1 for sym in symbols): - i = 0 - while i < len(symbols) - 1: - cur = symbols[i] - for j, other in enumerate(symbols[i + 1 :]): - if isequal(other, cur): - del symbols[i + j + 1] - break - elif masks(cur, other): - del symbols[i + j + 1] - symbols.insert(i, other) - break - else: - i += 1 - - if useRegex: - re_flags: int = re.IGNORECASE if caseless else 0 - - try: - if all(len(sym) == 1 for sym in symbols): - # symbols are just single characters, create range regex pattern - patt = f"[{''.join(_escape_regex_range_chars(sym) for sym in symbols)}]" - else: - patt = "|".join(re.escape(sym) for sym in symbols) - - # wrap with \b word break markers if defining as keywords - if asKeyword: - patt = rf"\b(?:{patt})\b" - - ret = Regex(patt, flags=re_flags).set_name(" | ".join(symbols)) - - if caseless: - # add parse action to return symbols as specified, not in random - # casing as found in input string - symbol_map = {sym.lower(): sym for sym in symbols} - ret.add_parse_action(lambda s, l, t: symbol_map[t[0].lower()]) - - return ret - - except re.error: - warnings.warn( - "Exception creating Regex for one_of, building MatchFirst", stacklevel=2 - ) - - # last resort, just use MatchFirst - return MatchFirst(parseElementClass(sym) for sym in symbols).set_name( - " | ".join(symbols) - ) - - -def dict_of(key: ParserElement, value: ParserElement) -> ParserElement: - """Helper to easily and clearly define a dictionary by specifying - the respective patterns for the key and value. Takes care of - defining the :class:`Dict`, :class:`ZeroOrMore`, and - :class:`Group` tokens in the proper order. The key pattern - can include delimiting markers or punctuation, as long as they are - suppressed, thereby leaving the significant key text. The value - pattern can include named results, so that the :class:`Dict` results - can include named token fields. - - Example:: - - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)) - print(attr_expr[1, ...].parse_string(text).dump()) - - attr_label = label - attr_value = Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join) - - # similar to Dict, but simpler call format - result = dict_of(attr_label, attr_value).parse_string(text) - print(result.dump()) - print(result['shape']) - print(result.shape) # object attribute access works too - print(result.as_dict()) - - prints:: - - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: 'light blue' - - posn: 'upper left' - - shape: 'SQUARE' - - texture: 'burlap' - SQUARE - SQUARE - {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} - """ - return Dict(OneOrMore(Group(key + value))) - - -def original_text_for( - expr: ParserElement, as_string: bool = True, *, asString: bool = True -) -> ParserElement: - """Helper to return the original, untokenized text for a given - expression. Useful to restore the parsed fields of an HTML start - tag into the raw tag text itself, or to revert separate tokens with - intervening whitespace back to the original matching input text. By - default, returns a string containing the original parsed text. - - If the optional ``as_string`` argument is passed as - ``False``, then the return value is - a :class:`ParseResults` containing any results names that - were originally matched, and a single token containing the original - matched text from the input string. So if the expression passed to - :class:`original_text_for` contains expressions with defined - results names, you must set ``as_string`` to ``False`` if you - want to preserve those results name values. - - The ``asString`` pre-PEP8 argument is retained for compatibility, - but will be removed in a future release. - - Example:: - - src = "this is test bold text normal text " - for tag in ("b", "i"): - opener, closer = make_html_tags(tag) - patt = original_text_for(opener + ... + closer) - print(patt.search_string(src)[0]) - - prints:: - - [' bold text '] - ['text'] - """ - asString = asString and as_string - - locMarker = Empty().set_parse_action(lambda s, loc, t: loc) - endlocMarker = locMarker.copy() - endlocMarker.callPreparse = False - matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") - if asString: - extractText = lambda s, l, t: s[t._original_start : t._original_end] - else: - - def extractText(s, l, t): - t[:] = [s[t.pop("_original_start") : t.pop("_original_end")]] - - matchExpr.set_parse_action(extractText) - matchExpr.ignoreExprs = expr.ignoreExprs - matchExpr.suppress_warning(Diagnostics.warn_ungrouped_named_tokens_in_collection) - return matchExpr - - -def ungroup(expr: ParserElement) -> ParserElement: - """Helper to undo pyparsing's default grouping of And expressions, - even if all but one are non-empty. - """ - return TokenConverter(expr).add_parse_action(lambda t: t[0]) - - -def locatedExpr(expr: ParserElement) -> ParserElement: - """ - (DEPRECATED - future code should use the :class:`Located` class) - Helper to decorate a returned token with its starting and ending - locations in the input string. - - This helper adds the following results names: - - - ``locn_start`` - location where matched expression begins - - ``locn_end`` - location where matched expression ends - - ``value`` - the actual parsed results - - Be careful if the input text contains ```` characters, you - may want to call :class:`ParserElement.parse_with_tabs` - - Example:: - - wd = Word(alphas) - for match in locatedExpr(wd).search_string("ljsdf123lksdjjf123lkkjj1222"): - print(match) - - prints:: - - [[0, 'ljsdf', 5]] - [[8, 'lksdjjf', 15]] - [[18, 'lkkjj', 23]] - """ - locator = Empty().set_parse_action(lambda ss, ll, tt: ll) - return Group( - locator("locn_start") - + expr("value") - + locator.copy().leaveWhitespace()("locn_end") - ) - - -def nested_expr( - opener: Union[str, ParserElement] = "(", - closer: Union[str, ParserElement] = ")", - content: typing.Optional[ParserElement] = None, - ignore_expr: ParserElement = quoted_string(), - *, - ignoreExpr: ParserElement = quoted_string(), -) -> ParserElement: - """Helper method for defining nested lists enclosed in opening and - closing delimiters (``"("`` and ``")"`` are the default). - - Parameters: - - - ``opener`` - opening character for a nested list - (default= ``"("``); can also be a pyparsing expression - - ``closer`` - closing character for a nested list - (default= ``")"``); can also be a pyparsing expression - - ``content`` - expression for items within the nested lists - (default= ``None``) - - ``ignore_expr`` - expression for ignoring opening and closing delimiters - (default= :class:`quoted_string`) - - ``ignoreExpr`` - this pre-PEP8 argument is retained for compatibility - but will be removed in a future release - - If an expression is not provided for the content argument, the - nested expression will capture all whitespace-delimited content - between delimiters as a list of separate values. - - Use the ``ignore_expr`` argument to define expressions that may - contain opening or closing characters that should not be treated as - opening or closing characters for nesting, such as quoted_string or - a comment expression. Specify multiple expressions using an - :class:`Or` or :class:`MatchFirst`. The default is - :class:`quoted_string`, but if no expressions are to be ignored, then - pass ``None`` for this argument. - - Example:: - - data_type = one_of("void int short long char float double") - decl_data_type = Combine(data_type + Opt(Word('*'))) - ident = Word(alphas+'_', alphanums+'_') - number = pyparsing_common.number - arg = Group(decl_data_type + ident) - LPAR, RPAR = map(Suppress, "()") - - code_body = nested_expr('{', '}', ignore_expr=(quoted_string | c_style_comment)) - - c_function = (decl_data_type("type") - + ident("name") - + LPAR + Opt(DelimitedList(arg), [])("args") + RPAR - + code_body("body")) - c_function.ignore(c_style_comment) - - source_code = ''' - int is_odd(int x) { - return (x%2); - } - - int dec_to_hex(char hchar) { - if (hchar >= '0' && hchar <= '9') { - return (ord(hchar)-ord('0')); - } else { - return (10+ord(hchar)-ord('A')); - } - } - ''' - for func in c_function.search_string(source_code): - print("%(name)s (%(type)s) args: %(args)s" % func) - - - prints:: - - is_odd (int) args: [['int', 'x']] - dec_to_hex (int) args: [['char', 'hchar']] - """ - if ignoreExpr != ignore_expr: - ignoreExpr = ignore_expr if ignoreExpr == quoted_string() else ignoreExpr - if opener == closer: - raise ValueError("opening and closing strings cannot be the same") - if content is None: - if isinstance(opener, str_type) and isinstance(closer, str_type): - opener = typing.cast(str, opener) - closer = typing.cast(str, closer) - if len(opener) == 1 and len(closer) == 1: - if ignoreExpr is not None: - content = Combine( - OneOrMore( - ~ignoreExpr - + CharsNotIn( - opener + closer + ParserElement.DEFAULT_WHITE_CHARS, - exact=1, - ) - ) - ).set_parse_action(lambda t: t[0].strip()) - else: - content = empty.copy() + CharsNotIn( - opener + closer + ParserElement.DEFAULT_WHITE_CHARS - ).set_parse_action(lambda t: t[0].strip()) - else: - if ignoreExpr is not None: - content = Combine( - OneOrMore( - ~ignoreExpr - + ~Literal(opener) - + ~Literal(closer) - + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS, exact=1) - ) - ).set_parse_action(lambda t: t[0].strip()) - else: - content = Combine( - OneOrMore( - ~Literal(opener) - + ~Literal(closer) - + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS, exact=1) - ) - ).set_parse_action(lambda t: t[0].strip()) - else: - raise ValueError( - "opening and closing arguments must be strings if no content expression is given" - ) - ret = Forward() - if ignoreExpr is not None: - ret <<= Group( - Suppress(opener) + ZeroOrMore(ignoreExpr | ret | content) + Suppress(closer) - ) - else: - ret <<= Group(Suppress(opener) + ZeroOrMore(ret | content) + Suppress(closer)) - ret.set_name("nested %s%s expression" % (opener, closer)) - return ret - - -def _makeTags(tagStr, xml, suppress_LT=Suppress("<"), suppress_GT=Suppress(">")): - """Internal helper to construct opening and closing tag expressions, given a tag name""" - if isinstance(tagStr, str_type): - resname = tagStr - tagStr = Keyword(tagStr, caseless=not xml) - else: - resname = tagStr.name - - tagAttrName = Word(alphas, alphanums + "_-:") - if xml: - tagAttrValue = dbl_quoted_string.copy().set_parse_action(remove_quotes) - openTag = ( - suppress_LT - + tagStr("tag") - + Dict(ZeroOrMore(Group(tagAttrName + Suppress("=") + tagAttrValue))) - + Opt("/", default=[False])("empty").set_parse_action( - lambda s, l, t: t[0] == "/" - ) - + suppress_GT - ) - else: - tagAttrValue = quoted_string.copy().set_parse_action(remove_quotes) | Word( - printables, exclude_chars=">" - ) - openTag = ( - suppress_LT - + tagStr("tag") - + Dict( - ZeroOrMore( - Group( - tagAttrName.set_parse_action(lambda t: t[0].lower()) - + Opt(Suppress("=") + tagAttrValue) - ) - ) - ) - + Opt("/", default=[False])("empty").set_parse_action( - lambda s, l, t: t[0] == "/" - ) - + suppress_GT - ) - closeTag = Combine(Literal("", adjacent=False) - - openTag.set_name("<%s>" % resname) - # add start results name in parse action now that ungrouped names are not reported at two levels - openTag.add_parse_action( - lambda t: t.__setitem__( - "start" + "".join(resname.replace(":", " ").title().split()), t.copy() - ) - ) - closeTag = closeTag( - "end" + "".join(resname.replace(":", " ").title().split()) - ).set_name("" % resname) - openTag.tag = resname - closeTag.tag = resname - openTag.tag_body = SkipTo(closeTag()) - return openTag, closeTag - - -def make_html_tags( - tag_str: Union[str, ParserElement] -) -> Tuple[ParserElement, ParserElement]: - """Helper to construct opening and closing tag expressions for HTML, - given a tag name. Matches tags in either upper or lower case, - attributes with namespaces and with quoted or unquoted values. - - Example:: - - text = 'More info at the pyparsing wiki page' - # make_html_tags returns pyparsing expressions for the opening and - # closing tags as a 2-tuple - a, a_end = make_html_tags("A") - link_expr = a + SkipTo(a_end)("link_text") + a_end - - for link in link_expr.search_string(text): - # attributes in the tag (like "href" shown here) are - # also accessible as named results - print(link.link_text, '->', link.href) - - prints:: - - pyparsing -> https://github.com/pyparsing/pyparsing/wiki - """ - return _makeTags(tag_str, False) - - -def make_xml_tags( - tag_str: Union[str, ParserElement] -) -> Tuple[ParserElement, ParserElement]: - """Helper to construct opening and closing tag expressions for XML, - given a tag name. Matches tags only in the given upper/lower case. - - Example: similar to :class:`make_html_tags` - """ - return _makeTags(tag_str, True) - - -any_open_tag: ParserElement -any_close_tag: ParserElement -any_open_tag, any_close_tag = make_html_tags( - Word(alphas, alphanums + "_:").set_name("any tag") -) - -_htmlEntityMap = {k.rstrip(";"): v for k, v in html.entities.html5.items()} -common_html_entity = Regex("&(?P" + "|".join(_htmlEntityMap) + ");").set_name( - "common HTML entity" -) - - -def replace_html_entity(s, l, t): - """Helper parser action to replace common HTML entities with their special characters""" - return _htmlEntityMap.get(t.entity) - - -class OpAssoc(Enum): - """Enumeration of operator associativity - - used in constructing InfixNotationOperatorSpec for :class:`infix_notation`""" - - LEFT = 1 - RIGHT = 2 - - -InfixNotationOperatorArgType = Union[ - ParserElement, str, Tuple[Union[ParserElement, str], Union[ParserElement, str]] -] -InfixNotationOperatorSpec = Union[ - Tuple[ - InfixNotationOperatorArgType, - int, - OpAssoc, - typing.Optional[ParseAction], - ], - Tuple[ - InfixNotationOperatorArgType, - int, - OpAssoc, - ], -] - - -def infix_notation( - base_expr: ParserElement, - op_list: List[InfixNotationOperatorSpec], - lpar: Union[str, ParserElement] = Suppress("("), - rpar: Union[str, ParserElement] = Suppress(")"), -) -> ParserElement: - """Helper method for constructing grammars of expressions made up of - operators working in a precedence hierarchy. Operators may be unary - or binary, left- or right-associative. Parse actions can also be - attached to operator expressions. The generated parser will also - recognize the use of parentheses to override operator precedences - (see example below). - - Note: if you define a deep operator list, you may see performance - issues when using infix_notation. See - :class:`ParserElement.enable_packrat` for a mechanism to potentially - improve your parser performance. - - Parameters: - - - ``base_expr`` - expression representing the most basic operand to - be used in the expression - - ``op_list`` - list of tuples, one for each operator precedence level - in the expression grammar; each tuple is of the form ``(op_expr, - num_operands, right_left_assoc, (optional)parse_action)``, where: - - - ``op_expr`` is the pyparsing expression for the operator; may also - be a string, which will be converted to a Literal; if ``num_operands`` - is 3, ``op_expr`` is a tuple of two expressions, for the two - operators separating the 3 terms - - ``num_operands`` is the number of terms for this operator (must be 1, - 2, or 3) - - ``right_left_assoc`` is the indicator whether the operator is right - or left associative, using the pyparsing-defined constants - ``OpAssoc.RIGHT`` and ``OpAssoc.LEFT``. - - ``parse_action`` is the parse action to be associated with - expressions matching this operator expression (the parse action - tuple member may be omitted); if the parse action is passed - a tuple or list of functions, this is equivalent to calling - ``set_parse_action(*fn)`` - (:class:`ParserElement.set_parse_action`) - - ``lpar`` - expression for matching left-parentheses; if passed as a - str, then will be parsed as ``Suppress(lpar)``. If lpar is passed as - an expression (such as ``Literal('(')``), then it will be kept in - the parsed results, and grouped with them. (default= ``Suppress('(')``) - - ``rpar`` - expression for matching right-parentheses; if passed as a - str, then will be parsed as ``Suppress(rpar)``. If rpar is passed as - an expression (such as ``Literal(')')``), then it will be kept in - the parsed results, and grouped with them. (default= ``Suppress(')')``) - - Example:: - - # simple example of four-function arithmetic with ints and - # variable names - integer = pyparsing_common.signed_integer - varname = pyparsing_common.identifier - - arith_expr = infix_notation(integer | varname, - [ - ('-', 1, OpAssoc.RIGHT), - (one_of('* /'), 2, OpAssoc.LEFT), - (one_of('+ -'), 2, OpAssoc.LEFT), - ]) - - arith_expr.run_tests(''' - 5+3*6 - (5+3)*6 - -2--11 - ''', full_dump=False) - - prints:: - - 5+3*6 - [[5, '+', [3, '*', 6]]] - - (5+3)*6 - [[[5, '+', 3], '*', 6]] - - (5+x)*y - [[[5, '+', 'x'], '*', 'y']] - - -2--11 - [[['-', 2], '-', ['-', 11]]] - """ - - # captive version of FollowedBy that does not do parse actions or capture results names - class _FB(FollowedBy): - def parseImpl(self, instring, loc, doActions=True): - self.expr.try_parse(instring, loc) - return loc, [] - - _FB.__name__ = "FollowedBy>" - - ret = Forward() - if isinstance(lpar, str): - lpar = Suppress(lpar) - if isinstance(rpar, str): - rpar = Suppress(rpar) - - # if lpar and rpar are not suppressed, wrap in group - if not (isinstance(rpar, Suppress) and isinstance(rpar, Suppress)): - lastExpr = base_expr | Group(lpar + ret + rpar) - else: - lastExpr = base_expr | (lpar + ret + rpar) - - arity: int - rightLeftAssoc: opAssoc - pa: typing.Optional[ParseAction] - opExpr1: ParserElement - opExpr2: ParserElement - for i, operDef in enumerate(op_list): - opExpr, arity, rightLeftAssoc, pa = (operDef + (None,))[:4] # type: ignore[assignment] - if isinstance(opExpr, str_type): - opExpr = ParserElement._literalStringClass(opExpr) - opExpr = typing.cast(ParserElement, opExpr) - if arity == 3: - if not isinstance(opExpr, (tuple, list)) or len(opExpr) != 2: - raise ValueError( - "if numterms=3, opExpr must be a tuple or list of two expressions" - ) - opExpr1, opExpr2 = opExpr - term_name = f"{opExpr1}{opExpr2} term" - else: - term_name = f"{opExpr} term" - - if not 1 <= arity <= 3: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - - if rightLeftAssoc not in (OpAssoc.LEFT, OpAssoc.RIGHT): - raise ValueError("operator must indicate right or left associativity") - - thisExpr: ParserElement = Forward().set_name(term_name) - thisExpr = typing.cast(Forward, thisExpr) - if rightLeftAssoc is OpAssoc.LEFT: - if arity == 1: - matchExpr = _FB(lastExpr + opExpr) + Group(lastExpr + opExpr[1, ...]) - elif arity == 2: - if opExpr is not None: - matchExpr = _FB(lastExpr + opExpr + lastExpr) + Group( - lastExpr + (opExpr + lastExpr)[1, ...] - ) - else: - matchExpr = _FB(lastExpr + lastExpr) + Group(lastExpr[2, ...]) - elif arity == 3: - matchExpr = _FB( - lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr - ) + Group(lastExpr + OneOrMore(opExpr1 + lastExpr + opExpr2 + lastExpr)) - elif rightLeftAssoc is OpAssoc.RIGHT: - if arity == 1: - # try to avoid LR with this extra test - if not isinstance(opExpr, Opt): - opExpr = Opt(opExpr) - matchExpr = _FB(opExpr.expr + thisExpr) + Group(opExpr + thisExpr) - elif arity == 2: - if opExpr is not None: - matchExpr = _FB(lastExpr + opExpr + thisExpr) + Group( - lastExpr + (opExpr + thisExpr)[1, ...] - ) - else: - matchExpr = _FB(lastExpr + thisExpr) + Group( - lastExpr + thisExpr[1, ...] - ) - elif arity == 3: - matchExpr = _FB( - lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr - ) + Group(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) - if pa: - if isinstance(pa, (tuple, list)): - matchExpr.set_parse_action(*pa) - else: - matchExpr.set_parse_action(pa) - thisExpr <<= (matchExpr | lastExpr).setName(term_name) - lastExpr = thisExpr - ret <<= lastExpr - return ret - - -def indentedBlock(blockStatementExpr, indentStack, indent=True, backup_stacks=[]): - """ - (DEPRECATED - use :class:`IndentedBlock` class instead) - Helper method for defining space-delimited indentation blocks, - such as those used to define block statements in Python source code. - - Parameters: - - - ``blockStatementExpr`` - expression defining syntax of statement that - is repeated within the indented block - - ``indentStack`` - list created by caller to manage indentation stack - (multiple ``statementWithIndentedBlock`` expressions within a single - grammar should share a common ``indentStack``) - - ``indent`` - boolean indicating whether block must be indented beyond - the current level; set to ``False`` for block of left-most statements - (default= ``True``) - - A valid block must contain at least one ``blockStatement``. - - (Note that indentedBlock uses internal parse actions which make it - incompatible with packrat parsing.) - - Example:: - - data = ''' - def A(z): - A1 - B = 100 - G = A2 - A2 - A3 - B - def BB(a,b,c): - BB1 - def BBA(): - bba1 - bba2 - bba3 - C - D - def spam(x,y): - def eggs(z): - pass - ''' - - - indentStack = [1] - stmt = Forward() - - identifier = Word(alphas, alphanums) - funcDecl = ("def" + identifier + Group("(" + Opt(delimitedList(identifier)) + ")") + ":") - func_body = indentedBlock(stmt, indentStack) - funcDef = Group(funcDecl + func_body) - - rvalue = Forward() - funcCall = Group(identifier + "(" + Opt(delimitedList(rvalue)) + ")") - rvalue << (funcCall | identifier | Word(nums)) - assignment = Group(identifier + "=" + rvalue) - stmt << (funcDef | assignment | identifier) - - module_body = stmt[1, ...] - - parseTree = module_body.parseString(data) - parseTree.pprint() - - prints:: - - [['def', - 'A', - ['(', 'z', ')'], - ':', - [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], - 'B', - ['def', - 'BB', - ['(', 'a', 'b', 'c', ')'], - ':', - [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], - 'C', - 'D', - ['def', - 'spam', - ['(', 'x', 'y', ')'], - ':', - [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] - """ - backup_stacks.append(indentStack[:]) - - def reset_stack(): - indentStack[:] = backup_stacks[-1] - - def checkPeerIndent(s, l, t): - if l >= len(s): - return - curCol = col(l, s) - if curCol != indentStack[-1]: - if curCol > indentStack[-1]: - raise ParseException(s, l, "illegal nesting") - raise ParseException(s, l, "not a peer entry") - - def checkSubIndent(s, l, t): - curCol = col(l, s) - if curCol > indentStack[-1]: - indentStack.append(curCol) - else: - raise ParseException(s, l, "not a subentry") - - def checkUnindent(s, l, t): - if l >= len(s): - return - curCol = col(l, s) - if not (indentStack and curCol in indentStack): - raise ParseException(s, l, "not an unindent") - if curCol < indentStack[-1]: - indentStack.pop() - - NL = OneOrMore(LineEnd().set_whitespace_chars("\t ").suppress()) - INDENT = (Empty() + Empty().set_parse_action(checkSubIndent)).set_name("INDENT") - PEER = Empty().set_parse_action(checkPeerIndent).set_name("") - UNDENT = Empty().set_parse_action(checkUnindent).set_name("UNINDENT") - if indent: - smExpr = Group( - Opt(NL) - + INDENT - + OneOrMore(PEER + Group(blockStatementExpr) + Opt(NL)) - + UNDENT - ) - else: - smExpr = Group( - Opt(NL) - + OneOrMore(PEER + Group(blockStatementExpr) + Opt(NL)) - + Opt(UNDENT) - ) - - # add a parse action to remove backup_stack from list of backups - smExpr.add_parse_action( - lambda: backup_stacks.pop(-1) and None if backup_stacks else None - ) - smExpr.set_fail_action(lambda a, b, c, d: reset_stack()) - blockStatementExpr.ignore(_bslash + LineEnd()) - return smExpr.set_name("indented block") - - -# it's easy to get these comment structures wrong - they're very common, so may as well make them available -c_style_comment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + "*/").set_name( - "C style comment" -) -"Comment of the form ``/* ... */``" - -html_comment = Regex(r"").set_name("HTML comment") -"Comment of the form ````" - -rest_of_line = Regex(r".*").leave_whitespace().set_name("rest of line") -dbl_slash_comment = Regex(r"//(?:\\\n|[^\n])*").set_name("// comment") -"Comment of the form ``// ... (to end of line)``" - -cpp_style_comment = Combine( - Regex(r"/\*(?:[^*]|\*(?!/))*") + "*/" | dbl_slash_comment -).set_name("C++ style comment") -"Comment of either form :class:`c_style_comment` or :class:`dbl_slash_comment`" - -java_style_comment = cpp_style_comment -"Same as :class:`cpp_style_comment`" - -python_style_comment = Regex(r"#.*").set_name("Python style comment") -"Comment of the form ``# ... (to end of line)``" - - -# build list of built-in expressions, for future reference if a global default value -# gets updated -_builtin_exprs: List[ParserElement] = [ - v for v in vars().values() if isinstance(v, ParserElement) -] - - -# compatibility function, superseded by DelimitedList class -def delimited_list( - expr: Union[str, ParserElement], - delim: Union[str, ParserElement] = ",", - combine: bool = False, - min: typing.Optional[int] = None, - max: typing.Optional[int] = None, - *, - allow_trailing_delim: bool = False, -) -> ParserElement: - """(DEPRECATED - use :class:`DelimitedList` class)""" - return DelimitedList( - expr, delim, combine, min, max, allow_trailing_delim=allow_trailing_delim - ) - - -# pre-PEP8 compatible names -# fmt: off -opAssoc = OpAssoc -anyOpenTag = any_open_tag -anyCloseTag = any_close_tag -commonHTMLEntity = common_html_entity -cStyleComment = c_style_comment -htmlComment = html_comment -restOfLine = rest_of_line -dblSlashComment = dbl_slash_comment -cppStyleComment = cpp_style_comment -javaStyleComment = java_style_comment -pythonStyleComment = python_style_comment - -@replaced_by_pep8(DelimitedList) -def delimitedList(): ... - -@replaced_by_pep8(DelimitedList) -def delimited_list(): ... - -@replaced_by_pep8(counted_array) -def countedArray(): ... - -@replaced_by_pep8(match_previous_literal) -def matchPreviousLiteral(): ... - -@replaced_by_pep8(match_previous_expr) -def matchPreviousExpr(): ... - -@replaced_by_pep8(one_of) -def oneOf(): ... - -@replaced_by_pep8(dict_of) -def dictOf(): ... - -@replaced_by_pep8(original_text_for) -def originalTextFor(): ... - -@replaced_by_pep8(nested_expr) -def nestedExpr(): ... - -@replaced_by_pep8(make_html_tags) -def makeHTMLTags(): ... - -@replaced_by_pep8(make_xml_tags) -def makeXMLTags(): ... - -@replaced_by_pep8(replace_html_entity) -def replaceHTMLEntity(): ... - -@replaced_by_pep8(infix_notation) -def infixNotation(): ... -# fmt: on diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/results.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/results.py deleted file mode 100644 index 0313049..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/results.py +++ /dev/null @@ -1,796 +0,0 @@ -# results.py -from collections.abc import ( - MutableMapping, - Mapping, - MutableSequence, - Iterator, - Sequence, - Container, -) -import pprint -from typing import Tuple, Any, Dict, Set, List - -str_type: Tuple[type, ...] = (str, bytes) -_generator_type = type((_ for _ in ())) - - -class _ParseResultsWithOffset: - tup: Tuple["ParseResults", int] - __slots__ = ["tup"] - - def __init__(self, p1: "ParseResults", p2: int): - self.tup: Tuple[ParseResults, int] = (p1, p2) - - def __getitem__(self, i): - return self.tup[i] - - def __getstate__(self): - return self.tup - - def __setstate__(self, *args): - self.tup = args[0] - - -class ParseResults: - """Structured parse results, to provide multiple means of access to - the parsed data: - - - as a list (``len(results)``) - - by list index (``results[0], results[1]``, etc.) - - by attribute (``results.`` - see :class:`ParserElement.set_results_name`) - - Example:: - - integer = Word(nums) - date_str = (integer.set_results_name("year") + '/' - + integer.set_results_name("month") + '/' - + integer.set_results_name("day")) - # equivalent form: - # date_str = (integer("year") + '/' - # + integer("month") + '/' - # + integer("day")) - - # parse_string returns a ParseResults object - result = date_str.parse_string("1999/12/31") - - def test(s, fn=repr): - print(f"{s} -> {fn(eval(s))}") - test("list(result)") - test("result[0]") - test("result['month']") - test("result.day") - test("'month' in result") - test("'minutes' in result") - test("result.dump()", str) - - prints:: - - list(result) -> ['1999', '/', '12', '/', '31'] - result[0] -> '1999' - result['month'] -> '12' - result.day -> '31' - 'month' in result -> True - 'minutes' in result -> False - result.dump() -> ['1999', '/', '12', '/', '31'] - - day: '31' - - month: '12' - - year: '1999' - """ - - _null_values: Tuple[Any, ...] = (None, [], ()) - - _name: str - _parent: "ParseResults" - _all_names: Set[str] - _modal: bool - _toklist: List[Any] - _tokdict: Dict[str, Any] - - __slots__ = ( - "_name", - "_parent", - "_all_names", - "_modal", - "_toklist", - "_tokdict", - ) - - class List(list): - """ - Simple wrapper class to distinguish parsed list results that should be preserved - as actual Python lists, instead of being converted to :class:`ParseResults`:: - - LBRACK, RBRACK = map(pp.Suppress, "[]") - element = pp.Forward() - item = ppc.integer - element_list = LBRACK + pp.DelimitedList(element) + RBRACK - - # add parse actions to convert from ParseResults to actual Python collection types - def as_python_list(t): - return pp.ParseResults.List(t.as_list()) - element_list.add_parse_action(as_python_list) - - element <<= item | element_list - - element.run_tests(''' - 100 - [2,3,4] - [[2, 1],3,4] - [(2, 1),3,4] - (2,3,4) - ''', post_parse=lambda s, r: (r[0], type(r[0]))) - - prints:: - - 100 - (100, ) - - [2,3,4] - ([2, 3, 4], ) - - [[2, 1],3,4] - ([[2, 1], 3, 4], ) - - (Used internally by :class:`Group` when `aslist=True`.) - """ - - def __new__(cls, contained=None): - if contained is None: - contained = [] - - if not isinstance(contained, list): - raise TypeError( - f"{cls.__name__} may only be constructed with a list, not {type(contained).__name__}" - ) - - return list.__new__(cls) - - def __new__(cls, toklist=None, name=None, **kwargs): - if isinstance(toklist, ParseResults): - return toklist - self = object.__new__(cls) - self._name = None - self._parent = None - self._all_names = set() - - if toklist is None: - self._toklist = [] - elif isinstance(toklist, (list, _generator_type)): - self._toklist = ( - [toklist[:]] - if isinstance(toklist, ParseResults.List) - else list(toklist) - ) - else: - self._toklist = [toklist] - self._tokdict = dict() - return self - - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( - self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance - ): - self._tokdict: Dict[str, _ParseResultsWithOffset] - self._modal = modal - if name is not None and name != "": - if isinstance(name, int): - name = str(name) - if not modal: - self._all_names = {name} - self._name = name - if toklist not in self._null_values: - if isinstance(toklist, (str_type, type)): - toklist = [toklist] - if asList: - if isinstance(toklist, ParseResults): - self[name] = _ParseResultsWithOffset( - ParseResults(toklist._toklist), 0 - ) - else: - self[name] = _ParseResultsWithOffset( - ParseResults(toklist[0]), 0 - ) - self[name]._name = name - else: - try: - self[name] = toklist[0] - except (KeyError, TypeError, IndexError): - if toklist is not self: - self[name] = toklist - else: - self._name = name - - def __getitem__(self, i): - if isinstance(i, (int, slice)): - return self._toklist[i] - else: - if i not in self._all_names: - return self._tokdict[i][-1][0] - else: - return ParseResults([v[0] for v in self._tokdict[i]]) - - def __setitem__(self, k, v, isinstance=isinstance): - if isinstance(v, _ParseResultsWithOffset): - self._tokdict[k] = self._tokdict.get(k, list()) + [v] - sub = v[0] - elif isinstance(k, (int, slice)): - self._toklist[k] = v - sub = v - else: - self._tokdict[k] = self._tokdict.get(k, list()) + [ - _ParseResultsWithOffset(v, 0) - ] - sub = v - if isinstance(sub, ParseResults): - sub._parent = self - - def __delitem__(self, i): - if isinstance(i, (int, slice)): - mylen = len(self._toklist) - del self._toklist[i] - - # convert int to slice - if isinstance(i, int): - if i < 0: - i += mylen - i = slice(i, i + 1) - # get removed indices - removed = list(range(*i.indices(mylen))) - removed.reverse() - # fixup indices in token dictionary - for name, occurrences in self._tokdict.items(): - for j in removed: - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset( - value, position - (position > j) - ) - else: - del self._tokdict[i] - - def __contains__(self, k) -> bool: - return k in self._tokdict - - def __len__(self) -> int: - return len(self._toklist) - - def __bool__(self) -> bool: - return not not (self._toklist or self._tokdict) - - def __iter__(self) -> Iterator: - return iter(self._toklist) - - def __reversed__(self) -> Iterator: - return iter(self._toklist[::-1]) - - def keys(self): - return iter(self._tokdict) - - def values(self): - return (self[k] for k in self.keys()) - - def items(self): - return ((k, self[k]) for k in self.keys()) - - def haskeys(self) -> bool: - """ - Since ``keys()`` returns an iterator, this method is helpful in bypassing - code that looks for the existence of any defined results names.""" - return not not self._tokdict - - def pop(self, *args, **kwargs): - """ - Removes and returns item at specified index (default= ``last``). - Supports both ``list`` and ``dict`` semantics for ``pop()``. If - passed no argument or an integer argument, it will use ``list`` - semantics and pop tokens from the list of parsed tokens. If passed - a non-integer argument (most likely a string), it will use ``dict`` - semantics and pop the corresponding value from any defined results - names. A second default return value argument is supported, just as in - ``dict.pop()``. - - Example:: - - numlist = Word(nums)[...] - print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] - - def remove_first(tokens): - tokens.pop(0) - numlist.add_parse_action(remove_first) - print(numlist.parse_string("0 123 321")) # -> ['123', '321'] - - label = Word(alphas) - patt = label("LABEL") + Word(nums)[1, ...] - print(patt.parse_string("AAB 123 321").dump()) - - # Use pop() in a parse action to remove named result (note that corresponding value is not - # removed from list form of results) - def remove_LABEL(tokens): - tokens.pop("LABEL") - return tokens - patt.add_parse_action(remove_LABEL) - print(patt.parse_string("AAB 123 321").dump()) - - prints:: - - ['AAB', '123', '321'] - - LABEL: 'AAB' - - ['AAB', '123', '321'] - """ - if not args: - args = [-1] - for k, v in kwargs.items(): - if k == "default": - args = (args[0], v) - else: - raise TypeError(f"pop() got an unexpected keyword argument {k!r}") - if isinstance(args[0], int) or len(args) == 1 or args[0] in self: - index = args[0] - ret = self[index] - del self[index] - return ret - else: - defaultvalue = args[1] - return defaultvalue - - def get(self, key, default_value=None): - """ - Returns named result matching the given key, or if there is no - such name, then returns the given ``default_value`` or ``None`` if no - ``default_value`` is specified. - - Similar to ``dict.get()``. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parse_string("1999/12/31") - print(result.get("year")) # -> '1999' - print(result.get("hour", "not specified")) # -> 'not specified' - print(result.get("hour")) # -> None - """ - if key in self: - return self[key] - else: - return default_value - - def insert(self, index, ins_string): - """ - Inserts new element at location index in the list of parsed tokens. - - Similar to ``list.insert()``. - - Example:: - - numlist = Word(nums)[...] - print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to insert the parse location in the front of the parsed results - def insert_locn(locn, tokens): - tokens.insert(0, locn) - numlist.add_parse_action(insert_locn) - print(numlist.parse_string("0 123 321")) # -> [0, '0', '123', '321'] - """ - self._toklist.insert(index, ins_string) - # fixup indices in token dictionary - for name, occurrences in self._tokdict.items(): - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset( - value, position + (position > index) - ) - - def append(self, item): - """ - Add single element to end of ``ParseResults`` list of elements. - - Example:: - - numlist = Word(nums)[...] - print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to compute the sum of the parsed integers, and add it to the end - def append_sum(tokens): - tokens.append(sum(map(int, tokens))) - numlist.add_parse_action(append_sum) - print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321', 444] - """ - self._toklist.append(item) - - def extend(self, itemseq): - """ - Add sequence of elements to end of ``ParseResults`` list of elements. - - Example:: - - patt = Word(alphas)[1, ...] - - # use a parse action to append the reverse of the matched strings, to make a palindrome - def make_palindrome(tokens): - tokens.extend(reversed([t[::-1] for t in tokens])) - return ''.join(tokens) - patt.add_parse_action(make_palindrome) - print(patt.parse_string("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' - """ - if isinstance(itemseq, ParseResults): - self.__iadd__(itemseq) - else: - self._toklist.extend(itemseq) - - def clear(self): - """ - Clear all elements and results names. - """ - del self._toklist[:] - self._tokdict.clear() - - def __getattr__(self, name): - try: - return self[name] - except KeyError: - if name.startswith("__"): - raise AttributeError(name) - return "" - - def __add__(self, other: "ParseResults") -> "ParseResults": - ret = self.copy() - ret += other - return ret - - def __iadd__(self, other: "ParseResults") -> "ParseResults": - if not other: - return self - - if other._tokdict: - offset = len(self._toklist) - addoffset = lambda a: offset if a < 0 else a + offset - otheritems = other._tokdict.items() - otherdictitems = [ - (k, _ParseResultsWithOffset(v[0], addoffset(v[1]))) - for k, vlist in otheritems - for v in vlist - ] - for k, v in otherdictitems: - self[k] = v - if isinstance(v[0], ParseResults): - v[0]._parent = self - - self._toklist += other._toklist - self._all_names |= other._all_names - return self - - def __radd__(self, other) -> "ParseResults": - if isinstance(other, int) and other == 0: - # useful for merging many ParseResults using sum() builtin - return self.copy() - else: - # this may raise a TypeError - so be it - return other + self - - def __repr__(self) -> str: - return f"{type(self).__name__}({self._toklist!r}, {self.as_dict()})" - - def __str__(self) -> str: - return ( - "[" - + ", ".join( - [ - str(i) if isinstance(i, ParseResults) else repr(i) - for i in self._toklist - ] - ) - + "]" - ) - - def _asStringList(self, sep=""): - out = [] - for item in self._toklist: - if out and sep: - out.append(sep) - if isinstance(item, ParseResults): - out += item._asStringList() - else: - out.append(str(item)) - return out - - def as_list(self) -> list: - """ - Returns the parse results as a nested list of matching tokens, all converted to strings. - - Example:: - - patt = Word(alphas)[1, ...] - result = patt.parse_string("sldkj lsdkj sldkj") - # even though the result prints in string-like form, it is actually a pyparsing ParseResults - print(type(result), result) # -> ['sldkj', 'lsdkj', 'sldkj'] - - # Use as_list() to create an actual list - result_list = result.as_list() - print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj'] - """ - return [ - res.as_list() if isinstance(res, ParseResults) else res - for res in self._toklist - ] - - def as_dict(self) -> dict: - """ - Returns the named parse results as a nested dictionary. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parse_string('12/31/1999') - print(type(result), repr(result)) # -> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) - - result_dict = result.as_dict() - print(type(result_dict), repr(result_dict)) # -> {'day': '1999', 'year': '12', 'month': '31'} - - # even though a ParseResults supports dict-like access, sometime you just need to have a dict - import json - print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable - print(json.dumps(result.as_dict())) # -> {"month": "31", "day": "1999", "year": "12"} - """ - - def to_item(obj): - if isinstance(obj, ParseResults): - return obj.as_dict() if obj.haskeys() else [to_item(v) for v in obj] - else: - return obj - - return dict((k, to_item(v)) for k, v in self.items()) - - def copy(self) -> "ParseResults": - """ - Returns a new shallow copy of a :class:`ParseResults` object. `ParseResults` - items contained within the source are shared with the copy. Use - :class:`ParseResults.deepcopy()` to create a copy with its own separate - content values. - """ - ret = ParseResults(self._toklist) - ret._tokdict = self._tokdict.copy() - ret._parent = self._parent - ret._all_names |= self._all_names - ret._name = self._name - return ret - - def deepcopy(self) -> "ParseResults": - """ - Returns a new deep copy of a :class:`ParseResults` object. - """ - ret = self.copy() - # replace values with copies if they are of known mutable types - for i, obj in enumerate(self._toklist): - if isinstance(obj, ParseResults): - self._toklist[i] = obj.deepcopy() - elif isinstance(obj, (str, bytes)): - pass - elif isinstance(obj, MutableMapping): - self._toklist[i] = dest = type(obj)() - for k, v in obj.items(): - dest[k] = v.deepcopy() if isinstance(v, ParseResults) else v - elif isinstance(obj, Container): - self._toklist[i] = type(obj)( - v.deepcopy() if isinstance(v, ParseResults) else v for v in obj - ) - return ret - - def get_name(self): - r""" - Returns the results name for this token expression. Useful when several - different expressions might match at a particular location. - - Example:: - - integer = Word(nums) - ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") - house_number_expr = Suppress('#') + Word(nums, alphanums) - user_data = (Group(house_number_expr)("house_number") - | Group(ssn_expr)("ssn") - | Group(integer)("age")) - user_info = user_data[1, ...] - - result = user_info.parse_string("22 111-22-3333 #221B") - for item in result: - print(item.get_name(), ':', item[0]) - - prints:: - - age : 22 - ssn : 111-22-3333 - house_number : 221B - """ - if self._name: - return self._name - elif self._parent: - par: "ParseResults" = self._parent - parent_tokdict_items = par._tokdict.items() - return next( - ( - k - for k, vlist in parent_tokdict_items - for v, loc in vlist - if v is self - ), - None, - ) - elif ( - len(self) == 1 - and len(self._tokdict) == 1 - and next(iter(self._tokdict.values()))[0][1] in (0, -1) - ): - return next(iter(self._tokdict.keys())) - else: - return None - - def dump(self, indent="", full=True, include_list=True, _depth=0) -> str: - """ - Diagnostic method for listing out the contents of - a :class:`ParseResults`. Accepts an optional ``indent`` argument so - that this string can be embedded in a nested display of other data. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parse_string('1999/12/31') - print(result.dump()) - - prints:: - - ['1999', '/', '12', '/', '31'] - - day: '31' - - month: '12' - - year: '1999' - """ - out = [] - NL = "\n" - out.append(indent + str(self.as_list()) if include_list else "") - - if full: - if self.haskeys(): - items = sorted((str(k), v) for k, v in self.items()) - for k, v in items: - if out: - out.append(NL) - out.append(f"{indent}{(' ' * _depth)}- {k}: ") - if isinstance(v, ParseResults): - if v: - out.append( - v.dump( - indent=indent, - full=full, - include_list=include_list, - _depth=_depth + 1, - ) - ) - else: - out.append(str(v)) - else: - out.append(repr(v)) - if any(isinstance(vv, ParseResults) for vv in self): - v = self - for i, vv in enumerate(v): - if isinstance(vv, ParseResults): - out.append( - "\n{}{}[{}]:\n{}{}{}".format( - indent, - (" " * (_depth)), - i, - indent, - (" " * (_depth + 1)), - vv.dump( - indent=indent, - full=full, - include_list=include_list, - _depth=_depth + 1, - ), - ) - ) - else: - out.append( - "\n%s%s[%d]:\n%s%s%s" - % ( - indent, - (" " * (_depth)), - i, - indent, - (" " * (_depth + 1)), - str(vv), - ) - ) - - return "".join(out) - - def pprint(self, *args, **kwargs): - """ - Pretty-printer for parsed results as a list, using the - `pprint `_ module. - Accepts additional positional or keyword args as defined for - `pprint.pprint `_ . - - Example:: - - ident = Word(alphas, alphanums) - num = Word(nums) - func = Forward() - term = ident | num | Group('(' + func + ')') - func <<= ident + Group(Optional(DelimitedList(term))) - result = func.parse_string("fna a,b,(fnb c,d,200),100") - result.pprint(width=40) - - prints:: - - ['fna', - ['a', - 'b', - ['(', 'fnb', ['c', 'd', '200'], ')'], - '100']] - """ - pprint.pprint(self.as_list(), *args, **kwargs) - - # add support for pickle protocol - def __getstate__(self): - return ( - self._toklist, - ( - self._tokdict.copy(), - None, - self._all_names, - self._name, - ), - ) - - def __setstate__(self, state): - self._toklist, (self._tokdict, par, inAccumNames, self._name) = state - self._all_names = set(inAccumNames) - self._parent = None - - def __getnewargs__(self): - return self._toklist, self._name - - def __dir__(self): - return dir(type(self)) + list(self.keys()) - - @classmethod - def from_dict(cls, other, name=None) -> "ParseResults": - """ - Helper classmethod to construct a ``ParseResults`` from a ``dict``, preserving the - name-value relations as results names. If an optional ``name`` argument is - given, a nested ``ParseResults`` will be returned. - """ - - def is_iterable(obj): - try: - iter(obj) - except Exception: - return False - # str's are iterable, but in pyparsing, we don't want to iterate over them - else: - return not isinstance(obj, str_type) - - ret = cls([]) - for k, v in other.items(): - if isinstance(v, Mapping): - ret += cls.from_dict(v, name=k) - else: - ret += cls([v], name=k, asList=is_iterable(v)) - if name is not None: - ret = cls([ret], name=name) - return ret - - asList = as_list - """Deprecated - use :class:`as_list`""" - asDict = as_dict - """Deprecated - use :class:`as_dict`""" - getName = get_name - """Deprecated - use :class:`get_name`""" - - -MutableMapping.register(ParseResults) -MutableSequence.register(ParseResults) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/testing.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/testing.py deleted file mode 100644 index 6a254c1..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/testing.py +++ /dev/null @@ -1,331 +0,0 @@ -# testing.py - -from contextlib import contextmanager -import typing - -from .core import ( - ParserElement, - ParseException, - Keyword, - __diag__, - __compat__, -) - - -class pyparsing_test: - """ - namespace class for classes useful in writing unit tests - """ - - class reset_pyparsing_context: - """ - Context manager to be used when writing unit tests that modify pyparsing config values: - - packrat parsing - - bounded recursion parsing - - default whitespace characters. - - default keyword characters - - literal string auto-conversion class - - __diag__ settings - - Example:: - - with reset_pyparsing_context(): - # test that literals used to construct a grammar are automatically suppressed - ParserElement.inlineLiteralsUsing(Suppress) - - term = Word(alphas) | Word(nums) - group = Group('(' + term[...] + ')') - - # assert that the '()' characters are not included in the parsed tokens - self.assertParseAndCheckList(group, "(abc 123 def)", ['abc', '123', 'def']) - - # after exiting context manager, literals are converted to Literal expressions again - """ - - def __init__(self): - self._save_context = {} - - def save(self): - self._save_context["default_whitespace"] = ParserElement.DEFAULT_WHITE_CHARS - self._save_context["default_keyword_chars"] = Keyword.DEFAULT_KEYWORD_CHARS - - self._save_context[ - "literal_string_class" - ] = ParserElement._literalStringClass - - self._save_context["verbose_stacktrace"] = ParserElement.verbose_stacktrace - - self._save_context["packrat_enabled"] = ParserElement._packratEnabled - if ParserElement._packratEnabled: - self._save_context[ - "packrat_cache_size" - ] = ParserElement.packrat_cache.size - else: - self._save_context["packrat_cache_size"] = None - self._save_context["packrat_parse"] = ParserElement._parse - self._save_context[ - "recursion_enabled" - ] = ParserElement._left_recursion_enabled - - self._save_context["__diag__"] = { - name: getattr(__diag__, name) for name in __diag__._all_names - } - - self._save_context["__compat__"] = { - "collect_all_And_tokens": __compat__.collect_all_And_tokens - } - - return self - - def restore(self): - # reset pyparsing global state - if ( - ParserElement.DEFAULT_WHITE_CHARS - != self._save_context["default_whitespace"] - ): - ParserElement.set_default_whitespace_chars( - self._save_context["default_whitespace"] - ) - - ParserElement.verbose_stacktrace = self._save_context["verbose_stacktrace"] - - Keyword.DEFAULT_KEYWORD_CHARS = self._save_context["default_keyword_chars"] - ParserElement.inlineLiteralsUsing( - self._save_context["literal_string_class"] - ) - - for name, value in self._save_context["__diag__"].items(): - (__diag__.enable if value else __diag__.disable)(name) - - ParserElement._packratEnabled = False - if self._save_context["packrat_enabled"]: - ParserElement.enable_packrat(self._save_context["packrat_cache_size"]) - else: - ParserElement._parse = self._save_context["packrat_parse"] - ParserElement._left_recursion_enabled = self._save_context[ - "recursion_enabled" - ] - - __compat__.collect_all_And_tokens = self._save_context["__compat__"] - - return self - - def copy(self): - ret = type(self)() - ret._save_context.update(self._save_context) - return ret - - def __enter__(self): - return self.save() - - def __exit__(self, *args): - self.restore() - - class TestParseResultsAsserts: - """ - A mixin class to add parse results assertion methods to normal unittest.TestCase classes. - """ - - def assertParseResultsEquals( - self, result, expected_list=None, expected_dict=None, msg=None - ): - """ - Unit test assertion to compare a :class:`ParseResults` object with an optional ``expected_list``, - and compare any defined results names with an optional ``expected_dict``. - """ - if expected_list is not None: - self.assertEqual(expected_list, result.as_list(), msg=msg) - if expected_dict is not None: - self.assertEqual(expected_dict, result.as_dict(), msg=msg) - - def assertParseAndCheckList( - self, expr, test_string, expected_list, msg=None, verbose=True - ): - """ - Convenience wrapper assert to test a parser element and input string, and assert that - the resulting ``ParseResults.asList()`` is equal to the ``expected_list``. - """ - result = expr.parse_string(test_string, parse_all=True) - if verbose: - print(result.dump()) - else: - print(result.as_list()) - self.assertParseResultsEquals(result, expected_list=expected_list, msg=msg) - - def assertParseAndCheckDict( - self, expr, test_string, expected_dict, msg=None, verbose=True - ): - """ - Convenience wrapper assert to test a parser element and input string, and assert that - the resulting ``ParseResults.asDict()`` is equal to the ``expected_dict``. - """ - result = expr.parse_string(test_string, parseAll=True) - if verbose: - print(result.dump()) - else: - print(result.as_list()) - self.assertParseResultsEquals(result, expected_dict=expected_dict, msg=msg) - - def assertRunTestResults( - self, run_tests_report, expected_parse_results=None, msg=None - ): - """ - Unit test assertion to evaluate output of ``ParserElement.runTests()``. If a list of - list-dict tuples is given as the ``expected_parse_results`` argument, then these are zipped - with the report tuples returned by ``runTests`` and evaluated using ``assertParseResultsEquals``. - Finally, asserts that the overall ``runTests()`` success value is ``True``. - - :param run_tests_report: tuple(bool, [tuple(str, ParseResults or Exception)]) returned from runTests - :param expected_parse_results (optional): [tuple(str, list, dict, Exception)] - """ - run_test_success, run_test_results = run_tests_report - - if expected_parse_results is not None: - merged = [ - (*rpt, expected) - for rpt, expected in zip(run_test_results, expected_parse_results) - ] - for test_string, result, expected in merged: - # expected should be a tuple containing a list and/or a dict or an exception, - # and optional failure message string - # an empty tuple will skip any result validation - fail_msg = next( - (exp for exp in expected if isinstance(exp, str)), None - ) - expected_exception = next( - ( - exp - for exp in expected - if isinstance(exp, type) and issubclass(exp, Exception) - ), - None, - ) - if expected_exception is not None: - with self.assertRaises( - expected_exception=expected_exception, msg=fail_msg or msg - ): - if isinstance(result, Exception): - raise result - else: - expected_list = next( - (exp for exp in expected if isinstance(exp, list)), None - ) - expected_dict = next( - (exp for exp in expected if isinstance(exp, dict)), None - ) - if (expected_list, expected_dict) != (None, None): - self.assertParseResultsEquals( - result, - expected_list=expected_list, - expected_dict=expected_dict, - msg=fail_msg or msg, - ) - else: - # warning here maybe? - print(f"no validation for {test_string!r}") - - # do this last, in case some specific test results can be reported instead - self.assertTrue( - run_test_success, msg=msg if msg is not None else "failed runTests" - ) - - @contextmanager - def assertRaisesParseException(self, exc_type=ParseException, msg=None): - with self.assertRaises(exc_type, msg=msg): - yield - - @staticmethod - def with_line_numbers( - s: str, - start_line: typing.Optional[int] = None, - end_line: typing.Optional[int] = None, - expand_tabs: bool = True, - eol_mark: str = "|", - mark_spaces: typing.Optional[str] = None, - mark_control: typing.Optional[str] = None, - ) -> str: - """ - Helpful method for debugging a parser - prints a string with line and column numbers. - (Line and column numbers are 1-based.) - - :param s: tuple(bool, str - string to be printed with line and column numbers - :param start_line: int - (optional) starting line number in s to print (default=1) - :param end_line: int - (optional) ending line number in s to print (default=len(s)) - :param expand_tabs: bool - (optional) expand tabs to spaces, to match the pyparsing default - :param eol_mark: str - (optional) string to mark the end of lines, helps visualize trailing spaces (default="|") - :param mark_spaces: str - (optional) special character to display in place of spaces - :param mark_control: str - (optional) convert non-printing control characters to a placeholding - character; valid values: - - "unicode" - replaces control chars with Unicode symbols, such as "â" and "âŠ" - - any single character string - replace control characters with given string - - None (default) - string is displayed as-is - - :return: str - input string with leading line numbers and column number headers - """ - if expand_tabs: - s = s.expandtabs() - if mark_control is not None: - mark_control = typing.cast(str, mark_control) - if mark_control == "unicode": - transtable_map = { - c: u for c, u in zip(range(0, 33), range(0x2400, 0x2433)) - } - transtable_map[127] = 0x2421 - tbl = str.maketrans(transtable_map) - eol_mark = "" - else: - ord_mark_control = ord(mark_control) - tbl = str.maketrans( - {c: ord_mark_control for c in list(range(0, 32)) + [127]} - ) - s = s.translate(tbl) - if mark_spaces is not None and mark_spaces != " ": - if mark_spaces == "unicode": - tbl = str.maketrans({9: 0x2409, 32: 0x2423}) - s = s.translate(tbl) - else: - s = s.replace(" ", mark_spaces) - if start_line is None: - start_line = 1 - if end_line is None: - end_line = len(s) - end_line = min(end_line, len(s)) - start_line = min(max(1, start_line), end_line) - - if mark_control != "unicode": - s_lines = s.splitlines()[start_line - 1 : end_line] - else: - s_lines = [line + "âŠ" for line in s.split("âŠ")[start_line - 1 : end_line]] - if not s_lines: - return "" - - lineno_width = len(str(end_line)) - max_line_len = max(len(line) for line in s_lines) - lead = " " * (lineno_width + 1) - if max_line_len >= 99: - header0 = ( - lead - + "".join( - f"{' ' * 99}{(i + 1) % 100}" - for i in range(max(max_line_len // 100, 1)) - ) - + "\n" - ) - else: - header0 = "" - header1 = ( - header0 - + lead - + "".join(f" {(i + 1) % 10}" for i in range(-(-max_line_len // 10))) - + "\n" - ) - header2 = lead + "1234567890" * (-(-max_line_len // 10)) + "\n" - return ( - header1 - + header2 - + "\n".join( - f"{i:{lineno_width}d}:{line}{eol_mark}" - for i, line in enumerate(s_lines, start=start_line) - ) - + "\n" - ) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/unicode.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/unicode.py deleted file mode 100644 index ec0b3a4..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/unicode.py +++ /dev/null @@ -1,361 +0,0 @@ -# unicode.py - -import sys -from itertools import filterfalse -from typing import List, Tuple, Union - - -class _lazyclassproperty: - def __init__(self, fn): - self.fn = fn - self.__doc__ = fn.__doc__ - self.__name__ = fn.__name__ - - def __get__(self, obj, cls): - if cls is None: - cls = type(obj) - if not hasattr(cls, "_intern") or any( - cls._intern is getattr(superclass, "_intern", []) - for superclass in cls.__mro__[1:] - ): - cls._intern = {} - attrname = self.fn.__name__ - if attrname not in cls._intern: - cls._intern[attrname] = self.fn(cls) - return cls._intern[attrname] - - -UnicodeRangeList = List[Union[Tuple[int, int], Tuple[int]]] - - -class unicode_set: - """ - A set of Unicode characters, for language-specific strings for - ``alphas``, ``nums``, ``alphanums``, and ``printables``. - A unicode_set is defined by a list of ranges in the Unicode character - set, in a class attribute ``_ranges``. Ranges can be specified using - 2-tuples or a 1-tuple, such as:: - - _ranges = [ - (0x0020, 0x007e), - (0x00a0, 0x00ff), - (0x0100,), - ] - - Ranges are left- and right-inclusive. A 1-tuple of (x,) is treated as (x, x). - - A unicode set can also be defined using multiple inheritance of other unicode sets:: - - class CJK(Chinese, Japanese, Korean): - pass - """ - - _ranges: UnicodeRangeList = [] - - @_lazyclassproperty - def _chars_for_ranges(cls): - ret = [] - for cc in cls.__mro__: - if cc is unicode_set: - break - for rr in getattr(cc, "_ranges", ()): - ret.extend(range(rr[0], rr[-1] + 1)) - return [chr(c) for c in sorted(set(ret))] - - @_lazyclassproperty - def printables(cls): - """all non-whitespace characters in this range""" - return "".join(filterfalse(str.isspace, cls._chars_for_ranges)) - - @_lazyclassproperty - def alphas(cls): - """all alphabetic characters in this range""" - return "".join(filter(str.isalpha, cls._chars_for_ranges)) - - @_lazyclassproperty - def nums(cls): - """all numeric digit characters in this range""" - return "".join(filter(str.isdigit, cls._chars_for_ranges)) - - @_lazyclassproperty - def alphanums(cls): - """all alphanumeric characters in this range""" - return cls.alphas + cls.nums - - @_lazyclassproperty - def identchars(cls): - """all characters in this range that are valid identifier characters, plus underscore '_'""" - return "".join( - sorted( - set( - "".join(filter(str.isidentifier, cls._chars_for_ranges)) - + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµº" - + "ÀÃÂÃÄÅÆÇÈÉÊËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ" - + "_" - ) - ) - ) - - @_lazyclassproperty - def identbodychars(cls): - """ - all characters in this range that are valid identifier body characters, - plus the digits 0-9, and · (Unicode MIDDLE DOT) - """ - return "".join( - sorted( - set( - cls.identchars - + "0123456789·" - + "".join( - [c for c in cls._chars_for_ranges if ("_" + c).isidentifier()] - ) - ) - ) - ) - - @_lazyclassproperty - def identifier(cls): - """ - a pyparsing Word expression for an identifier using this range's definitions for - identchars and identbodychars - """ - from pip._vendor.pyparsing import Word - - return Word(cls.identchars, cls.identbodychars) - - -class pyparsing_unicode(unicode_set): - """ - A namespace class for defining common language unicode_sets. - """ - - # fmt: off - - # define ranges in language character sets - _ranges: UnicodeRangeList = [ - (0x0020, sys.maxunicode), - ] - - class BasicMultilingualPlane(unicode_set): - """Unicode set for the Basic Multilingual Plane""" - _ranges: UnicodeRangeList = [ - (0x0020, 0xFFFF), - ] - - class Latin1(unicode_set): - """Unicode set for Latin-1 Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x0020, 0x007E), - (0x00A0, 0x00FF), - ] - - class LatinA(unicode_set): - """Unicode set for Latin-A Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x0100, 0x017F), - ] - - class LatinB(unicode_set): - """Unicode set for Latin-B Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x0180, 0x024F), - ] - - class Greek(unicode_set): - """Unicode set for Greek Unicode Character Ranges""" - _ranges: UnicodeRangeList = [ - (0x0342, 0x0345), - (0x0370, 0x0377), - (0x037A, 0x037F), - (0x0384, 0x038A), - (0x038C,), - (0x038E, 0x03A1), - (0x03A3, 0x03E1), - (0x03F0, 0x03FF), - (0x1D26, 0x1D2A), - (0x1D5E,), - (0x1D60,), - (0x1D66, 0x1D6A), - (0x1F00, 0x1F15), - (0x1F18, 0x1F1D), - (0x1F20, 0x1F45), - (0x1F48, 0x1F4D), - (0x1F50, 0x1F57), - (0x1F59,), - (0x1F5B,), - (0x1F5D,), - (0x1F5F, 0x1F7D), - (0x1F80, 0x1FB4), - (0x1FB6, 0x1FC4), - (0x1FC6, 0x1FD3), - (0x1FD6, 0x1FDB), - (0x1FDD, 0x1FEF), - (0x1FF2, 0x1FF4), - (0x1FF6, 0x1FFE), - (0x2129,), - (0x2719, 0x271A), - (0xAB65,), - (0x10140, 0x1018D), - (0x101A0,), - (0x1D200, 0x1D245), - (0x1F7A1, 0x1F7A7), - ] - - class Cyrillic(unicode_set): - """Unicode set for Cyrillic Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x0400, 0x052F), - (0x1C80, 0x1C88), - (0x1D2B,), - (0x1D78,), - (0x2DE0, 0x2DFF), - (0xA640, 0xA672), - (0xA674, 0xA69F), - (0xFE2E, 0xFE2F), - ] - - class Chinese(unicode_set): - """Unicode set for Chinese Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x2E80, 0x2E99), - (0x2E9B, 0x2EF3), - (0x31C0, 0x31E3), - (0x3400, 0x4DB5), - (0x4E00, 0x9FEF), - (0xA700, 0xA707), - (0xF900, 0xFA6D), - (0xFA70, 0xFAD9), - (0x16FE2, 0x16FE3), - (0x1F210, 0x1F212), - (0x1F214, 0x1F23B), - (0x1F240, 0x1F248), - (0x20000, 0x2A6D6), - (0x2A700, 0x2B734), - (0x2B740, 0x2B81D), - (0x2B820, 0x2CEA1), - (0x2CEB0, 0x2EBE0), - (0x2F800, 0x2FA1D), - ] - - class Japanese(unicode_set): - """Unicode set for Japanese Unicode Character Range, combining Kanji, Hiragana, and Katakana ranges""" - - class Kanji(unicode_set): - "Unicode set for Kanji Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x4E00, 0x9FBF), - (0x3000, 0x303F), - ] - - class Hiragana(unicode_set): - """Unicode set for Hiragana Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x3041, 0x3096), - (0x3099, 0x30A0), - (0x30FC,), - (0xFF70,), - (0x1B001,), - (0x1B150, 0x1B152), - (0x1F200,), - ] - - class Katakana(unicode_set): - """Unicode set for Katakana Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x3099, 0x309C), - (0x30A0, 0x30FF), - (0x31F0, 0x31FF), - (0x32D0, 0x32FE), - (0xFF65, 0xFF9F), - (0x1B000,), - (0x1B164, 0x1B167), - (0x1F201, 0x1F202), - (0x1F213,), - ] - - 漢字 = Kanji - カタカナ = Katakana - ã²ã‚‰ãŒãª = Hiragana - - _ranges = ( - Kanji._ranges - + Hiragana._ranges - + Katakana._ranges - ) - - class Hangul(unicode_set): - """Unicode set for Hangul (Korean) Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x1100, 0x11FF), - (0x302E, 0x302F), - (0x3131, 0x318E), - (0x3200, 0x321C), - (0x3260, 0x327B), - (0x327E,), - (0xA960, 0xA97C), - (0xAC00, 0xD7A3), - (0xD7B0, 0xD7C6), - (0xD7CB, 0xD7FB), - (0xFFA0, 0xFFBE), - (0xFFC2, 0xFFC7), - (0xFFCA, 0xFFCF), - (0xFFD2, 0xFFD7), - (0xFFDA, 0xFFDC), - ] - - Korean = Hangul - - class CJK(Chinese, Japanese, Hangul): - """Unicode set for combined Chinese, Japanese, and Korean (CJK) Unicode Character Range""" - - class Thai(unicode_set): - """Unicode set for Thai Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x0E01, 0x0E3A), - (0x0E3F, 0x0E5B) - ] - - class Arabic(unicode_set): - """Unicode set for Arabic Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x0600, 0x061B), - (0x061E, 0x06FF), - (0x0700, 0x077F), - ] - - class Hebrew(unicode_set): - """Unicode set for Hebrew Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x0591, 0x05C7), - (0x05D0, 0x05EA), - (0x05EF, 0x05F4), - (0xFB1D, 0xFB36), - (0xFB38, 0xFB3C), - (0xFB3E,), - (0xFB40, 0xFB41), - (0xFB43, 0xFB44), - (0xFB46, 0xFB4F), - ] - - class Devanagari(unicode_set): - """Unicode set for Devanagari Unicode Character Range""" - _ranges: UnicodeRangeList = [ - (0x0900, 0x097F), - (0xA8E0, 0xA8FF) - ] - - BMP = BasicMultilingualPlane - - # add language identifiers using language Unicode - العربية = Arabic - 中文 = Chinese - кириллица = Cyrillic - Ελληνικά = Greek - עִברִית = Hebrew - 日本語 = Japanese - 한국어 = Korean - ไทย = Thai - देवनागरी = Devanagari - - # fmt: on diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/util.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/util.py deleted file mode 100644 index d8d3f41..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/util.py +++ /dev/null @@ -1,284 +0,0 @@ -# util.py -import inspect -import warnings -import types -import collections -import itertools -from functools import lru_cache, wraps -from typing import Callable, List, Union, Iterable, TypeVar, cast - -_bslash = chr(92) -C = TypeVar("C", bound=Callable) - - -class __config_flags: - """Internal class for defining compatibility and debugging flags""" - - _all_names: List[str] = [] - _fixed_names: List[str] = [] - _type_desc = "configuration" - - @classmethod - def _set(cls, dname, value): - if dname in cls._fixed_names: - warnings.warn( - f"{cls.__name__}.{dname} {cls._type_desc} is {str(getattr(cls, dname)).upper()}" - f" and cannot be overridden", - stacklevel=3, - ) - return - if dname in cls._all_names: - setattr(cls, dname, value) - else: - raise ValueError(f"no such {cls._type_desc} {dname!r}") - - enable = classmethod(lambda cls, name: cls._set(name, True)) - disable = classmethod(lambda cls, name: cls._set(name, False)) - - -@lru_cache(maxsize=128) -def col(loc: int, strg: str) -> int: - """ - Returns current column within a string, counting newlines as line separators. - The first column is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See - :class:`ParserElement.parse_string` for more - information on parsing strings containing ```` s, and suggested - methods to maintain a consistent view of the parsed string, the parse - location, and line and column positions within the parsed string. - """ - s = strg - return 1 if 0 < loc < len(s) and s[loc - 1] == "\n" else loc - s.rfind("\n", 0, loc) - - -@lru_cache(maxsize=128) -def lineno(loc: int, strg: str) -> int: - """Returns current line number within a string, counting newlines as line separators. - The first line is number 1. - - Note - the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See :class:`ParserElement.parse_string` - for more information on parsing strings containing ```` s, and - suggested methods to maintain a consistent view of the parsed string, the - parse location, and line and column positions within the parsed string. - """ - return strg.count("\n", 0, loc) + 1 - - -@lru_cache(maxsize=128) -def line(loc: int, strg: str) -> str: - """ - Returns the line of text containing loc within a string, counting newlines as line separators. - """ - last_cr = strg.rfind("\n", 0, loc) - next_cr = strg.find("\n", loc) - return strg[last_cr + 1 : next_cr] if next_cr >= 0 else strg[last_cr + 1 :] - - -class _UnboundedCache: - def __init__(self): - cache = {} - cache_get = cache.get - self.not_in_cache = not_in_cache = object() - - def get(_, key): - return cache_get(key, not_in_cache) - - def set_(_, key, value): - cache[key] = value - - def clear(_): - cache.clear() - - self.size = None - self.get = types.MethodType(get, self) - self.set = types.MethodType(set_, self) - self.clear = types.MethodType(clear, self) - - -class _FifoCache: - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - cache = {} - keyring = [object()] * size - cache_get = cache.get - cache_pop = cache.pop - keyiter = itertools.cycle(range(size)) - - def get(_, key): - return cache_get(key, not_in_cache) - - def set_(_, key, value): - cache[key] = value - i = next(keyiter) - cache_pop(keyring[i], None) - keyring[i] = key - - def clear(_): - cache.clear() - keyring[:] = [object()] * size - - self.size = size - self.get = types.MethodType(get, self) - self.set = types.MethodType(set_, self) - self.clear = types.MethodType(clear, self) - - -class LRUMemo: - """ - A memoizing mapping that retains `capacity` deleted items - - The memo tracks retained items by their access order; once `capacity` items - are retained, the least recently used item is discarded. - """ - - def __init__(self, capacity): - self._capacity = capacity - self._active = {} - self._memory = collections.OrderedDict() - - def __getitem__(self, key): - try: - return self._active[key] - except KeyError: - self._memory.move_to_end(key) - return self._memory[key] - - def __setitem__(self, key, value): - self._memory.pop(key, None) - self._active[key] = value - - def __delitem__(self, key): - try: - value = self._active.pop(key) - except KeyError: - pass - else: - while len(self._memory) >= self._capacity: - self._memory.popitem(last=False) - self._memory[key] = value - - def clear(self): - self._active.clear() - self._memory.clear() - - -class UnboundedMemo(dict): - """ - A memoizing mapping that retains all deleted items - """ - - def __delitem__(self, key): - pass - - -def _escape_regex_range_chars(s: str) -> str: - # escape these chars: ^-[] - for c in r"\^-[]": - s = s.replace(c, _bslash + c) - s = s.replace("\n", r"\n") - s = s.replace("\t", r"\t") - return str(s) - - -def _collapse_string_to_ranges( - s: Union[str, Iterable[str]], re_escape: bool = True -) -> str: - def is_consecutive(c): - c_int = ord(c) - is_consecutive.prev, prev = c_int, is_consecutive.prev - if c_int - prev > 1: - is_consecutive.value = next(is_consecutive.counter) - return is_consecutive.value - - is_consecutive.prev = 0 # type: ignore [attr-defined] - is_consecutive.counter = itertools.count() # type: ignore [attr-defined] - is_consecutive.value = -1 # type: ignore [attr-defined] - - def escape_re_range_char(c): - return "\\" + c if c in r"\^-][" else c - - def no_escape_re_range_char(c): - return c - - if not re_escape: - escape_re_range_char = no_escape_re_range_char - - ret = [] - s = "".join(sorted(set(s))) - if len(s) > 3: - for _, chars in itertools.groupby(s, key=is_consecutive): - first = last = next(chars) - last = collections.deque( - itertools.chain(iter([last]), chars), maxlen=1 - ).pop() - if first == last: - ret.append(escape_re_range_char(first)) - else: - sep = "" if ord(last) == ord(first) + 1 else "-" - ret.append( - f"{escape_re_range_char(first)}{sep}{escape_re_range_char(last)}" - ) - else: - ret = [escape_re_range_char(c) for c in s] - - return "".join(ret) - - -def _flatten(ll: list) -> list: - ret = [] - for i in ll: - if isinstance(i, list): - ret.extend(_flatten(i)) - else: - ret.append(i) - return ret - - -def _make_synonym_function(compat_name: str, fn: C) -> C: - # In a future version, uncomment the code in the internal _inner() functions - # to begin emitting DeprecationWarnings. - - # Unwrap staticmethod/classmethod - fn = getattr(fn, "__func__", fn) - - # (Presence of 'self' arg in signature is used by explain_exception() methods, so we take - # some extra steps to add it if present in decorated function.) - if "self" == list(inspect.signature(fn).parameters)[0]: - - @wraps(fn) - def _inner(self, *args, **kwargs): - # warnings.warn( - # f"Deprecated - use {fn.__name__}", DeprecationWarning, stacklevel=3 - # ) - return fn(self, *args, **kwargs) - - else: - - @wraps(fn) - def _inner(*args, **kwargs): - # warnings.warn( - # f"Deprecated - use {fn.__name__}", DeprecationWarning, stacklevel=3 - # ) - return fn(*args, **kwargs) - - _inner.__doc__ = f"""Deprecated - use :class:`{fn.__name__}`""" - _inner.__name__ = compat_name - _inner.__annotations__ = fn.__annotations__ - if isinstance(fn, types.FunctionType): - _inner.__kwdefaults__ = fn.__kwdefaults__ - elif isinstance(fn, type) and hasattr(fn, "__init__"): - _inner.__kwdefaults__ = fn.__init__.__kwdefaults__ - else: - _inner.__kwdefaults__ = None - _inner.__qualname__ = fn.__qualname__ - return cast(C, _inner) - - -def replaced_by_pep8(fn: C) -> Callable[[Callable], C]: - """ - Decorator for pre-PEP8 compatibility synonyms, to link them to the new function. - """ - return lambda other: _make_synonym_function(other.__name__, fn) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py deleted file mode 100644 index ddfcf7f..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Wrappers to call pyproject.toml-based build backend hooks. -""" - -from ._impl import ( - BackendInvalid, - BackendUnavailable, - BuildBackendHookCaller, - HookMissing, - UnsupportedOperation, - default_subprocess_runner, - quiet_subprocess_runner, -) - -__version__ = '1.0.0' -__all__ = [ - 'BackendUnavailable', - 'BackendInvalid', - 'HookMissing', - 'UnsupportedOperation', - 'default_subprocess_runner', - 'quiet_subprocess_runner', - 'BuildBackendHookCaller', -] diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index cbbd019..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc deleted file mode 100644 index 56b8244..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc deleted file mode 100644 index 32b9944..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py deleted file mode 100644 index 95e509c..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py +++ /dev/null @@ -1,8 +0,0 @@ -__all__ = ("tomllib",) - -import sys - -if sys.version_info >= (3, 11): - import tomllib -else: - from pip._vendor import tomli as tomllib diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py deleted file mode 100644 index 37b0e65..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py +++ /dev/null @@ -1,330 +0,0 @@ -import json -import os -import sys -import tempfile -from contextlib import contextmanager -from os.path import abspath -from os.path import join as pjoin -from subprocess import STDOUT, check_call, check_output - -from ._in_process import _in_proc_script_path - - -def write_json(obj, path, **kwargs): - with open(path, 'w', encoding='utf-8') as f: - json.dump(obj, f, **kwargs) - - -def read_json(path): - with open(path, encoding='utf-8') as f: - return json.load(f) - - -class BackendUnavailable(Exception): - """Will be raised if the backend cannot be imported in the hook process.""" - def __init__(self, traceback): - self.traceback = traceback - - -class BackendInvalid(Exception): - """Will be raised if the backend is invalid.""" - def __init__(self, backend_name, backend_path, message): - super().__init__(message) - self.backend_name = backend_name - self.backend_path = backend_path - - -class HookMissing(Exception): - """Will be raised on missing hooks (if a fallback can't be used).""" - def __init__(self, hook_name): - super().__init__(hook_name) - self.hook_name = hook_name - - -class UnsupportedOperation(Exception): - """May be raised by build_sdist if the backend indicates that it can't.""" - def __init__(self, traceback): - self.traceback = traceback - - -def default_subprocess_runner(cmd, cwd=None, extra_environ=None): - """The default method of calling the wrapper subprocess. - - This uses :func:`subprocess.check_call` under the hood. - """ - env = os.environ.copy() - if extra_environ: - env.update(extra_environ) - - check_call(cmd, cwd=cwd, env=env) - - -def quiet_subprocess_runner(cmd, cwd=None, extra_environ=None): - """Call the subprocess while suppressing output. - - This uses :func:`subprocess.check_output` under the hood. - """ - env = os.environ.copy() - if extra_environ: - env.update(extra_environ) - - check_output(cmd, cwd=cwd, env=env, stderr=STDOUT) - - -def norm_and_check(source_tree, requested): - """Normalise and check a backend path. - - Ensure that the requested backend path is specified as a relative path, - and resolves to a location under the given source tree. - - Return an absolute version of the requested path. - """ - if os.path.isabs(requested): - raise ValueError("paths must be relative") - - abs_source = os.path.abspath(source_tree) - abs_requested = os.path.normpath(os.path.join(abs_source, requested)) - # We have to use commonprefix for Python 2.7 compatibility. So we - # normalise case to avoid problems because commonprefix is a character - # based comparison :-( - norm_source = os.path.normcase(abs_source) - norm_requested = os.path.normcase(abs_requested) - if os.path.commonprefix([norm_source, norm_requested]) != norm_source: - raise ValueError("paths must be inside source tree") - - return abs_requested - - -class BuildBackendHookCaller: - """A wrapper to call the build backend hooks for a source directory. - """ - - def __init__( - self, - source_dir, - build_backend, - backend_path=None, - runner=None, - python_executable=None, - ): - """ - :param source_dir: The source directory to invoke the build backend for - :param build_backend: The build backend spec - :param backend_path: Additional path entries for the build backend spec - :param runner: The :ref:`subprocess runner ` to use - :param python_executable: - The Python executable used to invoke the build backend - """ - if runner is None: - runner = default_subprocess_runner - - self.source_dir = abspath(source_dir) - self.build_backend = build_backend - if backend_path: - backend_path = [ - norm_and_check(self.source_dir, p) for p in backend_path - ] - self.backend_path = backend_path - self._subprocess_runner = runner - if not python_executable: - python_executable = sys.executable - self.python_executable = python_executable - - @contextmanager - def subprocess_runner(self, runner): - """A context manager for temporarily overriding the default - :ref:`subprocess runner `. - - .. code-block:: python - - hook_caller = BuildBackendHookCaller(...) - with hook_caller.subprocess_runner(quiet_subprocess_runner): - ... - """ - prev = self._subprocess_runner - self._subprocess_runner = runner - try: - yield - finally: - self._subprocess_runner = prev - - def _supported_features(self): - """Return the list of optional features supported by the backend.""" - return self._call_hook('_supported_features', {}) - - def get_requires_for_build_wheel(self, config_settings=None): - """Get additional dependencies required for building a wheel. - - :returns: A list of :pep:`dependency specifiers <508>`. - :rtype: list[str] - - .. admonition:: Fallback - - If the build backend does not defined a hook with this name, an - empty list will be returned. - """ - return self._call_hook('get_requires_for_build_wheel', { - 'config_settings': config_settings - }) - - def prepare_metadata_for_build_wheel( - self, metadata_directory, config_settings=None, - _allow_fallback=True): - """Prepare a ``*.dist-info`` folder with metadata for this project. - - :returns: Name of the newly created subfolder within - ``metadata_directory``, containing the metadata. - :rtype: str - - .. admonition:: Fallback - - If the build backend does not define a hook with this name and - ``_allow_fallback`` is truthy, the backend will be asked to build a - wheel via the ``build_wheel`` hook and the dist-info extracted from - that will be returned. - """ - return self._call_hook('prepare_metadata_for_build_wheel', { - 'metadata_directory': abspath(metadata_directory), - 'config_settings': config_settings, - '_allow_fallback': _allow_fallback, - }) - - def build_wheel( - self, wheel_directory, config_settings=None, - metadata_directory=None): - """Build a wheel from this project. - - :returns: - The name of the newly created wheel within ``wheel_directory``. - - .. admonition:: Interaction with fallback - - If the ``build_wheel`` hook was called in the fallback for - :meth:`prepare_metadata_for_build_wheel`, the build backend would - not be invoked. Instead, the previously built wheel will be copied - to ``wheel_directory`` and the name of that file will be returned. - """ - if metadata_directory is not None: - metadata_directory = abspath(metadata_directory) - return self._call_hook('build_wheel', { - 'wheel_directory': abspath(wheel_directory), - 'config_settings': config_settings, - 'metadata_directory': metadata_directory, - }) - - def get_requires_for_build_editable(self, config_settings=None): - """Get additional dependencies required for building an editable wheel. - - :returns: A list of :pep:`dependency specifiers <508>`. - :rtype: list[str] - - .. admonition:: Fallback - - If the build backend does not defined a hook with this name, an - empty list will be returned. - """ - return self._call_hook('get_requires_for_build_editable', { - 'config_settings': config_settings - }) - - def prepare_metadata_for_build_editable( - self, metadata_directory, config_settings=None, - _allow_fallback=True): - """Prepare a ``*.dist-info`` folder with metadata for this project. - - :returns: Name of the newly created subfolder within - ``metadata_directory``, containing the metadata. - :rtype: str - - .. admonition:: Fallback - - If the build backend does not define a hook with this name and - ``_allow_fallback`` is truthy, the backend will be asked to build a - wheel via the ``build_editable`` hook and the dist-info - extracted from that will be returned. - """ - return self._call_hook('prepare_metadata_for_build_editable', { - 'metadata_directory': abspath(metadata_directory), - 'config_settings': config_settings, - '_allow_fallback': _allow_fallback, - }) - - def build_editable( - self, wheel_directory, config_settings=None, - metadata_directory=None): - """Build an editable wheel from this project. - - :returns: - The name of the newly created wheel within ``wheel_directory``. - - .. admonition:: Interaction with fallback - - If the ``build_editable`` hook was called in the fallback for - :meth:`prepare_metadata_for_build_editable`, the build backend - would not be invoked. Instead, the previously built wheel will be - copied to ``wheel_directory`` and the name of that file will be - returned. - """ - if metadata_directory is not None: - metadata_directory = abspath(metadata_directory) - return self._call_hook('build_editable', { - 'wheel_directory': abspath(wheel_directory), - 'config_settings': config_settings, - 'metadata_directory': metadata_directory, - }) - - def get_requires_for_build_sdist(self, config_settings=None): - """Get additional dependencies required for building an sdist. - - :returns: A list of :pep:`dependency specifiers <508>`. - :rtype: list[str] - """ - return self._call_hook('get_requires_for_build_sdist', { - 'config_settings': config_settings - }) - - def build_sdist(self, sdist_directory, config_settings=None): - """Build an sdist from this project. - - :returns: - The name of the newly created sdist within ``wheel_directory``. - """ - return self._call_hook('build_sdist', { - 'sdist_directory': abspath(sdist_directory), - 'config_settings': config_settings, - }) - - def _call_hook(self, hook_name, kwargs): - extra_environ = {'PEP517_BUILD_BACKEND': self.build_backend} - - if self.backend_path: - backend_path = os.pathsep.join(self.backend_path) - extra_environ['PEP517_BACKEND_PATH'] = backend_path - - with tempfile.TemporaryDirectory() as td: - hook_input = {'kwargs': kwargs} - write_json(hook_input, pjoin(td, 'input.json'), indent=2) - - # Run the hook in a subprocess - with _in_proc_script_path() as script: - python = self.python_executable - self._subprocess_runner( - [python, abspath(str(script)), hook_name, td], - cwd=self.source_dir, - extra_environ=extra_environ - ) - - data = read_json(pjoin(td, 'output.json')) - if data.get('unsupported'): - raise UnsupportedOperation(data.get('traceback', '')) - if data.get('no_backend'): - raise BackendUnavailable(data.get('traceback', '')) - if data.get('backend_invalid'): - raise BackendInvalid( - backend_name=self.build_backend, - backend_path=self.backend_path, - message=data.get('backend_error', '') - ) - if data.get('hook_missing'): - raise HookMissing(data.get('missing_hook_name') or hook_name) - return data['return_val'] diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py deleted file mode 100644 index 917fa06..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -"""This is a subpackage because the directory is on sys.path for _in_process.py - -The subpackage should stay as empty as possible to avoid shadowing modules that -the backend might import. -""" - -import importlib.resources as resources - -try: - resources.files -except AttributeError: - # Python 3.8 compatibility - def _in_proc_script_path(): - return resources.path(__package__, '_in_process.py') -else: - def _in_proc_script_path(): - return resources.as_file( - resources.files(__package__).joinpath('_in_process.py')) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 14cf045..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc deleted file mode 100644 index 5bf4978..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py deleted file mode 100644 index ee511ff..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py +++ /dev/null @@ -1,353 +0,0 @@ -"""This is invoked in a subprocess to call the build backend hooks. - -It expects: -- Command line args: hook_name, control_dir -- Environment variables: - PEP517_BUILD_BACKEND=entry.point:spec - PEP517_BACKEND_PATH=paths (separated with os.pathsep) -- control_dir/input.json: - - {"kwargs": {...}} - -Results: -- control_dir/output.json - - {"return_val": ...} -""" -import json -import os -import os.path -import re -import shutil -import sys -import traceback -from glob import glob -from importlib import import_module -from os.path import join as pjoin - -# This file is run as a script, and `import wrappers` is not zip-safe, so we -# include write_json() and read_json() from wrappers.py. - - -def write_json(obj, path, **kwargs): - with open(path, 'w', encoding='utf-8') as f: - json.dump(obj, f, **kwargs) - - -def read_json(path): - with open(path, encoding='utf-8') as f: - return json.load(f) - - -class BackendUnavailable(Exception): - """Raised if we cannot import the backend""" - def __init__(self, traceback): - self.traceback = traceback - - -class BackendInvalid(Exception): - """Raised if the backend is invalid""" - def __init__(self, message): - self.message = message - - -class HookMissing(Exception): - """Raised if a hook is missing and we are not executing the fallback""" - def __init__(self, hook_name=None): - super().__init__(hook_name) - self.hook_name = hook_name - - -def contained_in(filename, directory): - """Test if a file is located within the given directory.""" - filename = os.path.normcase(os.path.abspath(filename)) - directory = os.path.normcase(os.path.abspath(directory)) - return os.path.commonprefix([filename, directory]) == directory - - -def _build_backend(): - """Find and load the build backend""" - # Add in-tree backend directories to the front of sys.path. - backend_path = os.environ.get('PEP517_BACKEND_PATH') - if backend_path: - extra_pathitems = backend_path.split(os.pathsep) - sys.path[:0] = extra_pathitems - - ep = os.environ['PEP517_BUILD_BACKEND'] - mod_path, _, obj_path = ep.partition(':') - try: - obj = import_module(mod_path) - except ImportError: - raise BackendUnavailable(traceback.format_exc()) - - if backend_path: - if not any( - contained_in(obj.__file__, path) - for path in extra_pathitems - ): - raise BackendInvalid("Backend was not loaded from backend-path") - - if obj_path: - for path_part in obj_path.split('.'): - obj = getattr(obj, path_part) - return obj - - -def _supported_features(): - """Return the list of options features supported by the backend. - - Returns a list of strings. - The only possible value is 'build_editable'. - """ - backend = _build_backend() - features = [] - if hasattr(backend, "build_editable"): - features.append("build_editable") - return features - - -def get_requires_for_build_wheel(config_settings): - """Invoke the optional get_requires_for_build_wheel hook - - Returns [] if the hook is not defined. - """ - backend = _build_backend() - try: - hook = backend.get_requires_for_build_wheel - except AttributeError: - return [] - else: - return hook(config_settings) - - -def get_requires_for_build_editable(config_settings): - """Invoke the optional get_requires_for_build_editable hook - - Returns [] if the hook is not defined. - """ - backend = _build_backend() - try: - hook = backend.get_requires_for_build_editable - except AttributeError: - return [] - else: - return hook(config_settings) - - -def prepare_metadata_for_build_wheel( - metadata_directory, config_settings, _allow_fallback): - """Invoke optional prepare_metadata_for_build_wheel - - Implements a fallback by building a wheel if the hook isn't defined, - unless _allow_fallback is False in which case HookMissing is raised. - """ - backend = _build_backend() - try: - hook = backend.prepare_metadata_for_build_wheel - except AttributeError: - if not _allow_fallback: - raise HookMissing() - else: - return hook(metadata_directory, config_settings) - # fallback to build_wheel outside the try block to avoid exception chaining - # which can be confusing to users and is not relevant - whl_basename = backend.build_wheel(metadata_directory, config_settings) - return _get_wheel_metadata_from_wheel(whl_basename, metadata_directory, - config_settings) - - -def prepare_metadata_for_build_editable( - metadata_directory, config_settings, _allow_fallback): - """Invoke optional prepare_metadata_for_build_editable - - Implements a fallback by building an editable wheel if the hook isn't - defined, unless _allow_fallback is False in which case HookMissing is - raised. - """ - backend = _build_backend() - try: - hook = backend.prepare_metadata_for_build_editable - except AttributeError: - if not _allow_fallback: - raise HookMissing() - try: - build_hook = backend.build_editable - except AttributeError: - raise HookMissing(hook_name='build_editable') - else: - whl_basename = build_hook(metadata_directory, config_settings) - return _get_wheel_metadata_from_wheel(whl_basename, - metadata_directory, - config_settings) - else: - return hook(metadata_directory, config_settings) - - -WHEEL_BUILT_MARKER = 'PEP517_ALREADY_BUILT_WHEEL' - - -def _dist_info_files(whl_zip): - """Identify the .dist-info folder inside a wheel ZipFile.""" - res = [] - for path in whl_zip.namelist(): - m = re.match(r'[^/\\]+-[^/\\]+\.dist-info/', path) - if m: - res.append(path) - if res: - return res - raise Exception("No .dist-info folder found in wheel") - - -def _get_wheel_metadata_from_wheel( - whl_basename, metadata_directory, config_settings): - """Extract the metadata from a wheel. - - Fallback for when the build backend does not - define the 'get_wheel_metadata' hook. - """ - from zipfile import ZipFile - with open(os.path.join(metadata_directory, WHEEL_BUILT_MARKER), 'wb'): - pass # Touch marker file - - whl_file = os.path.join(metadata_directory, whl_basename) - with ZipFile(whl_file) as zipf: - dist_info = _dist_info_files(zipf) - zipf.extractall(path=metadata_directory, members=dist_info) - return dist_info[0].split('/')[0] - - -def _find_already_built_wheel(metadata_directory): - """Check for a wheel already built during the get_wheel_metadata hook. - """ - if not metadata_directory: - return None - metadata_parent = os.path.dirname(metadata_directory) - if not os.path.isfile(pjoin(metadata_parent, WHEEL_BUILT_MARKER)): - return None - - whl_files = glob(os.path.join(metadata_parent, '*.whl')) - if not whl_files: - print('Found wheel built marker, but no .whl files') - return None - if len(whl_files) > 1: - print('Found multiple .whl files; unspecified behaviour. ' - 'Will call build_wheel.') - return None - - # Exactly one .whl file - return whl_files[0] - - -def build_wheel(wheel_directory, config_settings, metadata_directory=None): - """Invoke the mandatory build_wheel hook. - - If a wheel was already built in the - prepare_metadata_for_build_wheel fallback, this - will copy it rather than rebuilding the wheel. - """ - prebuilt_whl = _find_already_built_wheel(metadata_directory) - if prebuilt_whl: - shutil.copy2(prebuilt_whl, wheel_directory) - return os.path.basename(prebuilt_whl) - - return _build_backend().build_wheel(wheel_directory, config_settings, - metadata_directory) - - -def build_editable(wheel_directory, config_settings, metadata_directory=None): - """Invoke the optional build_editable hook. - - If a wheel was already built in the - prepare_metadata_for_build_editable fallback, this - will copy it rather than rebuilding the wheel. - """ - backend = _build_backend() - try: - hook = backend.build_editable - except AttributeError: - raise HookMissing() - else: - prebuilt_whl = _find_already_built_wheel(metadata_directory) - if prebuilt_whl: - shutil.copy2(prebuilt_whl, wheel_directory) - return os.path.basename(prebuilt_whl) - - return hook(wheel_directory, config_settings, metadata_directory) - - -def get_requires_for_build_sdist(config_settings): - """Invoke the optional get_requires_for_build_wheel hook - - Returns [] if the hook is not defined. - """ - backend = _build_backend() - try: - hook = backend.get_requires_for_build_sdist - except AttributeError: - return [] - else: - return hook(config_settings) - - -class _DummyException(Exception): - """Nothing should ever raise this exception""" - - -class GotUnsupportedOperation(Exception): - """For internal use when backend raises UnsupportedOperation""" - def __init__(self, traceback): - self.traceback = traceback - - -def build_sdist(sdist_directory, config_settings): - """Invoke the mandatory build_sdist hook.""" - backend = _build_backend() - try: - return backend.build_sdist(sdist_directory, config_settings) - except getattr(backend, 'UnsupportedOperation', _DummyException): - raise GotUnsupportedOperation(traceback.format_exc()) - - -HOOK_NAMES = { - 'get_requires_for_build_wheel', - 'prepare_metadata_for_build_wheel', - 'build_wheel', - 'get_requires_for_build_editable', - 'prepare_metadata_for_build_editable', - 'build_editable', - 'get_requires_for_build_sdist', - 'build_sdist', - '_supported_features', -} - - -def main(): - if len(sys.argv) < 3: - sys.exit("Needs args: hook_name, control_dir") - hook_name = sys.argv[1] - control_dir = sys.argv[2] - if hook_name not in HOOK_NAMES: - sys.exit("Unknown hook: %s" % hook_name) - hook = globals()[hook_name] - - hook_input = read_json(pjoin(control_dir, 'input.json')) - - json_out = {'unsupported': False, 'return_val': None} - try: - json_out['return_val'] = hook(**hook_input['kwargs']) - except BackendUnavailable as e: - json_out['no_backend'] = True - json_out['traceback'] = e.traceback - except BackendInvalid as e: - json_out['backend_invalid'] = True - json_out['backend_error'] = e.message - except GotUnsupportedOperation as e: - json_out['unsupported'] = True - json_out['traceback'] = e.traceback - except HookMissing as e: - json_out['hook_missing'] = True - json_out['missing_hook_name'] = e.hook_name or hook_name - - write_json(json_out, pjoin(control_dir, 'output.json'), indent=2) - - -if __name__ == '__main__': - main() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py deleted file mode 100644 index 10ff67f..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py +++ /dev/null @@ -1,182 +0,0 @@ -# __ -# /__) _ _ _ _ _/ _ -# / ( (- (/ (/ (- _) / _) -# / - -""" -Requests HTTP Library -~~~~~~~~~~~~~~~~~~~~~ - -Requests is an HTTP library, written in Python, for human beings. -Basic GET usage: - - >>> import requests - >>> r = requests.get('https://www.python.org') - >>> r.status_code - 200 - >>> b'Python is a programming language' in r.content - True - -... or POST: - - >>> payload = dict(key1='value1', key2='value2') - >>> r = requests.post('https://httpbin.org/post', data=payload) - >>> print(r.text) - { - ... - "form": { - "key1": "value1", - "key2": "value2" - }, - ... - } - -The other HTTP methods are supported - see `requests.api`. Full documentation -is at . - -:copyright: (c) 2017 by Kenneth Reitz. -:license: Apache 2.0, see LICENSE for more details. -""" - -import warnings - -from pip._vendor import urllib3 - -from .exceptions import RequestsDependencyWarning - -charset_normalizer_version = None - -try: - from pip._vendor.chardet import __version__ as chardet_version -except ImportError: - chardet_version = None - - -def check_compatibility(urllib3_version, chardet_version, charset_normalizer_version): - urllib3_version = urllib3_version.split(".") - assert urllib3_version != ["dev"] # Verify urllib3 isn't installed from git. - - # Sometimes, urllib3 only reports its version as 16.1. - if len(urllib3_version) == 2: - urllib3_version.append("0") - - # Check urllib3 for compatibility. - major, minor, patch = urllib3_version # noqa: F811 - major, minor, patch = int(major), int(minor), int(patch) - # urllib3 >= 1.21.1 - assert major >= 1 - if major == 1: - assert minor >= 21 - - # Check charset_normalizer for compatibility. - if chardet_version: - major, minor, patch = chardet_version.split(".")[:3] - major, minor, patch = int(major), int(minor), int(patch) - # chardet_version >= 3.0.2, < 6.0.0 - assert (3, 0, 2) <= (major, minor, patch) < (6, 0, 0) - elif charset_normalizer_version: - major, minor, patch = charset_normalizer_version.split(".")[:3] - major, minor, patch = int(major), int(minor), int(patch) - # charset_normalizer >= 2.0.0 < 4.0.0 - assert (2, 0, 0) <= (major, minor, patch) < (4, 0, 0) - else: - raise Exception("You need either charset_normalizer or chardet installed") - - -def _check_cryptography(cryptography_version): - # cryptography < 1.3.4 - try: - cryptography_version = list(map(int, cryptography_version.split("."))) - except ValueError: - return - - if cryptography_version < [1, 3, 4]: - warning = "Old version of cryptography ({}) may cause slowdown.".format( - cryptography_version - ) - warnings.warn(warning, RequestsDependencyWarning) - - -# Check imported dependencies for compatibility. -try: - check_compatibility( - urllib3.__version__, chardet_version, charset_normalizer_version - ) -except (AssertionError, ValueError): - warnings.warn( - "urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported " - "version!".format( - urllib3.__version__, chardet_version, charset_normalizer_version - ), - RequestsDependencyWarning, - ) - -# Attempt to enable urllib3's fallback for SNI support -# if the standard library doesn't support SNI or the -# 'ssl' library isn't available. -try: - # Note: This logic prevents upgrading cryptography on Windows, if imported - # as part of pip. - from pip._internal.utils.compat import WINDOWS - if not WINDOWS: - raise ImportError("pip internals: don't import cryptography on Windows") - try: - import ssl - except ImportError: - ssl = None - - if not getattr(ssl, "HAS_SNI", False): - from pip._vendor.urllib3.contrib import pyopenssl - - pyopenssl.inject_into_urllib3() - - # Check cryptography version - from cryptography import __version__ as cryptography_version - - _check_cryptography(cryptography_version) -except ImportError: - pass - -# urllib3's DependencyWarnings should be silenced. -from pip._vendor.urllib3.exceptions import DependencyWarning - -warnings.simplefilter("ignore", DependencyWarning) - -# Set default logging handler to avoid "No handler found" warnings. -import logging -from logging import NullHandler - -from . import packages, utils -from .__version__ import ( - __author__, - __author_email__, - __build__, - __cake__, - __copyright__, - __description__, - __license__, - __title__, - __url__, - __version__, -) -from .api import delete, get, head, options, patch, post, put, request -from .exceptions import ( - ConnectionError, - ConnectTimeout, - FileModeWarning, - HTTPError, - JSONDecodeError, - ReadTimeout, - RequestException, - Timeout, - TooManyRedirects, - URLRequired, -) -from .models import PreparedRequest, Request, Response -from .sessions import Session, session -from .status_codes import codes - -logging.getLogger(__name__).addHandler(NullHandler()) - -# FileModeWarnings go off per the default. -warnings.simplefilter("default", FileModeWarning, append=True) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 06c7a7c..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc deleted file mode 100644 index 22dc772..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc deleted file mode 100644 index 5592e88..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc deleted file mode 100644 index 9db4373..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc deleted file mode 100644 index f138db6..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc deleted file mode 100644 index 1458c0d..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc deleted file mode 100644 index 2acfb2e..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc deleted file mode 100644 index 8d35cc4..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc deleted file mode 100644 index 4067289..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc deleted file mode 100644 index bdfd4ba..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc deleted file mode 100644 index dc59b24..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc deleted file mode 100644 index af0a09e..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc deleted file mode 100644 index f52b691..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc deleted file mode 100644 index f0ab9e2..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc deleted file mode 100644 index 6f6646f..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc deleted file mode 100644 index 1eeb5a0..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc deleted file mode 100644 index f6e267c..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index 00640be..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py deleted file mode 100644 index 5063c3f..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py +++ /dev/null @@ -1,14 +0,0 @@ -# .-. .-. .-. . . .-. .-. .-. .-. -# |( |- |.| | | |- `-. | `-. -# ' ' `-' `-`.`-' `-' `-' ' `-' - -__title__ = "requests" -__description__ = "Python HTTP for Humans." -__url__ = "https://requests.readthedocs.io" -__version__ = "2.31.0" -__build__ = 0x023100 -__author__ = "Kenneth Reitz" -__author_email__ = "me@kennethreitz.org" -__license__ = "Apache 2.0" -__copyright__ = "Copyright Kenneth Reitz" -__cake__ = "\u2728 \U0001f370 \u2728" diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py deleted file mode 100644 index f2cf635..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -requests._internal_utils -~~~~~~~~~~~~~~ - -Provides utility functions that are consumed internally by Requests -which depend on extremely few external helpers (such as compat) -""" -import re - -from .compat import builtin_str - -_VALID_HEADER_NAME_RE_BYTE = re.compile(rb"^[^:\s][^:\r\n]*$") -_VALID_HEADER_NAME_RE_STR = re.compile(r"^[^:\s][^:\r\n]*$") -_VALID_HEADER_VALUE_RE_BYTE = re.compile(rb"^\S[^\r\n]*$|^$") -_VALID_HEADER_VALUE_RE_STR = re.compile(r"^\S[^\r\n]*$|^$") - -_HEADER_VALIDATORS_STR = (_VALID_HEADER_NAME_RE_STR, _VALID_HEADER_VALUE_RE_STR) -_HEADER_VALIDATORS_BYTE = (_VALID_HEADER_NAME_RE_BYTE, _VALID_HEADER_VALUE_RE_BYTE) -HEADER_VALIDATORS = { - bytes: _HEADER_VALIDATORS_BYTE, - str: _HEADER_VALIDATORS_STR, -} - - -def to_native_string(string, encoding="ascii"): - """Given a string object, regardless of type, returns a representation of - that string in the native string type, encoding and decoding where - necessary. This assumes ASCII unless told otherwise. - """ - if isinstance(string, builtin_str): - out = string - else: - out = string.decode(encoding) - - return out - - -def unicode_is_ascii(u_string): - """Determine if unicode string only contains ASCII characters. - - :param str u_string: unicode string to check. Must be unicode - and not Python 2 `str`. - :rtype: bool - """ - assert isinstance(u_string, str) - try: - u_string.encode("ascii") - return True - except UnicodeEncodeError: - return False diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py deleted file mode 100644 index 10c1767..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py +++ /dev/null @@ -1,538 +0,0 @@ -""" -requests.adapters -~~~~~~~~~~~~~~~~~ - -This module contains the transport adapters that Requests uses to define -and maintain connections. -""" - -import os.path -import socket # noqa: F401 - -from pip._vendor.urllib3.exceptions import ClosedPoolError, ConnectTimeoutError -from pip._vendor.urllib3.exceptions import HTTPError as _HTTPError -from pip._vendor.urllib3.exceptions import InvalidHeader as _InvalidHeader -from pip._vendor.urllib3.exceptions import ( - LocationValueError, - MaxRetryError, - NewConnectionError, - ProtocolError, -) -from pip._vendor.urllib3.exceptions import ProxyError as _ProxyError -from pip._vendor.urllib3.exceptions import ReadTimeoutError, ResponseError -from pip._vendor.urllib3.exceptions import SSLError as _SSLError -from pip._vendor.urllib3.poolmanager import PoolManager, proxy_from_url -from pip._vendor.urllib3.util import Timeout as TimeoutSauce -from pip._vendor.urllib3.util import parse_url -from pip._vendor.urllib3.util.retry import Retry - -from .auth import _basic_auth_str -from .compat import basestring, urlparse -from .cookies import extract_cookies_to_jar -from .exceptions import ( - ConnectionError, - ConnectTimeout, - InvalidHeader, - InvalidProxyURL, - InvalidSchema, - InvalidURL, - ProxyError, - ReadTimeout, - RetryError, - SSLError, -) -from .models import Response -from .structures import CaseInsensitiveDict -from .utils import ( - DEFAULT_CA_BUNDLE_PATH, - extract_zipped_paths, - get_auth_from_url, - get_encoding_from_headers, - prepend_scheme_if_needed, - select_proxy, - urldefragauth, -) - -try: - from pip._vendor.urllib3.contrib.socks import SOCKSProxyManager -except ImportError: - - def SOCKSProxyManager(*args, **kwargs): - raise InvalidSchema("Missing dependencies for SOCKS support.") - - -DEFAULT_POOLBLOCK = False -DEFAULT_POOLSIZE = 10 -DEFAULT_RETRIES = 0 -DEFAULT_POOL_TIMEOUT = None - - -class BaseAdapter: - """The Base Transport Adapter""" - - def __init__(self): - super().__init__() - - def send( - self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None - ): - """Sends PreparedRequest object. Returns Response object. - - :param request: The :class:`PreparedRequest ` being sent. - :param stream: (optional) Whether to stream the request content. - :param timeout: (optional) How long to wait for the server to send - data before giving up, as a float, or a :ref:`(connect timeout, - read timeout) ` tuple. - :type timeout: float or tuple - :param verify: (optional) Either a boolean, in which case it controls whether we verify - the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use - :param cert: (optional) Any user-provided SSL certificate to be trusted. - :param proxies: (optional) The proxies dictionary to apply to the request. - """ - raise NotImplementedError - - def close(self): - """Cleans up adapter specific items.""" - raise NotImplementedError - - -class HTTPAdapter(BaseAdapter): - """The built-in HTTP Adapter for urllib3. - - Provides a general-case interface for Requests sessions to contact HTTP and - HTTPS urls by implementing the Transport Adapter interface. This class will - usually be created by the :class:`Session ` class under the - covers. - - :param pool_connections: The number of urllib3 connection pools to cache. - :param pool_maxsize: The maximum number of connections to save in the pool. - :param max_retries: The maximum number of retries each connection - should attempt. Note, this applies only to failed DNS lookups, socket - connections and connection timeouts, never to requests where data has - made it to the server. By default, Requests does not retry failed - connections. If you need granular control over the conditions under - which we retry a request, import urllib3's ``Retry`` class and pass - that instead. - :param pool_block: Whether the connection pool should block for connections. - - Usage:: - - >>> import requests - >>> s = requests.Session() - >>> a = requests.adapters.HTTPAdapter(max_retries=3) - >>> s.mount('http://', a) - """ - - __attrs__ = [ - "max_retries", - "config", - "_pool_connections", - "_pool_maxsize", - "_pool_block", - ] - - def __init__( - self, - pool_connections=DEFAULT_POOLSIZE, - pool_maxsize=DEFAULT_POOLSIZE, - max_retries=DEFAULT_RETRIES, - pool_block=DEFAULT_POOLBLOCK, - ): - if max_retries == DEFAULT_RETRIES: - self.max_retries = Retry(0, read=False) - else: - self.max_retries = Retry.from_int(max_retries) - self.config = {} - self.proxy_manager = {} - - super().__init__() - - self._pool_connections = pool_connections - self._pool_maxsize = pool_maxsize - self._pool_block = pool_block - - self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) - - def __getstate__(self): - return {attr: getattr(self, attr, None) for attr in self.__attrs__} - - def __setstate__(self, state): - # Can't handle by adding 'proxy_manager' to self.__attrs__ because - # self.poolmanager uses a lambda function, which isn't pickleable. - self.proxy_manager = {} - self.config = {} - - for attr, value in state.items(): - setattr(self, attr, value) - - self.init_poolmanager( - self._pool_connections, self._pool_maxsize, block=self._pool_block - ) - - def init_poolmanager( - self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs - ): - """Initializes a urllib3 PoolManager. - - This method should not be called from user code, and is only - exposed for use when subclassing the - :class:`HTTPAdapter `. - - :param connections: The number of urllib3 connection pools to cache. - :param maxsize: The maximum number of connections to save in the pool. - :param block: Block when no free connections are available. - :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager. - """ - # save these values for pickling - self._pool_connections = connections - self._pool_maxsize = maxsize - self._pool_block = block - - self.poolmanager = PoolManager( - num_pools=connections, - maxsize=maxsize, - block=block, - **pool_kwargs, - ) - - def proxy_manager_for(self, proxy, **proxy_kwargs): - """Return urllib3 ProxyManager for the given proxy. - - This method should not be called from user code, and is only - exposed for use when subclassing the - :class:`HTTPAdapter `. - - :param proxy: The proxy to return a urllib3 ProxyManager for. - :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager. - :returns: ProxyManager - :rtype: urllib3.ProxyManager - """ - if proxy in self.proxy_manager: - manager = self.proxy_manager[proxy] - elif proxy.lower().startswith("socks"): - username, password = get_auth_from_url(proxy) - manager = self.proxy_manager[proxy] = SOCKSProxyManager( - proxy, - username=username, - password=password, - num_pools=self._pool_connections, - maxsize=self._pool_maxsize, - block=self._pool_block, - **proxy_kwargs, - ) - else: - proxy_headers = self.proxy_headers(proxy) - manager = self.proxy_manager[proxy] = proxy_from_url( - proxy, - proxy_headers=proxy_headers, - num_pools=self._pool_connections, - maxsize=self._pool_maxsize, - block=self._pool_block, - **proxy_kwargs, - ) - - return manager - - def cert_verify(self, conn, url, verify, cert): - """Verify a SSL certificate. This method should not be called from user - code, and is only exposed for use when subclassing the - :class:`HTTPAdapter `. - - :param conn: The urllib3 connection object associated with the cert. - :param url: The requested URL. - :param verify: Either a boolean, in which case it controls whether we verify - the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use - :param cert: The SSL certificate to verify. - """ - if url.lower().startswith("https") and verify: - - cert_loc = None - - # Allow self-specified cert location. - if verify is not True: - cert_loc = verify - - if not cert_loc: - cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH) - - if not cert_loc or not os.path.exists(cert_loc): - raise OSError( - f"Could not find a suitable TLS CA certificate bundle, " - f"invalid path: {cert_loc}" - ) - - conn.cert_reqs = "CERT_REQUIRED" - - if not os.path.isdir(cert_loc): - conn.ca_certs = cert_loc - else: - conn.ca_cert_dir = cert_loc - else: - conn.cert_reqs = "CERT_NONE" - conn.ca_certs = None - conn.ca_cert_dir = None - - if cert: - if not isinstance(cert, basestring): - conn.cert_file = cert[0] - conn.key_file = cert[1] - else: - conn.cert_file = cert - conn.key_file = None - if conn.cert_file and not os.path.exists(conn.cert_file): - raise OSError( - f"Could not find the TLS certificate file, " - f"invalid path: {conn.cert_file}" - ) - if conn.key_file and not os.path.exists(conn.key_file): - raise OSError( - f"Could not find the TLS key file, invalid path: {conn.key_file}" - ) - - def build_response(self, req, resp): - """Builds a :class:`Response ` object from a urllib3 - response. This should not be called from user code, and is only exposed - for use when subclassing the - :class:`HTTPAdapter ` - - :param req: The :class:`PreparedRequest ` used to generate the response. - :param resp: The urllib3 response object. - :rtype: requests.Response - """ - response = Response() - - # Fallback to None if there's no status_code, for whatever reason. - response.status_code = getattr(resp, "status", None) - - # Make headers case-insensitive. - response.headers = CaseInsensitiveDict(getattr(resp, "headers", {})) - - # Set encoding. - response.encoding = get_encoding_from_headers(response.headers) - response.raw = resp - response.reason = response.raw.reason - - if isinstance(req.url, bytes): - response.url = req.url.decode("utf-8") - else: - response.url = req.url - - # Add new cookies from the server. - extract_cookies_to_jar(response.cookies, req, resp) - - # Give the Response some context. - response.request = req - response.connection = self - - return response - - def get_connection(self, url, proxies=None): - """Returns a urllib3 connection for the given URL. This should not be - called from user code, and is only exposed for use when subclassing the - :class:`HTTPAdapter `. - - :param url: The URL to connect to. - :param proxies: (optional) A Requests-style dictionary of proxies used on this request. - :rtype: urllib3.ConnectionPool - """ - proxy = select_proxy(url, proxies) - - if proxy: - proxy = prepend_scheme_if_needed(proxy, "http") - proxy_url = parse_url(proxy) - if not proxy_url.host: - raise InvalidProxyURL( - "Please check proxy URL. It is malformed " - "and could be missing the host." - ) - proxy_manager = self.proxy_manager_for(proxy) - conn = proxy_manager.connection_from_url(url) - else: - # Only scheme should be lower case - parsed = urlparse(url) - url = parsed.geturl() - conn = self.poolmanager.connection_from_url(url) - - return conn - - def close(self): - """Disposes of any internal state. - - Currently, this closes the PoolManager and any active ProxyManager, - which closes any pooled connections. - """ - self.poolmanager.clear() - for proxy in self.proxy_manager.values(): - proxy.clear() - - def request_url(self, request, proxies): - """Obtain the url to use when making the final request. - - If the message is being sent through a HTTP proxy, the full URL has to - be used. Otherwise, we should only use the path portion of the URL. - - This should not be called from user code, and is only exposed for use - when subclassing the - :class:`HTTPAdapter `. - - :param request: The :class:`PreparedRequest ` being sent. - :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs. - :rtype: str - """ - proxy = select_proxy(request.url, proxies) - scheme = urlparse(request.url).scheme - - is_proxied_http_request = proxy and scheme != "https" - using_socks_proxy = False - if proxy: - proxy_scheme = urlparse(proxy).scheme.lower() - using_socks_proxy = proxy_scheme.startswith("socks") - - url = request.path_url - if is_proxied_http_request and not using_socks_proxy: - url = urldefragauth(request.url) - - return url - - def add_headers(self, request, **kwargs): - """Add any headers needed by the connection. As of v2.0 this does - nothing by default, but is left for overriding by users that subclass - the :class:`HTTPAdapter `. - - This should not be called from user code, and is only exposed for use - when subclassing the - :class:`HTTPAdapter `. - - :param request: The :class:`PreparedRequest ` to add headers to. - :param kwargs: The keyword arguments from the call to send(). - """ - pass - - def proxy_headers(self, proxy): - """Returns a dictionary of the headers to add to any request sent - through a proxy. This works with urllib3 magic to ensure that they are - correctly sent to the proxy, rather than in a tunnelled request if - CONNECT is being used. - - This should not be called from user code, and is only exposed for use - when subclassing the - :class:`HTTPAdapter `. - - :param proxy: The url of the proxy being used for this request. - :rtype: dict - """ - headers = {} - username, password = get_auth_from_url(proxy) - - if username: - headers["Proxy-Authorization"] = _basic_auth_str(username, password) - - return headers - - def send( - self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None - ): - """Sends PreparedRequest object. Returns Response object. - - :param request: The :class:`PreparedRequest ` being sent. - :param stream: (optional) Whether to stream the request content. - :param timeout: (optional) How long to wait for the server to send - data before giving up, as a float, or a :ref:`(connect timeout, - read timeout) ` tuple. - :type timeout: float or tuple or urllib3 Timeout object - :param verify: (optional) Either a boolean, in which case it controls whether - we verify the server's TLS certificate, or a string, in which case it - must be a path to a CA bundle to use - :param cert: (optional) Any user-provided SSL certificate to be trusted. - :param proxies: (optional) The proxies dictionary to apply to the request. - :rtype: requests.Response - """ - - try: - conn = self.get_connection(request.url, proxies) - except LocationValueError as e: - raise InvalidURL(e, request=request) - - self.cert_verify(conn, request.url, verify, cert) - url = self.request_url(request, proxies) - self.add_headers( - request, - stream=stream, - timeout=timeout, - verify=verify, - cert=cert, - proxies=proxies, - ) - - chunked = not (request.body is None or "Content-Length" in request.headers) - - if isinstance(timeout, tuple): - try: - connect, read = timeout - timeout = TimeoutSauce(connect=connect, read=read) - except ValueError: - raise ValueError( - f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " - f"or a single float to set both timeouts to the same value." - ) - elif isinstance(timeout, TimeoutSauce): - pass - else: - timeout = TimeoutSauce(connect=timeout, read=timeout) - - try: - resp = conn.urlopen( - method=request.method, - url=url, - body=request.body, - headers=request.headers, - redirect=False, - assert_same_host=False, - preload_content=False, - decode_content=False, - retries=self.max_retries, - timeout=timeout, - chunked=chunked, - ) - - except (ProtocolError, OSError) as err: - raise ConnectionError(err, request=request) - - except MaxRetryError as e: - if isinstance(e.reason, ConnectTimeoutError): - # TODO: Remove this in 3.0.0: see #2811 - if not isinstance(e.reason, NewConnectionError): - raise ConnectTimeout(e, request=request) - - if isinstance(e.reason, ResponseError): - raise RetryError(e, request=request) - - if isinstance(e.reason, _ProxyError): - raise ProxyError(e, request=request) - - if isinstance(e.reason, _SSLError): - # This branch is for urllib3 v1.22 and later. - raise SSLError(e, request=request) - - raise ConnectionError(e, request=request) - - except ClosedPoolError as e: - raise ConnectionError(e, request=request) - - except _ProxyError as e: - raise ProxyError(e) - - except (_SSLError, _HTTPError) as e: - if isinstance(e, _SSLError): - # This branch is for urllib3 versions earlier than v1.22 - raise SSLError(e, request=request) - elif isinstance(e, ReadTimeoutError): - raise ReadTimeout(e, request=request) - elif isinstance(e, _InvalidHeader): - raise InvalidHeader(e, request=request) - else: - raise - - return self.build_response(request, resp) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/api.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/api.py deleted file mode 100644 index cd0b3ee..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/api.py +++ /dev/null @@ -1,157 +0,0 @@ -""" -requests.api -~~~~~~~~~~~~ - -This module implements the Requests API. - -:copyright: (c) 2012 by Kenneth Reitz. -:license: Apache2, see LICENSE for more details. -""" - -from . import sessions - - -def request(method, url, **kwargs): - """Constructs and sends a :class:`Request `. - - :param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``. - :param url: URL for the new :class:`Request` object. - :param params: (optional) Dictionary, list of tuples or bytes to send - in the query string for the :class:`Request`. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. - :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. - :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. - :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload. - ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` - or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string - defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers - to add for the file. - :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. - :param timeout: (optional) How many seconds to wait for the server to send data - before giving up, as a float, or a :ref:`(connect timeout, read - timeout) ` tuple. - :type timeout: float or tuple - :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``. - :type allow_redirects: bool - :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. - :param verify: (optional) Either a boolean, in which case it controls whether we verify - the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use. Defaults to ``True``. - :param stream: (optional) if ``False``, the response content will be immediately downloaded. - :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. - :return: :class:`Response ` object - :rtype: requests.Response - - Usage:: - - >>> import requests - >>> req = requests.request('GET', 'https://httpbin.org/get') - >>> req - - """ - - # By using the 'with' statement we are sure the session is closed, thus we - # avoid leaving sockets open which can trigger a ResourceWarning in some - # cases, and look like a memory leak in others. - with sessions.Session() as session: - return session.request(method=method, url=url, **kwargs) - - -def get(url, params=None, **kwargs): - r"""Sends a GET request. - - :param url: URL for the new :class:`Request` object. - :param params: (optional) Dictionary, list of tuples or bytes to send - in the query string for the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response ` object - :rtype: requests.Response - """ - - return request("get", url, params=params, **kwargs) - - -def options(url, **kwargs): - r"""Sends an OPTIONS request. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response ` object - :rtype: requests.Response - """ - - return request("options", url, **kwargs) - - -def head(url, **kwargs): - r"""Sends a HEAD request. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. If - `allow_redirects` is not provided, it will be set to `False` (as - opposed to the default :meth:`request` behavior). - :return: :class:`Response ` object - :rtype: requests.Response - """ - - kwargs.setdefault("allow_redirects", False) - return request("head", url, **kwargs) - - -def post(url, data=None, json=None, **kwargs): - r"""Sends a POST request. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response ` object - :rtype: requests.Response - """ - - return request("post", url, data=data, json=json, **kwargs) - - -def put(url, data=None, **kwargs): - r"""Sends a PUT request. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response ` object - :rtype: requests.Response - """ - - return request("put", url, data=data, **kwargs) - - -def patch(url, data=None, **kwargs): - r"""Sends a PATCH request. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response ` object - :rtype: requests.Response - """ - - return request("patch", url, data=data, **kwargs) - - -def delete(url, **kwargs): - r"""Sends a DELETE request. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :return: :class:`Response ` object - :rtype: requests.Response - """ - - return request("delete", url, **kwargs) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/auth.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/auth.py deleted file mode 100644 index 9733686..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/auth.py +++ /dev/null @@ -1,315 +0,0 @@ -""" -requests.auth -~~~~~~~~~~~~~ - -This module contains the authentication handlers for Requests. -""" - -import hashlib -import os -import re -import threading -import time -import warnings -from base64 import b64encode - -from ._internal_utils import to_native_string -from .compat import basestring, str, urlparse -from .cookies import extract_cookies_to_jar -from .utils import parse_dict_header - -CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded" -CONTENT_TYPE_MULTI_PART = "multipart/form-data" - - -def _basic_auth_str(username, password): - """Returns a Basic Auth string.""" - - # "I want us to put a big-ol' comment on top of it that - # says that this behaviour is dumb but we need to preserve - # it because people are relying on it." - # - Lukasa - # - # These are here solely to maintain backwards compatibility - # for things like ints. This will be removed in 3.0.0. - if not isinstance(username, basestring): - warnings.warn( - "Non-string usernames will no longer be supported in Requests " - "3.0.0. Please convert the object you've passed in ({!r}) to " - "a string or bytes object in the near future to avoid " - "problems.".format(username), - category=DeprecationWarning, - ) - username = str(username) - - if not isinstance(password, basestring): - warnings.warn( - "Non-string passwords will no longer be supported in Requests " - "3.0.0. Please convert the object you've passed in ({!r}) to " - "a string or bytes object in the near future to avoid " - "problems.".format(type(password)), - category=DeprecationWarning, - ) - password = str(password) - # -- End Removal -- - - if isinstance(username, str): - username = username.encode("latin1") - - if isinstance(password, str): - password = password.encode("latin1") - - authstr = "Basic " + to_native_string( - b64encode(b":".join((username, password))).strip() - ) - - return authstr - - -class AuthBase: - """Base class that all auth implementations derive from""" - - def __call__(self, r): - raise NotImplementedError("Auth hooks must be callable.") - - -class HTTPBasicAuth(AuthBase): - """Attaches HTTP Basic Authentication to the given Request object.""" - - def __init__(self, username, password): - self.username = username - self.password = password - - def __eq__(self, other): - return all( - [ - self.username == getattr(other, "username", None), - self.password == getattr(other, "password", None), - ] - ) - - def __ne__(self, other): - return not self == other - - def __call__(self, r): - r.headers["Authorization"] = _basic_auth_str(self.username, self.password) - return r - - -class HTTPProxyAuth(HTTPBasicAuth): - """Attaches HTTP Proxy Authentication to a given Request object.""" - - def __call__(self, r): - r.headers["Proxy-Authorization"] = _basic_auth_str(self.username, self.password) - return r - - -class HTTPDigestAuth(AuthBase): - """Attaches HTTP Digest Authentication to the given Request object.""" - - def __init__(self, username, password): - self.username = username - self.password = password - # Keep state in per-thread local storage - self._thread_local = threading.local() - - def init_per_thread_state(self): - # Ensure state is initialized just once per-thread - if not hasattr(self._thread_local, "init"): - self._thread_local.init = True - self._thread_local.last_nonce = "" - self._thread_local.nonce_count = 0 - self._thread_local.chal = {} - self._thread_local.pos = None - self._thread_local.num_401_calls = None - - def build_digest_header(self, method, url): - """ - :rtype: str - """ - - realm = self._thread_local.chal["realm"] - nonce = self._thread_local.chal["nonce"] - qop = self._thread_local.chal.get("qop") - algorithm = self._thread_local.chal.get("algorithm") - opaque = self._thread_local.chal.get("opaque") - hash_utf8 = None - - if algorithm is None: - _algorithm = "MD5" - else: - _algorithm = algorithm.upper() - # lambdas assume digest modules are imported at the top level - if _algorithm == "MD5" or _algorithm == "MD5-SESS": - - def md5_utf8(x): - if isinstance(x, str): - x = x.encode("utf-8") - return hashlib.md5(x).hexdigest() - - hash_utf8 = md5_utf8 - elif _algorithm == "SHA": - - def sha_utf8(x): - if isinstance(x, str): - x = x.encode("utf-8") - return hashlib.sha1(x).hexdigest() - - hash_utf8 = sha_utf8 - elif _algorithm == "SHA-256": - - def sha256_utf8(x): - if isinstance(x, str): - x = x.encode("utf-8") - return hashlib.sha256(x).hexdigest() - - hash_utf8 = sha256_utf8 - elif _algorithm == "SHA-512": - - def sha512_utf8(x): - if isinstance(x, str): - x = x.encode("utf-8") - return hashlib.sha512(x).hexdigest() - - hash_utf8 = sha512_utf8 - - KD = lambda s, d: hash_utf8(f"{s}:{d}") # noqa:E731 - - if hash_utf8 is None: - return None - - # XXX not implemented yet - entdig = None - p_parsed = urlparse(url) - #: path is request-uri defined in RFC 2616 which should not be empty - path = p_parsed.path or "/" - if p_parsed.query: - path += f"?{p_parsed.query}" - - A1 = f"{self.username}:{realm}:{self.password}" - A2 = f"{method}:{path}" - - HA1 = hash_utf8(A1) - HA2 = hash_utf8(A2) - - if nonce == self._thread_local.last_nonce: - self._thread_local.nonce_count += 1 - else: - self._thread_local.nonce_count = 1 - ncvalue = f"{self._thread_local.nonce_count:08x}" - s = str(self._thread_local.nonce_count).encode("utf-8") - s += nonce.encode("utf-8") - s += time.ctime().encode("utf-8") - s += os.urandom(8) - - cnonce = hashlib.sha1(s).hexdigest()[:16] - if _algorithm == "MD5-SESS": - HA1 = hash_utf8(f"{HA1}:{nonce}:{cnonce}") - - if not qop: - respdig = KD(HA1, f"{nonce}:{HA2}") - elif qop == "auth" or "auth" in qop.split(","): - noncebit = f"{nonce}:{ncvalue}:{cnonce}:auth:{HA2}" - respdig = KD(HA1, noncebit) - else: - # XXX handle auth-int. - return None - - self._thread_local.last_nonce = nonce - - # XXX should the partial digests be encoded too? - base = ( - f'username="{self.username}", realm="{realm}", nonce="{nonce}", ' - f'uri="{path}", response="{respdig}"' - ) - if opaque: - base += f', opaque="{opaque}"' - if algorithm: - base += f', algorithm="{algorithm}"' - if entdig: - base += f', digest="{entdig}"' - if qop: - base += f', qop="auth", nc={ncvalue}, cnonce="{cnonce}"' - - return f"Digest {base}" - - def handle_redirect(self, r, **kwargs): - """Reset num_401_calls counter on redirects.""" - if r.is_redirect: - self._thread_local.num_401_calls = 1 - - def handle_401(self, r, **kwargs): - """ - Takes the given response and tries digest-auth, if needed. - - :rtype: requests.Response - """ - - # If response is not 4xx, do not auth - # See https://github.com/psf/requests/issues/3772 - if not 400 <= r.status_code < 500: - self._thread_local.num_401_calls = 1 - return r - - if self._thread_local.pos is not None: - # Rewind the file position indicator of the body to where - # it was to resend the request. - r.request.body.seek(self._thread_local.pos) - s_auth = r.headers.get("www-authenticate", "") - - if "digest" in s_auth.lower() and self._thread_local.num_401_calls < 2: - - self._thread_local.num_401_calls += 1 - pat = re.compile(r"digest ", flags=re.IGNORECASE) - self._thread_local.chal = parse_dict_header(pat.sub("", s_auth, count=1)) - - # Consume content and release the original connection - # to allow our new request to reuse the same one. - r.content - r.close() - prep = r.request.copy() - extract_cookies_to_jar(prep._cookies, r.request, r.raw) - prep.prepare_cookies(prep._cookies) - - prep.headers["Authorization"] = self.build_digest_header( - prep.method, prep.url - ) - _r = r.connection.send(prep, **kwargs) - _r.history.append(r) - _r.request = prep - - return _r - - self._thread_local.num_401_calls = 1 - return r - - def __call__(self, r): - # Initialize per-thread state, if needed - self.init_per_thread_state() - # If we have a saved nonce, skip the 401 - if self._thread_local.last_nonce: - r.headers["Authorization"] = self.build_digest_header(r.method, r.url) - try: - self._thread_local.pos = r.body.tell() - except AttributeError: - # In the case of HTTPDigestAuth being reused and the body of - # the previous request was a file-like object, pos has the - # file position of the previous body. Ensure it's set to - # None. - self._thread_local.pos = None - r.register_hook("response", self.handle_401) - r.register_hook("response", self.handle_redirect) - self._thread_local.num_401_calls = 1 - - return r - - def __eq__(self, other): - return all( - [ - self.username == getattr(other, "username", None), - self.password == getattr(other, "password", None), - ] - ) - - def __ne__(self, other): - return not self == other diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/certs.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/certs.py deleted file mode 100644 index 38696a1..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/certs.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python - -""" -requests.certs -~~~~~~~~~~~~~~ - -This module returns the preferred default CA certificate bundle. There is -only one — the one from the certifi package. - -If you are packaging Requests, e.g., for a Linux distribution or a managed -environment, you can change the definition of where() to return a separately -packaged CA bundle. -""" - -import os - -if "_PIP_STANDALONE_CERT" not in os.environ: - from pip._vendor.certifi import where -else: - def where(): - return os.environ["_PIP_STANDALONE_CERT"] - -if __name__ == "__main__": - print(where()) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/compat.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/compat.py deleted file mode 100644 index 9ab2bb4..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/compat.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -requests.compat -~~~~~~~~~~~~~~~ - -This module previously handled import compatibility issues -between Python 2 and Python 3. It remains for backwards -compatibility until the next major version. -""" - -from pip._vendor import chardet - -import sys - -# ------- -# Pythons -# ------- - -# Syntax sugar. -_ver = sys.version_info - -#: Python 2.x? -is_py2 = _ver[0] == 2 - -#: Python 3.x? -is_py3 = _ver[0] == 3 - -# Note: We've patched out simplejson support in pip because it prevents -# upgrading simplejson on Windows. -import json -from json import JSONDecodeError - -# Keep OrderedDict for backwards compatibility. -from collections import OrderedDict -from collections.abc import Callable, Mapping, MutableMapping -from http import cookiejar as cookielib -from http.cookies import Morsel -from io import StringIO - -# -------------- -# Legacy Imports -# -------------- -from urllib.parse import ( - quote, - quote_plus, - unquote, - unquote_plus, - urldefrag, - urlencode, - urljoin, - urlparse, - urlsplit, - urlunparse, -) -from urllib.request import ( - getproxies, - getproxies_environment, - parse_http_list, - proxy_bypass, - proxy_bypass_environment, -) - -builtin_str = str -str = str -bytes = bytes -basestring = (str, bytes) -numeric_types = (int, float) -integer_types = (int,) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py deleted file mode 100644 index bf54ab2..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py +++ /dev/null @@ -1,561 +0,0 @@ -""" -requests.cookies -~~~~~~~~~~~~~~~~ - -Compatibility code to be able to use `cookielib.CookieJar` with requests. - -requests.utils imports from here, so be careful with imports. -""" - -import calendar -import copy -import time - -from ._internal_utils import to_native_string -from .compat import Morsel, MutableMapping, cookielib, urlparse, urlunparse - -try: - import threading -except ImportError: - import dummy_threading as threading - - -class MockRequest: - """Wraps a `requests.Request` to mimic a `urllib2.Request`. - - The code in `cookielib.CookieJar` expects this interface in order to correctly - manage cookie policies, i.e., determine whether a cookie can be set, given the - domains of the request and the cookie. - - The original request object is read-only. The client is responsible for collecting - the new headers via `get_new_headers()` and interpreting them appropriately. You - probably want `get_cookie_header`, defined below. - """ - - def __init__(self, request): - self._r = request - self._new_headers = {} - self.type = urlparse(self._r.url).scheme - - def get_type(self): - return self.type - - def get_host(self): - return urlparse(self._r.url).netloc - - def get_origin_req_host(self): - return self.get_host() - - def get_full_url(self): - # Only return the response's URL if the user hadn't set the Host - # header - if not self._r.headers.get("Host"): - return self._r.url - # If they did set it, retrieve it and reconstruct the expected domain - host = to_native_string(self._r.headers["Host"], encoding="utf-8") - parsed = urlparse(self._r.url) - # Reconstruct the URL as we expect it - return urlunparse( - [ - parsed.scheme, - host, - parsed.path, - parsed.params, - parsed.query, - parsed.fragment, - ] - ) - - def is_unverifiable(self): - return True - - def has_header(self, name): - return name in self._r.headers or name in self._new_headers - - def get_header(self, name, default=None): - return self._r.headers.get(name, self._new_headers.get(name, default)) - - def add_header(self, key, val): - """cookielib has no legitimate use for this method; add it back if you find one.""" - raise NotImplementedError( - "Cookie headers should be added with add_unredirected_header()" - ) - - def add_unredirected_header(self, name, value): - self._new_headers[name] = value - - def get_new_headers(self): - return self._new_headers - - @property - def unverifiable(self): - return self.is_unverifiable() - - @property - def origin_req_host(self): - return self.get_origin_req_host() - - @property - def host(self): - return self.get_host() - - -class MockResponse: - """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`. - - ...what? Basically, expose the parsed HTTP headers from the server response - the way `cookielib` expects to see them. - """ - - def __init__(self, headers): - """Make a MockResponse for `cookielib` to read. - - :param headers: a httplib.HTTPMessage or analogous carrying the headers - """ - self._headers = headers - - def info(self): - return self._headers - - def getheaders(self, name): - self._headers.getheaders(name) - - -def extract_cookies_to_jar(jar, request, response): - """Extract the cookies from the response into a CookieJar. - - :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) - :param request: our own requests.Request object - :param response: urllib3.HTTPResponse object - """ - if not (hasattr(response, "_original_response") and response._original_response): - return - # the _original_response field is the wrapped httplib.HTTPResponse object, - req = MockRequest(request) - # pull out the HTTPMessage with the headers and put it in the mock: - res = MockResponse(response._original_response.msg) - jar.extract_cookies(res, req) - - -def get_cookie_header(jar, request): - """ - Produce an appropriate Cookie header string to be sent with `request`, or None. - - :rtype: str - """ - r = MockRequest(request) - jar.add_cookie_header(r) - return r.get_new_headers().get("Cookie") - - -def remove_cookie_by_name(cookiejar, name, domain=None, path=None): - """Unsets a cookie by name, by default over all domains and paths. - - Wraps CookieJar.clear(), is O(n). - """ - clearables = [] - for cookie in cookiejar: - if cookie.name != name: - continue - if domain is not None and domain != cookie.domain: - continue - if path is not None and path != cookie.path: - continue - clearables.append((cookie.domain, cookie.path, cookie.name)) - - for domain, path, name in clearables: - cookiejar.clear(domain, path, name) - - -class CookieConflictError(RuntimeError): - """There are two cookies that meet the criteria specified in the cookie jar. - Use .get and .set and include domain and path args in order to be more specific. - """ - - -class RequestsCookieJar(cookielib.CookieJar, MutableMapping): - """Compatibility class; is a cookielib.CookieJar, but exposes a dict - interface. - - This is the CookieJar we create by default for requests and sessions that - don't specify one, since some clients may expect response.cookies and - session.cookies to support dict operations. - - Requests does not use the dict interface internally; it's just for - compatibility with external client code. All requests code should work - out of the box with externally provided instances of ``CookieJar``, e.g. - ``LWPCookieJar`` and ``FileCookieJar``. - - Unlike a regular CookieJar, this class is pickleable. - - .. warning:: dictionary operations that are normally O(1) may be O(n). - """ - - def get(self, name, default=None, domain=None, path=None): - """Dict-like get() that also supports optional domain and path args in - order to resolve naming collisions from using one cookie jar over - multiple domains. - - .. warning:: operation is O(n), not O(1). - """ - try: - return self._find_no_duplicates(name, domain, path) - except KeyError: - return default - - def set(self, name, value, **kwargs): - """Dict-like set() that also supports optional domain and path args in - order to resolve naming collisions from using one cookie jar over - multiple domains. - """ - # support client code that unsets cookies by assignment of a None value: - if value is None: - remove_cookie_by_name( - self, name, domain=kwargs.get("domain"), path=kwargs.get("path") - ) - return - - if isinstance(value, Morsel): - c = morsel_to_cookie(value) - else: - c = create_cookie(name, value, **kwargs) - self.set_cookie(c) - return c - - def iterkeys(self): - """Dict-like iterkeys() that returns an iterator of names of cookies - from the jar. - - .. seealso:: itervalues() and iteritems(). - """ - for cookie in iter(self): - yield cookie.name - - def keys(self): - """Dict-like keys() that returns a list of names of cookies from the - jar. - - .. seealso:: values() and items(). - """ - return list(self.iterkeys()) - - def itervalues(self): - """Dict-like itervalues() that returns an iterator of values of cookies - from the jar. - - .. seealso:: iterkeys() and iteritems(). - """ - for cookie in iter(self): - yield cookie.value - - def values(self): - """Dict-like values() that returns a list of values of cookies from the - jar. - - .. seealso:: keys() and items(). - """ - return list(self.itervalues()) - - def iteritems(self): - """Dict-like iteritems() that returns an iterator of name-value tuples - from the jar. - - .. seealso:: iterkeys() and itervalues(). - """ - for cookie in iter(self): - yield cookie.name, cookie.value - - def items(self): - """Dict-like items() that returns a list of name-value tuples from the - jar. Allows client-code to call ``dict(RequestsCookieJar)`` and get a - vanilla python dict of key value pairs. - - .. seealso:: keys() and values(). - """ - return list(self.iteritems()) - - def list_domains(self): - """Utility method to list all the domains in the jar.""" - domains = [] - for cookie in iter(self): - if cookie.domain not in domains: - domains.append(cookie.domain) - return domains - - def list_paths(self): - """Utility method to list all the paths in the jar.""" - paths = [] - for cookie in iter(self): - if cookie.path not in paths: - paths.append(cookie.path) - return paths - - def multiple_domains(self): - """Returns True if there are multiple domains in the jar. - Returns False otherwise. - - :rtype: bool - """ - domains = [] - for cookie in iter(self): - if cookie.domain is not None and cookie.domain in domains: - return True - domains.append(cookie.domain) - return False # there is only one domain in jar - - def get_dict(self, domain=None, path=None): - """Takes as an argument an optional domain and path and returns a plain - old Python dict of name-value pairs of cookies that meet the - requirements. - - :rtype: dict - """ - dictionary = {} - for cookie in iter(self): - if (domain is None or cookie.domain == domain) and ( - path is None or cookie.path == path - ): - dictionary[cookie.name] = cookie.value - return dictionary - - def __contains__(self, name): - try: - return super().__contains__(name) - except CookieConflictError: - return True - - def __getitem__(self, name): - """Dict-like __getitem__() for compatibility with client code. Throws - exception if there are more than one cookie with name. In that case, - use the more explicit get() method instead. - - .. warning:: operation is O(n), not O(1). - """ - return self._find_no_duplicates(name) - - def __setitem__(self, name, value): - """Dict-like __setitem__ for compatibility with client code. Throws - exception if there is already a cookie of that name in the jar. In that - case, use the more explicit set() method instead. - """ - self.set(name, value) - - def __delitem__(self, name): - """Deletes a cookie given a name. Wraps ``cookielib.CookieJar``'s - ``remove_cookie_by_name()``. - """ - remove_cookie_by_name(self, name) - - def set_cookie(self, cookie, *args, **kwargs): - if ( - hasattr(cookie.value, "startswith") - and cookie.value.startswith('"') - and cookie.value.endswith('"') - ): - cookie.value = cookie.value.replace('\\"', "") - return super().set_cookie(cookie, *args, **kwargs) - - def update(self, other): - """Updates this jar with cookies from another CookieJar or dict-like""" - if isinstance(other, cookielib.CookieJar): - for cookie in other: - self.set_cookie(copy.copy(cookie)) - else: - super().update(other) - - def _find(self, name, domain=None, path=None): - """Requests uses this method internally to get cookie values. - - If there are conflicting cookies, _find arbitrarily chooses one. - See _find_no_duplicates if you want an exception thrown if there are - conflicting cookies. - - :param name: a string containing name of cookie - :param domain: (optional) string containing domain of cookie - :param path: (optional) string containing path of cookie - :return: cookie.value - """ - for cookie in iter(self): - if cookie.name == name: - if domain is None or cookie.domain == domain: - if path is None or cookie.path == path: - return cookie.value - - raise KeyError(f"name={name!r}, domain={domain!r}, path={path!r}") - - def _find_no_duplicates(self, name, domain=None, path=None): - """Both ``__get_item__`` and ``get`` call this function: it's never - used elsewhere in Requests. - - :param name: a string containing name of cookie - :param domain: (optional) string containing domain of cookie - :param path: (optional) string containing path of cookie - :raises KeyError: if cookie is not found - :raises CookieConflictError: if there are multiple cookies - that match name and optionally domain and path - :return: cookie.value - """ - toReturn = None - for cookie in iter(self): - if cookie.name == name: - if domain is None or cookie.domain == domain: - if path is None or cookie.path == path: - if toReturn is not None: - # if there are multiple cookies that meet passed in criteria - raise CookieConflictError( - f"There are multiple cookies with name, {name!r}" - ) - # we will eventually return this as long as no cookie conflict - toReturn = cookie.value - - if toReturn: - return toReturn - raise KeyError(f"name={name!r}, domain={domain!r}, path={path!r}") - - def __getstate__(self): - """Unlike a normal CookieJar, this class is pickleable.""" - state = self.__dict__.copy() - # remove the unpickleable RLock object - state.pop("_cookies_lock") - return state - - def __setstate__(self, state): - """Unlike a normal CookieJar, this class is pickleable.""" - self.__dict__.update(state) - if "_cookies_lock" not in self.__dict__: - self._cookies_lock = threading.RLock() - - def copy(self): - """Return a copy of this RequestsCookieJar.""" - new_cj = RequestsCookieJar() - new_cj.set_policy(self.get_policy()) - new_cj.update(self) - return new_cj - - def get_policy(self): - """Return the CookiePolicy instance used.""" - return self._policy - - -def _copy_cookie_jar(jar): - if jar is None: - return None - - if hasattr(jar, "copy"): - # We're dealing with an instance of RequestsCookieJar - return jar.copy() - # We're dealing with a generic CookieJar instance - new_jar = copy.copy(jar) - new_jar.clear() - for cookie in jar: - new_jar.set_cookie(copy.copy(cookie)) - return new_jar - - -def create_cookie(name, value, **kwargs): - """Make a cookie from underspecified parameters. - - By default, the pair of `name` and `value` will be set for the domain '' - and sent on every request (this is sometimes called a "supercookie"). - """ - result = { - "version": 0, - "name": name, - "value": value, - "port": None, - "domain": "", - "path": "/", - "secure": False, - "expires": None, - "discard": True, - "comment": None, - "comment_url": None, - "rest": {"HttpOnly": None}, - "rfc2109": False, - } - - badargs = set(kwargs) - set(result) - if badargs: - raise TypeError( - f"create_cookie() got unexpected keyword arguments: {list(badargs)}" - ) - - result.update(kwargs) - result["port_specified"] = bool(result["port"]) - result["domain_specified"] = bool(result["domain"]) - result["domain_initial_dot"] = result["domain"].startswith(".") - result["path_specified"] = bool(result["path"]) - - return cookielib.Cookie(**result) - - -def morsel_to_cookie(morsel): - """Convert a Morsel object into a Cookie containing the one k/v pair.""" - - expires = None - if morsel["max-age"]: - try: - expires = int(time.time() + int(morsel["max-age"])) - except ValueError: - raise TypeError(f"max-age: {morsel['max-age']} must be integer") - elif morsel["expires"]: - time_template = "%a, %d-%b-%Y %H:%M:%S GMT" - expires = calendar.timegm(time.strptime(morsel["expires"], time_template)) - return create_cookie( - comment=morsel["comment"], - comment_url=bool(morsel["comment"]), - discard=False, - domain=morsel["domain"], - expires=expires, - name=morsel.key, - path=morsel["path"], - port=None, - rest={"HttpOnly": morsel["httponly"]}, - rfc2109=False, - secure=bool(morsel["secure"]), - value=morsel.value, - version=morsel["version"] or 0, - ) - - -def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True): - """Returns a CookieJar from a key/value dictionary. - - :param cookie_dict: Dict of key/values to insert into CookieJar. - :param cookiejar: (optional) A cookiejar to add the cookies to. - :param overwrite: (optional) If False, will not replace cookies - already in the jar with new ones. - :rtype: CookieJar - """ - if cookiejar is None: - cookiejar = RequestsCookieJar() - - if cookie_dict is not None: - names_from_jar = [cookie.name for cookie in cookiejar] - for name in cookie_dict: - if overwrite or (name not in names_from_jar): - cookiejar.set_cookie(create_cookie(name, cookie_dict[name])) - - return cookiejar - - -def merge_cookies(cookiejar, cookies): - """Add cookies to cookiejar and returns a merged CookieJar. - - :param cookiejar: CookieJar object to add the cookies to. - :param cookies: Dictionary or CookieJar object to be added. - :rtype: CookieJar - """ - if not isinstance(cookiejar, cookielib.CookieJar): - raise ValueError("You can only merge into CookieJar") - - if isinstance(cookies, dict): - cookiejar = cookiejar_from_dict(cookies, cookiejar=cookiejar, overwrite=False) - elif isinstance(cookies, cookielib.CookieJar): - try: - cookiejar.update(cookies) - except AttributeError: - for cookie_in_jar in cookies: - cookiejar.set_cookie(cookie_in_jar) - - return cookiejar diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py deleted file mode 100644 index 168d073..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py +++ /dev/null @@ -1,141 +0,0 @@ -""" -requests.exceptions -~~~~~~~~~~~~~~~~~~~ - -This module contains the set of Requests' exceptions. -""" -from pip._vendor.urllib3.exceptions import HTTPError as BaseHTTPError - -from .compat import JSONDecodeError as CompatJSONDecodeError - - -class RequestException(IOError): - """There was an ambiguous exception that occurred while handling your - request. - """ - - def __init__(self, *args, **kwargs): - """Initialize RequestException with `request` and `response` objects.""" - response = kwargs.pop("response", None) - self.response = response - self.request = kwargs.pop("request", None) - if response is not None and not self.request and hasattr(response, "request"): - self.request = self.response.request - super().__init__(*args, **kwargs) - - -class InvalidJSONError(RequestException): - """A JSON error occurred.""" - - -class JSONDecodeError(InvalidJSONError, CompatJSONDecodeError): - """Couldn't decode the text into json""" - - def __init__(self, *args, **kwargs): - """ - Construct the JSONDecodeError instance first with all - args. Then use it's args to construct the IOError so that - the json specific args aren't used as IOError specific args - and the error message from JSONDecodeError is preserved. - """ - CompatJSONDecodeError.__init__(self, *args) - InvalidJSONError.__init__(self, *self.args, **kwargs) - - -class HTTPError(RequestException): - """An HTTP error occurred.""" - - -class ConnectionError(RequestException): - """A Connection error occurred.""" - - -class ProxyError(ConnectionError): - """A proxy error occurred.""" - - -class SSLError(ConnectionError): - """An SSL error occurred.""" - - -class Timeout(RequestException): - """The request timed out. - - Catching this error will catch both - :exc:`~requests.exceptions.ConnectTimeout` and - :exc:`~requests.exceptions.ReadTimeout` errors. - """ - - -class ConnectTimeout(ConnectionError, Timeout): - """The request timed out while trying to connect to the remote server. - - Requests that produced this error are safe to retry. - """ - - -class ReadTimeout(Timeout): - """The server did not send any data in the allotted amount of time.""" - - -class URLRequired(RequestException): - """A valid URL is required to make a request.""" - - -class TooManyRedirects(RequestException): - """Too many redirects.""" - - -class MissingSchema(RequestException, ValueError): - """The URL scheme (e.g. http or https) is missing.""" - - -class InvalidSchema(RequestException, ValueError): - """The URL scheme provided is either invalid or unsupported.""" - - -class InvalidURL(RequestException, ValueError): - """The URL provided was somehow invalid.""" - - -class InvalidHeader(RequestException, ValueError): - """The header value provided was somehow invalid.""" - - -class InvalidProxyURL(InvalidURL): - """The proxy URL provided is invalid.""" - - -class ChunkedEncodingError(RequestException): - """The server declared chunked encoding but sent an invalid chunk.""" - - -class ContentDecodingError(RequestException, BaseHTTPError): - """Failed to decode response content.""" - - -class StreamConsumedError(RequestException, TypeError): - """The content for this response was already consumed.""" - - -class RetryError(RequestException): - """Custom retries logic failed""" - - -class UnrewindableBodyError(RequestException): - """Requests encountered an error when trying to rewind a body.""" - - -# Warnings - - -class RequestsWarning(Warning): - """Base warning for Requests.""" - - -class FileModeWarning(RequestsWarning, DeprecationWarning): - """A file was opened in text mode, but Requests determined its binary length.""" - - -class RequestsDependencyWarning(RequestsWarning): - """An imported dependency doesn't match the expected version range.""" diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/help.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/help.py deleted file mode 100644 index 2d292c2..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/help.py +++ /dev/null @@ -1,131 +0,0 @@ -"""Module containing bug report helper(s).""" - -import json -import platform -import ssl -import sys - -from pip._vendor import idna -from pip._vendor import urllib3 - -from . import __version__ as requests_version - -charset_normalizer = None - -try: - from pip._vendor import chardet -except ImportError: - chardet = None - -try: - from pip._vendor.urllib3.contrib import pyopenssl -except ImportError: - pyopenssl = None - OpenSSL = None - cryptography = None -else: - import cryptography - import OpenSSL - - -def _implementation(): - """Return a dict with the Python implementation and version. - - Provide both the name and the version of the Python implementation - currently running. For example, on CPython 3.10.3 it will return - {'name': 'CPython', 'version': '3.10.3'}. - - This function works best on CPython and PyPy: in particular, it probably - doesn't work for Jython or IronPython. Future investigation should be done - to work out the correct shape of the code for those platforms. - """ - implementation = platform.python_implementation() - - if implementation == "CPython": - implementation_version = platform.python_version() - elif implementation == "PyPy": - implementation_version = "{}.{}.{}".format( - sys.pypy_version_info.major, - sys.pypy_version_info.minor, - sys.pypy_version_info.micro, - ) - if sys.pypy_version_info.releaselevel != "final": - implementation_version = "".join( - [implementation_version, sys.pypy_version_info.releaselevel] - ) - elif implementation == "Jython": - implementation_version = platform.python_version() # Complete Guess - elif implementation == "IronPython": - implementation_version = platform.python_version() # Complete Guess - else: - implementation_version = "Unknown" - - return {"name": implementation, "version": implementation_version} - - -def info(): - """Generate information for a bug report.""" - try: - platform_info = { - "system": platform.system(), - "release": platform.release(), - } - except OSError: - platform_info = { - "system": "Unknown", - "release": "Unknown", - } - - implementation_info = _implementation() - urllib3_info = {"version": urllib3.__version__} - charset_normalizer_info = {"version": None} - chardet_info = {"version": None} - if charset_normalizer: - charset_normalizer_info = {"version": charset_normalizer.__version__} - if chardet: - chardet_info = {"version": chardet.__version__} - - pyopenssl_info = { - "version": None, - "openssl_version": "", - } - if OpenSSL: - pyopenssl_info = { - "version": OpenSSL.__version__, - "openssl_version": f"{OpenSSL.SSL.OPENSSL_VERSION_NUMBER:x}", - } - cryptography_info = { - "version": getattr(cryptography, "__version__", ""), - } - idna_info = { - "version": getattr(idna, "__version__", ""), - } - - system_ssl = ssl.OPENSSL_VERSION_NUMBER - system_ssl_info = {"version": f"{system_ssl:x}" if system_ssl is not None else ""} - - return { - "platform": platform_info, - "implementation": implementation_info, - "system_ssl": system_ssl_info, - "using_pyopenssl": pyopenssl is not None, - "using_charset_normalizer": chardet is None, - "pyOpenSSL": pyopenssl_info, - "urllib3": urllib3_info, - "chardet": chardet_info, - "charset_normalizer": charset_normalizer_info, - "cryptography": cryptography_info, - "idna": idna_info, - "requests": { - "version": requests_version, - }, - } - - -def main(): - """Pretty-print the bug information as JSON.""" - print(json.dumps(info(), sort_keys=True, indent=2)) - - -if __name__ == "__main__": - main() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py deleted file mode 100644 index d181ba2..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -requests.hooks -~~~~~~~~~~~~~~ - -This module provides the capabilities for the Requests hooks system. - -Available hooks: - -``response``: - The response generated from a Request. -""" -HOOKS = ["response"] - - -def default_hooks(): - return {event: [] for event in HOOKS} - - -# TODO: response is the only one - - -def dispatch_hook(key, hooks, hook_data, **kwargs): - """Dispatches a hook dictionary on a given piece of data.""" - hooks = hooks or {} - hooks = hooks.get(key) - if hooks: - if hasattr(hooks, "__call__"): - hooks = [hooks] - for hook in hooks: - _hook_data = hook(hook_data, **kwargs) - if _hook_data is not None: - hook_data = _hook_data - return hook_data diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/models.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/models.py deleted file mode 100644 index 76e6f19..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/models.py +++ /dev/null @@ -1,1034 +0,0 @@ -""" -requests.models -~~~~~~~~~~~~~~~ - -This module contains the primary objects that power Requests. -""" - -import datetime - -# Import encoding now, to avoid implicit import later. -# Implicit import within threads may cause LookupError when standard library is in a ZIP, -# such as in Embedded Python. See https://github.com/psf/requests/issues/3578. -import encodings.idna # noqa: F401 -from io import UnsupportedOperation - -from pip._vendor.urllib3.exceptions import ( - DecodeError, - LocationParseError, - ProtocolError, - ReadTimeoutError, - SSLError, -) -from pip._vendor.urllib3.fields import RequestField -from pip._vendor.urllib3.filepost import encode_multipart_formdata -from pip._vendor.urllib3.util import parse_url - -from ._internal_utils import to_native_string, unicode_is_ascii -from .auth import HTTPBasicAuth -from .compat import ( - Callable, - JSONDecodeError, - Mapping, - basestring, - builtin_str, - chardet, - cookielib, -) -from .compat import json as complexjson -from .compat import urlencode, urlsplit, urlunparse -from .cookies import _copy_cookie_jar, cookiejar_from_dict, get_cookie_header -from .exceptions import ( - ChunkedEncodingError, - ConnectionError, - ContentDecodingError, - HTTPError, - InvalidJSONError, - InvalidURL, -) -from .exceptions import JSONDecodeError as RequestsJSONDecodeError -from .exceptions import MissingSchema -from .exceptions import SSLError as RequestsSSLError -from .exceptions import StreamConsumedError -from .hooks import default_hooks -from .status_codes import codes -from .structures import CaseInsensitiveDict -from .utils import ( - check_header_validity, - get_auth_from_url, - guess_filename, - guess_json_utf, - iter_slices, - parse_header_links, - requote_uri, - stream_decode_response_unicode, - super_len, - to_key_val_list, -) - -#: The set of HTTP status codes that indicate an automatically -#: processable redirect. -REDIRECT_STATI = ( - codes.moved, # 301 - codes.found, # 302 - codes.other, # 303 - codes.temporary_redirect, # 307 - codes.permanent_redirect, # 308 -) - -DEFAULT_REDIRECT_LIMIT = 30 -CONTENT_CHUNK_SIZE = 10 * 1024 -ITER_CHUNK_SIZE = 512 - - -class RequestEncodingMixin: - @property - def path_url(self): - """Build the path URL to use.""" - - url = [] - - p = urlsplit(self.url) - - path = p.path - if not path: - path = "/" - - url.append(path) - - query = p.query - if query: - url.append("?") - url.append(query) - - return "".join(url) - - @staticmethod - def _encode_params(data): - """Encode parameters in a piece of data. - - Will successfully encode parameters when passed as a dict or a list of - 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary - if parameters are supplied as a dict. - """ - - if isinstance(data, (str, bytes)): - return data - elif hasattr(data, "read"): - return data - elif hasattr(data, "__iter__"): - result = [] - for k, vs in to_key_val_list(data): - if isinstance(vs, basestring) or not hasattr(vs, "__iter__"): - vs = [vs] - for v in vs: - if v is not None: - result.append( - ( - k.encode("utf-8") if isinstance(k, str) else k, - v.encode("utf-8") if isinstance(v, str) else v, - ) - ) - return urlencode(result, doseq=True) - else: - return data - - @staticmethod - def _encode_files(files, data): - """Build the body for a multipart/form-data request. - - Will successfully encode files when passed as a dict or a list of - tuples. Order is retained if data is a list of tuples but arbitrary - if parameters are supplied as a dict. - The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype) - or 4-tuples (filename, fileobj, contentype, custom_headers). - """ - if not files: - raise ValueError("Files must be provided.") - elif isinstance(data, basestring): - raise ValueError("Data must not be a string.") - - new_fields = [] - fields = to_key_val_list(data or {}) - files = to_key_val_list(files or {}) - - for field, val in fields: - if isinstance(val, basestring) or not hasattr(val, "__iter__"): - val = [val] - for v in val: - if v is not None: - # Don't call str() on bytestrings: in Py3 it all goes wrong. - if not isinstance(v, bytes): - v = str(v) - - new_fields.append( - ( - field.decode("utf-8") - if isinstance(field, bytes) - else field, - v.encode("utf-8") if isinstance(v, str) else v, - ) - ) - - for (k, v) in files: - # support for explicit filename - ft = None - fh = None - if isinstance(v, (tuple, list)): - if len(v) == 2: - fn, fp = v - elif len(v) == 3: - fn, fp, ft = v - else: - fn, fp, ft, fh = v - else: - fn = guess_filename(v) or k - fp = v - - if isinstance(fp, (str, bytes, bytearray)): - fdata = fp - elif hasattr(fp, "read"): - fdata = fp.read() - elif fp is None: - continue - else: - fdata = fp - - rf = RequestField(name=k, data=fdata, filename=fn, headers=fh) - rf.make_multipart(content_type=ft) - new_fields.append(rf) - - body, content_type = encode_multipart_formdata(new_fields) - - return body, content_type - - -class RequestHooksMixin: - def register_hook(self, event, hook): - """Properly register a hook.""" - - if event not in self.hooks: - raise ValueError(f'Unsupported event specified, with event name "{event}"') - - if isinstance(hook, Callable): - self.hooks[event].append(hook) - elif hasattr(hook, "__iter__"): - self.hooks[event].extend(h for h in hook if isinstance(h, Callable)) - - def deregister_hook(self, event, hook): - """Deregister a previously registered hook. - Returns True if the hook existed, False if not. - """ - - try: - self.hooks[event].remove(hook) - return True - except ValueError: - return False - - -class Request(RequestHooksMixin): - """A user-created :class:`Request ` object. - - Used to prepare a :class:`PreparedRequest `, which is sent to the server. - - :param method: HTTP method to use. - :param url: URL to send. - :param headers: dictionary of headers to send. - :param files: dictionary of {filename: fileobject} files to multipart upload. - :param data: the body to attach to the request. If a dictionary or - list of tuples ``[(key, value)]`` is provided, form-encoding will - take place. - :param json: json for the body to attach to the request (if files or data is not specified). - :param params: URL parameters to append to the URL. If a dictionary or - list of tuples ``[(key, value)]`` is provided, form-encoding will - take place. - :param auth: Auth handler or (user, pass) tuple. - :param cookies: dictionary or CookieJar of cookies to attach to this request. - :param hooks: dictionary of callback hooks, for internal usage. - - Usage:: - - >>> import requests - >>> req = requests.Request('GET', 'https://httpbin.org/get') - >>> req.prepare() - - """ - - def __init__( - self, - method=None, - url=None, - headers=None, - files=None, - data=None, - params=None, - auth=None, - cookies=None, - hooks=None, - json=None, - ): - - # Default empty dicts for dict params. - data = [] if data is None else data - files = [] if files is None else files - headers = {} if headers is None else headers - params = {} if params is None else params - hooks = {} if hooks is None else hooks - - self.hooks = default_hooks() - for (k, v) in list(hooks.items()): - self.register_hook(event=k, hook=v) - - self.method = method - self.url = url - self.headers = headers - self.files = files - self.data = data - self.json = json - self.params = params - self.auth = auth - self.cookies = cookies - - def __repr__(self): - return f"" - - def prepare(self): - """Constructs a :class:`PreparedRequest ` for transmission and returns it.""" - p = PreparedRequest() - p.prepare( - method=self.method, - url=self.url, - headers=self.headers, - files=self.files, - data=self.data, - json=self.json, - params=self.params, - auth=self.auth, - cookies=self.cookies, - hooks=self.hooks, - ) - return p - - -class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): - """The fully mutable :class:`PreparedRequest ` object, - containing the exact bytes that will be sent to the server. - - Instances are generated from a :class:`Request ` object, and - should not be instantiated manually; doing so may produce undesirable - effects. - - Usage:: - - >>> import requests - >>> req = requests.Request('GET', 'https://httpbin.org/get') - >>> r = req.prepare() - >>> r - - - >>> s = requests.Session() - >>> s.send(r) - - """ - - def __init__(self): - #: HTTP verb to send to the server. - self.method = None - #: HTTP URL to send the request to. - self.url = None - #: dictionary of HTTP headers. - self.headers = None - # The `CookieJar` used to create the Cookie header will be stored here - # after prepare_cookies is called - self._cookies = None - #: request body to send to the server. - self.body = None - #: dictionary of callback hooks, for internal usage. - self.hooks = default_hooks() - #: integer denoting starting position of a readable file-like body. - self._body_position = None - - def prepare( - self, - method=None, - url=None, - headers=None, - files=None, - data=None, - params=None, - auth=None, - cookies=None, - hooks=None, - json=None, - ): - """Prepares the entire request with the given parameters.""" - - self.prepare_method(method) - self.prepare_url(url, params) - self.prepare_headers(headers) - self.prepare_cookies(cookies) - self.prepare_body(data, files, json) - self.prepare_auth(auth, url) - - # Note that prepare_auth must be last to enable authentication schemes - # such as OAuth to work on a fully prepared request. - - # This MUST go after prepare_auth. Authenticators could add a hook - self.prepare_hooks(hooks) - - def __repr__(self): - return f"" - - def copy(self): - p = PreparedRequest() - p.method = self.method - p.url = self.url - p.headers = self.headers.copy() if self.headers is not None else None - p._cookies = _copy_cookie_jar(self._cookies) - p.body = self.body - p.hooks = self.hooks - p._body_position = self._body_position - return p - - def prepare_method(self, method): - """Prepares the given HTTP method.""" - self.method = method - if self.method is not None: - self.method = to_native_string(self.method.upper()) - - @staticmethod - def _get_idna_encoded_host(host): - from pip._vendor import idna - - try: - host = idna.encode(host, uts46=True).decode("utf-8") - except idna.IDNAError: - raise UnicodeError - return host - - def prepare_url(self, url, params): - """Prepares the given HTTP URL.""" - #: Accept objects that have string representations. - #: We're unable to blindly call unicode/str functions - #: as this will include the bytestring indicator (b'') - #: on python 3.x. - #: https://github.com/psf/requests/pull/2238 - if isinstance(url, bytes): - url = url.decode("utf8") - else: - url = str(url) - - # Remove leading whitespaces from url - url = url.lstrip() - - # Don't do any URL preparation for non-HTTP schemes like `mailto`, - # `data` etc to work around exceptions from `url_parse`, which - # handles RFC 3986 only. - if ":" in url and not url.lower().startswith("http"): - self.url = url - return - - # Support for unicode domain names and paths. - try: - scheme, auth, host, port, path, query, fragment = parse_url(url) - except LocationParseError as e: - raise InvalidURL(*e.args) - - if not scheme: - raise MissingSchema( - f"Invalid URL {url!r}: No scheme supplied. " - f"Perhaps you meant https://{url}?" - ) - - if not host: - raise InvalidURL(f"Invalid URL {url!r}: No host supplied") - - # In general, we want to try IDNA encoding the hostname if the string contains - # non-ASCII characters. This allows users to automatically get the correct IDNA - # behaviour. For strings containing only ASCII characters, we need to also verify - # it doesn't start with a wildcard (*), before allowing the unencoded hostname. - if not unicode_is_ascii(host): - try: - host = self._get_idna_encoded_host(host) - except UnicodeError: - raise InvalidURL("URL has an invalid label.") - elif host.startswith(("*", ".")): - raise InvalidURL("URL has an invalid label.") - - # Carefully reconstruct the network location - netloc = auth or "" - if netloc: - netloc += "@" - netloc += host - if port: - netloc += f":{port}" - - # Bare domains aren't valid URLs. - if not path: - path = "/" - - if isinstance(params, (str, bytes)): - params = to_native_string(params) - - enc_params = self._encode_params(params) - if enc_params: - if query: - query = f"{query}&{enc_params}" - else: - query = enc_params - - url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment])) - self.url = url - - def prepare_headers(self, headers): - """Prepares the given HTTP headers.""" - - self.headers = CaseInsensitiveDict() - if headers: - for header in headers.items(): - # Raise exception on invalid header value. - check_header_validity(header) - name, value = header - self.headers[to_native_string(name)] = value - - def prepare_body(self, data, files, json=None): - """Prepares the given HTTP body data.""" - - # Check if file, fo, generator, iterator. - # If not, run through normal process. - - # Nottin' on you. - body = None - content_type = None - - if not data and json is not None: - # urllib3 requires a bytes-like body. Python 2's json.dumps - # provides this natively, but Python 3 gives a Unicode string. - content_type = "application/json" - - try: - body = complexjson.dumps(json, allow_nan=False) - except ValueError as ve: - raise InvalidJSONError(ve, request=self) - - if not isinstance(body, bytes): - body = body.encode("utf-8") - - is_stream = all( - [ - hasattr(data, "__iter__"), - not isinstance(data, (basestring, list, tuple, Mapping)), - ] - ) - - if is_stream: - try: - length = super_len(data) - except (TypeError, AttributeError, UnsupportedOperation): - length = None - - body = data - - if getattr(body, "tell", None) is not None: - # Record the current file position before reading. - # This will allow us to rewind a file in the event - # of a redirect. - try: - self._body_position = body.tell() - except OSError: - # This differentiates from None, allowing us to catch - # a failed `tell()` later when trying to rewind the body - self._body_position = object() - - if files: - raise NotImplementedError( - "Streamed bodies and files are mutually exclusive." - ) - - if length: - self.headers["Content-Length"] = builtin_str(length) - else: - self.headers["Transfer-Encoding"] = "chunked" - else: - # Multi-part file uploads. - if files: - (body, content_type) = self._encode_files(files, data) - else: - if data: - body = self._encode_params(data) - if isinstance(data, basestring) or hasattr(data, "read"): - content_type = None - else: - content_type = "application/x-www-form-urlencoded" - - self.prepare_content_length(body) - - # Add content-type if it wasn't explicitly provided. - if content_type and ("content-type" not in self.headers): - self.headers["Content-Type"] = content_type - - self.body = body - - def prepare_content_length(self, body): - """Prepare Content-Length header based on request method and body""" - if body is not None: - length = super_len(body) - if length: - # If length exists, set it. Otherwise, we fallback - # to Transfer-Encoding: chunked. - self.headers["Content-Length"] = builtin_str(length) - elif ( - self.method not in ("GET", "HEAD") - and self.headers.get("Content-Length") is None - ): - # Set Content-Length to 0 for methods that can have a body - # but don't provide one. (i.e. not GET or HEAD) - self.headers["Content-Length"] = "0" - - def prepare_auth(self, auth, url=""): - """Prepares the given HTTP auth data.""" - - # If no Auth is explicitly provided, extract it from the URL first. - if auth is None: - url_auth = get_auth_from_url(self.url) - auth = url_auth if any(url_auth) else None - - if auth: - if isinstance(auth, tuple) and len(auth) == 2: - # special-case basic HTTP auth - auth = HTTPBasicAuth(*auth) - - # Allow auth to make its changes. - r = auth(self) - - # Update self to reflect the auth changes. - self.__dict__.update(r.__dict__) - - # Recompute Content-Length - self.prepare_content_length(self.body) - - def prepare_cookies(self, cookies): - """Prepares the given HTTP cookie data. - - This function eventually generates a ``Cookie`` header from the - given cookies using cookielib. Due to cookielib's design, the header - will not be regenerated if it already exists, meaning this function - can only be called once for the life of the - :class:`PreparedRequest ` object. Any subsequent calls - to ``prepare_cookies`` will have no actual effect, unless the "Cookie" - header is removed beforehand. - """ - if isinstance(cookies, cookielib.CookieJar): - self._cookies = cookies - else: - self._cookies = cookiejar_from_dict(cookies) - - cookie_header = get_cookie_header(self._cookies, self) - if cookie_header is not None: - self.headers["Cookie"] = cookie_header - - def prepare_hooks(self, hooks): - """Prepares the given hooks.""" - # hooks can be passed as None to the prepare method and to this - # method. To prevent iterating over None, simply use an empty list - # if hooks is False-y - hooks = hooks or [] - for event in hooks: - self.register_hook(event, hooks[event]) - - -class Response: - """The :class:`Response ` object, which contains a - server's response to an HTTP request. - """ - - __attrs__ = [ - "_content", - "status_code", - "headers", - "url", - "history", - "encoding", - "reason", - "cookies", - "elapsed", - "request", - ] - - def __init__(self): - self._content = False - self._content_consumed = False - self._next = None - - #: Integer Code of responded HTTP Status, e.g. 404 or 200. - self.status_code = None - - #: Case-insensitive Dictionary of Response Headers. - #: For example, ``headers['content-encoding']`` will return the - #: value of a ``'Content-Encoding'`` response header. - self.headers = CaseInsensitiveDict() - - #: File-like object representation of response (for advanced usage). - #: Use of ``raw`` requires that ``stream=True`` be set on the request. - #: This requirement does not apply for use internally to Requests. - self.raw = None - - #: Final URL location of Response. - self.url = None - - #: Encoding to decode with when accessing r.text. - self.encoding = None - - #: A list of :class:`Response ` objects from - #: the history of the Request. Any redirect responses will end - #: up here. The list is sorted from the oldest to the most recent request. - self.history = [] - - #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK". - self.reason = None - - #: A CookieJar of Cookies the server sent back. - self.cookies = cookiejar_from_dict({}) - - #: The amount of time elapsed between sending the request - #: and the arrival of the response (as a timedelta). - #: This property specifically measures the time taken between sending - #: the first byte of the request and finishing parsing the headers. It - #: is therefore unaffected by consuming the response content or the - #: value of the ``stream`` keyword argument. - self.elapsed = datetime.timedelta(0) - - #: The :class:`PreparedRequest ` object to which this - #: is a response. - self.request = None - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - def __getstate__(self): - # Consume everything; accessing the content attribute makes - # sure the content has been fully read. - if not self._content_consumed: - self.content - - return {attr: getattr(self, attr, None) for attr in self.__attrs__} - - def __setstate__(self, state): - for name, value in state.items(): - setattr(self, name, value) - - # pickled objects do not have .raw - setattr(self, "_content_consumed", True) - setattr(self, "raw", None) - - def __repr__(self): - return f"" - - def __bool__(self): - """Returns True if :attr:`status_code` is less than 400. - - This attribute checks if the status code of the response is between - 400 and 600 to see if there was a client error or a server error. If - the status code, is between 200 and 400, this will return True. This - is **not** a check to see if the response code is ``200 OK``. - """ - return self.ok - - def __nonzero__(self): - """Returns True if :attr:`status_code` is less than 400. - - This attribute checks if the status code of the response is between - 400 and 600 to see if there was a client error or a server error. If - the status code, is between 200 and 400, this will return True. This - is **not** a check to see if the response code is ``200 OK``. - """ - return self.ok - - def __iter__(self): - """Allows you to use a response as an iterator.""" - return self.iter_content(128) - - @property - def ok(self): - """Returns True if :attr:`status_code` is less than 400, False if not. - - This attribute checks if the status code of the response is between - 400 and 600 to see if there was a client error or a server error. If - the status code is between 200 and 400, this will return True. This - is **not** a check to see if the response code is ``200 OK``. - """ - try: - self.raise_for_status() - except HTTPError: - return False - return True - - @property - def is_redirect(self): - """True if this Response is a well-formed HTTP redirect that could have - been processed automatically (by :meth:`Session.resolve_redirects`). - """ - return "location" in self.headers and self.status_code in REDIRECT_STATI - - @property - def is_permanent_redirect(self): - """True if this Response one of the permanent versions of redirect.""" - return "location" in self.headers and self.status_code in ( - codes.moved_permanently, - codes.permanent_redirect, - ) - - @property - def next(self): - """Returns a PreparedRequest for the next request in a redirect chain, if there is one.""" - return self._next - - @property - def apparent_encoding(self): - """The apparent encoding, provided by the charset_normalizer or chardet libraries.""" - return chardet.detect(self.content)["encoding"] - - def iter_content(self, chunk_size=1, decode_unicode=False): - """Iterates over the response data. When stream=True is set on the - request, this avoids reading the content at once into memory for - large responses. The chunk size is the number of bytes it should - read into memory. This is not necessarily the length of each item - returned as decoding can take place. - - chunk_size must be of type int or None. A value of None will - function differently depending on the value of `stream`. - stream=True will read data as it arrives in whatever size the - chunks are received. If stream=False, data is returned as - a single chunk. - - If decode_unicode is True, content will be decoded using the best - available encoding based on the response. - """ - - def generate(): - # Special case for urllib3. - if hasattr(self.raw, "stream"): - try: - yield from self.raw.stream(chunk_size, decode_content=True) - except ProtocolError as e: - raise ChunkedEncodingError(e) - except DecodeError as e: - raise ContentDecodingError(e) - except ReadTimeoutError as e: - raise ConnectionError(e) - except SSLError as e: - raise RequestsSSLError(e) - else: - # Standard file-like object. - while True: - chunk = self.raw.read(chunk_size) - if not chunk: - break - yield chunk - - self._content_consumed = True - - if self._content_consumed and isinstance(self._content, bool): - raise StreamConsumedError() - elif chunk_size is not None and not isinstance(chunk_size, int): - raise TypeError( - f"chunk_size must be an int, it is instead a {type(chunk_size)}." - ) - # simulate reading small chunks of the content - reused_chunks = iter_slices(self._content, chunk_size) - - stream_chunks = generate() - - chunks = reused_chunks if self._content_consumed else stream_chunks - - if decode_unicode: - chunks = stream_decode_response_unicode(chunks, self) - - return chunks - - def iter_lines( - self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=False, delimiter=None - ): - """Iterates over the response data, one line at a time. When - stream=True is set on the request, this avoids reading the - content at once into memory for large responses. - - .. note:: This method is not reentrant safe. - """ - - pending = None - - for chunk in self.iter_content( - chunk_size=chunk_size, decode_unicode=decode_unicode - ): - - if pending is not None: - chunk = pending + chunk - - if delimiter: - lines = chunk.split(delimiter) - else: - lines = chunk.splitlines() - - if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]: - pending = lines.pop() - else: - pending = None - - yield from lines - - if pending is not None: - yield pending - - @property - def content(self): - """Content of the response, in bytes.""" - - if self._content is False: - # Read the contents. - if self._content_consumed: - raise RuntimeError("The content for this response was already consumed") - - if self.status_code == 0 or self.raw is None: - self._content = None - else: - self._content = b"".join(self.iter_content(CONTENT_CHUNK_SIZE)) or b"" - - self._content_consumed = True - # don't need to release the connection; that's been handled by urllib3 - # since we exhausted the data. - return self._content - - @property - def text(self): - """Content of the response, in unicode. - - If Response.encoding is None, encoding will be guessed using - ``charset_normalizer`` or ``chardet``. - - The encoding of the response content is determined based solely on HTTP - headers, following RFC 2616 to the letter. If you can take advantage of - non-HTTP knowledge to make a better guess at the encoding, you should - set ``r.encoding`` appropriately before accessing this property. - """ - - # Try charset from content-type - content = None - encoding = self.encoding - - if not self.content: - return "" - - # Fallback to auto-detected encoding. - if self.encoding is None: - encoding = self.apparent_encoding - - # Decode unicode from given encoding. - try: - content = str(self.content, encoding, errors="replace") - except (LookupError, TypeError): - # A LookupError is raised if the encoding was not found which could - # indicate a misspelling or similar mistake. - # - # A TypeError can be raised if encoding is None - # - # So we try blindly encoding. - content = str(self.content, errors="replace") - - return content - - def json(self, **kwargs): - r"""Returns the json-encoded content of a response, if any. - - :param \*\*kwargs: Optional arguments that ``json.loads`` takes. - :raises requests.exceptions.JSONDecodeError: If the response body does not - contain valid json. - """ - - if not self.encoding and self.content and len(self.content) > 3: - # No encoding set. JSON RFC 4627 section 3 states we should expect - # UTF-8, -16 or -32. Detect which one to use; If the detection or - # decoding fails, fall back to `self.text` (using charset_normalizer to make - # a best guess). - encoding = guess_json_utf(self.content) - if encoding is not None: - try: - return complexjson.loads(self.content.decode(encoding), **kwargs) - except UnicodeDecodeError: - # Wrong UTF codec detected; usually because it's not UTF-8 - # but some other 8-bit codec. This is an RFC violation, - # and the server didn't bother to tell us what codec *was* - # used. - pass - except JSONDecodeError as e: - raise RequestsJSONDecodeError(e.msg, e.doc, e.pos) - - try: - return complexjson.loads(self.text, **kwargs) - except JSONDecodeError as e: - # Catch JSON-related errors and raise as requests.JSONDecodeError - # This aliases json.JSONDecodeError and simplejson.JSONDecodeError - raise RequestsJSONDecodeError(e.msg, e.doc, e.pos) - - @property - def links(self): - """Returns the parsed header links of the response, if any.""" - - header = self.headers.get("link") - - resolved_links = {} - - if header: - links = parse_header_links(header) - - for link in links: - key = link.get("rel") or link.get("url") - resolved_links[key] = link - - return resolved_links - - def raise_for_status(self): - """Raises :class:`HTTPError`, if one occurred.""" - - http_error_msg = "" - if isinstance(self.reason, bytes): - # We attempt to decode utf-8 first because some servers - # choose to localize their reason strings. If the string - # isn't utf-8, we fall back to iso-8859-1 for all other - # encodings. (See PR #3538) - try: - reason = self.reason.decode("utf-8") - except UnicodeDecodeError: - reason = self.reason.decode("iso-8859-1") - else: - reason = self.reason - - if 400 <= self.status_code < 500: - http_error_msg = ( - f"{self.status_code} Client Error: {reason} for url: {self.url}" - ) - - elif 500 <= self.status_code < 600: - http_error_msg = ( - f"{self.status_code} Server Error: {reason} for url: {self.url}" - ) - - if http_error_msg: - raise HTTPError(http_error_msg, response=self) - - def close(self): - """Releases the connection back to the pool. Once this method has been - called the underlying ``raw`` object must not be accessed again. - - *Note: Should not normally need to be called explicitly.* - """ - if not self._content_consumed: - self.raw.close() - - release_conn = getattr(self.raw, "release_conn", None) - if release_conn is not None: - release_conn() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/packages.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/packages.py deleted file mode 100644 index 9582fa7..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/packages.py +++ /dev/null @@ -1,16 +0,0 @@ -import sys - -# This code exists for backwards compatibility reasons. -# I don't like it either. Just look the other way. :) - -for package in ('urllib3', 'idna', 'chardet'): - vendored_package = "pip._vendor." + package - locals()[package] = __import__(vendored_package) - # This traversal is apparently necessary such that the identities are - # preserved (requests.packages.urllib3.* is urllib3.*) - for mod in list(sys.modules): - if mod == vendored_package or mod.startswith(vendored_package + '.'): - unprefixed_mod = mod[len("pip._vendor."):] - sys.modules['pip._vendor.requests.packages.' + unprefixed_mod] = sys.modules[mod] - -# Kinda cool, though, right? diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py deleted file mode 100644 index dbcf2a7..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py +++ /dev/null @@ -1,833 +0,0 @@ -""" -requests.sessions -~~~~~~~~~~~~~~~~~ - -This module provides a Session object to manage and persist settings across -requests (cookies, auth, proxies). -""" -import os -import sys -import time -from collections import OrderedDict -from datetime import timedelta - -from ._internal_utils import to_native_string -from .adapters import HTTPAdapter -from .auth import _basic_auth_str -from .compat import Mapping, cookielib, urljoin, urlparse -from .cookies import ( - RequestsCookieJar, - cookiejar_from_dict, - extract_cookies_to_jar, - merge_cookies, -) -from .exceptions import ( - ChunkedEncodingError, - ContentDecodingError, - InvalidSchema, - TooManyRedirects, -) -from .hooks import default_hooks, dispatch_hook - -# formerly defined here, reexposed here for backward compatibility -from .models import ( # noqa: F401 - DEFAULT_REDIRECT_LIMIT, - REDIRECT_STATI, - PreparedRequest, - Request, -) -from .status_codes import codes -from .structures import CaseInsensitiveDict -from .utils import ( # noqa: F401 - DEFAULT_PORTS, - default_headers, - get_auth_from_url, - get_environ_proxies, - get_netrc_auth, - requote_uri, - resolve_proxies, - rewind_body, - should_bypass_proxies, - to_key_val_list, -) - -# Preferred clock, based on which one is more accurate on a given system. -if sys.platform == "win32": - preferred_clock = time.perf_counter -else: - preferred_clock = time.time - - -def merge_setting(request_setting, session_setting, dict_class=OrderedDict): - """Determines appropriate setting for a given request, taking into account - the explicit setting on that request, and the setting in the session. If a - setting is a dictionary, they will be merged together using `dict_class` - """ - - if session_setting is None: - return request_setting - - if request_setting is None: - return session_setting - - # Bypass if not a dictionary (e.g. verify) - if not ( - isinstance(session_setting, Mapping) and isinstance(request_setting, Mapping) - ): - return request_setting - - merged_setting = dict_class(to_key_val_list(session_setting)) - merged_setting.update(to_key_val_list(request_setting)) - - # Remove keys that are set to None. Extract keys first to avoid altering - # the dictionary during iteration. - none_keys = [k for (k, v) in merged_setting.items() if v is None] - for key in none_keys: - del merged_setting[key] - - return merged_setting - - -def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict): - """Properly merges both requests and session hooks. - - This is necessary because when request_hooks == {'response': []}, the - merge breaks Session hooks entirely. - """ - if session_hooks is None or session_hooks.get("response") == []: - return request_hooks - - if request_hooks is None or request_hooks.get("response") == []: - return session_hooks - - return merge_setting(request_hooks, session_hooks, dict_class) - - -class SessionRedirectMixin: - def get_redirect_target(self, resp): - """Receives a Response. Returns a redirect URI or ``None``""" - # Due to the nature of how requests processes redirects this method will - # be called at least once upon the original response and at least twice - # on each subsequent redirect response (if any). - # If a custom mixin is used to handle this logic, it may be advantageous - # to cache the redirect location onto the response object as a private - # attribute. - if resp.is_redirect: - location = resp.headers["location"] - # Currently the underlying http module on py3 decode headers - # in latin1, but empirical evidence suggests that latin1 is very - # rarely used with non-ASCII characters in HTTP headers. - # It is more likely to get UTF8 header rather than latin1. - # This causes incorrect handling of UTF8 encoded location headers. - # To solve this, we re-encode the location in latin1. - location = location.encode("latin1") - return to_native_string(location, "utf8") - return None - - def should_strip_auth(self, old_url, new_url): - """Decide whether Authorization header should be removed when redirecting""" - old_parsed = urlparse(old_url) - new_parsed = urlparse(new_url) - if old_parsed.hostname != new_parsed.hostname: - return True - # Special case: allow http -> https redirect when using the standard - # ports. This isn't specified by RFC 7235, but is kept to avoid - # breaking backwards compatibility with older versions of requests - # that allowed any redirects on the same host. - if ( - old_parsed.scheme == "http" - and old_parsed.port in (80, None) - and new_parsed.scheme == "https" - and new_parsed.port in (443, None) - ): - return False - - # Handle default port usage corresponding to scheme. - changed_port = old_parsed.port != new_parsed.port - changed_scheme = old_parsed.scheme != new_parsed.scheme - default_port = (DEFAULT_PORTS.get(old_parsed.scheme, None), None) - if ( - not changed_scheme - and old_parsed.port in default_port - and new_parsed.port in default_port - ): - return False - - # Standard case: root URI must match - return changed_port or changed_scheme - - def resolve_redirects( - self, - resp, - req, - stream=False, - timeout=None, - verify=True, - cert=None, - proxies=None, - yield_requests=False, - **adapter_kwargs, - ): - """Receives a Response. Returns a generator of Responses or Requests.""" - - hist = [] # keep track of history - - url = self.get_redirect_target(resp) - previous_fragment = urlparse(req.url).fragment - while url: - prepared_request = req.copy() - - # Update history and keep track of redirects. - # resp.history must ignore the original request in this loop - hist.append(resp) - resp.history = hist[1:] - - try: - resp.content # Consume socket so it can be released - except (ChunkedEncodingError, ContentDecodingError, RuntimeError): - resp.raw.read(decode_content=False) - - if len(resp.history) >= self.max_redirects: - raise TooManyRedirects( - f"Exceeded {self.max_redirects} redirects.", response=resp - ) - - # Release the connection back into the pool. - resp.close() - - # Handle redirection without scheme (see: RFC 1808 Section 4) - if url.startswith("//"): - parsed_rurl = urlparse(resp.url) - url = ":".join([to_native_string(parsed_rurl.scheme), url]) - - # Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2) - parsed = urlparse(url) - if parsed.fragment == "" and previous_fragment: - parsed = parsed._replace(fragment=previous_fragment) - elif parsed.fragment: - previous_fragment = parsed.fragment - url = parsed.geturl() - - # Facilitate relative 'location' headers, as allowed by RFC 7231. - # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource') - # Compliant with RFC3986, we percent encode the url. - if not parsed.netloc: - url = urljoin(resp.url, requote_uri(url)) - else: - url = requote_uri(url) - - prepared_request.url = to_native_string(url) - - self.rebuild_method(prepared_request, resp) - - # https://github.com/psf/requests/issues/1084 - if resp.status_code not in ( - codes.temporary_redirect, - codes.permanent_redirect, - ): - # https://github.com/psf/requests/issues/3490 - purged_headers = ("Content-Length", "Content-Type", "Transfer-Encoding") - for header in purged_headers: - prepared_request.headers.pop(header, None) - prepared_request.body = None - - headers = prepared_request.headers - headers.pop("Cookie", None) - - # Extract any cookies sent on the response to the cookiejar - # in the new request. Because we've mutated our copied prepared - # request, use the old one that we haven't yet touched. - extract_cookies_to_jar(prepared_request._cookies, req, resp.raw) - merge_cookies(prepared_request._cookies, self.cookies) - prepared_request.prepare_cookies(prepared_request._cookies) - - # Rebuild auth and proxy information. - proxies = self.rebuild_proxies(prepared_request, proxies) - self.rebuild_auth(prepared_request, resp) - - # A failed tell() sets `_body_position` to `object()`. This non-None - # value ensures `rewindable` will be True, allowing us to raise an - # UnrewindableBodyError, instead of hanging the connection. - rewindable = prepared_request._body_position is not None and ( - "Content-Length" in headers or "Transfer-Encoding" in headers - ) - - # Attempt to rewind consumed file-like object. - if rewindable: - rewind_body(prepared_request) - - # Override the original request. - req = prepared_request - - if yield_requests: - yield req - else: - - resp = self.send( - req, - stream=stream, - timeout=timeout, - verify=verify, - cert=cert, - proxies=proxies, - allow_redirects=False, - **adapter_kwargs, - ) - - extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) - - # extract redirect url, if any, for the next loop - url = self.get_redirect_target(resp) - yield resp - - def rebuild_auth(self, prepared_request, response): - """When being redirected we may want to strip authentication from the - request to avoid leaking credentials. This method intelligently removes - and reapplies authentication where possible to avoid credential loss. - """ - headers = prepared_request.headers - url = prepared_request.url - - if "Authorization" in headers and self.should_strip_auth( - response.request.url, url - ): - # If we get redirected to a new host, we should strip out any - # authentication headers. - del headers["Authorization"] - - # .netrc might have more auth for us on our new host. - new_auth = get_netrc_auth(url) if self.trust_env else None - if new_auth is not None: - prepared_request.prepare_auth(new_auth) - - def rebuild_proxies(self, prepared_request, proxies): - """This method re-evaluates the proxy configuration by considering the - environment variables. If we are redirected to a URL covered by - NO_PROXY, we strip the proxy configuration. Otherwise, we set missing - proxy keys for this URL (in case they were stripped by a previous - redirect). - - This method also replaces the Proxy-Authorization header where - necessary. - - :rtype: dict - """ - headers = prepared_request.headers - scheme = urlparse(prepared_request.url).scheme - new_proxies = resolve_proxies(prepared_request, proxies, self.trust_env) - - if "Proxy-Authorization" in headers: - del headers["Proxy-Authorization"] - - try: - username, password = get_auth_from_url(new_proxies[scheme]) - except KeyError: - username, password = None, None - - # urllib3 handles proxy authorization for us in the standard adapter. - # Avoid appending this to TLS tunneled requests where it may be leaked. - if not scheme.startswith('https') and username and password: - headers["Proxy-Authorization"] = _basic_auth_str(username, password) - - return new_proxies - - def rebuild_method(self, prepared_request, response): - """When being redirected we may want to change the method of the request - based on certain specs or browser behavior. - """ - method = prepared_request.method - - # https://tools.ietf.org/html/rfc7231#section-6.4.4 - if response.status_code == codes.see_other and method != "HEAD": - method = "GET" - - # Do what the browsers do, despite standards... - # First, turn 302s into GETs. - if response.status_code == codes.found and method != "HEAD": - method = "GET" - - # Second, if a POST is responded to with a 301, turn it into a GET. - # This bizarre behaviour is explained in Issue 1704. - if response.status_code == codes.moved and method == "POST": - method = "GET" - - prepared_request.method = method - - -class Session(SessionRedirectMixin): - """A Requests session. - - Provides cookie persistence, connection-pooling, and configuration. - - Basic Usage:: - - >>> import requests - >>> s = requests.Session() - >>> s.get('https://httpbin.org/get') - - - Or as a context manager:: - - >>> with requests.Session() as s: - ... s.get('https://httpbin.org/get') - - """ - - __attrs__ = [ - "headers", - "cookies", - "auth", - "proxies", - "hooks", - "params", - "verify", - "cert", - "adapters", - "stream", - "trust_env", - "max_redirects", - ] - - def __init__(self): - - #: A case-insensitive dictionary of headers to be sent on each - #: :class:`Request ` sent from this - #: :class:`Session `. - self.headers = default_headers() - - #: Default Authentication tuple or object to attach to - #: :class:`Request `. - self.auth = None - - #: Dictionary mapping protocol or protocol and host to the URL of the proxy - #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to - #: be used on each :class:`Request `. - self.proxies = {} - - #: Event-handling hooks. - self.hooks = default_hooks() - - #: Dictionary of querystring data to attach to each - #: :class:`Request `. The dictionary values may be lists for - #: representing multivalued query parameters. - self.params = {} - - #: Stream response content default. - self.stream = False - - #: SSL Verification default. - #: Defaults to `True`, requiring requests to verify the TLS certificate at the - #: remote end. - #: If verify is set to `False`, requests will accept any TLS certificate - #: presented by the server, and will ignore hostname mismatches and/or - #: expired certificates, which will make your application vulnerable to - #: man-in-the-middle (MitM) attacks. - #: Only set this to `False` for testing. - self.verify = True - - #: SSL client certificate default, if String, path to ssl client - #: cert file (.pem). If Tuple, ('cert', 'key') pair. - self.cert = None - - #: Maximum number of redirects allowed. If the request exceeds this - #: limit, a :class:`TooManyRedirects` exception is raised. - #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is - #: 30. - self.max_redirects = DEFAULT_REDIRECT_LIMIT - - #: Trust environment settings for proxy configuration, default - #: authentication and similar. - self.trust_env = True - - #: A CookieJar containing all currently outstanding cookies set on this - #: session. By default it is a - #: :class:`RequestsCookieJar `, but - #: may be any other ``cookielib.CookieJar`` compatible object. - self.cookies = cookiejar_from_dict({}) - - # Default connection adapters. - self.adapters = OrderedDict() - self.mount("https://", HTTPAdapter()) - self.mount("http://", HTTPAdapter()) - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - def prepare_request(self, request): - """Constructs a :class:`PreparedRequest ` for - transmission and returns it. The :class:`PreparedRequest` has settings - merged from the :class:`Request ` instance and those of the - :class:`Session`. - - :param request: :class:`Request` instance to prepare with this - session's settings. - :rtype: requests.PreparedRequest - """ - cookies = request.cookies or {} - - # Bootstrap CookieJar. - if not isinstance(cookies, cookielib.CookieJar): - cookies = cookiejar_from_dict(cookies) - - # Merge with session cookies - merged_cookies = merge_cookies( - merge_cookies(RequestsCookieJar(), self.cookies), cookies - ) - - # Set environment's basic authentication if not explicitly set. - auth = request.auth - if self.trust_env and not auth and not self.auth: - auth = get_netrc_auth(request.url) - - p = PreparedRequest() - p.prepare( - method=request.method.upper(), - url=request.url, - files=request.files, - data=request.data, - json=request.json, - headers=merge_setting( - request.headers, self.headers, dict_class=CaseInsensitiveDict - ), - params=merge_setting(request.params, self.params), - auth=merge_setting(auth, self.auth), - cookies=merged_cookies, - hooks=merge_hooks(request.hooks, self.hooks), - ) - return p - - def request( - self, - method, - url, - params=None, - data=None, - headers=None, - cookies=None, - files=None, - auth=None, - timeout=None, - allow_redirects=True, - proxies=None, - hooks=None, - stream=None, - verify=None, - cert=None, - json=None, - ): - """Constructs a :class:`Request `, prepares it and sends it. - Returns :class:`Response ` object. - - :param method: method for the new :class:`Request` object. - :param url: URL for the new :class:`Request` object. - :param params: (optional) Dictionary or bytes to be sent in the query - string for the :class:`Request`. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) json to send in the body of the - :class:`Request`. - :param headers: (optional) Dictionary of HTTP Headers to send with the - :class:`Request`. - :param cookies: (optional) Dict or CookieJar object to send with the - :class:`Request`. - :param files: (optional) Dictionary of ``'filename': file-like-objects`` - for multipart encoding upload. - :param auth: (optional) Auth tuple or callable to enable - Basic/Digest/Custom HTTP Auth. - :param timeout: (optional) How long to wait for the server to send - data before giving up, as a float, or a :ref:`(connect timeout, - read timeout) ` tuple. - :type timeout: float or tuple - :param allow_redirects: (optional) Set to True by default. - :type allow_redirects: bool - :param proxies: (optional) Dictionary mapping protocol or protocol and - hostname to the URL of the proxy. - :param stream: (optional) whether to immediately download the response - content. Defaults to ``False``. - :param verify: (optional) Either a boolean, in which case it controls whether we verify - the server's TLS certificate, or a string, in which case it must be a path - to a CA bundle to use. Defaults to ``True``. When set to - ``False``, requests will accept any TLS certificate presented by - the server, and will ignore hostname mismatches and/or expired - certificates, which will make your application vulnerable to - man-in-the-middle (MitM) attacks. Setting verify to ``False`` - may be useful during local development or testing. - :param cert: (optional) if String, path to ssl client cert file (.pem). - If Tuple, ('cert', 'key') pair. - :rtype: requests.Response - """ - # Create the Request. - req = Request( - method=method.upper(), - url=url, - headers=headers, - files=files, - data=data or {}, - json=json, - params=params or {}, - auth=auth, - cookies=cookies, - hooks=hooks, - ) - prep = self.prepare_request(req) - - proxies = proxies or {} - - settings = self.merge_environment_settings( - prep.url, proxies, stream, verify, cert - ) - - # Send the request. - send_kwargs = { - "timeout": timeout, - "allow_redirects": allow_redirects, - } - send_kwargs.update(settings) - resp = self.send(prep, **send_kwargs) - - return resp - - def get(self, url, **kwargs): - r"""Sends a GET request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - kwargs.setdefault("allow_redirects", True) - return self.request("GET", url, **kwargs) - - def options(self, url, **kwargs): - r"""Sends a OPTIONS request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - kwargs.setdefault("allow_redirects", True) - return self.request("OPTIONS", url, **kwargs) - - def head(self, url, **kwargs): - r"""Sends a HEAD request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - kwargs.setdefault("allow_redirects", False) - return self.request("HEAD", url, **kwargs) - - def post(self, url, data=None, json=None, **kwargs): - r"""Sends a POST request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param json: (optional) json to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - return self.request("POST", url, data=data, json=json, **kwargs) - - def put(self, url, data=None, **kwargs): - r"""Sends a PUT request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - return self.request("PUT", url, data=data, **kwargs) - - def patch(self, url, data=None, **kwargs): - r"""Sends a PATCH request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param data: (optional) Dictionary, list of tuples, bytes, or file-like - object to send in the body of the :class:`Request`. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - return self.request("PATCH", url, data=data, **kwargs) - - def delete(self, url, **kwargs): - r"""Sends a DELETE request. Returns :class:`Response` object. - - :param url: URL for the new :class:`Request` object. - :param \*\*kwargs: Optional arguments that ``request`` takes. - :rtype: requests.Response - """ - - return self.request("DELETE", url, **kwargs) - - def send(self, request, **kwargs): - """Send a given PreparedRequest. - - :rtype: requests.Response - """ - # Set defaults that the hooks can utilize to ensure they always have - # the correct parameters to reproduce the previous request. - kwargs.setdefault("stream", self.stream) - kwargs.setdefault("verify", self.verify) - kwargs.setdefault("cert", self.cert) - if "proxies" not in kwargs: - kwargs["proxies"] = resolve_proxies(request, self.proxies, self.trust_env) - - # It's possible that users might accidentally send a Request object. - # Guard against that specific failure case. - if isinstance(request, Request): - raise ValueError("You can only send PreparedRequests.") - - # Set up variables needed for resolve_redirects and dispatching of hooks - allow_redirects = kwargs.pop("allow_redirects", True) - stream = kwargs.get("stream") - hooks = request.hooks - - # Get the appropriate adapter to use - adapter = self.get_adapter(url=request.url) - - # Start time (approximately) of the request - start = preferred_clock() - - # Send the request - r = adapter.send(request, **kwargs) - - # Total elapsed time of the request (approximately) - elapsed = preferred_clock() - start - r.elapsed = timedelta(seconds=elapsed) - - # Response manipulation hooks - r = dispatch_hook("response", hooks, r, **kwargs) - - # Persist cookies - if r.history: - - # If the hooks create history then we want those cookies too - for resp in r.history: - extract_cookies_to_jar(self.cookies, resp.request, resp.raw) - - extract_cookies_to_jar(self.cookies, request, r.raw) - - # Resolve redirects if allowed. - if allow_redirects: - # Redirect resolving generator. - gen = self.resolve_redirects(r, request, **kwargs) - history = [resp for resp in gen] - else: - history = [] - - # Shuffle things around if there's history. - if history: - # Insert the first (original) request at the start - history.insert(0, r) - # Get the last request made - r = history.pop() - r.history = history - - # If redirects aren't being followed, store the response on the Request for Response.next(). - if not allow_redirects: - try: - r._next = next( - self.resolve_redirects(r, request, yield_requests=True, **kwargs) - ) - except StopIteration: - pass - - if not stream: - r.content - - return r - - def merge_environment_settings(self, url, proxies, stream, verify, cert): - """ - Check the environment and merge it with some settings. - - :rtype: dict - """ - # Gather clues from the surrounding environment. - if self.trust_env: - # Set environment's proxies. - no_proxy = proxies.get("no_proxy") if proxies is not None else None - env_proxies = get_environ_proxies(url, no_proxy=no_proxy) - for (k, v) in env_proxies.items(): - proxies.setdefault(k, v) - - # Look for requests environment configuration - # and be compatible with cURL. - if verify is True or verify is None: - verify = ( - os.environ.get("REQUESTS_CA_BUNDLE") - or os.environ.get("CURL_CA_BUNDLE") - or verify - ) - - # Merge all the kwargs. - proxies = merge_setting(proxies, self.proxies) - stream = merge_setting(stream, self.stream) - verify = merge_setting(verify, self.verify) - cert = merge_setting(cert, self.cert) - - return {"proxies": proxies, "stream": stream, "verify": verify, "cert": cert} - - def get_adapter(self, url): - """ - Returns the appropriate connection adapter for the given URL. - - :rtype: requests.adapters.BaseAdapter - """ - for (prefix, adapter) in self.adapters.items(): - - if url.lower().startswith(prefix.lower()): - return adapter - - # Nothing matches :-/ - raise InvalidSchema(f"No connection adapters were found for {url!r}") - - def close(self): - """Closes all adapters and as such the session""" - for v in self.adapters.values(): - v.close() - - def mount(self, prefix, adapter): - """Registers a connection adapter to a prefix. - - Adapters are sorted in descending order by prefix length. - """ - self.adapters[prefix] = adapter - keys_to_move = [k for k in self.adapters if len(k) < len(prefix)] - - for key in keys_to_move: - self.adapters[key] = self.adapters.pop(key) - - def __getstate__(self): - state = {attr: getattr(self, attr, None) for attr in self.__attrs__} - return state - - def __setstate__(self, state): - for attr, value in state.items(): - setattr(self, attr, value) - - -def session(): - """ - Returns a :class:`Session` for context-management. - - .. deprecated:: 1.0.0 - - This method has been deprecated since version 1.0.0 and is only kept for - backwards compatibility. New code should use :class:`~requests.sessions.Session` - to create a session. This may be removed at a future date. - - :rtype: Session - """ - return Session() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py deleted file mode 100644 index 4bd072b..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py +++ /dev/null @@ -1,128 +0,0 @@ -r""" -The ``codes`` object defines a mapping from common names for HTTP statuses -to their numerical codes, accessible either as attributes or as dictionary -items. - -Example:: - - >>> import requests - >>> requests.codes['temporary_redirect'] - 307 - >>> requests.codes.teapot - 418 - >>> requests.codes['\o/'] - 200 - -Some codes have multiple names, and both upper- and lower-case versions of -the names are allowed. For example, ``codes.ok``, ``codes.OK``, and -``codes.okay`` all correspond to the HTTP status code 200. -""" - -from .structures import LookupDict - -_codes = { - # Informational. - 100: ("continue",), - 101: ("switching_protocols",), - 102: ("processing",), - 103: ("checkpoint",), - 122: ("uri_too_long", "request_uri_too_long"), - 200: ("ok", "okay", "all_ok", "all_okay", "all_good", "\\o/", "✓"), - 201: ("created",), - 202: ("accepted",), - 203: ("non_authoritative_info", "non_authoritative_information"), - 204: ("no_content",), - 205: ("reset_content", "reset"), - 206: ("partial_content", "partial"), - 207: ("multi_status", "multiple_status", "multi_stati", "multiple_stati"), - 208: ("already_reported",), - 226: ("im_used",), - # Redirection. - 300: ("multiple_choices",), - 301: ("moved_permanently", "moved", "\\o-"), - 302: ("found",), - 303: ("see_other", "other"), - 304: ("not_modified",), - 305: ("use_proxy",), - 306: ("switch_proxy",), - 307: ("temporary_redirect", "temporary_moved", "temporary"), - 308: ( - "permanent_redirect", - "resume_incomplete", - "resume", - ), # "resume" and "resume_incomplete" to be removed in 3.0 - # Client Error. - 400: ("bad_request", "bad"), - 401: ("unauthorized",), - 402: ("payment_required", "payment"), - 403: ("forbidden",), - 404: ("not_found", "-o-"), - 405: ("method_not_allowed", "not_allowed"), - 406: ("not_acceptable",), - 407: ("proxy_authentication_required", "proxy_auth", "proxy_authentication"), - 408: ("request_timeout", "timeout"), - 409: ("conflict",), - 410: ("gone",), - 411: ("length_required",), - 412: ("precondition_failed", "precondition"), - 413: ("request_entity_too_large",), - 414: ("request_uri_too_large",), - 415: ("unsupported_media_type", "unsupported_media", "media_type"), - 416: ( - "requested_range_not_satisfiable", - "requested_range", - "range_not_satisfiable", - ), - 417: ("expectation_failed",), - 418: ("im_a_teapot", "teapot", "i_am_a_teapot"), - 421: ("misdirected_request",), - 422: ("unprocessable_entity", "unprocessable"), - 423: ("locked",), - 424: ("failed_dependency", "dependency"), - 425: ("unordered_collection", "unordered"), - 426: ("upgrade_required", "upgrade"), - 428: ("precondition_required", "precondition"), - 429: ("too_many_requests", "too_many"), - 431: ("header_fields_too_large", "fields_too_large"), - 444: ("no_response", "none"), - 449: ("retry_with", "retry"), - 450: ("blocked_by_windows_parental_controls", "parental_controls"), - 451: ("unavailable_for_legal_reasons", "legal_reasons"), - 499: ("client_closed_request",), - # Server Error. - 500: ("internal_server_error", "server_error", "/o\\", "✗"), - 501: ("not_implemented",), - 502: ("bad_gateway",), - 503: ("service_unavailable", "unavailable"), - 504: ("gateway_timeout",), - 505: ("http_version_not_supported", "http_version"), - 506: ("variant_also_negotiates",), - 507: ("insufficient_storage",), - 509: ("bandwidth_limit_exceeded", "bandwidth"), - 510: ("not_extended",), - 511: ("network_authentication_required", "network_auth", "network_authentication"), -} - -codes = LookupDict(name="status_codes") - - -def _init(): - for code, titles in _codes.items(): - for title in titles: - setattr(codes, title, code) - if not title.startswith(("\\", "/")): - setattr(codes, title.upper(), code) - - def doc(code): - names = ", ".join(f"``{n}``" for n in _codes[code]) - return "* %d: %s" % (code, names) - - global __doc__ - __doc__ = ( - __doc__ + "\n" + "\n".join(doc(code) for code in sorted(_codes)) - if __doc__ is not None - else None - ) - - -_init() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/structures.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/structures.py deleted file mode 100644 index 188e13e..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/structures.py +++ /dev/null @@ -1,99 +0,0 @@ -""" -requests.structures -~~~~~~~~~~~~~~~~~~~ - -Data structures that power Requests. -""" - -from collections import OrderedDict - -from .compat import Mapping, MutableMapping - - -class CaseInsensitiveDict(MutableMapping): - """A case-insensitive ``dict``-like object. - - Implements all methods and operations of - ``MutableMapping`` as well as dict's ``copy``. Also - provides ``lower_items``. - - All keys are expected to be strings. The structure remembers the - case of the last key to be set, and ``iter(instance)``, - ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` - will contain case-sensitive keys. However, querying and contains - testing is case insensitive:: - - cid = CaseInsensitiveDict() - cid['Accept'] = 'application/json' - cid['aCCEPT'] == 'application/json' # True - list(cid) == ['Accept'] # True - - For example, ``headers['content-encoding']`` will return the - value of a ``'Content-Encoding'`` response header, regardless - of how the header name was originally stored. - - If the constructor, ``.update``, or equality comparison - operations are given keys that have equal ``.lower()``s, the - behavior is undefined. - """ - - def __init__(self, data=None, **kwargs): - self._store = OrderedDict() - if data is None: - data = {} - self.update(data, **kwargs) - - def __setitem__(self, key, value): - # Use the lowercased key for lookups, but store the actual - # key alongside the value. - self._store[key.lower()] = (key, value) - - def __getitem__(self, key): - return self._store[key.lower()][1] - - def __delitem__(self, key): - del self._store[key.lower()] - - def __iter__(self): - return (casedkey for casedkey, mappedvalue in self._store.values()) - - def __len__(self): - return len(self._store) - - def lower_items(self): - """Like iteritems(), but with all lowercase keys.""" - return ((lowerkey, keyval[1]) for (lowerkey, keyval) in self._store.items()) - - def __eq__(self, other): - if isinstance(other, Mapping): - other = CaseInsensitiveDict(other) - else: - return NotImplemented - # Compare insensitively - return dict(self.lower_items()) == dict(other.lower_items()) - - # Copy is required - def copy(self): - return CaseInsensitiveDict(self._store.values()) - - def __repr__(self): - return str(dict(self.items())) - - -class LookupDict(dict): - """Dictionary lookup object.""" - - def __init__(self, name=None): - self.name = name - super().__init__() - - def __repr__(self): - return f"" - - def __getitem__(self, key): - # We allow fall-through here, so values default to None - - return self.__dict__.get(key, None) - - def get(self, key, default=None): - return self.__dict__.get(key, default) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/utils.py b/.venv/lib/python3.12/site-packages/pip/_vendor/requests/utils.py deleted file mode 100644 index 36607ed..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/requests/utils.py +++ /dev/null @@ -1,1094 +0,0 @@ -""" -requests.utils -~~~~~~~~~~~~~~ - -This module provides utility functions that are used within Requests -that are also useful for external consumption. -""" - -import codecs -import contextlib -import io -import os -import re -import socket -import struct -import sys -import tempfile -import warnings -import zipfile -from collections import OrderedDict - -from pip._vendor.urllib3.util import make_headers, parse_url - -from . import certs -from .__version__ import __version__ - -# to_native_string is unused here, but imported here for backwards compatibility -from ._internal_utils import ( # noqa: F401 - _HEADER_VALIDATORS_BYTE, - _HEADER_VALIDATORS_STR, - HEADER_VALIDATORS, - to_native_string, -) -from .compat import ( - Mapping, - basestring, - bytes, - getproxies, - getproxies_environment, - integer_types, -) -from .compat import parse_http_list as _parse_list_header -from .compat import ( - proxy_bypass, - proxy_bypass_environment, - quote, - str, - unquote, - urlparse, - urlunparse, -) -from .cookies import cookiejar_from_dict -from .exceptions import ( - FileModeWarning, - InvalidHeader, - InvalidURL, - UnrewindableBodyError, -) -from .structures import CaseInsensitiveDict - -NETRC_FILES = (".netrc", "_netrc") - -DEFAULT_CA_BUNDLE_PATH = certs.where() - -DEFAULT_PORTS = {"http": 80, "https": 443} - -# Ensure that ', ' is used to preserve previous delimiter behavior. -DEFAULT_ACCEPT_ENCODING = ", ".join( - re.split(r",\s*", make_headers(accept_encoding=True)["accept-encoding"]) -) - - -if sys.platform == "win32": - # provide a proxy_bypass version on Windows without DNS lookups - - def proxy_bypass_registry(host): - try: - import winreg - except ImportError: - return False - - try: - internetSettings = winreg.OpenKey( - winreg.HKEY_CURRENT_USER, - r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", - ) - # ProxyEnable could be REG_SZ or REG_DWORD, normalizing it - proxyEnable = int(winreg.QueryValueEx(internetSettings, "ProxyEnable")[0]) - # ProxyOverride is almost always a string - proxyOverride = winreg.QueryValueEx(internetSettings, "ProxyOverride")[0] - except (OSError, ValueError): - return False - if not proxyEnable or not proxyOverride: - return False - - # make a check value list from the registry entry: replace the - # '' string by the localhost entry and the corresponding - # canonical entry. - proxyOverride = proxyOverride.split(";") - # now check if we match one of the registry values. - for test in proxyOverride: - if test == "": - if "." not in host: - return True - test = test.replace(".", r"\.") # mask dots - test = test.replace("*", r".*") # change glob sequence - test = test.replace("?", r".") # change glob char - if re.match(test, host, re.I): - return True - return False - - def proxy_bypass(host): # noqa - """Return True, if the host should be bypassed. - - Checks proxy settings gathered from the environment, if specified, - or the registry. - """ - if getproxies_environment(): - return proxy_bypass_environment(host) - else: - return proxy_bypass_registry(host) - - -def dict_to_sequence(d): - """Returns an internal sequence dictionary update.""" - - if hasattr(d, "items"): - d = d.items() - - return d - - -def super_len(o): - total_length = None - current_position = 0 - - if hasattr(o, "__len__"): - total_length = len(o) - - elif hasattr(o, "len"): - total_length = o.len - - elif hasattr(o, "fileno"): - try: - fileno = o.fileno() - except (io.UnsupportedOperation, AttributeError): - # AttributeError is a surprising exception, seeing as how we've just checked - # that `hasattr(o, 'fileno')`. It happens for objects obtained via - # `Tarfile.extractfile()`, per issue 5229. - pass - else: - total_length = os.fstat(fileno).st_size - - # Having used fstat to determine the file length, we need to - # confirm that this file was opened up in binary mode. - if "b" not in o.mode: - warnings.warn( - ( - "Requests has determined the content-length for this " - "request using the binary size of the file: however, the " - "file has been opened in text mode (i.e. without the 'b' " - "flag in the mode). This may lead to an incorrect " - "content-length. In Requests 3.0, support will be removed " - "for files in text mode." - ), - FileModeWarning, - ) - - if hasattr(o, "tell"): - try: - current_position = o.tell() - except OSError: - # This can happen in some weird situations, such as when the file - # is actually a special file descriptor like stdin. In this - # instance, we don't know what the length is, so set it to zero and - # let requests chunk it instead. - if total_length is not None: - current_position = total_length - else: - if hasattr(o, "seek") and total_length is None: - # StringIO and BytesIO have seek but no usable fileno - try: - # seek to end of file - o.seek(0, 2) - total_length = o.tell() - - # seek back to current position to support - # partially read file-like objects - o.seek(current_position or 0) - except OSError: - total_length = 0 - - if total_length is None: - total_length = 0 - - return max(0, total_length - current_position) - - -def get_netrc_auth(url, raise_errors=False): - """Returns the Requests tuple auth for a given url from netrc.""" - - netrc_file = os.environ.get("NETRC") - if netrc_file is not None: - netrc_locations = (netrc_file,) - else: - netrc_locations = (f"~/{f}" for f in NETRC_FILES) - - try: - from netrc import NetrcParseError, netrc - - netrc_path = None - - for f in netrc_locations: - try: - loc = os.path.expanduser(f) - except KeyError: - # os.path.expanduser can fail when $HOME is undefined and - # getpwuid fails. See https://bugs.python.org/issue20164 & - # https://github.com/psf/requests/issues/1846 - return - - if os.path.exists(loc): - netrc_path = loc - break - - # Abort early if there isn't one. - if netrc_path is None: - return - - ri = urlparse(url) - - # Strip port numbers from netloc. This weird `if...encode`` dance is - # used for Python 3.2, which doesn't support unicode literals. - splitstr = b":" - if isinstance(url, str): - splitstr = splitstr.decode("ascii") - host = ri.netloc.split(splitstr)[0] - - try: - _netrc = netrc(netrc_path).authenticators(host) - if _netrc: - # Return with login / password - login_i = 0 if _netrc[0] else 1 - return (_netrc[login_i], _netrc[2]) - except (NetrcParseError, OSError): - # If there was a parsing error or a permissions issue reading the file, - # we'll just skip netrc auth unless explicitly asked to raise errors. - if raise_errors: - raise - - # App Engine hackiness. - except (ImportError, AttributeError): - pass - - -def guess_filename(obj): - """Tries to guess the filename of the given object.""" - name = getattr(obj, "name", None) - if name and isinstance(name, basestring) and name[0] != "<" and name[-1] != ">": - return os.path.basename(name) - - -def extract_zipped_paths(path): - """Replace nonexistent paths that look like they refer to a member of a zip - archive with the location of an extracted copy of the target, or else - just return the provided path unchanged. - """ - if os.path.exists(path): - # this is already a valid path, no need to do anything further - return path - - # find the first valid part of the provided path and treat that as a zip archive - # assume the rest of the path is the name of a member in the archive - archive, member = os.path.split(path) - while archive and not os.path.exists(archive): - archive, prefix = os.path.split(archive) - if not prefix: - # If we don't check for an empty prefix after the split (in other words, archive remains unchanged after the split), - # we _can_ end up in an infinite loop on a rare corner case affecting a small number of users - break - member = "/".join([prefix, member]) - - if not zipfile.is_zipfile(archive): - return path - - zip_file = zipfile.ZipFile(archive) - if member not in zip_file.namelist(): - return path - - # we have a valid zip archive and a valid member of that archive - tmp = tempfile.gettempdir() - extracted_path = os.path.join(tmp, member.split("/")[-1]) - if not os.path.exists(extracted_path): - # use read + write to avoid the creating nested folders, we only want the file, avoids mkdir racing condition - with atomic_open(extracted_path) as file_handler: - file_handler.write(zip_file.read(member)) - return extracted_path - - -@contextlib.contextmanager -def atomic_open(filename): - """Write a file to the disk in an atomic fashion""" - tmp_descriptor, tmp_name = tempfile.mkstemp(dir=os.path.dirname(filename)) - try: - with os.fdopen(tmp_descriptor, "wb") as tmp_handler: - yield tmp_handler - os.replace(tmp_name, filename) - except BaseException: - os.remove(tmp_name) - raise - - -def from_key_val_list(value): - """Take an object and test to see if it can be represented as a - dictionary. Unless it can not be represented as such, return an - OrderedDict, e.g., - - :: - - >>> from_key_val_list([('key', 'val')]) - OrderedDict([('key', 'val')]) - >>> from_key_val_list('string') - Traceback (most recent call last): - ... - ValueError: cannot encode objects that are not 2-tuples - >>> from_key_val_list({'key': 'val'}) - OrderedDict([('key', 'val')]) - - :rtype: OrderedDict - """ - if value is None: - return None - - if isinstance(value, (str, bytes, bool, int)): - raise ValueError("cannot encode objects that are not 2-tuples") - - return OrderedDict(value) - - -def to_key_val_list(value): - """Take an object and test to see if it can be represented as a - dictionary. If it can be, return a list of tuples, e.g., - - :: - - >>> to_key_val_list([('key', 'val')]) - [('key', 'val')] - >>> to_key_val_list({'key': 'val'}) - [('key', 'val')] - >>> to_key_val_list('string') - Traceback (most recent call last): - ... - ValueError: cannot encode objects that are not 2-tuples - - :rtype: list - """ - if value is None: - return None - - if isinstance(value, (str, bytes, bool, int)): - raise ValueError("cannot encode objects that are not 2-tuples") - - if isinstance(value, Mapping): - value = value.items() - - return list(value) - - -# From mitsuhiko/werkzeug (used with permission). -def parse_list_header(value): - """Parse lists as described by RFC 2068 Section 2. - - In particular, parse comma-separated lists where the elements of - the list may include quoted-strings. A quoted-string could - contain a comma. A non-quoted string could have quotes in the - middle. Quotes are removed automatically after parsing. - - It basically works like :func:`parse_set_header` just that items - may appear multiple times and case sensitivity is preserved. - - The return value is a standard :class:`list`: - - >>> parse_list_header('token, "quoted value"') - ['token', 'quoted value'] - - To create a header from the :class:`list` again, use the - :func:`dump_header` function. - - :param value: a string with a list header. - :return: :class:`list` - :rtype: list - """ - result = [] - for item in _parse_list_header(value): - if item[:1] == item[-1:] == '"': - item = unquote_header_value(item[1:-1]) - result.append(item) - return result - - -# From mitsuhiko/werkzeug (used with permission). -def parse_dict_header(value): - """Parse lists of key, value pairs as described by RFC 2068 Section 2 and - convert them into a python dict: - - >>> d = parse_dict_header('foo="is a fish", bar="as well"') - >>> type(d) is dict - True - >>> sorted(d.items()) - [('bar', 'as well'), ('foo', 'is a fish')] - - If there is no value for a key it will be `None`: - - >>> parse_dict_header('key_without_value') - {'key_without_value': None} - - To create a header from the :class:`dict` again, use the - :func:`dump_header` function. - - :param value: a string with a dict header. - :return: :class:`dict` - :rtype: dict - """ - result = {} - for item in _parse_list_header(value): - if "=" not in item: - result[item] = None - continue - name, value = item.split("=", 1) - if value[:1] == value[-1:] == '"': - value = unquote_header_value(value[1:-1]) - result[name] = value - return result - - -# From mitsuhiko/werkzeug (used with permission). -def unquote_header_value(value, is_filename=False): - r"""Unquotes a header value. (Reversal of :func:`quote_header_value`). - This does not use the real unquoting but what browsers are actually - using for quoting. - - :param value: the header value to unquote. - :rtype: str - """ - if value and value[0] == value[-1] == '"': - # this is not the real unquoting, but fixing this so that the - # RFC is met will result in bugs with internet explorer and - # probably some other browsers as well. IE for example is - # uploading files with "C:\foo\bar.txt" as filename - value = value[1:-1] - - # if this is a filename and the starting characters look like - # a UNC path, then just return the value without quotes. Using the - # replace sequence below on a UNC path has the effect of turning - # the leading double slash into a single slash and then - # _fix_ie_filename() doesn't work correctly. See #458. - if not is_filename or value[:2] != "\\\\": - return value.replace("\\\\", "\\").replace('\\"', '"') - return value - - -def dict_from_cookiejar(cj): - """Returns a key/value dictionary from a CookieJar. - - :param cj: CookieJar object to extract cookies from. - :rtype: dict - """ - - cookie_dict = {} - - for cookie in cj: - cookie_dict[cookie.name] = cookie.value - - return cookie_dict - - -def add_dict_to_cookiejar(cj, cookie_dict): - """Returns a CookieJar from a key/value dictionary. - - :param cj: CookieJar to insert cookies into. - :param cookie_dict: Dict of key/values to insert into CookieJar. - :rtype: CookieJar - """ - - return cookiejar_from_dict(cookie_dict, cj) - - -def get_encodings_from_content(content): - """Returns encodings from given content string. - - :param content: bytestring to extract encodings from. - """ - warnings.warn( - ( - "In requests 3.0, get_encodings_from_content will be removed. For " - "more information, please see the discussion on issue #2266. (This" - " warning should only appear once.)" - ), - DeprecationWarning, - ) - - charset_re = re.compile(r']', flags=re.I) - pragma_re = re.compile(r']', flags=re.I) - xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]') - - return ( - charset_re.findall(content) - + pragma_re.findall(content) - + xml_re.findall(content) - ) - - -def _parse_content_type_header(header): - """Returns content type and parameters from given header - - :param header: string - :return: tuple containing content type and dictionary of - parameters - """ - - tokens = header.split(";") - content_type, params = tokens[0].strip(), tokens[1:] - params_dict = {} - items_to_strip = "\"' " - - for param in params: - param = param.strip() - if param: - key, value = param, True - index_of_equals = param.find("=") - if index_of_equals != -1: - key = param[:index_of_equals].strip(items_to_strip) - value = param[index_of_equals + 1 :].strip(items_to_strip) - params_dict[key.lower()] = value - return content_type, params_dict - - -def get_encoding_from_headers(headers): - """Returns encodings from given HTTP Header Dict. - - :param headers: dictionary to extract encoding from. - :rtype: str - """ - - content_type = headers.get("content-type") - - if not content_type: - return None - - content_type, params = _parse_content_type_header(content_type) - - if "charset" in params: - return params["charset"].strip("'\"") - - if "text" in content_type: - return "ISO-8859-1" - - if "application/json" in content_type: - # Assume UTF-8 based on RFC 4627: https://www.ietf.org/rfc/rfc4627.txt since the charset was unset - return "utf-8" - - -def stream_decode_response_unicode(iterator, r): - """Stream decodes an iterator.""" - - if r.encoding is None: - yield from iterator - return - - decoder = codecs.getincrementaldecoder(r.encoding)(errors="replace") - for chunk in iterator: - rv = decoder.decode(chunk) - if rv: - yield rv - rv = decoder.decode(b"", final=True) - if rv: - yield rv - - -def iter_slices(string, slice_length): - """Iterate over slices of a string.""" - pos = 0 - if slice_length is None or slice_length <= 0: - slice_length = len(string) - while pos < len(string): - yield string[pos : pos + slice_length] - pos += slice_length - - -def get_unicode_from_response(r): - """Returns the requested content back in unicode. - - :param r: Response object to get unicode content from. - - Tried: - - 1. charset from content-type - 2. fall back and replace all unicode characters - - :rtype: str - """ - warnings.warn( - ( - "In requests 3.0, get_unicode_from_response will be removed. For " - "more information, please see the discussion on issue #2266. (This" - " warning should only appear once.)" - ), - DeprecationWarning, - ) - - tried_encodings = [] - - # Try charset from content-type - encoding = get_encoding_from_headers(r.headers) - - if encoding: - try: - return str(r.content, encoding) - except UnicodeError: - tried_encodings.append(encoding) - - # Fall back: - try: - return str(r.content, encoding, errors="replace") - except TypeError: - return r.content - - -# The unreserved URI characters (RFC 3986) -UNRESERVED_SET = frozenset( - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789-._~" -) - - -def unquote_unreserved(uri): - """Un-escape any percent-escape sequences in a URI that are unreserved - characters. This leaves all reserved, illegal and non-ASCII bytes encoded. - - :rtype: str - """ - parts = uri.split("%") - for i in range(1, len(parts)): - h = parts[i][0:2] - if len(h) == 2 and h.isalnum(): - try: - c = chr(int(h, 16)) - except ValueError: - raise InvalidURL(f"Invalid percent-escape sequence: '{h}'") - - if c in UNRESERVED_SET: - parts[i] = c + parts[i][2:] - else: - parts[i] = f"%{parts[i]}" - else: - parts[i] = f"%{parts[i]}" - return "".join(parts) - - -def requote_uri(uri): - """Re-quote the given URI. - - This function passes the given URI through an unquote/quote cycle to - ensure that it is fully and consistently quoted. - - :rtype: str - """ - safe_with_percent = "!#$%&'()*+,/:;=?@[]~" - safe_without_percent = "!#$&'()*+,/:;=?@[]~" - try: - # Unquote only the unreserved characters - # Then quote only illegal characters (do not quote reserved, - # unreserved, or '%') - return quote(unquote_unreserved(uri), safe=safe_with_percent) - except InvalidURL: - # We couldn't unquote the given URI, so let's try quoting it, but - # there may be unquoted '%'s in the URI. We need to make sure they're - # properly quoted so they do not cause issues elsewhere. - return quote(uri, safe=safe_without_percent) - - -def address_in_network(ip, net): - """This function allows you to check if an IP belongs to a network subnet - - Example: returns True if ip = 192.168.1.1 and net = 192.168.1.0/24 - returns False if ip = 192.168.1.1 and net = 192.168.100.0/24 - - :rtype: bool - """ - ipaddr = struct.unpack("=L", socket.inet_aton(ip))[0] - netaddr, bits = net.split("/") - netmask = struct.unpack("=L", socket.inet_aton(dotted_netmask(int(bits))))[0] - network = struct.unpack("=L", socket.inet_aton(netaddr))[0] & netmask - return (ipaddr & netmask) == (network & netmask) - - -def dotted_netmask(mask): - """Converts mask from /xx format to xxx.xxx.xxx.xxx - - Example: if mask is 24 function returns 255.255.255.0 - - :rtype: str - """ - bits = 0xFFFFFFFF ^ (1 << 32 - mask) - 1 - return socket.inet_ntoa(struct.pack(">I", bits)) - - -def is_ipv4_address(string_ip): - """ - :rtype: bool - """ - try: - socket.inet_aton(string_ip) - except OSError: - return False - return True - - -def is_valid_cidr(string_network): - """ - Very simple check of the cidr format in no_proxy variable. - - :rtype: bool - """ - if string_network.count("/") == 1: - try: - mask = int(string_network.split("/")[1]) - except ValueError: - return False - - if mask < 1 or mask > 32: - return False - - try: - socket.inet_aton(string_network.split("/")[0]) - except OSError: - return False - else: - return False - return True - - -@contextlib.contextmanager -def set_environ(env_name, value): - """Set the environment variable 'env_name' to 'value' - - Save previous value, yield, and then restore the previous value stored in - the environment variable 'env_name'. - - If 'value' is None, do nothing""" - value_changed = value is not None - if value_changed: - old_value = os.environ.get(env_name) - os.environ[env_name] = value - try: - yield - finally: - if value_changed: - if old_value is None: - del os.environ[env_name] - else: - os.environ[env_name] = old_value - - -def should_bypass_proxies(url, no_proxy): - """ - Returns whether we should bypass proxies or not. - - :rtype: bool - """ - # Prioritize lowercase environment variables over uppercase - # to keep a consistent behaviour with other http projects (curl, wget). - def get_proxy(key): - return os.environ.get(key) or os.environ.get(key.upper()) - - # First check whether no_proxy is defined. If it is, check that the URL - # we're getting isn't in the no_proxy list. - no_proxy_arg = no_proxy - if no_proxy is None: - no_proxy = get_proxy("no_proxy") - parsed = urlparse(url) - - if parsed.hostname is None: - # URLs don't always have hostnames, e.g. file:/// urls. - return True - - if no_proxy: - # We need to check whether we match here. We need to see if we match - # the end of the hostname, both with and without the port. - no_proxy = (host for host in no_proxy.replace(" ", "").split(",") if host) - - if is_ipv4_address(parsed.hostname): - for proxy_ip in no_proxy: - if is_valid_cidr(proxy_ip): - if address_in_network(parsed.hostname, proxy_ip): - return True - elif parsed.hostname == proxy_ip: - # If no_proxy ip was defined in plain IP notation instead of cidr notation & - # matches the IP of the index - return True - else: - host_with_port = parsed.hostname - if parsed.port: - host_with_port += f":{parsed.port}" - - for host in no_proxy: - if parsed.hostname.endswith(host) or host_with_port.endswith(host): - # The URL does match something in no_proxy, so we don't want - # to apply the proxies on this URL. - return True - - with set_environ("no_proxy", no_proxy_arg): - # parsed.hostname can be `None` in cases such as a file URI. - try: - bypass = proxy_bypass(parsed.hostname) - except (TypeError, socket.gaierror): - bypass = False - - if bypass: - return True - - return False - - -def get_environ_proxies(url, no_proxy=None): - """ - Return a dict of environment proxies. - - :rtype: dict - """ - if should_bypass_proxies(url, no_proxy=no_proxy): - return {} - else: - return getproxies() - - -def select_proxy(url, proxies): - """Select a proxy for the url, if applicable. - - :param url: The url being for the request - :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs - """ - proxies = proxies or {} - urlparts = urlparse(url) - if urlparts.hostname is None: - return proxies.get(urlparts.scheme, proxies.get("all")) - - proxy_keys = [ - urlparts.scheme + "://" + urlparts.hostname, - urlparts.scheme, - "all://" + urlparts.hostname, - "all", - ] - proxy = None - for proxy_key in proxy_keys: - if proxy_key in proxies: - proxy = proxies[proxy_key] - break - - return proxy - - -def resolve_proxies(request, proxies, trust_env=True): - """This method takes proxy information from a request and configuration - input to resolve a mapping of target proxies. This will consider settings - such a NO_PROXY to strip proxy configurations. - - :param request: Request or PreparedRequest - :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs - :param trust_env: Boolean declaring whether to trust environment configs - - :rtype: dict - """ - proxies = proxies if proxies is not None else {} - url = request.url - scheme = urlparse(url).scheme - no_proxy = proxies.get("no_proxy") - new_proxies = proxies.copy() - - if trust_env and not should_bypass_proxies(url, no_proxy=no_proxy): - environ_proxies = get_environ_proxies(url, no_proxy=no_proxy) - - proxy = environ_proxies.get(scheme, environ_proxies.get("all")) - - if proxy: - new_proxies.setdefault(scheme, proxy) - return new_proxies - - -def default_user_agent(name="python-requests"): - """ - Return a string representing the default user agent. - - :rtype: str - """ - return f"{name}/{__version__}" - - -def default_headers(): - """ - :rtype: requests.structures.CaseInsensitiveDict - """ - return CaseInsensitiveDict( - { - "User-Agent": default_user_agent(), - "Accept-Encoding": DEFAULT_ACCEPT_ENCODING, - "Accept": "*/*", - "Connection": "keep-alive", - } - ) - - -def parse_header_links(value): - """Return a list of parsed link headers proxies. - - i.e. Link: ; rel=front; type="image/jpeg",; rel=back;type="image/jpeg" - - :rtype: list - """ - - links = [] - - replace_chars = " '\"" - - value = value.strip(replace_chars) - if not value: - return links - - for val in re.split(", *<", value): - try: - url, params = val.split(";", 1) - except ValueError: - url, params = val, "" - - link = {"url": url.strip("<> '\"")} - - for param in params.split(";"): - try: - key, value = param.split("=") - except ValueError: - break - - link[key.strip(replace_chars)] = value.strip(replace_chars) - - links.append(link) - - return links - - -# Null bytes; no need to recreate these on each call to guess_json_utf -_null = "\x00".encode("ascii") # encoding to ASCII for Python 3 -_null2 = _null * 2 -_null3 = _null * 3 - - -def guess_json_utf(data): - """ - :rtype: str - """ - # JSON always starts with two ASCII characters, so detection is as - # easy as counting the nulls and from their location and count - # determine the encoding. Also detect a BOM, if present. - sample = data[:4] - if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE): - return "utf-32" # BOM included - if sample[:3] == codecs.BOM_UTF8: - return "utf-8-sig" # BOM included, MS style (discouraged) - if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE): - return "utf-16" # BOM included - nullcount = sample.count(_null) - if nullcount == 0: - return "utf-8" - if nullcount == 2: - if sample[::2] == _null2: # 1st and 3rd are null - return "utf-16-be" - if sample[1::2] == _null2: # 2nd and 4th are null - return "utf-16-le" - # Did not detect 2 valid UTF-16 ascii-range characters - if nullcount == 3: - if sample[:3] == _null3: - return "utf-32-be" - if sample[1:] == _null3: - return "utf-32-le" - # Did not detect a valid UTF-32 ascii-range character - return None - - -def prepend_scheme_if_needed(url, new_scheme): - """Given a URL that may or may not have a scheme, prepend the given scheme. - Does not replace a present scheme with the one provided as an argument. - - :rtype: str - """ - parsed = parse_url(url) - scheme, auth, host, port, path, query, fragment = parsed - - # A defect in urlparse determines that there isn't a netloc present in some - # urls. We previously assumed parsing was overly cautious, and swapped the - # netloc and path. Due to a lack of tests on the original defect, this is - # maintained with parse_url for backwards compatibility. - netloc = parsed.netloc - if not netloc: - netloc, path = path, netloc - - if auth: - # parse_url doesn't provide the netloc with auth - # so we'll add it ourselves. - netloc = "@".join([auth, netloc]) - if scheme is None: - scheme = new_scheme - if path is None: - path = "" - - return urlunparse((scheme, netloc, path, "", query, fragment)) - - -def get_auth_from_url(url): - """Given a url with authentication components, extract them into a tuple of - username,password. - - :rtype: (str,str) - """ - parsed = urlparse(url) - - try: - auth = (unquote(parsed.username), unquote(parsed.password)) - except (AttributeError, TypeError): - auth = ("", "") - - return auth - - -def check_header_validity(header): - """Verifies that header parts don't contain leading whitespace - reserved characters, or return characters. - - :param header: tuple, in the format (name, value). - """ - name, value = header - _validate_header_part(header, name, 0) - _validate_header_part(header, value, 1) - - -def _validate_header_part(header, header_part, header_validator_index): - if isinstance(header_part, str): - validator = _HEADER_VALIDATORS_STR[header_validator_index] - elif isinstance(header_part, bytes): - validator = _HEADER_VALIDATORS_BYTE[header_validator_index] - else: - raise InvalidHeader( - f"Header part ({header_part!r}) from {header} " - f"must be of type str or bytes, not {type(header_part)}" - ) - - if not validator.match(header_part): - header_kind = "name" if header_validator_index == 0 else "value" - raise InvalidHeader( - f"Invalid leading whitespace, reserved character(s), or return" - f"character(s) in header {header_kind}: {header_part!r}" - ) - - -def urldefragauth(url): - """ - Given a url remove the fragment and the authentication part. - - :rtype: str - """ - scheme, netloc, path, params, query, fragment = urlparse(url) - - # see func:`prepend_scheme_if_needed` - if not netloc: - netloc, path = path, netloc - - netloc = netloc.rsplit("@", 1)[-1] - - return urlunparse((scheme, netloc, path, params, query, "")) - - -def rewind_body(prepared_request): - """Move file pointer back to its recorded starting position - so it can be read again on redirect. - """ - body_seek = getattr(prepared_request.body, "seek", None) - if body_seek is not None and isinstance( - prepared_request._body_position, integer_types - ): - try: - body_seek(prepared_request._body_position) - except OSError: - raise UnrewindableBodyError( - "An error occurred when rewinding request body for redirect." - ) - else: - raise UnrewindableBodyError("Unable to rewind request body for redirect.") diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py deleted file mode 100644 index d92acc7..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -__all__ = [ - "__version__", - "AbstractProvider", - "AbstractResolver", - "BaseReporter", - "InconsistentCandidate", - "Resolver", - "RequirementsConflicted", - "ResolutionError", - "ResolutionImpossible", - "ResolutionTooDeep", -] - -__version__ = "1.0.1" - - -from .providers import AbstractProvider, AbstractResolver -from .reporters import BaseReporter -from .resolvers import ( - InconsistentCandidate, - RequirementsConflicted, - ResolutionError, - ResolutionImpossible, - ResolutionTooDeep, - Resolver, -) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f1eb96b..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc deleted file mode 100644 index 45554dc..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc deleted file mode 100644 index 653fe51..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc deleted file mode 100644 index 1db6309..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc deleted file mode 100644 index 10c4176..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index ff7649e..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc deleted file mode 100644 index 83b9f22..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py deleted file mode 100644 index 1becc50..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py +++ /dev/null @@ -1,6 +0,0 @@ -__all__ = ["Mapping", "Sequence"] - -try: - from collections.abc import Mapping, Sequence -except ImportError: - from collections import Mapping, Sequence diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py deleted file mode 100644 index e99d87e..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py +++ /dev/null @@ -1,133 +0,0 @@ -class AbstractProvider(object): - """Delegate class to provide the required interface for the resolver.""" - - def identify(self, requirement_or_candidate): - """Given a requirement, return an identifier for it. - - This is used to identify a requirement, e.g. whether two requirements - should have their specifier parts merged. - """ - raise NotImplementedError - - def get_preference( - self, - identifier, - resolutions, - candidates, - information, - backtrack_causes, - ): - """Produce a sort key for given requirement based on preference. - - The preference is defined as "I think this requirement should be - resolved first". The lower the return value is, the more preferred - this group of arguments is. - - :param identifier: An identifier as returned by ``identify()``. This - identifies the dependency matches which should be returned. - :param resolutions: Mapping of candidates currently pinned by the - resolver. Each key is an identifier, and the value is a candidate. - The candidate may conflict with requirements from ``information``. - :param candidates: Mapping of each dependency's possible candidates. - Each value is an iterator of candidates. - :param information: Mapping of requirement information of each package. - Each value is an iterator of *requirement information*. - :param backtrack_causes: Sequence of requirement information that were - the requirements that caused the resolver to most recently backtrack. - - A *requirement information* instance is a named tuple with two members: - - * ``requirement`` specifies a requirement contributing to the current - list of candidates. - * ``parent`` specifies the candidate that provides (depended on) the - requirement, or ``None`` to indicate a root requirement. - - The preference could depend on various issues, including (not - necessarily in this order): - - * Is this package pinned in the current resolution result? - * How relaxed is the requirement? Stricter ones should probably be - worked on first? (I don't know, actually.) - * How many possibilities are there to satisfy this requirement? Those - with few left should likely be worked on first, I guess? - * Are there any known conflicts for this requirement? We should - probably work on those with the most known conflicts. - - A sortable value should be returned (this will be used as the ``key`` - parameter of the built-in sorting function). The smaller the value is, - the more preferred this requirement is (i.e. the sorting function - is called with ``reverse=False``). - """ - raise NotImplementedError - - def find_matches(self, identifier, requirements, incompatibilities): - """Find all possible candidates that satisfy the given constraints. - - :param identifier: An identifier as returned by ``identify()``. This - identifies the dependency matches of which should be returned. - :param requirements: A mapping of requirements that all returned - candidates must satisfy. Each key is an identifier, and the value - an iterator of requirements for that dependency. - :param incompatibilities: A mapping of known incompatibilities of - each dependency. Each key is an identifier, and the value an - iterator of incompatibilities known to the resolver. All - incompatibilities *must* be excluded from the return value. - - This should try to get candidates based on the requirements' types. - For VCS, local, and archive requirements, the one-and-only match is - returned, and for a "named" requirement, the index(es) should be - consulted to find concrete candidates for this requirement. - - The return value should produce candidates ordered by preference; the - most preferred candidate should come first. The return type may be one - of the following: - - * A callable that returns an iterator that yields candidates. - * An collection of candidates. - * An iterable of candidates. This will be consumed immediately into a - list of candidates. - """ - raise NotImplementedError - - def is_satisfied_by(self, requirement, candidate): - """Whether the given requirement can be satisfied by a candidate. - - The candidate is guaranteed to have been generated from the - requirement. - - A boolean should be returned to indicate whether ``candidate`` is a - viable solution to the requirement. - """ - raise NotImplementedError - - def get_dependencies(self, candidate): - """Get dependencies of a candidate. - - This should return a collection of requirements that `candidate` - specifies as its dependencies. - """ - raise NotImplementedError - - -class AbstractResolver(object): - """The thing that performs the actual resolution work.""" - - base_exception = Exception - - def __init__(self, provider, reporter): - self.provider = provider - self.reporter = reporter - - def resolve(self, requirements, **kwargs): - """Take a collection of constraints, spit out the resolution result. - - This returns a representation of the final resolution state, with one - guarenteed attribute ``mapping`` that contains resolved candidates as - values. The keys are their respective identifiers. - - :param requirements: A collection of constraints. - :param kwargs: Additional keyword arguments that subclasses may accept. - - :raises: ``self.base_exception`` or its subclass. - """ - raise NotImplementedError diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py deleted file mode 100644 index 688b5e1..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py +++ /dev/null @@ -1,43 +0,0 @@ -class BaseReporter(object): - """Delegate class to provider progress reporting for the resolver.""" - - def starting(self): - """Called before the resolution actually starts.""" - - def starting_round(self, index): - """Called before each round of resolution starts. - - The index is zero-based. - """ - - def ending_round(self, index, state): - """Called before each round of resolution ends. - - This is NOT called if the resolution ends at this round. Use `ending` - if you want to report finalization. The index is zero-based. - """ - - def ending(self, state): - """Called before the resolution ends successfully.""" - - def adding_requirement(self, requirement, parent): - """Called when adding a new requirement into the resolve criteria. - - :param requirement: The additional requirement to be applied to filter - the available candidaites. - :param parent: The candidate that requires ``requirement`` as a - dependency, or None if ``requirement`` is one of the root - requirements passed in from ``Resolver.resolve()``. - """ - - def resolving_conflicts(self, causes): - """Called when starting to attempt requirement conflict resolution. - - :param causes: The information on the collision that caused the backtracking. - """ - - def rejecting_candidate(self, criterion, candidate): - """Called when rejecting a candidate during backtracking.""" - - def pinning(self, candidate): - """Called when adding a candidate to the potential solution.""" diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py deleted file mode 100644 index 2c3d0e3..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py +++ /dev/null @@ -1,547 +0,0 @@ -import collections -import itertools -import operator - -from .providers import AbstractResolver -from .structs import DirectedGraph, IteratorMapping, build_iter_view - -RequirementInformation = collections.namedtuple( - "RequirementInformation", ["requirement", "parent"] -) - - -class ResolverException(Exception): - """A base class for all exceptions raised by this module. - - Exceptions derived by this class should all be handled in this module. Any - bubbling pass the resolver should be treated as a bug. - """ - - -class RequirementsConflicted(ResolverException): - def __init__(self, criterion): - super(RequirementsConflicted, self).__init__(criterion) - self.criterion = criterion - - def __str__(self): - return "Requirements conflict: {}".format( - ", ".join(repr(r) for r in self.criterion.iter_requirement()), - ) - - -class InconsistentCandidate(ResolverException): - def __init__(self, candidate, criterion): - super(InconsistentCandidate, self).__init__(candidate, criterion) - self.candidate = candidate - self.criterion = criterion - - def __str__(self): - return "Provided candidate {!r} does not satisfy {}".format( - self.candidate, - ", ".join(repr(r) for r in self.criterion.iter_requirement()), - ) - - -class Criterion(object): - """Representation of possible resolution results of a package. - - This holds three attributes: - - * `information` is a collection of `RequirementInformation` pairs. - Each pair is a requirement contributing to this criterion, and the - candidate that provides the requirement. - * `incompatibilities` is a collection of all known not-to-work candidates - to exclude from consideration. - * `candidates` is a collection containing all possible candidates deducted - from the union of contributing requirements and known incompatibilities. - It should never be empty, except when the criterion is an attribute of a - raised `RequirementsConflicted` (in which case it is always empty). - - .. note:: - This class is intended to be externally immutable. **Do not** mutate - any of its attribute containers. - """ - - def __init__(self, candidates, information, incompatibilities): - self.candidates = candidates - self.information = information - self.incompatibilities = incompatibilities - - def __repr__(self): - requirements = ", ".join( - "({!r}, via={!r})".format(req, parent) - for req, parent in self.information - ) - return "Criterion({})".format(requirements) - - def iter_requirement(self): - return (i.requirement for i in self.information) - - def iter_parent(self): - return (i.parent for i in self.information) - - -class ResolutionError(ResolverException): - pass - - -class ResolutionImpossible(ResolutionError): - def __init__(self, causes): - super(ResolutionImpossible, self).__init__(causes) - # causes is a list of RequirementInformation objects - self.causes = causes - - -class ResolutionTooDeep(ResolutionError): - def __init__(self, round_count): - super(ResolutionTooDeep, self).__init__(round_count) - self.round_count = round_count - - -# Resolution state in a round. -State = collections.namedtuple("State", "mapping criteria backtrack_causes") - - -class Resolution(object): - """Stateful resolution object. - - This is designed as a one-off object that holds information to kick start - the resolution process, and holds the results afterwards. - """ - - def __init__(self, provider, reporter): - self._p = provider - self._r = reporter - self._states = [] - - @property - def state(self): - try: - return self._states[-1] - except IndexError: - raise AttributeError("state") - - def _push_new_state(self): - """Push a new state into history. - - This new state will be used to hold resolution results of the next - coming round. - """ - base = self._states[-1] - state = State( - mapping=base.mapping.copy(), - criteria=base.criteria.copy(), - backtrack_causes=base.backtrack_causes[:], - ) - self._states.append(state) - - def _add_to_criteria(self, criteria, requirement, parent): - self._r.adding_requirement(requirement=requirement, parent=parent) - - identifier = self._p.identify(requirement_or_candidate=requirement) - criterion = criteria.get(identifier) - if criterion: - incompatibilities = list(criterion.incompatibilities) - else: - incompatibilities = [] - - matches = self._p.find_matches( - identifier=identifier, - requirements=IteratorMapping( - criteria, - operator.methodcaller("iter_requirement"), - {identifier: [requirement]}, - ), - incompatibilities=IteratorMapping( - criteria, - operator.attrgetter("incompatibilities"), - {identifier: incompatibilities}, - ), - ) - - if criterion: - information = list(criterion.information) - information.append(RequirementInformation(requirement, parent)) - else: - information = [RequirementInformation(requirement, parent)] - - criterion = Criterion( - candidates=build_iter_view(matches), - information=information, - incompatibilities=incompatibilities, - ) - if not criterion.candidates: - raise RequirementsConflicted(criterion) - criteria[identifier] = criterion - - def _remove_information_from_criteria(self, criteria, parents): - """Remove information from parents of criteria. - - Concretely, removes all values from each criterion's ``information`` - field that have one of ``parents`` as provider of the requirement. - - :param criteria: The criteria to update. - :param parents: Identifiers for which to remove information from all criteria. - """ - if not parents: - return - for key, criterion in criteria.items(): - criteria[key] = Criterion( - criterion.candidates, - [ - information - for information in criterion.information - if ( - information.parent is None - or self._p.identify(information.parent) not in parents - ) - ], - criterion.incompatibilities, - ) - - def _get_preference(self, name): - return self._p.get_preference( - identifier=name, - resolutions=self.state.mapping, - candidates=IteratorMapping( - self.state.criteria, - operator.attrgetter("candidates"), - ), - information=IteratorMapping( - self.state.criteria, - operator.attrgetter("information"), - ), - backtrack_causes=self.state.backtrack_causes, - ) - - def _is_current_pin_satisfying(self, name, criterion): - try: - current_pin = self.state.mapping[name] - except KeyError: - return False - return all( - self._p.is_satisfied_by(requirement=r, candidate=current_pin) - for r in criterion.iter_requirement() - ) - - def _get_updated_criteria(self, candidate): - criteria = self.state.criteria.copy() - for requirement in self._p.get_dependencies(candidate=candidate): - self._add_to_criteria(criteria, requirement, parent=candidate) - return criteria - - def _attempt_to_pin_criterion(self, name): - criterion = self.state.criteria[name] - - causes = [] - for candidate in criterion.candidates: - try: - criteria = self._get_updated_criteria(candidate) - except RequirementsConflicted as e: - self._r.rejecting_candidate(e.criterion, candidate) - causes.append(e.criterion) - continue - - # Check the newly-pinned candidate actually works. This should - # always pass under normal circumstances, but in the case of a - # faulty provider, we will raise an error to notify the implementer - # to fix find_matches() and/or is_satisfied_by(). - satisfied = all( - self._p.is_satisfied_by(requirement=r, candidate=candidate) - for r in criterion.iter_requirement() - ) - if not satisfied: - raise InconsistentCandidate(candidate, criterion) - - self._r.pinning(candidate=candidate) - self.state.criteria.update(criteria) - - # Put newly-pinned candidate at the end. This is essential because - # backtracking looks at this mapping to get the last pin. - self.state.mapping.pop(name, None) - self.state.mapping[name] = candidate - - return [] - - # All candidates tried, nothing works. This criterion is a dead - # end, signal for backtracking. - return causes - - def _backjump(self, causes): - """Perform backjumping. - - When we enter here, the stack is like this:: - - [ state Z ] - [ state Y ] - [ state X ] - .... earlier states are irrelevant. - - 1. No pins worked for Z, so it does not have a pin. - 2. We want to reset state Y to unpinned, and pin another candidate. - 3. State X holds what state Y was before the pin, but does not - have the incompatibility information gathered in state Y. - - Each iteration of the loop will: - - 1. Identify Z. The incompatibility is not always caused by the latest - state. For example, given three requirements A, B and C, with - dependencies A1, B1 and C1, where A1 and B1 are incompatible: the - last state might be related to C, so we want to discard the - previous state. - 2. Discard Z. - 3. Discard Y but remember its incompatibility information gathered - previously, and the failure we're dealing with right now. - 4. Push a new state Y' based on X, and apply the incompatibility - information from Y to Y'. - 5a. If this causes Y' to conflict, we need to backtrack again. Make Y' - the new Z and go back to step 2. - 5b. If the incompatibilities apply cleanly, end backtracking. - """ - incompatible_reqs = itertools.chain( - (c.parent for c in causes if c.parent is not None), - (c.requirement for c in causes), - ) - incompatible_deps = {self._p.identify(r) for r in incompatible_reqs} - while len(self._states) >= 3: - # Remove the state that triggered backtracking. - del self._states[-1] - - # Ensure to backtrack to a state that caused the incompatibility - incompatible_state = False - while not incompatible_state: - # Retrieve the last candidate pin and known incompatibilities. - try: - broken_state = self._states.pop() - name, candidate = broken_state.mapping.popitem() - except (IndexError, KeyError): - raise ResolutionImpossible(causes) - current_dependencies = { - self._p.identify(d) - for d in self._p.get_dependencies(candidate) - } - incompatible_state = not current_dependencies.isdisjoint( - incompatible_deps - ) - - incompatibilities_from_broken = [ - (k, list(v.incompatibilities)) - for k, v in broken_state.criteria.items() - ] - - # Also mark the newly known incompatibility. - incompatibilities_from_broken.append((name, [candidate])) - - # Create a new state from the last known-to-work one, and apply - # the previously gathered incompatibility information. - def _patch_criteria(): - for k, incompatibilities in incompatibilities_from_broken: - if not incompatibilities: - continue - try: - criterion = self.state.criteria[k] - except KeyError: - continue - matches = self._p.find_matches( - identifier=k, - requirements=IteratorMapping( - self.state.criteria, - operator.methodcaller("iter_requirement"), - ), - incompatibilities=IteratorMapping( - self.state.criteria, - operator.attrgetter("incompatibilities"), - {k: incompatibilities}, - ), - ) - candidates = build_iter_view(matches) - if not candidates: - return False - incompatibilities.extend(criterion.incompatibilities) - self.state.criteria[k] = Criterion( - candidates=candidates, - information=list(criterion.information), - incompatibilities=incompatibilities, - ) - return True - - self._push_new_state() - success = _patch_criteria() - - # It works! Let's work on this new state. - if success: - return True - - # State does not work after applying known incompatibilities. - # Try the still previous state. - - # No way to backtrack anymore. - return False - - def resolve(self, requirements, max_rounds): - if self._states: - raise RuntimeError("already resolved") - - self._r.starting() - - # Initialize the root state. - self._states = [ - State( - mapping=collections.OrderedDict(), - criteria={}, - backtrack_causes=[], - ) - ] - for r in requirements: - try: - self._add_to_criteria(self.state.criteria, r, parent=None) - except RequirementsConflicted as e: - raise ResolutionImpossible(e.criterion.information) - - # The root state is saved as a sentinel so the first ever pin can have - # something to backtrack to if it fails. The root state is basically - # pinning the virtual "root" package in the graph. - self._push_new_state() - - for round_index in range(max_rounds): - self._r.starting_round(index=round_index) - - unsatisfied_names = [ - key - for key, criterion in self.state.criteria.items() - if not self._is_current_pin_satisfying(key, criterion) - ] - - # All criteria are accounted for. Nothing more to pin, we are done! - if not unsatisfied_names: - self._r.ending(state=self.state) - return self.state - - # keep track of satisfied names to calculate diff after pinning - satisfied_names = set(self.state.criteria.keys()) - set( - unsatisfied_names - ) - - # Choose the most preferred unpinned criterion to try. - name = min(unsatisfied_names, key=self._get_preference) - failure_causes = self._attempt_to_pin_criterion(name) - - if failure_causes: - causes = [i for c in failure_causes for i in c.information] - # Backjump if pinning fails. The backjump process puts us in - # an unpinned state, so we can work on it in the next round. - self._r.resolving_conflicts(causes=causes) - success = self._backjump(causes) - self.state.backtrack_causes[:] = causes - - # Dead ends everywhere. Give up. - if not success: - raise ResolutionImpossible(self.state.backtrack_causes) - else: - # discard as information sources any invalidated names - # (unsatisfied names that were previously satisfied) - newly_unsatisfied_names = { - key - for key, criterion in self.state.criteria.items() - if key in satisfied_names - and not self._is_current_pin_satisfying(key, criterion) - } - self._remove_information_from_criteria( - self.state.criteria, newly_unsatisfied_names - ) - # Pinning was successful. Push a new state to do another pin. - self._push_new_state() - - self._r.ending_round(index=round_index, state=self.state) - - raise ResolutionTooDeep(max_rounds) - - -def _has_route_to_root(criteria, key, all_keys, connected): - if key in connected: - return True - if key not in criteria: - return False - for p in criteria[key].iter_parent(): - try: - pkey = all_keys[id(p)] - except KeyError: - continue - if pkey in connected: - connected.add(key) - return True - if _has_route_to_root(criteria, pkey, all_keys, connected): - connected.add(key) - return True - return False - - -Result = collections.namedtuple("Result", "mapping graph criteria") - - -def _build_result(state): - mapping = state.mapping - all_keys = {id(v): k for k, v in mapping.items()} - all_keys[id(None)] = None - - graph = DirectedGraph() - graph.add(None) # Sentinel as root dependencies' parent. - - connected = {None} - for key, criterion in state.criteria.items(): - if not _has_route_to_root(state.criteria, key, all_keys, connected): - continue - if key not in graph: - graph.add(key) - for p in criterion.iter_parent(): - try: - pkey = all_keys[id(p)] - except KeyError: - continue - if pkey not in graph: - graph.add(pkey) - graph.connect(pkey, key) - - return Result( - mapping={k: v for k, v in mapping.items() if k in connected}, - graph=graph, - criteria=state.criteria, - ) - - -class Resolver(AbstractResolver): - """The thing that performs the actual resolution work.""" - - base_exception = ResolverException - - def resolve(self, requirements, max_rounds=100): - """Take a collection of constraints, spit out the resolution result. - - The return value is a representation to the final resolution result. It - is a tuple subclass with three public members: - - * `mapping`: A dict of resolved candidates. Each key is an identifier - of a requirement (as returned by the provider's `identify` method), - and the value is the resolved candidate. - * `graph`: A `DirectedGraph` instance representing the dependency tree. - The vertices are keys of `mapping`, and each edge represents *why* - a particular package is included. A special vertex `None` is - included to represent parents of user-supplied requirements. - * `criteria`: A dict of "criteria" that hold detailed information on - how edges in the graph are derived. Each key is an identifier of a - requirement, and the value is a `Criterion` instance. - - The following exceptions may be raised if a resolution cannot be found: - - * `ResolutionImpossible`: A resolution cannot be found for the given - combination of requirements. The `causes` attribute of the - exception is a list of (requirement, parent), giving the - requirements that could not be satisfied. - * `ResolutionTooDeep`: The dependency tree is too deeply nested and - the resolver gave up. This is usually caused by a circular - dependency, but you can try to resolve this by increasing the - `max_rounds` argument. - """ - resolution = Resolution(self.provider, self.reporter) - state = resolution.resolve(requirements, max_rounds=max_rounds) - return _build_result(state) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py b/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py deleted file mode 100644 index 359a34f..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py +++ /dev/null @@ -1,170 +0,0 @@ -import itertools - -from .compat import collections_abc - - -class DirectedGraph(object): - """A graph structure with directed edges.""" - - def __init__(self): - self._vertices = set() - self._forwards = {} # -> Set[] - self._backwards = {} # -> Set[] - - def __iter__(self): - return iter(self._vertices) - - def __len__(self): - return len(self._vertices) - - def __contains__(self, key): - return key in self._vertices - - def copy(self): - """Return a shallow copy of this graph.""" - other = DirectedGraph() - other._vertices = set(self._vertices) - other._forwards = {k: set(v) for k, v in self._forwards.items()} - other._backwards = {k: set(v) for k, v in self._backwards.items()} - return other - - def add(self, key): - """Add a new vertex to the graph.""" - if key in self._vertices: - raise ValueError("vertex exists") - self._vertices.add(key) - self._forwards[key] = set() - self._backwards[key] = set() - - def remove(self, key): - """Remove a vertex from the graph, disconnecting all edges from/to it.""" - self._vertices.remove(key) - for f in self._forwards.pop(key): - self._backwards[f].remove(key) - for t in self._backwards.pop(key): - self._forwards[t].remove(key) - - def connected(self, f, t): - return f in self._backwards[t] and t in self._forwards[f] - - def connect(self, f, t): - """Connect two existing vertices. - - Nothing happens if the vertices are already connected. - """ - if t not in self._vertices: - raise KeyError(t) - self._forwards[f].add(t) - self._backwards[t].add(f) - - def iter_edges(self): - for f, children in self._forwards.items(): - for t in children: - yield f, t - - def iter_children(self, key): - return iter(self._forwards[key]) - - def iter_parents(self, key): - return iter(self._backwards[key]) - - -class IteratorMapping(collections_abc.Mapping): - def __init__(self, mapping, accessor, appends=None): - self._mapping = mapping - self._accessor = accessor - self._appends = appends or {} - - def __repr__(self): - return "IteratorMapping({!r}, {!r}, {!r})".format( - self._mapping, - self._accessor, - self._appends, - ) - - def __bool__(self): - return bool(self._mapping or self._appends) - - __nonzero__ = __bool__ # XXX: Python 2. - - def __contains__(self, key): - return key in self._mapping or key in self._appends - - def __getitem__(self, k): - try: - v = self._mapping[k] - except KeyError: - return iter(self._appends[k]) - return itertools.chain(self._accessor(v), self._appends.get(k, ())) - - def __iter__(self): - more = (k for k in self._appends if k not in self._mapping) - return itertools.chain(self._mapping, more) - - def __len__(self): - more = sum(1 for k in self._appends if k not in self._mapping) - return len(self._mapping) + more - - -class _FactoryIterableView(object): - """Wrap an iterator factory returned by `find_matches()`. - - Calling `iter()` on this class would invoke the underlying iterator - factory, making it a "collection with ordering" that can be iterated - through multiple times, but lacks random access methods presented in - built-in Python sequence types. - """ - - def __init__(self, factory): - self._factory = factory - self._iterable = None - - def __repr__(self): - return "{}({})".format(type(self).__name__, list(self)) - - def __bool__(self): - try: - next(iter(self)) - except StopIteration: - return False - return True - - __nonzero__ = __bool__ # XXX: Python 2. - - def __iter__(self): - iterable = ( - self._factory() if self._iterable is None else self._iterable - ) - self._iterable, current = itertools.tee(iterable) - return current - - -class _SequenceIterableView(object): - """Wrap an iterable returned by find_matches(). - - This is essentially just a proxy to the underlying sequence that provides - the same interface as `_FactoryIterableView`. - """ - - def __init__(self, sequence): - self._sequence = sequence - - def __repr__(self): - return "{}({})".format(type(self).__name__, self._sequence) - - def __bool__(self): - return bool(self._sequence) - - __nonzero__ = __bool__ # XXX: Python 2. - - def __iter__(self): - return iter(self._sequence) - - -def build_iter_view(matches): - """Build an iterable view from the value returned by `find_matches()`.""" - if callable(matches): - return _FactoryIterableView(matches) - if not isinstance(matches, collections_abc.Sequence): - matches = list(matches) - return _SequenceIterableView(matches) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py deleted file mode 100644 index 73f58d7..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py +++ /dev/null @@ -1,177 +0,0 @@ -"""Rich text and beautiful formatting in the terminal.""" - -import os -from typing import IO, TYPE_CHECKING, Any, Callable, Optional, Union - -from ._extension import load_ipython_extension # noqa: F401 - -__all__ = ["get_console", "reconfigure", "print", "inspect", "print_json"] - -if TYPE_CHECKING: - from .console import Console - -# Global console used by alternative print -_console: Optional["Console"] = None - -try: - _IMPORT_CWD = os.path.abspath(os.getcwd()) -except FileNotFoundError: - # Can happen if the cwd has been deleted - _IMPORT_CWD = "" - - -def get_console() -> "Console": - """Get a global :class:`~rich.console.Console` instance. This function is used when Rich requires a Console, - and hasn't been explicitly given one. - - Returns: - Console: A console instance. - """ - global _console - if _console is None: - from .console import Console - - _console = Console() - - return _console - - -def reconfigure(*args: Any, **kwargs: Any) -> None: - """Reconfigures the global console by replacing it with another. - - Args: - *args (Any): Positional arguments for the replacement :class:`~rich.console.Console`. - **kwargs (Any): Keyword arguments for the replacement :class:`~rich.console.Console`. - """ - from pip._vendor.rich.console import Console - - new_console = Console(*args, **kwargs) - _console = get_console() - _console.__dict__ = new_console.__dict__ - - -def print( - *objects: Any, - sep: str = " ", - end: str = "\n", - file: Optional[IO[str]] = None, - flush: bool = False, -) -> None: - r"""Print object(s) supplied via positional arguments. - This function has an identical signature to the built-in print. - For more advanced features, see the :class:`~rich.console.Console` class. - - Args: - sep (str, optional): Separator between printed objects. Defaults to " ". - end (str, optional): Character to write at end of output. Defaults to "\\n". - file (IO[str], optional): File to write to, or None for stdout. Defaults to None. - flush (bool, optional): Has no effect as Rich always flushes output. Defaults to False. - - """ - from .console import Console - - write_console = get_console() if file is None else Console(file=file) - return write_console.print(*objects, sep=sep, end=end) - - -def print_json( - json: Optional[str] = None, - *, - data: Any = None, - indent: Union[None, int, str] = 2, - highlight: bool = True, - skip_keys: bool = False, - ensure_ascii: bool = False, - check_circular: bool = True, - allow_nan: bool = True, - default: Optional[Callable[[Any], Any]] = None, - sort_keys: bool = False, -) -> None: - """Pretty prints JSON. Output will be valid JSON. - - Args: - json (str): A string containing JSON. - data (Any): If json is not supplied, then encode this data. - indent (int, optional): Number of spaces to indent. Defaults to 2. - highlight (bool, optional): Enable highlighting of output: Defaults to True. - skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. - ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. - check_circular (bool, optional): Check for circular references. Defaults to True. - allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True. - default (Callable, optional): A callable that converts values that can not be encoded - in to something that can be JSON encoded. Defaults to None. - sort_keys (bool, optional): Sort dictionary keys. Defaults to False. - """ - - get_console().print_json( - json, - data=data, - indent=indent, - highlight=highlight, - skip_keys=skip_keys, - ensure_ascii=ensure_ascii, - check_circular=check_circular, - allow_nan=allow_nan, - default=default, - sort_keys=sort_keys, - ) - - -def inspect( - obj: Any, - *, - console: Optional["Console"] = None, - title: Optional[str] = None, - help: bool = False, - methods: bool = False, - docs: bool = True, - private: bool = False, - dunder: bool = False, - sort: bool = True, - all: bool = False, - value: bool = True, -) -> None: - """Inspect any Python object. - - * inspect() to see summarized info. - * inspect(, methods=True) to see methods. - * inspect(, help=True) to see full (non-abbreviated) help. - * inspect(, private=True) to see private attributes (single underscore). - * inspect(, dunder=True) to see attributes beginning with double underscore. - * inspect(, all=True) to see all attributes. - - Args: - obj (Any): An object to inspect. - title (str, optional): Title to display over inspect result, or None use type. Defaults to None. - help (bool, optional): Show full help text rather than just first paragraph. Defaults to False. - methods (bool, optional): Enable inspection of callables. Defaults to False. - docs (bool, optional): Also render doc strings. Defaults to True. - private (bool, optional): Show private attributes (beginning with underscore). Defaults to False. - dunder (bool, optional): Show attributes starting with double underscore. Defaults to False. - sort (bool, optional): Sort attributes alphabetically. Defaults to True. - all (bool, optional): Show all attributes. Defaults to False. - value (bool, optional): Pretty print value. Defaults to True. - """ - _console = console or get_console() - from pip._vendor.rich._inspect import Inspect - - # Special case for inspect(inspect) - is_inspect = obj is inspect - - _inspect = Inspect( - obj, - title=title, - help=is_inspect or help, - methods=is_inspect or methods, - docs=is_inspect or docs, - private=private, - dunder=dunder, - sort=sort, - all=all, - value=value, - ) - _console.print(_inspect) - - -if __name__ == "__main__": # pragma: no cover - print("Hello, **World**") diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py deleted file mode 100644 index 270629f..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py +++ /dev/null @@ -1,274 +0,0 @@ -import colorsys -import io -from time import process_time - -from pip._vendor.rich import box -from pip._vendor.rich.color import Color -from pip._vendor.rich.console import Console, ConsoleOptions, Group, RenderableType, RenderResult -from pip._vendor.rich.markdown import Markdown -from pip._vendor.rich.measure import Measurement -from pip._vendor.rich.pretty import Pretty -from pip._vendor.rich.segment import Segment -from pip._vendor.rich.style import Style -from pip._vendor.rich.syntax import Syntax -from pip._vendor.rich.table import Table -from pip._vendor.rich.text import Text - - -class ColorBox: - def __rich_console__( - self, console: Console, options: ConsoleOptions - ) -> RenderResult: - for y in range(0, 5): - for x in range(options.max_width): - h = x / options.max_width - l = 0.1 + ((y / 5) * 0.7) - r1, g1, b1 = colorsys.hls_to_rgb(h, l, 1.0) - r2, g2, b2 = colorsys.hls_to_rgb(h, l + 0.7 / 10, 1.0) - bgcolor = Color.from_rgb(r1 * 255, g1 * 255, b1 * 255) - color = Color.from_rgb(r2 * 255, g2 * 255, b2 * 255) - yield Segment("â–„", Style(color=color, bgcolor=bgcolor)) - yield Segment.line() - - def __rich_measure__( - self, console: "Console", options: ConsoleOptions - ) -> Measurement: - return Measurement(1, options.max_width) - - -def make_test_card() -> Table: - """Get a renderable that demonstrates a number of features.""" - table = Table.grid(padding=1, pad_edge=True) - table.title = "Rich features" - table.add_column("Feature", no_wrap=True, justify="center", style="bold red") - table.add_column("Demonstration") - - color_table = Table( - box=None, - expand=False, - show_header=False, - show_edge=False, - pad_edge=False, - ) - color_table.add_row( - ( - "✓ [bold green]4-bit color[/]\n" - "✓ [bold blue]8-bit color[/]\n" - "✓ [bold magenta]Truecolor (16.7 million)[/]\n" - "✓ [bold yellow]Dumb terminals[/]\n" - "✓ [bold cyan]Automatic color conversion" - ), - ColorBox(), - ) - - table.add_row("Colors", color_table) - - table.add_row( - "Styles", - "All ansi styles: [bold]bold[/], [dim]dim[/], [italic]italic[/italic], [underline]underline[/], [strike]strikethrough[/], [reverse]reverse[/], and even [blink]blink[/].", - ) - - lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque in metus sed sapien ultricies pretium a at justo. Maecenas luctus velit et auctor maximus." - lorem_table = Table.grid(padding=1, collapse_padding=True) - lorem_table.pad_edge = False - lorem_table.add_row( - Text(lorem, justify="left", style="green"), - Text(lorem, justify="center", style="yellow"), - Text(lorem, justify="right", style="blue"), - Text(lorem, justify="full", style="red"), - ) - table.add_row( - "Text", - Group( - Text.from_markup( - """Word wrap text. Justify [green]left[/], [yellow]center[/], [blue]right[/] or [red]full[/].\n""" - ), - lorem_table, - ), - ) - - def comparison(renderable1: RenderableType, renderable2: RenderableType) -> Table: - table = Table(show_header=False, pad_edge=False, box=None, expand=True) - table.add_column("1", ratio=1) - table.add_column("2", ratio=1) - table.add_row(renderable1, renderable2) - return table - - table.add_row( - "Asian\nlanguage\nsupport", - ":flag_for_china: 该库支æŒä¸­æ–‡ï¼Œæ—¥æ–‡å’ŒéŸ©æ–‡æ–‡æœ¬ï¼\n:flag_for_japan: ライブラリã¯ä¸­å›½èªžã€æ—¥æœ¬èªžã€éŸ“国語ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™\n:flag_for_south_korea: ì´ ë¼ì´ë¸ŒëŸ¬ë¦¬ëŠ” 중국어, ì¼ë³¸ì–´ ë° í•œêµ­ì–´ í…스트를 ì§€ì›í•©ë‹ˆë‹¤", - ) - - markup_example = ( - "[bold magenta]Rich[/] supports a simple [i]bbcode[/i]-like [b]markup[/b] for [yellow]color[/], [underline]style[/], and emoji! " - ":+1: :apple: :ant: :bear: :baguette_bread: :bus: " - ) - table.add_row("Markup", markup_example) - - example_table = Table( - show_edge=False, - show_header=True, - expand=False, - row_styles=["none", "dim"], - box=box.SIMPLE, - ) - example_table.add_column("[green]Date", style="green", no_wrap=True) - example_table.add_column("[blue]Title", style="blue") - example_table.add_column( - "[cyan]Production Budget", - style="cyan", - justify="right", - no_wrap=True, - ) - example_table.add_column( - "[magenta]Box Office", - style="magenta", - justify="right", - no_wrap=True, - ) - example_table.add_row( - "Dec 20, 2019", - "Star Wars: The Rise of Skywalker", - "$275,000,000", - "$375,126,118", - ) - example_table.add_row( - "May 25, 2018", - "[b]Solo[/]: A Star Wars Story", - "$275,000,000", - "$393,151,347", - ) - example_table.add_row( - "Dec 15, 2017", - "Star Wars Ep. VIII: The Last Jedi", - "$262,000,000", - "[bold]$1,332,539,889[/bold]", - ) - example_table.add_row( - "May 19, 1999", - "Star Wars Ep. [b]I[/b]: [i]The phantom Menace", - "$115,000,000", - "$1,027,044,677", - ) - - table.add_row("Tables", example_table) - - code = '''\ -def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: - """Iterate and generate a tuple with a flag for last value.""" - iter_values = iter(values) - try: - previous_value = next(iter_values) - except StopIteration: - return - for value in iter_values: - yield False, previous_value - previous_value = value - yield True, previous_value''' - - pretty_data = { - "foo": [ - 3.1427, - ( - "Paul Atreides", - "Vladimir Harkonnen", - "Thufir Hawat", - ), - ], - "atomic": (False, True, None), - } - table.add_row( - "Syntax\nhighlighting\n&\npretty\nprinting", - comparison( - Syntax(code, "python3", line_numbers=True, indent_guides=True), - Pretty(pretty_data, indent_guides=True), - ), - ) - - markdown_example = """\ -# Markdown - -Supports much of the *markdown* __syntax__! - -- Headers -- Basic formatting: **bold**, *italic*, `code` -- Block quotes -- Lists, and more... - """ - table.add_row( - "Markdown", comparison("[cyan]" + markdown_example, Markdown(markdown_example)) - ) - - table.add_row( - "+more!", - """Progress bars, columns, styled logging handler, tracebacks, etc...""", - ) - return table - - -if __name__ == "__main__": # pragma: no cover - - console = Console( - file=io.StringIO(), - force_terminal=True, - ) - test_card = make_test_card() - - # Print once to warm cache - start = process_time() - console.print(test_card) - pre_cache_taken = round((process_time() - start) * 1000.0, 1) - - console.file = io.StringIO() - - start = process_time() - console.print(test_card) - taken = round((process_time() - start) * 1000.0, 1) - - c = Console(record=True) - c.print(test_card) - - print(f"rendered in {pre_cache_taken}ms (cold cache)") - print(f"rendered in {taken}ms (warm cache)") - - from pip._vendor.rich.panel import Panel - - console = Console() - - sponsor_message = Table.grid(padding=1) - sponsor_message.add_column(style="green", justify="right") - sponsor_message.add_column(no_wrap=True) - - sponsor_message.add_row( - "Textualize", - "[u blue link=https://github.com/textualize]https://github.com/textualize", - ) - sponsor_message.add_row( - "Twitter", - "[u blue link=https://twitter.com/willmcgugan]https://twitter.com/willmcgugan", - ) - - intro_message = Text.from_markup( - """\ -We hope you enjoy using Rich! - -Rich is maintained with [red]:heart:[/] by [link=https://www.textualize.io]Textualize.io[/] - -- Will McGugan""" - ) - - message = Table.grid(padding=2) - message.add_column() - message.add_column(no_wrap=True) - message.add_row(intro_message, sponsor_message) - - console.print( - Panel.fit( - message, - box=box.ROUNDED, - padding=(1, 2), - title="[b red]Thanks for trying out Rich!", - border_style="bright_blue", - ), - justify="center", - ) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 28a44b3..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc deleted file mode 100644 index f976213..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc deleted file mode 100644 index 21ef23a..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc deleted file mode 100644 index ecee518..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc deleted file mode 100644 index 8b9914d..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc deleted file mode 100644 index 70a2d06..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc deleted file mode 100644 index 77770c5..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc deleted file mode 100644 index 7d43466..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc deleted file mode 100644 index 04a637c..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc deleted file mode 100644 index faaca93..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc deleted file mode 100644 index e254164..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc deleted file mode 100644 index 65be789..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc deleted file mode 100644 index d01651f..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc deleted file mode 100644 index 6739def..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc deleted file mode 100644 index 3badf7e..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc deleted file mode 100644 index 5d6d0fe..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc deleted file mode 100644 index 2089625..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc deleted file mode 100644 index 1a04834..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc deleted file mode 100644 index 3b1c672..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc deleted file mode 100644 index d871fdc..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc deleted file mode 100644 index 53ef586..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc deleted file mode 100644 index b196f56..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc deleted file mode 100644 index ac35c3d..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc deleted file mode 100644 index 4fe00e5..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc deleted file mode 100644 index a4eae29..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc deleted file mode 100644 index 0665bcb..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc deleted file mode 100644 index 1ffa4f6..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc deleted file mode 100644 index dea8cb0..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc deleted file mode 100644 index 8e825cf..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc deleted file mode 100644 index f398b12..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc deleted file mode 100644 index ed91b63..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc deleted file mode 100644 index 5fc3645..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc deleted file mode 100644 index 700e29c..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc deleted file mode 100644 index df02046..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc deleted file mode 100644 index 6987a72..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc deleted file mode 100644 index 3af6dfa..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc deleted file mode 100644 index a819122..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc deleted file mode 100644 index 49fd565..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc deleted file mode 100644 index 0472722..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc deleted file mode 100644 index 5b8f738..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc deleted file mode 100644 index 5db96ce..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc deleted file mode 100644 index e2aa221..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc deleted file mode 100644 index 3449531..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc deleted file mode 100644 index 28e5f5f..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc deleted file mode 100644 index 9362d02..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc deleted file mode 100644 index fb7e99f..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc deleted file mode 100644 index 6087622..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc deleted file mode 100644 index 52c7e82..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc deleted file mode 100644 index b620b71..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc deleted file mode 100644 index e4b33ca..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc deleted file mode 100644 index cf7302e..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc deleted file mode 100644 index 68f268a..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc deleted file mode 100644 index 0124e8b..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc deleted file mode 100644 index 617d3bd..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc deleted file mode 100644 index e359141..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc deleted file mode 100644 index 02edd34..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc deleted file mode 100644 index fb41ff7..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc deleted file mode 100644 index af5f2fc..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc deleted file mode 100644 index 104ec77..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc deleted file mode 100644 index 481ce5a..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc deleted file mode 100644 index 0350332..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc deleted file mode 100644 index 7a7e8b4..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc deleted file mode 100644 index f74202c..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc deleted file mode 100644 index 6c38cb0..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc deleted file mode 100644 index 31f6307..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc deleted file mode 100644 index 791acd8..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc deleted file mode 100644 index fb9ad48..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc deleted file mode 100644 index 56f5b3b..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc deleted file mode 100644 index d9301c5..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc deleted file mode 100644 index 0f03a76..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc deleted file mode 100644 index adcc6e3..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc deleted file mode 100644 index b1edd79..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc deleted file mode 100644 index 8451847..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc deleted file mode 100644 index a160486..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc deleted file mode 100644 index 738280f..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc deleted file mode 100644 index a27b88c..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc deleted file mode 100644 index 7b8f92f..0000000 Binary files a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc and /dev/null differ diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py deleted file mode 100644 index 36286df..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py +++ /dev/null @@ -1,451 +0,0 @@ -# Auto generated by make_terminal_widths.py - -CELL_WIDTHS = [ - (0, 0, 0), - (1, 31, -1), - (127, 159, -1), - (768, 879, 0), - (1155, 1161, 0), - (1425, 1469, 0), - (1471, 1471, 0), - (1473, 1474, 0), - (1476, 1477, 0), - (1479, 1479, 0), - (1552, 1562, 0), - (1611, 1631, 0), - (1648, 1648, 0), - (1750, 1756, 0), - (1759, 1764, 0), - (1767, 1768, 0), - (1770, 1773, 0), - (1809, 1809, 0), - (1840, 1866, 0), - (1958, 1968, 0), - (2027, 2035, 0), - (2045, 2045, 0), - (2070, 2073, 0), - (2075, 2083, 0), - (2085, 2087, 0), - (2089, 2093, 0), - (2137, 2139, 0), - (2259, 2273, 0), - (2275, 2306, 0), - (2362, 2362, 0), - (2364, 2364, 0), - (2369, 2376, 0), - (2381, 2381, 0), - (2385, 2391, 0), - (2402, 2403, 0), - (2433, 2433, 0), - (2492, 2492, 0), - (2497, 2500, 0), - (2509, 2509, 0), - (2530, 2531, 0), - (2558, 2558, 0), - (2561, 2562, 0), - (2620, 2620, 0), - (2625, 2626, 0), - (2631, 2632, 0), - (2635, 2637, 0), - (2641, 2641, 0), - (2672, 2673, 0), - (2677, 2677, 0), - (2689, 2690, 0), - (2748, 2748, 0), - (2753, 2757, 0), - (2759, 2760, 0), - (2765, 2765, 0), - (2786, 2787, 0), - (2810, 2815, 0), - (2817, 2817, 0), - (2876, 2876, 0), - (2879, 2879, 0), - (2881, 2884, 0), - (2893, 2893, 0), - (2901, 2902, 0), - (2914, 2915, 0), - (2946, 2946, 0), - (3008, 3008, 0), - (3021, 3021, 0), - (3072, 3072, 0), - (3076, 3076, 0), - (3134, 3136, 0), - (3142, 3144, 0), - (3146, 3149, 0), - (3157, 3158, 0), - (3170, 3171, 0), - (3201, 3201, 0), - (3260, 3260, 0), - (3263, 3263, 0), - (3270, 3270, 0), - (3276, 3277, 0), - (3298, 3299, 0), - (3328, 3329, 0), - (3387, 3388, 0), - (3393, 3396, 0), - (3405, 3405, 0), - (3426, 3427, 0), - (3457, 3457, 0), - (3530, 3530, 0), - (3538, 3540, 0), - (3542, 3542, 0), - (3633, 3633, 0), - (3636, 3642, 0), - (3655, 3662, 0), - (3761, 3761, 0), - (3764, 3772, 0), - (3784, 3789, 0), - (3864, 3865, 0), - (3893, 3893, 0), - (3895, 3895, 0), - (3897, 3897, 0), - (3953, 3966, 0), - (3968, 3972, 0), - (3974, 3975, 0), - (3981, 3991, 0), - (3993, 4028, 0), - (4038, 4038, 0), - (4141, 4144, 0), - (4146, 4151, 0), - (4153, 4154, 0), - (4157, 4158, 0), - (4184, 4185, 0), - (4190, 4192, 0), - (4209, 4212, 0), - (4226, 4226, 0), - (4229, 4230, 0), - (4237, 4237, 0), - (4253, 4253, 0), - (4352, 4447, 2), - (4957, 4959, 0), - (5906, 5908, 0), - (5938, 5940, 0), - (5970, 5971, 0), - (6002, 6003, 0), - (6068, 6069, 0), - (6071, 6077, 0), - (6086, 6086, 0), - (6089, 6099, 0), - (6109, 6109, 0), - (6155, 6157, 0), - (6277, 6278, 0), - (6313, 6313, 0), - (6432, 6434, 0), - (6439, 6440, 0), - (6450, 6450, 0), - (6457, 6459, 0), - (6679, 6680, 0), - (6683, 6683, 0), - (6742, 6742, 0), - (6744, 6750, 0), - (6752, 6752, 0), - (6754, 6754, 0), - (6757, 6764, 0), - (6771, 6780, 0), - (6783, 6783, 0), - (6832, 6848, 0), - (6912, 6915, 0), - (6964, 6964, 0), - (6966, 6970, 0), - (6972, 6972, 0), - (6978, 6978, 0), - (7019, 7027, 0), - (7040, 7041, 0), - (7074, 7077, 0), - (7080, 7081, 0), - (7083, 7085, 0), - (7142, 7142, 0), - (7144, 7145, 0), - (7149, 7149, 0), - (7151, 7153, 0), - (7212, 7219, 0), - (7222, 7223, 0), - (7376, 7378, 0), - (7380, 7392, 0), - (7394, 7400, 0), - (7405, 7405, 0), - (7412, 7412, 0), - (7416, 7417, 0), - (7616, 7673, 0), - (7675, 7679, 0), - (8203, 8207, 0), - (8232, 8238, 0), - (8288, 8291, 0), - (8400, 8432, 0), - (8986, 8987, 2), - (9001, 9002, 2), - (9193, 9196, 2), - (9200, 9200, 2), - (9203, 9203, 2), - (9725, 9726, 2), - (9748, 9749, 2), - (9800, 9811, 2), - (9855, 9855, 2), - (9875, 9875, 2), - (9889, 9889, 2), - (9898, 9899, 2), - (9917, 9918, 2), - (9924, 9925, 2), - (9934, 9934, 2), - (9940, 9940, 2), - (9962, 9962, 2), - (9970, 9971, 2), - (9973, 9973, 2), - (9978, 9978, 2), - (9981, 9981, 2), - (9989, 9989, 2), - (9994, 9995, 2), - (10024, 10024, 2), - (10060, 10060, 2), - (10062, 10062, 2), - (10067, 10069, 2), - (10071, 10071, 2), - (10133, 10135, 2), - (10160, 10160, 2), - (10175, 10175, 2), - (11035, 11036, 2), - (11088, 11088, 2), - (11093, 11093, 2), - (11503, 11505, 0), - (11647, 11647, 0), - (11744, 11775, 0), - (11904, 11929, 2), - (11931, 12019, 2), - (12032, 12245, 2), - (12272, 12283, 2), - (12288, 12329, 2), - (12330, 12333, 0), - (12334, 12350, 2), - (12353, 12438, 2), - (12441, 12442, 0), - (12443, 12543, 2), - (12549, 12591, 2), - (12593, 12686, 2), - (12688, 12771, 2), - (12784, 12830, 2), - (12832, 12871, 2), - (12880, 19903, 2), - (19968, 42124, 2), - (42128, 42182, 2), - (42607, 42610, 0), - (42612, 42621, 0), - (42654, 42655, 0), - (42736, 42737, 0), - (43010, 43010, 0), - (43014, 43014, 0), - (43019, 43019, 0), - (43045, 43046, 0), - (43052, 43052, 0), - (43204, 43205, 0), - (43232, 43249, 0), - (43263, 43263, 0), - (43302, 43309, 0), - (43335, 43345, 0), - (43360, 43388, 2), - (43392, 43394, 0), - (43443, 43443, 0), - (43446, 43449, 0), - (43452, 43453, 0), - (43493, 43493, 0), - (43561, 43566, 0), - (43569, 43570, 0), - (43573, 43574, 0), - (43587, 43587, 0), - (43596, 43596, 0), - (43644, 43644, 0), - (43696, 43696, 0), - (43698, 43700, 0), - (43703, 43704, 0), - (43710, 43711, 0), - (43713, 43713, 0), - (43756, 43757, 0), - (43766, 43766, 0), - (44005, 44005, 0), - (44008, 44008, 0), - (44013, 44013, 0), - (44032, 55203, 2), - (63744, 64255, 2), - (64286, 64286, 0), - (65024, 65039, 0), - (65040, 65049, 2), - (65056, 65071, 0), - (65072, 65106, 2), - (65108, 65126, 2), - (65128, 65131, 2), - (65281, 65376, 2), - (65504, 65510, 2), - (66045, 66045, 0), - (66272, 66272, 0), - (66422, 66426, 0), - (68097, 68099, 0), - (68101, 68102, 0), - (68108, 68111, 0), - (68152, 68154, 0), - (68159, 68159, 0), - (68325, 68326, 0), - (68900, 68903, 0), - (69291, 69292, 0), - (69446, 69456, 0), - (69633, 69633, 0), - (69688, 69702, 0), - (69759, 69761, 0), - (69811, 69814, 0), - (69817, 69818, 0), - (69888, 69890, 0), - (69927, 69931, 0), - (69933, 69940, 0), - (70003, 70003, 0), - (70016, 70017, 0), - (70070, 70078, 0), - (70089, 70092, 0), - (70095, 70095, 0), - (70191, 70193, 0), - (70196, 70196, 0), - (70198, 70199, 0), - (70206, 70206, 0), - (70367, 70367, 0), - (70371, 70378, 0), - (70400, 70401, 0), - (70459, 70460, 0), - (70464, 70464, 0), - (70502, 70508, 0), - (70512, 70516, 0), - (70712, 70719, 0), - (70722, 70724, 0), - (70726, 70726, 0), - (70750, 70750, 0), - (70835, 70840, 0), - (70842, 70842, 0), - (70847, 70848, 0), - (70850, 70851, 0), - (71090, 71093, 0), - (71100, 71101, 0), - (71103, 71104, 0), - (71132, 71133, 0), - (71219, 71226, 0), - (71229, 71229, 0), - (71231, 71232, 0), - (71339, 71339, 0), - (71341, 71341, 0), - (71344, 71349, 0), - (71351, 71351, 0), - (71453, 71455, 0), - (71458, 71461, 0), - (71463, 71467, 0), - (71727, 71735, 0), - (71737, 71738, 0), - (71995, 71996, 0), - (71998, 71998, 0), - (72003, 72003, 0), - (72148, 72151, 0), - (72154, 72155, 0), - (72160, 72160, 0), - (72193, 72202, 0), - (72243, 72248, 0), - (72251, 72254, 0), - (72263, 72263, 0), - (72273, 72278, 0), - (72281, 72283, 0), - (72330, 72342, 0), - (72344, 72345, 0), - (72752, 72758, 0), - (72760, 72765, 0), - (72767, 72767, 0), - (72850, 72871, 0), - (72874, 72880, 0), - (72882, 72883, 0), - (72885, 72886, 0), - (73009, 73014, 0), - (73018, 73018, 0), - (73020, 73021, 0), - (73023, 73029, 0), - (73031, 73031, 0), - (73104, 73105, 0), - (73109, 73109, 0), - (73111, 73111, 0), - (73459, 73460, 0), - (92912, 92916, 0), - (92976, 92982, 0), - (94031, 94031, 0), - (94095, 94098, 0), - (94176, 94179, 2), - (94180, 94180, 0), - (94192, 94193, 2), - (94208, 100343, 2), - (100352, 101589, 2), - (101632, 101640, 2), - (110592, 110878, 2), - (110928, 110930, 2), - (110948, 110951, 2), - (110960, 111355, 2), - (113821, 113822, 0), - (119143, 119145, 0), - (119163, 119170, 0), - (119173, 119179, 0), - (119210, 119213, 0), - (119362, 119364, 0), - (121344, 121398, 0), - (121403, 121452, 0), - (121461, 121461, 0), - (121476, 121476, 0), - (121499, 121503, 0), - (121505, 121519, 0), - (122880, 122886, 0), - (122888, 122904, 0), - (122907, 122913, 0), - (122915, 122916, 0), - (122918, 122922, 0), - (123184, 123190, 0), - (123628, 123631, 0), - (125136, 125142, 0), - (125252, 125258, 0), - (126980, 126980, 2), - (127183, 127183, 2), - (127374, 127374, 2), - (127377, 127386, 2), - (127488, 127490, 2), - (127504, 127547, 2), - (127552, 127560, 2), - (127568, 127569, 2), - (127584, 127589, 2), - (127744, 127776, 2), - (127789, 127797, 2), - (127799, 127868, 2), - (127870, 127891, 2), - (127904, 127946, 2), - (127951, 127955, 2), - (127968, 127984, 2), - (127988, 127988, 2), - (127992, 128062, 2), - (128064, 128064, 2), - (128066, 128252, 2), - (128255, 128317, 2), - (128331, 128334, 2), - (128336, 128359, 2), - (128378, 128378, 2), - (128405, 128406, 2), - (128420, 128420, 2), - (128507, 128591, 2), - (128640, 128709, 2), - (128716, 128716, 2), - (128720, 128722, 2), - (128725, 128727, 2), - (128747, 128748, 2), - (128756, 128764, 2), - (128992, 129003, 2), - (129292, 129338, 2), - (129340, 129349, 2), - (129351, 129400, 2), - (129402, 129483, 2), - (129485, 129535, 2), - (129648, 129652, 2), - (129656, 129658, 2), - (129664, 129670, 2), - (129680, 129704, 2), - (129712, 129718, 2), - (129728, 129730, 2), - (129744, 129750, 2), - (131072, 196605, 2), - (196608, 262141, 2), - (917760, 917999, 0), -] diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py deleted file mode 100644 index 1f2877b..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py +++ /dev/null @@ -1,3610 +0,0 @@ -EMOJI = { - "1st_place_medal": "🥇", - "2nd_place_medal": "🥈", - "3rd_place_medal": "🥉", - "ab_button_(blood_type)": "🆎", - "atm_sign": "ðŸ§", - "a_button_(blood_type)": "🅰", - "afghanistan": "🇦🇫", - "albania": "🇦🇱", - "algeria": "🇩🇿", - "american_samoa": "🇦🇸", - "andorra": "🇦🇩", - "angola": "🇦🇴", - "anguilla": "🇦🇮", - "antarctica": "🇦🇶", - "antigua_&_barbuda": "🇦🇬", - "aquarius": "â™’", - "argentina": "🇦🇷", - "aries": "♈", - "armenia": "🇦🇲", - "aruba": "🇦🇼", - "ascension_island": "🇦🇨", - "australia": "🇦🇺", - "austria": "🇦🇹", - "azerbaijan": "🇦🇿", - "back_arrow": "🔙", - "b_button_(blood_type)": "🅱", - "bahamas": "🇧🇸", - "bahrain": "🇧🇭", - "bangladesh": "🇧🇩", - "barbados": "🇧🇧", - "belarus": "🇧🇾", - "belgium": "🇧🇪", - "belize": "🇧🇿", - "benin": "🇧🇯", - "bermuda": "🇧🇲", - "bhutan": "🇧🇹", - "bolivia": "🇧🇴", - "bosnia_&_herzegovina": "🇧🇦", - "botswana": "🇧🇼", - "bouvet_island": "🇧🇻", - "brazil": "🇧🇷", - "british_indian_ocean_territory": "🇮🇴", - "british_virgin_islands": "🇻🇬", - "brunei": "🇧🇳", - "bulgaria": "🇧🇬", - "burkina_faso": "🇧🇫", - "burundi": "🇧🇮", - "cl_button": "🆑", - "cool_button": "🆒", - "cambodia": "🇰🇭", - "cameroon": "🇨🇲", - "canada": "🇨🇦", - "canary_islands": "🇮🇨", - "cancer": "♋", - "cape_verde": "🇨🇻", - "capricorn": "♑", - "caribbean_netherlands": "🇧🇶", - "cayman_islands": "🇰🇾", - "central_african_republic": "🇨🇫", - "ceuta_&_melilla": "🇪🇦", - "chad": "🇹🇩", - "chile": "🇨🇱", - "china": "🇨🇳", - "christmas_island": "🇨🇽", - "christmas_tree": "🎄", - "clipperton_island": "🇨🇵", - "cocos_(keeling)_islands": "🇨🇨", - "colombia": "🇨🇴", - "comoros": "🇰🇲", - "congo_-_brazzaville": "🇨🇬", - "congo_-_kinshasa": "🇨🇩", - "cook_islands": "🇨🇰", - "costa_rica": "🇨🇷", - "croatia": "🇭🇷", - "cuba": "🇨🇺", - "curaçao": "🇨🇼", - "cyprus": "🇨🇾", - "czechia": "🇨🇿", - "côte_d’ivoire": "🇨🇮", - "denmark": "🇩🇰", - "diego_garcia": "🇩🇬", - "djibouti": "🇩🇯", - "dominica": "🇩🇲", - "dominican_republic": "🇩🇴", - "end_arrow": "🔚", - "ecuador": "🇪🇨", - "egypt": "🇪🇬", - "el_salvador": "🇸🇻", - "england": "ðŸ´\U000e0067\U000e0062\U000e0065\U000e006e\U000e0067\U000e007f", - "equatorial_guinea": "🇬🇶", - "eritrea": "🇪🇷", - "estonia": "🇪🇪", - "ethiopia": "🇪🇹", - "european_union": "🇪🇺", - "free_button": "🆓", - "falkland_islands": "🇫🇰", - "faroe_islands": "🇫🇴", - "fiji": "🇫🇯", - "finland": "🇫🇮", - "france": "🇫🇷", - "french_guiana": "🇬🇫", - "french_polynesia": "🇵🇫", - "french_southern_territories": "🇹🇫", - "gabon": "🇬🇦", - "gambia": "🇬🇲", - "gemini": "♊", - "georgia": "🇬🇪", - "germany": "🇩🇪", - "ghana": "🇬🇭", - "gibraltar": "🇬🇮", - "greece": "🇬🇷", - "greenland": "🇬🇱", - "grenada": "🇬🇩", - "guadeloupe": "🇬🇵", - "guam": "🇬🇺", - "guatemala": "🇬🇹", - "guernsey": "🇬🇬", - "guinea": "🇬🇳", - "guinea-bissau": "🇬🇼", - "guyana": "🇬🇾", - "haiti": "🇭🇹", - "heard_&_mcdonald_islands": "🇭🇲", - "honduras": "🇭🇳", - "hong_kong_sar_china": "🇭🇰", - "hungary": "🇭🇺", - "id_button": "🆔", - "iceland": "🇮🇸", - "india": "🇮🇳", - "indonesia": "🇮🇩", - "iran": "🇮🇷", - "iraq": "🇮🇶", - "ireland": "🇮🇪", - "isle_of_man": "🇮🇲", - "israel": "🇮🇱", - "italy": "🇮🇹", - "jamaica": "🇯🇲", - "japan": "🗾", - "japanese_acceptable_button": "🉑", - "japanese_application_button": "🈸", - "japanese_bargain_button": "ðŸ‰", - "japanese_castle": "ðŸ¯", - "japanese_congratulations_button": "㊗", - "japanese_discount_button": "🈹", - "japanese_dolls": "🎎", - "japanese_free_of_charge_button": "🈚", - "japanese_here_button": "ðŸˆ", - "japanese_monthly_amount_button": "🈷", - "japanese_no_vacancy_button": "🈵", - "japanese_not_free_of_charge_button": "🈶", - "japanese_open_for_business_button": "🈺", - "japanese_passing_grade_button": "🈴", - "japanese_post_office": "ðŸ£", - "japanese_prohibited_button": "🈲", - "japanese_reserved_button": "🈯", - "japanese_secret_button": "㊙", - "japanese_service_charge_button": "🈂", - "japanese_symbol_for_beginner": "🔰", - "japanese_vacancy_button": "🈳", - "jersey": "🇯🇪", - "jordan": "🇯🇴", - "kazakhstan": "🇰🇿", - "kenya": "🇰🇪", - "kiribati": "🇰🇮", - "kosovo": "🇽🇰", - "kuwait": "🇰🇼", - "kyrgyzstan": "🇰🇬", - "laos": "🇱🇦", - "latvia": "🇱🇻", - "lebanon": "🇱🇧", - "leo": "♌", - "lesotho": "🇱🇸", - "liberia": "🇱🇷", - "libra": "♎", - "libya": "🇱🇾", - "liechtenstein": "🇱🇮", - "lithuania": "🇱🇹", - "luxembourg": "🇱🇺", - "macau_sar_china": "🇲🇴", - "macedonia": "🇲🇰", - "madagascar": "🇲🇬", - "malawi": "🇲🇼", - "malaysia": "🇲🇾", - "maldives": "🇲🇻", - "mali": "🇲🇱", - "malta": "🇲🇹", - "marshall_islands": "🇲🇭", - "martinique": "🇲🇶", - "mauritania": "🇲🇷", - "mauritius": "🇲🇺", - "mayotte": "🇾🇹", - "mexico": "🇲🇽", - "micronesia": "🇫🇲", - "moldova": "🇲🇩", - "monaco": "🇲🇨", - "mongolia": "🇲🇳", - "montenegro": "🇲🇪", - "montserrat": "🇲🇸", - "morocco": "🇲🇦", - "mozambique": "🇲🇿", - "mrs._claus": "🤶", - "mrs._claus_dark_skin_tone": "🤶ðŸ¿", - "mrs._claus_light_skin_tone": "🤶ðŸ»", - "mrs._claus_medium-dark_skin_tone": "🤶ðŸ¾", - "mrs._claus_medium-light_skin_tone": "🤶ðŸ¼", - "mrs._claus_medium_skin_tone": "🤶ðŸ½", - "myanmar_(burma)": "🇲🇲", - "new_button": "🆕", - "ng_button": "🆖", - "namibia": "🇳🇦", - "nauru": "🇳🇷", - "nepal": "🇳🇵", - "netherlands": "🇳🇱", - "new_caledonia": "🇳🇨", - "new_zealand": "🇳🇿", - "nicaragua": "🇳🇮", - "niger": "🇳🇪", - "nigeria": "🇳🇬", - "niue": "🇳🇺", - "norfolk_island": "🇳🇫", - "north_korea": "🇰🇵", - "northern_mariana_islands": "🇲🇵", - "norway": "🇳🇴", - "ok_button": "🆗", - "ok_hand": "👌", - "ok_hand_dark_skin_tone": "👌ðŸ¿", - "ok_hand_light_skin_tone": "👌ðŸ»", - "ok_hand_medium-dark_skin_tone": "👌ðŸ¾", - "ok_hand_medium-light_skin_tone": "👌ðŸ¼", - "ok_hand_medium_skin_tone": "👌ðŸ½", - "on!_arrow": "🔛", - "o_button_(blood_type)": "🅾", - "oman": "🇴🇲", - "ophiuchus": "⛎", - "p_button": "🅿", - "pakistan": "🇵🇰", - "palau": "🇵🇼", - "palestinian_territories": "🇵🇸", - "panama": "🇵🇦", - "papua_new_guinea": "🇵🇬", - "paraguay": "🇵🇾", - "peru": "🇵🇪", - "philippines": "🇵🇭", - "pisces": "♓", - "pitcairn_islands": "🇵🇳", - "poland": "🇵🇱", - "portugal": "🇵🇹", - "puerto_rico": "🇵🇷", - "qatar": "🇶🇦", - "romania": "🇷🇴", - "russia": "🇷🇺", - "rwanda": "🇷🇼", - "réunion": "🇷🇪", - "soon_arrow": "🔜", - "sos_button": "🆘", - "sagittarius": "â™", - "samoa": "🇼🇸", - "san_marino": "🇸🇲", - "santa_claus": "🎅", - "santa_claus_dark_skin_tone": "🎅ðŸ¿", - "santa_claus_light_skin_tone": "🎅ðŸ»", - "santa_claus_medium-dark_skin_tone": "🎅ðŸ¾", - "santa_claus_medium-light_skin_tone": "🎅ðŸ¼", - "santa_claus_medium_skin_tone": "🎅ðŸ½", - "saudi_arabia": "🇸🇦", - "scorpio": "â™", - "scotland": "ðŸ´\U000e0067\U000e0062\U000e0073\U000e0063\U000e0074\U000e007f", - "senegal": "🇸🇳", - "serbia": "🇷🇸", - "seychelles": "🇸🇨", - "sierra_leone": "🇸🇱", - "singapore": "🇸🇬", - "sint_maarten": "🇸🇽", - "slovakia": "🇸🇰", - "slovenia": "🇸🇮", - "solomon_islands": "🇸🇧", - "somalia": "🇸🇴", - "south_africa": "🇿🇦", - "south_georgia_&_south_sandwich_islands": "🇬🇸", - "south_korea": "🇰🇷", - "south_sudan": "🇸🇸", - "spain": "🇪🇸", - "sri_lanka": "🇱🇰", - "st._barthélemy": "🇧🇱", - "st._helena": "🇸🇭", - "st._kitts_&_nevis": "🇰🇳", - "st._lucia": "🇱🇨", - "st._martin": "🇲🇫", - "st._pierre_&_miquelon": "🇵🇲", - "st._vincent_&_grenadines": "🇻🇨", - "statue_of_liberty": "🗽", - "sudan": "🇸🇩", - "suriname": "🇸🇷", - "svalbard_&_jan_mayen": "🇸🇯", - "swaziland": "🇸🇿", - "sweden": "🇸🇪", - "switzerland": "🇨🇭", - "syria": "🇸🇾", - "são_tomé_&_príncipe": "🇸🇹", - "t-rex": "🦖", - "top_arrow": "ðŸ”", - "taiwan": "🇹🇼", - "tajikistan": "🇹🇯", - "tanzania": "🇹🇿", - "taurus": "♉", - "thailand": "🇹🇭", - "timor-leste": "🇹🇱", - "togo": "🇹🇬", - "tokelau": "🇹🇰", - "tokyo_tower": "🗼", - "tonga": "🇹🇴", - "trinidad_&_tobago": "🇹🇹", - "tristan_da_cunha": "🇹🇦", - "tunisia": "🇹🇳", - "turkey": "🦃", - "turkmenistan": "🇹🇲", - "turks_&_caicos_islands": "🇹🇨", - "tuvalu": "🇹🇻", - "u.s._outlying_islands": "🇺🇲", - "u.s._virgin_islands": "🇻🇮", - "up!_button": "🆙", - "uganda": "🇺🇬", - "ukraine": "🇺🇦", - "united_arab_emirates": "🇦🇪", - "united_kingdom": "🇬🇧", - "united_nations": "🇺🇳", - "united_states": "🇺🇸", - "uruguay": "🇺🇾", - "uzbekistan": "🇺🇿", - "vs_button": "🆚", - "vanuatu": "🇻🇺", - "vatican_city": "🇻🇦", - "venezuela": "🇻🇪", - "vietnam": "🇻🇳", - "virgo": "â™", - "wales": "ðŸ´\U000e0067\U000e0062\U000e0077\U000e006c\U000e0073\U000e007f", - "wallis_&_futuna": "🇼🇫", - "western_sahara": "🇪🇭", - "yemen": "🇾🇪", - "zambia": "🇿🇲", - "zimbabwe": "🇿🇼", - "abacus": "🧮", - "adhesive_bandage": "🩹", - "admission_tickets": "🎟", - "adult": "🧑", - "adult_dark_skin_tone": "🧑ðŸ¿", - "adult_light_skin_tone": "🧑ðŸ»", - "adult_medium-dark_skin_tone": "🧑ðŸ¾", - "adult_medium-light_skin_tone": "🧑ðŸ¼", - "adult_medium_skin_tone": "🧑ðŸ½", - "aerial_tramway": "🚡", - "airplane": "✈", - "airplane_arrival": "🛬", - "airplane_departure": "🛫", - "alarm_clock": "â°", - "alembic": "âš—", - "alien": "👽", - "alien_monster": "👾", - "ambulance": "🚑", - "american_football": "ðŸˆ", - "amphora": "ðŸº", - "anchor": "âš“", - "anger_symbol": "💢", - "angry_face": "😠", - "angry_face_with_horns": "👿", - "anguished_face": "😧", - "ant": "ðŸœ", - "antenna_bars": "📶", - "anxious_face_with_sweat": "😰", - "articulated_lorry": "🚛", - "artist_palette": "🎨", - "astonished_face": "😲", - "atom_symbol": "âš›", - "auto_rickshaw": "🛺", - "automobile": "🚗", - "avocado": "🥑", - "axe": "🪓", - "baby": "👶", - "baby_angel": "👼", - "baby_angel_dark_skin_tone": "👼ðŸ¿", - "baby_angel_light_skin_tone": "👼ðŸ»", - "baby_angel_medium-dark_skin_tone": "👼ðŸ¾", - "baby_angel_medium-light_skin_tone": "👼ðŸ¼", - "baby_angel_medium_skin_tone": "👼ðŸ½", - "baby_bottle": "ðŸ¼", - "baby_chick": "ðŸ¤", - "baby_dark_skin_tone": "👶ðŸ¿", - "baby_light_skin_tone": "👶ðŸ»", - "baby_medium-dark_skin_tone": "👶ðŸ¾", - "baby_medium-light_skin_tone": "👶ðŸ¼", - "baby_medium_skin_tone": "👶ðŸ½", - "baby_symbol": "🚼", - "backhand_index_pointing_down": "👇", - "backhand_index_pointing_down_dark_skin_tone": "👇ðŸ¿", - "backhand_index_pointing_down_light_skin_tone": "👇ðŸ»", - "backhand_index_pointing_down_medium-dark_skin_tone": "👇ðŸ¾", - "backhand_index_pointing_down_medium-light_skin_tone": "👇ðŸ¼", - "backhand_index_pointing_down_medium_skin_tone": "👇ðŸ½", - "backhand_index_pointing_left": "👈", - "backhand_index_pointing_left_dark_skin_tone": "👈ðŸ¿", - "backhand_index_pointing_left_light_skin_tone": "👈ðŸ»", - "backhand_index_pointing_left_medium-dark_skin_tone": "👈ðŸ¾", - "backhand_index_pointing_left_medium-light_skin_tone": "👈ðŸ¼", - "backhand_index_pointing_left_medium_skin_tone": "👈ðŸ½", - "backhand_index_pointing_right": "👉", - "backhand_index_pointing_right_dark_skin_tone": "👉ðŸ¿", - "backhand_index_pointing_right_light_skin_tone": "👉ðŸ»", - "backhand_index_pointing_right_medium-dark_skin_tone": "👉ðŸ¾", - "backhand_index_pointing_right_medium-light_skin_tone": "👉ðŸ¼", - "backhand_index_pointing_right_medium_skin_tone": "👉ðŸ½", - "backhand_index_pointing_up": "👆", - "backhand_index_pointing_up_dark_skin_tone": "👆ðŸ¿", - "backhand_index_pointing_up_light_skin_tone": "👆ðŸ»", - "backhand_index_pointing_up_medium-dark_skin_tone": "👆ðŸ¾", - "backhand_index_pointing_up_medium-light_skin_tone": "👆ðŸ¼", - "backhand_index_pointing_up_medium_skin_tone": "👆ðŸ½", - "bacon": "🥓", - "badger": "🦡", - "badminton": "ðŸ¸", - "bagel": "🥯", - "baggage_claim": "🛄", - "baguette_bread": "🥖", - "balance_scale": "âš–", - "bald": "🦲", - "bald_man": "👨\u200d🦲", - "bald_woman": "👩\u200d🦲", - "ballet_shoes": "🩰", - "balloon": "🎈", - "ballot_box_with_ballot": "🗳", - "ballot_box_with_check": "☑", - "banana": "ðŸŒ", - "banjo": "🪕", - "bank": "ðŸ¦", - "bar_chart": "📊", - "barber_pole": "💈", - "baseball": "âš¾", - "basket": "🧺", - "basketball": "ðŸ€", - "bat": "🦇", - "bathtub": "ðŸ›", - "battery": "🔋", - "beach_with_umbrella": "ðŸ–", - "beaming_face_with_smiling_eyes": "ðŸ˜", - "bear_face": "ðŸ»", - "bearded_person": "🧔", - "bearded_person_dark_skin_tone": "🧔ðŸ¿", - "bearded_person_light_skin_tone": "🧔ðŸ»", - "bearded_person_medium-dark_skin_tone": "🧔ðŸ¾", - "bearded_person_medium-light_skin_tone": "🧔ðŸ¼", - "bearded_person_medium_skin_tone": "🧔ðŸ½", - "beating_heart": "💓", - "bed": "ðŸ›", - "beer_mug": "ðŸº", - "bell": "🔔", - "bell_with_slash": "🔕", - "bellhop_bell": "🛎", - "bento_box": "ðŸ±", - "beverage_box": "🧃", - "bicycle": "🚲", - "bikini": "👙", - "billed_cap": "🧢", - "biohazard": "☣", - "bird": "ðŸ¦", - "birthday_cake": "🎂", - "black_circle": "âš«", - "black_flag": "ðŸ´", - "black_heart": "🖤", - "black_large_square": "⬛", - "black_medium-small_square": "â—¾", - "black_medium_square": "â—¼", - "black_nib": "✒", - "black_small_square": "â–ª", - "black_square_button": "🔲", - "blond-haired_man": "👱\u200d♂ï¸", - "blond-haired_man_dark_skin_tone": "👱ðŸ¿\u200d♂ï¸", - "blond-haired_man_light_skin_tone": "👱ðŸ»\u200d♂ï¸", - "blond-haired_man_medium-dark_skin_tone": "👱ðŸ¾\u200d♂ï¸", - "blond-haired_man_medium-light_skin_tone": "👱ðŸ¼\u200d♂ï¸", - "blond-haired_man_medium_skin_tone": "👱ðŸ½\u200d♂ï¸", - "blond-haired_person": "👱", - "blond-haired_person_dark_skin_tone": "👱ðŸ¿", - "blond-haired_person_light_skin_tone": "👱ðŸ»", - "blond-haired_person_medium-dark_skin_tone": "👱ðŸ¾", - "blond-haired_person_medium-light_skin_tone": "👱ðŸ¼", - "blond-haired_person_medium_skin_tone": "👱ðŸ½", - "blond-haired_woman": "👱\u200d♀ï¸", - "blond-haired_woman_dark_skin_tone": "👱ðŸ¿\u200d♀ï¸", - "blond-haired_woman_light_skin_tone": "👱ðŸ»\u200d♀ï¸", - "blond-haired_woman_medium-dark_skin_tone": "👱ðŸ¾\u200d♀ï¸", - "blond-haired_woman_medium-light_skin_tone": "👱ðŸ¼\u200d♀ï¸", - "blond-haired_woman_medium_skin_tone": "👱ðŸ½\u200d♀ï¸", - "blossom": "🌼", - "blowfish": "ðŸ¡", - "blue_book": "📘", - "blue_circle": "🔵", - "blue_heart": "💙", - "blue_square": "🟦", - "boar": "ðŸ—", - "bomb": "💣", - "bone": "🦴", - "bookmark": "🔖", - "bookmark_tabs": "📑", - "books": "📚", - "bottle_with_popping_cork": "ðŸ¾", - "bouquet": "ðŸ’", - "bow_and_arrow": "ðŸ¹", - "bowl_with_spoon": "🥣", - "bowling": "🎳", - "boxing_glove": "🥊", - "boy": "👦", - "boy_dark_skin_tone": "👦ðŸ¿", - "boy_light_skin_tone": "👦ðŸ»", - "boy_medium-dark_skin_tone": "👦ðŸ¾", - "boy_medium-light_skin_tone": "👦ðŸ¼", - "boy_medium_skin_tone": "👦ðŸ½", - "brain": "🧠", - "bread": "ðŸž", - "breast-feeding": "🤱", - "breast-feeding_dark_skin_tone": "🤱ðŸ¿", - "breast-feeding_light_skin_tone": "🤱ðŸ»", - "breast-feeding_medium-dark_skin_tone": "🤱ðŸ¾", - "breast-feeding_medium-light_skin_tone": "🤱ðŸ¼", - "breast-feeding_medium_skin_tone": "🤱ðŸ½", - "brick": "🧱", - "bride_with_veil": "👰", - "bride_with_veil_dark_skin_tone": "👰ðŸ¿", - "bride_with_veil_light_skin_tone": "👰ðŸ»", - "bride_with_veil_medium-dark_skin_tone": "👰ðŸ¾", - "bride_with_veil_medium-light_skin_tone": "👰ðŸ¼", - "bride_with_veil_medium_skin_tone": "👰ðŸ½", - "bridge_at_night": "🌉", - "briefcase": "💼", - "briefs": "🩲", - "bright_button": "🔆", - "broccoli": "🥦", - "broken_heart": "💔", - "broom": "🧹", - "brown_circle": "🟤", - "brown_heart": "🤎", - "brown_square": "🟫", - "bug": "ðŸ›", - "building_construction": "ðŸ—", - "bullet_train": "🚅", - "burrito": "🌯", - "bus": "🚌", - "bus_stop": "ðŸš", - "bust_in_silhouette": "👤", - "busts_in_silhouette": "👥", - "butter": "🧈", - "butterfly": "🦋", - "cactus": "🌵", - "calendar": "📆", - "call_me_hand": "🤙", - "call_me_hand_dark_skin_tone": "🤙ðŸ¿", - "call_me_hand_light_skin_tone": "🤙ðŸ»", - "call_me_hand_medium-dark_skin_tone": "🤙ðŸ¾", - "call_me_hand_medium-light_skin_tone": "🤙ðŸ¼", - "call_me_hand_medium_skin_tone": "🤙ðŸ½", - "camel": "ðŸ«", - "camera": "📷", - "camera_with_flash": "📸", - "camping": "ðŸ•", - "candle": "🕯", - "candy": "ðŸ¬", - "canned_food": "🥫", - "canoe": "🛶", - "card_file_box": "🗃", - "card_index": "📇", - "card_index_dividers": "🗂", - "carousel_horse": "🎠", - "carp_streamer": "ðŸŽ", - "carrot": "🥕", - "castle": "ðŸ°", - "cat": "ðŸ±", - "cat_face": "ðŸ±", - "cat_face_with_tears_of_joy": "😹", - "cat_face_with_wry_smile": "😼", - "chains": "⛓", - "chair": "🪑", - "chart_decreasing": "📉", - "chart_increasing": "📈", - "chart_increasing_with_yen": "💹", - "cheese_wedge": "🧀", - "chequered_flag": "ðŸ", - "cherries": "ðŸ’", - "cherry_blossom": "🌸", - "chess_pawn": "♟", - "chestnut": "🌰", - "chicken": "ðŸ”", - "child": "🧒", - "child_dark_skin_tone": "🧒ðŸ¿", - "child_light_skin_tone": "🧒ðŸ»", - "child_medium-dark_skin_tone": "🧒ðŸ¾", - "child_medium-light_skin_tone": "🧒ðŸ¼", - "child_medium_skin_tone": "🧒ðŸ½", - "children_crossing": "🚸", - "chipmunk": "ðŸ¿", - "chocolate_bar": "ðŸ«", - "chopsticks": "🥢", - "church": "⛪", - "cigarette": "🚬", - "cinema": "🎦", - "circled_m": "â“‚", - "circus_tent": "🎪", - "cityscape": "ðŸ™", - "cityscape_at_dusk": "🌆", - "clamp": "🗜", - "clapper_board": "🎬", - "clapping_hands": "ðŸ‘", - "clapping_hands_dark_skin_tone": "ðŸ‘ðŸ¿", - "clapping_hands_light_skin_tone": "ðŸ‘ðŸ»", - "clapping_hands_medium-dark_skin_tone": "ðŸ‘ðŸ¾", - "clapping_hands_medium-light_skin_tone": "ðŸ‘ðŸ¼", - "clapping_hands_medium_skin_tone": "ðŸ‘ðŸ½", - "classical_building": "ðŸ›", - "clinking_beer_mugs": "ðŸ»", - "clinking_glasses": "🥂", - "clipboard": "📋", - "clockwise_vertical_arrows": "🔃", - "closed_book": "📕", - "closed_mailbox_with_lowered_flag": "📪", - "closed_mailbox_with_raised_flag": "📫", - "closed_umbrella": "🌂", - "cloud": "â˜", - "cloud_with_lightning": "🌩", - "cloud_with_lightning_and_rain": "⛈", - "cloud_with_rain": "🌧", - "cloud_with_snow": "🌨", - "clown_face": "🤡", - "club_suit": "♣", - "clutch_bag": "ðŸ‘", - "coat": "🧥", - "cocktail_glass": "ðŸ¸", - "coconut": "🥥", - "coffin": "âš°", - "cold_face": "🥶", - "collision": "💥", - "comet": "☄", - "compass": "🧭", - "computer_disk": "💽", - "computer_mouse": "🖱", - "confetti_ball": "🎊", - "confounded_face": "😖", - "confused_face": "😕", - "construction": "🚧", - "construction_worker": "👷", - "construction_worker_dark_skin_tone": "👷ðŸ¿", - "construction_worker_light_skin_tone": "👷ðŸ»", - "construction_worker_medium-dark_skin_tone": "👷ðŸ¾", - "construction_worker_medium-light_skin_tone": "👷ðŸ¼", - "construction_worker_medium_skin_tone": "👷ðŸ½", - "control_knobs": "🎛", - "convenience_store": "ðŸª", - "cooked_rice": "ðŸš", - "cookie": "ðŸª", - "cooking": "ðŸ³", - "copyright": "©", - "couch_and_lamp": "🛋", - "counterclockwise_arrows_button": "🔄", - "couple_with_heart": "💑", - "couple_with_heart_man_man": "👨\u200dâ¤ï¸\u200d👨", - "couple_with_heart_woman_man": "👩\u200dâ¤ï¸\u200d👨", - "couple_with_heart_woman_woman": "👩\u200dâ¤ï¸\u200d👩", - "cow": "ðŸ®", - "cow_face": "ðŸ®", - "cowboy_hat_face": "🤠", - "crab": "🦀", - "crayon": "ðŸ–", - "credit_card": "💳", - "crescent_moon": "🌙", - "cricket": "🦗", - "cricket_game": "ðŸ", - "crocodile": "ðŸŠ", - "croissant": "ðŸ¥", - "cross_mark": "âŒ", - "cross_mark_button": "âŽ", - "crossed_fingers": "🤞", - "crossed_fingers_dark_skin_tone": "🤞ðŸ¿", - "crossed_fingers_light_skin_tone": "🤞ðŸ»", - "crossed_fingers_medium-dark_skin_tone": "🤞ðŸ¾", - "crossed_fingers_medium-light_skin_tone": "🤞ðŸ¼", - "crossed_fingers_medium_skin_tone": "🤞ðŸ½", - "crossed_flags": "🎌", - "crossed_swords": "âš”", - "crown": "👑", - "crying_cat_face": "😿", - "crying_face": "😢", - "crystal_ball": "🔮", - "cucumber": "🥒", - "cupcake": "ðŸ§", - "cup_with_straw": "🥤", - "curling_stone": "🥌", - "curly_hair": "🦱", - "curly-haired_man": "👨\u200d🦱", - "curly-haired_woman": "👩\u200d🦱", - "curly_loop": "âž°", - "currency_exchange": "💱", - "curry_rice": "ðŸ›", - "custard": "ðŸ®", - "customs": "🛃", - "cut_of_meat": "🥩", - "cyclone": "🌀", - "dagger": "🗡", - "dango": "ðŸ¡", - "dashing_away": "💨", - "deaf_person": "ðŸ§", - "deciduous_tree": "🌳", - "deer": "🦌", - "delivery_truck": "🚚", - "department_store": "ðŸ¬", - "derelict_house": "ðŸš", - "desert": "ðŸœ", - "desert_island": "ðŸ", - "desktop_computer": "🖥", - "detective": "🕵", - "detective_dark_skin_tone": "🕵ðŸ¿", - "detective_light_skin_tone": "🕵ðŸ»", - "detective_medium-dark_skin_tone": "🕵ðŸ¾", - "detective_medium-light_skin_tone": "🕵ðŸ¼", - "detective_medium_skin_tone": "🕵ðŸ½", - "diamond_suit": "♦", - "diamond_with_a_dot": "💠", - "dim_button": "🔅", - "direct_hit": "🎯", - "disappointed_face": "😞", - "diving_mask": "🤿", - "diya_lamp": "🪔", - "dizzy": "💫", - "dizzy_face": "😵", - "dna": "🧬", - "dog": "ðŸ¶", - "dog_face": "ðŸ¶", - "dollar_banknote": "💵", - "dolphin": "ðŸ¬", - "door": "🚪", - "dotted_six-pointed_star": "🔯", - "double_curly_loop": "âž¿", - "double_exclamation_mark": "‼", - "doughnut": "ðŸ©", - "dove": "🕊", - "down-left_arrow": "↙", - "down-right_arrow": "↘", - "down_arrow": "⬇", - "downcast_face_with_sweat": "😓", - "downwards_button": "🔽", - "dragon": "ðŸ‰", - "dragon_face": "ðŸ²", - "dress": "👗", - "drooling_face": "🤤", - "drop_of_blood": "🩸", - "droplet": "💧", - "drum": "ðŸ¥", - "duck": "🦆", - "dumpling": "🥟", - "dvd": "📀", - "e-mail": "📧", - "eagle": "🦅", - "ear": "👂", - "ear_dark_skin_tone": "👂ðŸ¿", - "ear_light_skin_tone": "👂ðŸ»", - "ear_medium-dark_skin_tone": "👂ðŸ¾", - "ear_medium-light_skin_tone": "👂ðŸ¼", - "ear_medium_skin_tone": "👂ðŸ½", - "ear_of_corn": "🌽", - "ear_with_hearing_aid": "🦻", - "egg": "ðŸ³", - "eggplant": "ðŸ†", - "eight-pointed_star": "✴", - "eight-spoked_asterisk": "✳", - "eight-thirty": "🕣", - "eight_o’clock": "🕗", - "eject_button": "â", - "electric_plug": "🔌", - "elephant": "ðŸ˜", - "eleven-thirty": "🕦", - "eleven_o’clock": "🕚", - "elf": "ðŸ§", - "elf_dark_skin_tone": "ðŸ§ðŸ¿", - "elf_light_skin_tone": "ðŸ§ðŸ»", - "elf_medium-dark_skin_tone": "ðŸ§ðŸ¾", - "elf_medium-light_skin_tone": "ðŸ§ðŸ¼", - "elf_medium_skin_tone": "ðŸ§ðŸ½", - "envelope": "✉", - "envelope_with_arrow": "📩", - "euro_banknote": "💶", - "evergreen_tree": "🌲", - "ewe": "ðŸ‘", - "exclamation_mark": "â—", - "exclamation_question_mark": "â‰", - "exploding_head": "🤯", - "expressionless_face": "😑", - "eye": "ðŸ‘", - "eye_in_speech_bubble": "ðŸ‘ï¸\u200d🗨ï¸", - "eyes": "👀", - "face_blowing_a_kiss": "😘", - "face_savoring_food": "😋", - "face_screaming_in_fear": "😱", - "face_vomiting": "🤮", - "face_with_hand_over_mouth": "🤭", - "face_with_head-bandage": "🤕", - "face_with_medical_mask": "😷", - "face_with_monocle": "ðŸ§", - "face_with_open_mouth": "😮", - "face_with_raised_eyebrow": "🤨", - "face_with_rolling_eyes": "🙄", - "face_with_steam_from_nose": "😤", - "face_with_symbols_on_mouth": "🤬", - "face_with_tears_of_joy": "😂", - "face_with_thermometer": "🤒", - "face_with_tongue": "😛", - "face_without_mouth": "😶", - "factory": "ðŸ­", - "fairy": "🧚", - "fairy_dark_skin_tone": "🧚ðŸ¿", - "fairy_light_skin_tone": "🧚ðŸ»", - "fairy_medium-dark_skin_tone": "🧚ðŸ¾", - "fairy_medium-light_skin_tone": "🧚ðŸ¼", - "fairy_medium_skin_tone": "🧚ðŸ½", - "falafel": "🧆", - "fallen_leaf": "ðŸ‚", - "family": "👪", - "family_man_boy": "👨\u200d👦", - "family_man_boy_boy": "👨\u200d👦\u200d👦", - "family_man_girl": "👨\u200d👧", - "family_man_girl_boy": "👨\u200d👧\u200d👦", - "family_man_girl_girl": "👨\u200d👧\u200d👧", - "family_man_man_boy": "👨\u200d👨\u200d👦", - "family_man_man_boy_boy": "👨\u200d👨\u200d👦\u200d👦", - "family_man_man_girl": "👨\u200d👨\u200d👧", - "family_man_man_girl_boy": "👨\u200d👨\u200d👧\u200d👦", - "family_man_man_girl_girl": "👨\u200d👨\u200d👧\u200d👧", - "family_man_woman_boy": "👨\u200d👩\u200d👦", - "family_man_woman_boy_boy": "👨\u200d👩\u200d👦\u200d👦", - "family_man_woman_girl": "👨\u200d👩\u200d👧", - "family_man_woman_girl_boy": "👨\u200d👩\u200d👧\u200d👦", - "family_man_woman_girl_girl": "👨\u200d👩\u200d👧\u200d👧", - "family_woman_boy": "👩\u200d👦", - "family_woman_boy_boy": "👩\u200d👦\u200d👦", - "family_woman_girl": "👩\u200d👧", - "family_woman_girl_boy": "👩\u200d👧\u200d👦", - "family_woman_girl_girl": "👩\u200d👧\u200d👧", - "family_woman_woman_boy": "👩\u200d👩\u200d👦", - "family_woman_woman_boy_boy": "👩\u200d👩\u200d👦\u200d👦", - "family_woman_woman_girl": "👩\u200d👩\u200d👧", - "family_woman_woman_girl_boy": "👩\u200d👩\u200d👧\u200d👦", - "family_woman_woman_girl_girl": "👩\u200d👩\u200d👧\u200d👧", - "fast-forward_button": "â©", - "fast_down_button": "â¬", - "fast_reverse_button": "âª", - "fast_up_button": "â«", - "fax_machine": "📠", - "fearful_face": "😨", - "female_sign": "♀", - "ferris_wheel": "🎡", - "ferry": "â›´", - "field_hockey": "ðŸ‘", - "file_cabinet": "🗄", - "file_folder": "ðŸ“", - "film_frames": "🎞", - "film_projector": "📽", - "fire": "🔥", - "fire_extinguisher": "🧯", - "firecracker": "🧨", - "fire_engine": "🚒", - "fireworks": "🎆", - "first_quarter_moon": "🌓", - "first_quarter_moon_face": "🌛", - "fish": "ðŸŸ", - "fish_cake_with_swirl": "ðŸ¥", - "fishing_pole": "🎣", - "five-thirty": "🕠", - "five_o’clock": "🕔", - "flag_in_hole": "⛳", - "flamingo": "🦩", - "flashlight": "🔦", - "flat_shoe": "🥿", - "fleur-de-lis": "âšœ", - "flexed_biceps": "💪", - "flexed_biceps_dark_skin_tone": "💪ðŸ¿", - "flexed_biceps_light_skin_tone": "💪ðŸ»", - "flexed_biceps_medium-dark_skin_tone": "💪ðŸ¾", - "flexed_biceps_medium-light_skin_tone": "💪ðŸ¼", - "flexed_biceps_medium_skin_tone": "💪ðŸ½", - "floppy_disk": "💾", - "flower_playing_cards": "🎴", - "flushed_face": "😳", - "flying_disc": "ðŸ¥", - "flying_saucer": "🛸", - "fog": "🌫", - "foggy": "ðŸŒ", - "folded_hands": "ðŸ™", - "folded_hands_dark_skin_tone": "ðŸ™ðŸ¿", - "folded_hands_light_skin_tone": "ðŸ™ðŸ»", - "folded_hands_medium-dark_skin_tone": "ðŸ™ðŸ¾", - "folded_hands_medium-light_skin_tone": "ðŸ™ðŸ¼", - "folded_hands_medium_skin_tone": "ðŸ™ðŸ½", - "foot": "🦶", - "footprints": "👣", - "fork_and_knife": "ðŸ´", - "fork_and_knife_with_plate": "ðŸ½", - "fortune_cookie": "🥠", - "fountain": "⛲", - "fountain_pen": "🖋", - "four-thirty": "🕟", - "four_leaf_clover": "ðŸ€", - "four_o’clock": "🕓", - "fox_face": "🦊", - "framed_picture": "🖼", - "french_fries": "ðŸŸ", - "fried_shrimp": "ðŸ¤", - "frog_face": "ðŸ¸", - "front-facing_baby_chick": "ðŸ¥", - "frowning_face": "☹", - "frowning_face_with_open_mouth": "😦", - "fuel_pump": "⛽", - "full_moon": "🌕", - "full_moon_face": "ðŸŒ", - "funeral_urn": "âš±", - "game_die": "🎲", - "garlic": "🧄", - "gear": "âš™", - "gem_stone": "💎", - "genie": "🧞", - "ghost": "👻", - "giraffe": "🦒", - "girl": "👧", - "girl_dark_skin_tone": "👧ðŸ¿", - "girl_light_skin_tone": "👧ðŸ»", - "girl_medium-dark_skin_tone": "👧ðŸ¾", - "girl_medium-light_skin_tone": "👧ðŸ¼", - "girl_medium_skin_tone": "👧ðŸ½", - "glass_of_milk": "🥛", - "glasses": "👓", - "globe_showing_americas": "🌎", - "globe_showing_asia-australia": "ðŸŒ", - "globe_showing_europe-africa": "ðŸŒ", - "globe_with_meridians": "ðŸŒ", - "gloves": "🧤", - "glowing_star": "🌟", - "goal_net": "🥅", - "goat": "ðŸ", - "goblin": "👺", - "goggles": "🥽", - "gorilla": "ðŸ¦", - "graduation_cap": "🎓", - "grapes": "ðŸ‡", - "green_apple": "ðŸ", - "green_book": "📗", - "green_circle": "🟢", - "green_heart": "💚", - "green_salad": "🥗", - "green_square": "🟩", - "grimacing_face": "😬", - "grinning_cat_face": "😺", - "grinning_cat_face_with_smiling_eyes": "😸", - "grinning_face": "😀", - "grinning_face_with_big_eyes": "😃", - "grinning_face_with_smiling_eyes": "😄", - "grinning_face_with_sweat": "😅", - "grinning_squinting_face": "😆", - "growing_heart": "💗", - "guard": "💂", - "guard_dark_skin_tone": "💂ðŸ¿", - "guard_light_skin_tone": "💂ðŸ»", - "guard_medium-dark_skin_tone": "💂ðŸ¾", - "guard_medium-light_skin_tone": "💂ðŸ¼", - "guard_medium_skin_tone": "💂ðŸ½", - "guide_dog": "🦮", - "guitar": "🎸", - "hamburger": "ðŸ”", - "hammer": "🔨", - "hammer_and_pick": "âš’", - "hammer_and_wrench": "🛠", - "hamster_face": "ðŸ¹", - "hand_with_fingers_splayed": "ðŸ–", - "hand_with_fingers_splayed_dark_skin_tone": "ðŸ–ðŸ¿", - "hand_with_fingers_splayed_light_skin_tone": "ðŸ–ðŸ»", - "hand_with_fingers_splayed_medium-dark_skin_tone": "ðŸ–ðŸ¾", - "hand_with_fingers_splayed_medium-light_skin_tone": "ðŸ–ðŸ¼", - "hand_with_fingers_splayed_medium_skin_tone": "ðŸ–ðŸ½", - "handbag": "👜", - "handshake": "ðŸ¤", - "hatching_chick": "ðŸ£", - "headphone": "🎧", - "hear-no-evil_monkey": "🙉", - "heart_decoration": "💟", - "heart_suit": "♥", - "heart_with_arrow": "💘", - "heart_with_ribbon": "ðŸ’", - "heavy_check_mark": "✔", - "heavy_division_sign": "âž—", - "heavy_dollar_sign": "💲", - "heavy_heart_exclamation": "â£", - "heavy_large_circle": "â­•", - "heavy_minus_sign": "âž–", - "heavy_multiplication_x": "✖", - "heavy_plus_sign": "âž•", - "hedgehog": "🦔", - "helicopter": "ðŸš", - "herb": "🌿", - "hibiscus": "🌺", - "high-heeled_shoe": "👠", - "high-speed_train": "🚄", - "high_voltage": "âš¡", - "hiking_boot": "🥾", - "hindu_temple": "🛕", - "hippopotamus": "🦛", - "hole": "🕳", - "honey_pot": "ðŸ¯", - "honeybee": "ðŸ", - "horizontal_traffic_light": "🚥", - "horse": "ðŸ´", - "horse_face": "ðŸ´", - "horse_racing": "ðŸ‡", - "horse_racing_dark_skin_tone": "ðŸ‡ðŸ¿", - "horse_racing_light_skin_tone": "ðŸ‡ðŸ»", - "horse_racing_medium-dark_skin_tone": "ðŸ‡ðŸ¾", - "horse_racing_medium-light_skin_tone": "ðŸ‡ðŸ¼", - "horse_racing_medium_skin_tone": "ðŸ‡ðŸ½", - "hospital": "ðŸ¥", - "hot_beverage": "☕", - "hot_dog": "🌭", - "hot_face": "🥵", - "hot_pepper": "🌶", - "hot_springs": "♨", - "hotel": "ðŸ¨", - "hourglass_done": "⌛", - "hourglass_not_done": "â³", - "house": "ðŸ ", - "house_with_garden": "ðŸ¡", - "houses": "ðŸ˜", - "hugging_face": "🤗", - "hundred_points": "💯", - "hushed_face": "😯", - "ice": "🧊", - "ice_cream": "ðŸ¨", - "ice_hockey": "ðŸ’", - "ice_skate": "⛸", - "inbox_tray": "📥", - "incoming_envelope": "📨", - "index_pointing_up": "â˜", - "index_pointing_up_dark_skin_tone": "â˜ðŸ¿", - "index_pointing_up_light_skin_tone": "â˜ðŸ»", - "index_pointing_up_medium-dark_skin_tone": "â˜ðŸ¾", - "index_pointing_up_medium-light_skin_tone": "â˜ðŸ¼", - "index_pointing_up_medium_skin_tone": "â˜ðŸ½", - "infinity": "♾", - "information": "ℹ", - "input_latin_letters": "🔤", - "input_latin_lowercase": "🔡", - "input_latin_uppercase": "🔠", - "input_numbers": "🔢", - "input_symbols": "🔣", - "jack-o-lantern": "🎃", - "jeans": "👖", - "jigsaw": "🧩", - "joker": "ðŸƒ", - "joystick": "🕹", - "kaaba": "🕋", - "kangaroo": "🦘", - "key": "🔑", - "keyboard": "⌨", - "keycap_#": "#ï¸âƒ£", - "keycap_*": "*ï¸âƒ£", - "keycap_0": "0ï¸âƒ£", - "keycap_1": "1ï¸âƒ£", - "keycap_10": "🔟", - "keycap_2": "2ï¸âƒ£", - "keycap_3": "3ï¸âƒ£", - "keycap_4": "4ï¸âƒ£", - "keycap_5": "5ï¸âƒ£", - "keycap_6": "6ï¸âƒ£", - "keycap_7": "7ï¸âƒ£", - "keycap_8": "8ï¸âƒ£", - "keycap_9": "9ï¸âƒ£", - "kick_scooter": "🛴", - "kimono": "👘", - "kiss": "💋", - "kiss_man_man": "👨\u200dâ¤ï¸\u200d💋\u200d👨", - "kiss_mark": "💋", - "kiss_woman_man": "👩\u200dâ¤ï¸\u200d💋\u200d👨", - "kiss_woman_woman": "👩\u200dâ¤ï¸\u200d💋\u200d👩", - "kissing_cat_face": "😽", - "kissing_face": "😗", - "kissing_face_with_closed_eyes": "😚", - "kissing_face_with_smiling_eyes": "😙", - "kitchen_knife": "🔪", - "kite": "ðŸª", - "kiwi_fruit": "ðŸ¥", - "koala": "ðŸ¨", - "lab_coat": "🥼", - "label": "ðŸ·", - "lacrosse": "ðŸ¥", - "lady_beetle": "ðŸž", - "laptop_computer": "💻", - "large_blue_diamond": "🔷", - "large_orange_diamond": "🔶", - "last_quarter_moon": "🌗", - "last_quarter_moon_face": "🌜", - "last_track_button": "â®", - "latin_cross": "âœ", - "leaf_fluttering_in_wind": "ðŸƒ", - "leafy_green": "🥬", - "ledger": "📒", - "left-facing_fist": "🤛", - "left-facing_fist_dark_skin_tone": "🤛ðŸ¿", - "left-facing_fist_light_skin_tone": "🤛ðŸ»", - "left-facing_fist_medium-dark_skin_tone": "🤛ðŸ¾", - "left-facing_fist_medium-light_skin_tone": "🤛ðŸ¼", - "left-facing_fist_medium_skin_tone": "🤛ðŸ½", - "left-right_arrow": "↔", - "left_arrow": "⬅", - "left_arrow_curving_right": "↪", - "left_luggage": "🛅", - "left_speech_bubble": "🗨", - "leg": "🦵", - "lemon": "ðŸ‹", - "leopard": "ðŸ†", - "level_slider": "🎚", - "light_bulb": "💡", - "light_rail": "🚈", - "link": "🔗", - "linked_paperclips": "🖇", - "lion_face": "ðŸ¦", - "lipstick": "💄", - "litter_in_bin_sign": "🚮", - "lizard": "🦎", - "llama": "🦙", - "lobster": "🦞", - "locked": "🔒", - "locked_with_key": "ðŸ”", - "locked_with_pen": "ðŸ”", - "locomotive": "🚂", - "lollipop": "ðŸ­", - "lotion_bottle": "🧴", - "loudly_crying_face": "😭", - "loudspeaker": "📢", - "love-you_gesture": "🤟", - "love-you_gesture_dark_skin_tone": "🤟ðŸ¿", - "love-you_gesture_light_skin_tone": "🤟ðŸ»", - "love-you_gesture_medium-dark_skin_tone": "🤟ðŸ¾", - "love-you_gesture_medium-light_skin_tone": "🤟ðŸ¼", - "love-you_gesture_medium_skin_tone": "🤟ðŸ½", - "love_hotel": "ðŸ©", - "love_letter": "💌", - "luggage": "🧳", - "lying_face": "🤥", - "mage": "🧙", - "mage_dark_skin_tone": "🧙ðŸ¿", - "mage_light_skin_tone": "🧙ðŸ»", - "mage_medium-dark_skin_tone": "🧙ðŸ¾", - "mage_medium-light_skin_tone": "🧙ðŸ¼", - "mage_medium_skin_tone": "🧙ðŸ½", - "magnet": "🧲", - "magnifying_glass_tilted_left": "ðŸ”", - "magnifying_glass_tilted_right": "🔎", - "mahjong_red_dragon": "🀄", - "male_sign": "♂", - "man": "👨", - "man_and_woman_holding_hands": "👫", - "man_artist": "👨\u200d🎨", - "man_artist_dark_skin_tone": "👨ðŸ¿\u200d🎨", - "man_artist_light_skin_tone": "👨ðŸ»\u200d🎨", - "man_artist_medium-dark_skin_tone": "👨ðŸ¾\u200d🎨", - "man_artist_medium-light_skin_tone": "👨ðŸ¼\u200d🎨", - "man_artist_medium_skin_tone": "👨ðŸ½\u200d🎨", - "man_astronaut": "👨\u200d🚀", - "man_astronaut_dark_skin_tone": "👨ðŸ¿\u200d🚀", - "man_astronaut_light_skin_tone": "👨ðŸ»\u200d🚀", - "man_astronaut_medium-dark_skin_tone": "👨ðŸ¾\u200d🚀", - "man_astronaut_medium-light_skin_tone": "👨ðŸ¼\u200d🚀", - "man_astronaut_medium_skin_tone": "👨ðŸ½\u200d🚀", - "man_biking": "🚴\u200d♂ï¸", - "man_biking_dark_skin_tone": "🚴ðŸ¿\u200d♂ï¸", - "man_biking_light_skin_tone": "🚴ðŸ»\u200d♂ï¸", - "man_biking_medium-dark_skin_tone": "🚴ðŸ¾\u200d♂ï¸", - "man_biking_medium-light_skin_tone": "🚴ðŸ¼\u200d♂ï¸", - "man_biking_medium_skin_tone": "🚴ðŸ½\u200d♂ï¸", - "man_bouncing_ball": "⛹ï¸\u200d♂ï¸", - "man_bouncing_ball_dark_skin_tone": "⛹ðŸ¿\u200d♂ï¸", - "man_bouncing_ball_light_skin_tone": "⛹ðŸ»\u200d♂ï¸", - "man_bouncing_ball_medium-dark_skin_tone": "⛹ðŸ¾\u200d♂ï¸", - "man_bouncing_ball_medium-light_skin_tone": "⛹ðŸ¼\u200d♂ï¸", - "man_bouncing_ball_medium_skin_tone": "⛹ðŸ½\u200d♂ï¸", - "man_bowing": "🙇\u200d♂ï¸", - "man_bowing_dark_skin_tone": "🙇ðŸ¿\u200d♂ï¸", - "man_bowing_light_skin_tone": "🙇ðŸ»\u200d♂ï¸", - "man_bowing_medium-dark_skin_tone": "🙇ðŸ¾\u200d♂ï¸", - "man_bowing_medium-light_skin_tone": "🙇ðŸ¼\u200d♂ï¸", - "man_bowing_medium_skin_tone": "🙇ðŸ½\u200d♂ï¸", - "man_cartwheeling": "🤸\u200d♂ï¸", - "man_cartwheeling_dark_skin_tone": "🤸ðŸ¿\u200d♂ï¸", - "man_cartwheeling_light_skin_tone": "🤸ðŸ»\u200d♂ï¸", - "man_cartwheeling_medium-dark_skin_tone": "🤸ðŸ¾\u200d♂ï¸", - "man_cartwheeling_medium-light_skin_tone": "🤸ðŸ¼\u200d♂ï¸", - "man_cartwheeling_medium_skin_tone": "🤸ðŸ½\u200d♂ï¸", - "man_climbing": "🧗\u200d♂ï¸", - "man_climbing_dark_skin_tone": "🧗ðŸ¿\u200d♂ï¸", - "man_climbing_light_skin_tone": "🧗ðŸ»\u200d♂ï¸", - "man_climbing_medium-dark_skin_tone": "🧗ðŸ¾\u200d♂ï¸", - "man_climbing_medium-light_skin_tone": "🧗ðŸ¼\u200d♂ï¸", - "man_climbing_medium_skin_tone": "🧗ðŸ½\u200d♂ï¸", - "man_construction_worker": "👷\u200d♂ï¸", - "man_construction_worker_dark_skin_tone": "👷ðŸ¿\u200d♂ï¸", - "man_construction_worker_light_skin_tone": "👷ðŸ»\u200d♂ï¸", - "man_construction_worker_medium-dark_skin_tone": "👷ðŸ¾\u200d♂ï¸", - "man_construction_worker_medium-light_skin_tone": "👷ðŸ¼\u200d♂ï¸", - "man_construction_worker_medium_skin_tone": "👷ðŸ½\u200d♂ï¸", - "man_cook": "👨\u200dðŸ³", - "man_cook_dark_skin_tone": "👨ðŸ¿\u200dðŸ³", - "man_cook_light_skin_tone": "👨ðŸ»\u200dðŸ³", - "man_cook_medium-dark_skin_tone": "👨ðŸ¾\u200dðŸ³", - "man_cook_medium-light_skin_tone": "👨ðŸ¼\u200dðŸ³", - "man_cook_medium_skin_tone": "👨ðŸ½\u200dðŸ³", - "man_dancing": "🕺", - "man_dancing_dark_skin_tone": "🕺ðŸ¿", - "man_dancing_light_skin_tone": "🕺ðŸ»", - "man_dancing_medium-dark_skin_tone": "🕺ðŸ¾", - "man_dancing_medium-light_skin_tone": "🕺ðŸ¼", - "man_dancing_medium_skin_tone": "🕺ðŸ½", - "man_dark_skin_tone": "👨ðŸ¿", - "man_detective": "🕵ï¸\u200d♂ï¸", - "man_detective_dark_skin_tone": "🕵ðŸ¿\u200d♂ï¸", - "man_detective_light_skin_tone": "🕵ðŸ»\u200d♂ï¸", - "man_detective_medium-dark_skin_tone": "🕵ðŸ¾\u200d♂ï¸", - "man_detective_medium-light_skin_tone": "🕵ðŸ¼\u200d♂ï¸", - "man_detective_medium_skin_tone": "🕵ðŸ½\u200d♂ï¸", - "man_elf": "ðŸ§\u200d♂ï¸", - "man_elf_dark_skin_tone": "ðŸ§ðŸ¿\u200d♂ï¸", - "man_elf_light_skin_tone": "ðŸ§ðŸ»\u200d♂ï¸", - "man_elf_medium-dark_skin_tone": "ðŸ§ðŸ¾\u200d♂ï¸", - "man_elf_medium-light_skin_tone": "ðŸ§ðŸ¼\u200d♂ï¸", - "man_elf_medium_skin_tone": "ðŸ§ðŸ½\u200d♂ï¸", - "man_facepalming": "🤦\u200d♂ï¸", - "man_facepalming_dark_skin_tone": "🤦ðŸ¿\u200d♂ï¸", - "man_facepalming_light_skin_tone": "🤦ðŸ»\u200d♂ï¸", - "man_facepalming_medium-dark_skin_tone": "🤦ðŸ¾\u200d♂ï¸", - "man_facepalming_medium-light_skin_tone": "🤦ðŸ¼\u200d♂ï¸", - "man_facepalming_medium_skin_tone": "🤦ðŸ½\u200d♂ï¸", - "man_factory_worker": "👨\u200dðŸ­", - "man_factory_worker_dark_skin_tone": "👨ðŸ¿\u200dðŸ­", - "man_factory_worker_light_skin_tone": "👨ðŸ»\u200dðŸ­", - "man_factory_worker_medium-dark_skin_tone": "👨ðŸ¾\u200dðŸ­", - "man_factory_worker_medium-light_skin_tone": "👨ðŸ¼\u200dðŸ­", - "man_factory_worker_medium_skin_tone": "👨ðŸ½\u200dðŸ­", - "man_fairy": "🧚\u200d♂ï¸", - "man_fairy_dark_skin_tone": "🧚ðŸ¿\u200d♂ï¸", - "man_fairy_light_skin_tone": "🧚ðŸ»\u200d♂ï¸", - "man_fairy_medium-dark_skin_tone": "🧚ðŸ¾\u200d♂ï¸", - "man_fairy_medium-light_skin_tone": "🧚ðŸ¼\u200d♂ï¸", - "man_fairy_medium_skin_tone": "🧚ðŸ½\u200d♂ï¸", - "man_farmer": "👨\u200d🌾", - "man_farmer_dark_skin_tone": "👨ðŸ¿\u200d🌾", - "man_farmer_light_skin_tone": "👨ðŸ»\u200d🌾", - "man_farmer_medium-dark_skin_tone": "👨ðŸ¾\u200d🌾", - "man_farmer_medium-light_skin_tone": "👨ðŸ¼\u200d🌾", - "man_farmer_medium_skin_tone": "👨ðŸ½\u200d🌾", - "man_firefighter": "👨\u200d🚒", - "man_firefighter_dark_skin_tone": "👨ðŸ¿\u200d🚒", - "man_firefighter_light_skin_tone": "👨ðŸ»\u200d🚒", - "man_firefighter_medium-dark_skin_tone": "👨ðŸ¾\u200d🚒", - "man_firefighter_medium-light_skin_tone": "👨ðŸ¼\u200d🚒", - "man_firefighter_medium_skin_tone": "👨ðŸ½\u200d🚒", - "man_frowning": "ðŸ™\u200d♂ï¸", - "man_frowning_dark_skin_tone": "ðŸ™ðŸ¿\u200d♂ï¸", - "man_frowning_light_skin_tone": "ðŸ™ðŸ»\u200d♂ï¸", - "man_frowning_medium-dark_skin_tone": "ðŸ™ðŸ¾\u200d♂ï¸", - "man_frowning_medium-light_skin_tone": "ðŸ™ðŸ¼\u200d♂ï¸", - "man_frowning_medium_skin_tone": "ðŸ™ðŸ½\u200d♂ï¸", - "man_genie": "🧞\u200d♂ï¸", - "man_gesturing_no": "🙅\u200d♂ï¸", - "man_gesturing_no_dark_skin_tone": "🙅ðŸ¿\u200d♂ï¸", - "man_gesturing_no_light_skin_tone": "🙅ðŸ»\u200d♂ï¸", - "man_gesturing_no_medium-dark_skin_tone": "🙅ðŸ¾\u200d♂ï¸", - "man_gesturing_no_medium-light_skin_tone": "🙅ðŸ¼\u200d♂ï¸", - "man_gesturing_no_medium_skin_tone": "🙅ðŸ½\u200d♂ï¸", - "man_gesturing_ok": "🙆\u200d♂ï¸", - "man_gesturing_ok_dark_skin_tone": "🙆ðŸ¿\u200d♂ï¸", - "man_gesturing_ok_light_skin_tone": "🙆ðŸ»\u200d♂ï¸", - "man_gesturing_ok_medium-dark_skin_tone": "🙆ðŸ¾\u200d♂ï¸", - "man_gesturing_ok_medium-light_skin_tone": "🙆ðŸ¼\u200d♂ï¸", - "man_gesturing_ok_medium_skin_tone": "🙆ðŸ½\u200d♂ï¸", - "man_getting_haircut": "💇\u200d♂ï¸", - "man_getting_haircut_dark_skin_tone": "💇ðŸ¿\u200d♂ï¸", - "man_getting_haircut_light_skin_tone": "💇ðŸ»\u200d♂ï¸", - "man_getting_haircut_medium-dark_skin_tone": "💇ðŸ¾\u200d♂ï¸", - "man_getting_haircut_medium-light_skin_tone": "💇ðŸ¼\u200d♂ï¸", - "man_getting_haircut_medium_skin_tone": "💇ðŸ½\u200d♂ï¸", - "man_getting_massage": "💆\u200d♂ï¸", - "man_getting_massage_dark_skin_tone": "💆ðŸ¿\u200d♂ï¸", - "man_getting_massage_light_skin_tone": "💆ðŸ»\u200d♂ï¸", - "man_getting_massage_medium-dark_skin_tone": "💆ðŸ¾\u200d♂ï¸", - "man_getting_massage_medium-light_skin_tone": "💆ðŸ¼\u200d♂ï¸", - "man_getting_massage_medium_skin_tone": "💆ðŸ½\u200d♂ï¸", - "man_golfing": "ðŸŒï¸\u200d♂ï¸", - "man_golfing_dark_skin_tone": "ðŸŒðŸ¿\u200d♂ï¸", - "man_golfing_light_skin_tone": "ðŸŒðŸ»\u200d♂ï¸", - "man_golfing_medium-dark_skin_tone": "ðŸŒðŸ¾\u200d♂ï¸", - "man_golfing_medium-light_skin_tone": "ðŸŒðŸ¼\u200d♂ï¸", - "man_golfing_medium_skin_tone": "ðŸŒðŸ½\u200d♂ï¸", - "man_guard": "💂\u200d♂ï¸", - "man_guard_dark_skin_tone": "💂ðŸ¿\u200d♂ï¸", - "man_guard_light_skin_tone": "💂ðŸ»\u200d♂ï¸", - "man_guard_medium-dark_skin_tone": "💂ðŸ¾\u200d♂ï¸", - "man_guard_medium-light_skin_tone": "💂ðŸ¼\u200d♂ï¸", - "man_guard_medium_skin_tone": "💂ðŸ½\u200d♂ï¸", - "man_health_worker": "👨\u200dâš•ï¸", - "man_health_worker_dark_skin_tone": "👨ðŸ¿\u200dâš•ï¸", - "man_health_worker_light_skin_tone": "👨ðŸ»\u200dâš•ï¸", - "man_health_worker_medium-dark_skin_tone": "👨ðŸ¾\u200dâš•ï¸", - "man_health_worker_medium-light_skin_tone": "👨ðŸ¼\u200dâš•ï¸", - "man_health_worker_medium_skin_tone": "👨ðŸ½\u200dâš•ï¸", - "man_in_lotus_position": "🧘\u200d♂ï¸", - "man_in_lotus_position_dark_skin_tone": "🧘ðŸ¿\u200d♂ï¸", - "man_in_lotus_position_light_skin_tone": "🧘ðŸ»\u200d♂ï¸", - "man_in_lotus_position_medium-dark_skin_tone": "🧘ðŸ¾\u200d♂ï¸", - "man_in_lotus_position_medium-light_skin_tone": "🧘ðŸ¼\u200d♂ï¸", - "man_in_lotus_position_medium_skin_tone": "🧘ðŸ½\u200d♂ï¸", - "man_in_manual_wheelchair": "👨\u200d🦽", - "man_in_motorized_wheelchair": "👨\u200d🦼", - "man_in_steamy_room": "🧖\u200d♂ï¸", - "man_in_steamy_room_dark_skin_tone": "🧖ðŸ¿\u200d♂ï¸", - "man_in_steamy_room_light_skin_tone": "🧖ðŸ»\u200d♂ï¸", - "man_in_steamy_room_medium-dark_skin_tone": "🧖ðŸ¾\u200d♂ï¸", - "man_in_steamy_room_medium-light_skin_tone": "🧖ðŸ¼\u200d♂ï¸", - "man_in_steamy_room_medium_skin_tone": "🧖ðŸ½\u200d♂ï¸", - "man_in_suit_levitating": "🕴", - "man_in_suit_levitating_dark_skin_tone": "🕴ðŸ¿", - "man_in_suit_levitating_light_skin_tone": "🕴ðŸ»", - "man_in_suit_levitating_medium-dark_skin_tone": "🕴ðŸ¾", - "man_in_suit_levitating_medium-light_skin_tone": "🕴ðŸ¼", - "man_in_suit_levitating_medium_skin_tone": "🕴ðŸ½", - "man_in_tuxedo": "🤵", - "man_in_tuxedo_dark_skin_tone": "🤵ðŸ¿", - "man_in_tuxedo_light_skin_tone": "🤵ðŸ»", - "man_in_tuxedo_medium-dark_skin_tone": "🤵ðŸ¾", - "man_in_tuxedo_medium-light_skin_tone": "🤵ðŸ¼", - "man_in_tuxedo_medium_skin_tone": "🤵ðŸ½", - "man_judge": "👨\u200dâš–ï¸", - "man_judge_dark_skin_tone": "👨ðŸ¿\u200dâš–ï¸", - "man_judge_light_skin_tone": "👨ðŸ»\u200dâš–ï¸", - "man_judge_medium-dark_skin_tone": "👨ðŸ¾\u200dâš–ï¸", - "man_judge_medium-light_skin_tone": "👨ðŸ¼\u200dâš–ï¸", - "man_judge_medium_skin_tone": "👨ðŸ½\u200dâš–ï¸", - "man_juggling": "🤹\u200d♂ï¸", - "man_juggling_dark_skin_tone": "🤹ðŸ¿\u200d♂ï¸", - "man_juggling_light_skin_tone": "🤹ðŸ»\u200d♂ï¸", - "man_juggling_medium-dark_skin_tone": "🤹ðŸ¾\u200d♂ï¸", - "man_juggling_medium-light_skin_tone": "🤹ðŸ¼\u200d♂ï¸", - "man_juggling_medium_skin_tone": "🤹ðŸ½\u200d♂ï¸", - "man_lifting_weights": "ðŸ‹ï¸\u200d♂ï¸", - "man_lifting_weights_dark_skin_tone": "ðŸ‹ðŸ¿\u200d♂ï¸", - "man_lifting_weights_light_skin_tone": "ðŸ‹ðŸ»\u200d♂ï¸", - "man_lifting_weights_medium-dark_skin_tone": "ðŸ‹ðŸ¾\u200d♂ï¸", - "man_lifting_weights_medium-light_skin_tone": "ðŸ‹ðŸ¼\u200d♂ï¸", - "man_lifting_weights_medium_skin_tone": "ðŸ‹ðŸ½\u200d♂ï¸", - "man_light_skin_tone": "👨ðŸ»", - "man_mage": "🧙\u200d♂ï¸", - "man_mage_dark_skin_tone": "🧙ðŸ¿\u200d♂ï¸", - "man_mage_light_skin_tone": "🧙ðŸ»\u200d♂ï¸", - "man_mage_medium-dark_skin_tone": "🧙ðŸ¾\u200d♂ï¸", - "man_mage_medium-light_skin_tone": "🧙ðŸ¼\u200d♂ï¸", - "man_mage_medium_skin_tone": "🧙ðŸ½\u200d♂ï¸", - "man_mechanic": "👨\u200d🔧", - "man_mechanic_dark_skin_tone": "👨ðŸ¿\u200d🔧", - "man_mechanic_light_skin_tone": "👨ðŸ»\u200d🔧", - "man_mechanic_medium-dark_skin_tone": "👨ðŸ¾\u200d🔧", - "man_mechanic_medium-light_skin_tone": "👨ðŸ¼\u200d🔧", - "man_mechanic_medium_skin_tone": "👨ðŸ½\u200d🔧", - "man_medium-dark_skin_tone": "👨ðŸ¾", - "man_medium-light_skin_tone": "👨ðŸ¼", - "man_medium_skin_tone": "👨ðŸ½", - "man_mountain_biking": "🚵\u200d♂ï¸", - "man_mountain_biking_dark_skin_tone": "🚵ðŸ¿\u200d♂ï¸", - "man_mountain_biking_light_skin_tone": "🚵ðŸ»\u200d♂ï¸", - "man_mountain_biking_medium-dark_skin_tone": "🚵ðŸ¾\u200d♂ï¸", - "man_mountain_biking_medium-light_skin_tone": "🚵ðŸ¼\u200d♂ï¸", - "man_mountain_biking_medium_skin_tone": "🚵ðŸ½\u200d♂ï¸", - "man_office_worker": "👨\u200d💼", - "man_office_worker_dark_skin_tone": "👨ðŸ¿\u200d💼", - "man_office_worker_light_skin_tone": "👨ðŸ»\u200d💼", - "man_office_worker_medium-dark_skin_tone": "👨ðŸ¾\u200d💼", - "man_office_worker_medium-light_skin_tone": "👨ðŸ¼\u200d💼", - "man_office_worker_medium_skin_tone": "👨ðŸ½\u200d💼", - "man_pilot": "👨\u200d✈ï¸", - "man_pilot_dark_skin_tone": "👨ðŸ¿\u200d✈ï¸", - "man_pilot_light_skin_tone": "👨ðŸ»\u200d✈ï¸", - "man_pilot_medium-dark_skin_tone": "👨ðŸ¾\u200d✈ï¸", - "man_pilot_medium-light_skin_tone": "👨ðŸ¼\u200d✈ï¸", - "man_pilot_medium_skin_tone": "👨ðŸ½\u200d✈ï¸", - "man_playing_handball": "🤾\u200d♂ï¸", - "man_playing_handball_dark_skin_tone": "🤾ðŸ¿\u200d♂ï¸", - "man_playing_handball_light_skin_tone": "🤾ðŸ»\u200d♂ï¸", - "man_playing_handball_medium-dark_skin_tone": "🤾ðŸ¾\u200d♂ï¸", - "man_playing_handball_medium-light_skin_tone": "🤾ðŸ¼\u200d♂ï¸", - "man_playing_handball_medium_skin_tone": "🤾ðŸ½\u200d♂ï¸", - "man_playing_water_polo": "🤽\u200d♂ï¸", - "man_playing_water_polo_dark_skin_tone": "🤽ðŸ¿\u200d♂ï¸", - "man_playing_water_polo_light_skin_tone": "🤽ðŸ»\u200d♂ï¸", - "man_playing_water_polo_medium-dark_skin_tone": "🤽ðŸ¾\u200d♂ï¸", - "man_playing_water_polo_medium-light_skin_tone": "🤽ðŸ¼\u200d♂ï¸", - "man_playing_water_polo_medium_skin_tone": "🤽ðŸ½\u200d♂ï¸", - "man_police_officer": "👮\u200d♂ï¸", - "man_police_officer_dark_skin_tone": "👮ðŸ¿\u200d♂ï¸", - "man_police_officer_light_skin_tone": "👮ðŸ»\u200d♂ï¸", - "man_police_officer_medium-dark_skin_tone": "👮ðŸ¾\u200d♂ï¸", - "man_police_officer_medium-light_skin_tone": "👮ðŸ¼\u200d♂ï¸", - "man_police_officer_medium_skin_tone": "👮ðŸ½\u200d♂ï¸", - "man_pouting": "🙎\u200d♂ï¸", - "man_pouting_dark_skin_tone": "🙎ðŸ¿\u200d♂ï¸", - "man_pouting_light_skin_tone": "🙎ðŸ»\u200d♂ï¸", - "man_pouting_medium-dark_skin_tone": "🙎ðŸ¾\u200d♂ï¸", - "man_pouting_medium-light_skin_tone": "🙎ðŸ¼\u200d♂ï¸", - "man_pouting_medium_skin_tone": "🙎ðŸ½\u200d♂ï¸", - "man_raising_hand": "🙋\u200d♂ï¸", - "man_raising_hand_dark_skin_tone": "🙋ðŸ¿\u200d♂ï¸", - "man_raising_hand_light_skin_tone": "🙋ðŸ»\u200d♂ï¸", - "man_raising_hand_medium-dark_skin_tone": "🙋ðŸ¾\u200d♂ï¸", - "man_raising_hand_medium-light_skin_tone": "🙋ðŸ¼\u200d♂ï¸", - "man_raising_hand_medium_skin_tone": "🙋ðŸ½\u200d♂ï¸", - "man_rowing_boat": "🚣\u200d♂ï¸", - "man_rowing_boat_dark_skin_tone": "🚣ðŸ¿\u200d♂ï¸", - "man_rowing_boat_light_skin_tone": "🚣ðŸ»\u200d♂ï¸", - "man_rowing_boat_medium-dark_skin_tone": "🚣ðŸ¾\u200d♂ï¸", - "man_rowing_boat_medium-light_skin_tone": "🚣ðŸ¼\u200d♂ï¸", - "man_rowing_boat_medium_skin_tone": "🚣ðŸ½\u200d♂ï¸", - "man_running": "ðŸƒ\u200d♂ï¸", - "man_running_dark_skin_tone": "ðŸƒðŸ¿\u200d♂ï¸", - "man_running_light_skin_tone": "ðŸƒðŸ»\u200d♂ï¸", - "man_running_medium-dark_skin_tone": "ðŸƒðŸ¾\u200d♂ï¸", - "man_running_medium-light_skin_tone": "ðŸƒðŸ¼\u200d♂ï¸", - "man_running_medium_skin_tone": "ðŸƒðŸ½\u200d♂ï¸", - "man_scientist": "👨\u200d🔬", - "man_scientist_dark_skin_tone": "👨ðŸ¿\u200d🔬", - "man_scientist_light_skin_tone": "👨ðŸ»\u200d🔬", - "man_scientist_medium-dark_skin_tone": "👨ðŸ¾\u200d🔬", - "man_scientist_medium-light_skin_tone": "👨ðŸ¼\u200d🔬", - "man_scientist_medium_skin_tone": "👨ðŸ½\u200d🔬", - "man_shrugging": "🤷\u200d♂ï¸", - "man_shrugging_dark_skin_tone": "🤷ðŸ¿\u200d♂ï¸", - "man_shrugging_light_skin_tone": "🤷ðŸ»\u200d♂ï¸", - "man_shrugging_medium-dark_skin_tone": "🤷ðŸ¾\u200d♂ï¸", - "man_shrugging_medium-light_skin_tone": "🤷ðŸ¼\u200d♂ï¸", - "man_shrugging_medium_skin_tone": "🤷ðŸ½\u200d♂ï¸", - "man_singer": "👨\u200d🎤", - "man_singer_dark_skin_tone": "👨ðŸ¿\u200d🎤", - "man_singer_light_skin_tone": "👨ðŸ»\u200d🎤", - "man_singer_medium-dark_skin_tone": "👨ðŸ¾\u200d🎤", - "man_singer_medium-light_skin_tone": "👨ðŸ¼\u200d🎤", - "man_singer_medium_skin_tone": "👨ðŸ½\u200d🎤", - "man_student": "👨\u200d🎓", - "man_student_dark_skin_tone": "👨ðŸ¿\u200d🎓", - "man_student_light_skin_tone": "👨ðŸ»\u200d🎓", - "man_student_medium-dark_skin_tone": "👨ðŸ¾\u200d🎓", - "man_student_medium-light_skin_tone": "👨ðŸ¼\u200d🎓", - "man_student_medium_skin_tone": "👨ðŸ½\u200d🎓", - "man_surfing": "ðŸ„\u200d♂ï¸", - "man_surfing_dark_skin_tone": "ðŸ„ðŸ¿\u200d♂ï¸", - "man_surfing_light_skin_tone": "ðŸ„ðŸ»\u200d♂ï¸", - "man_surfing_medium-dark_skin_tone": "ðŸ„ðŸ¾\u200d♂ï¸", - "man_surfing_medium-light_skin_tone": "ðŸ„ðŸ¼\u200d♂ï¸", - "man_surfing_medium_skin_tone": "ðŸ„ðŸ½\u200d♂ï¸", - "man_swimming": "ðŸŠ\u200d♂ï¸", - "man_swimming_dark_skin_tone": "ðŸŠðŸ¿\u200d♂ï¸", - "man_swimming_light_skin_tone": "ðŸŠðŸ»\u200d♂ï¸", - "man_swimming_medium-dark_skin_tone": "ðŸŠðŸ¾\u200d♂ï¸", - "man_swimming_medium-light_skin_tone": "ðŸŠðŸ¼\u200d♂ï¸", - "man_swimming_medium_skin_tone": "ðŸŠðŸ½\u200d♂ï¸", - "man_teacher": "👨\u200dðŸ«", - "man_teacher_dark_skin_tone": "👨ðŸ¿\u200dðŸ«", - "man_teacher_light_skin_tone": "👨ðŸ»\u200dðŸ«", - "man_teacher_medium-dark_skin_tone": "👨ðŸ¾\u200dðŸ«", - "man_teacher_medium-light_skin_tone": "👨ðŸ¼\u200dðŸ«", - "man_teacher_medium_skin_tone": "👨ðŸ½\u200dðŸ«", - "man_technologist": "👨\u200d💻", - "man_technologist_dark_skin_tone": "👨ðŸ¿\u200d💻", - "man_technologist_light_skin_tone": "👨ðŸ»\u200d💻", - "man_technologist_medium-dark_skin_tone": "👨ðŸ¾\u200d💻", - "man_technologist_medium-light_skin_tone": "👨ðŸ¼\u200d💻", - "man_technologist_medium_skin_tone": "👨ðŸ½\u200d💻", - "man_tipping_hand": "ðŸ’\u200d♂ï¸", - "man_tipping_hand_dark_skin_tone": "ðŸ’ðŸ¿\u200d♂ï¸", - "man_tipping_hand_light_skin_tone": "ðŸ’ðŸ»\u200d♂ï¸", - "man_tipping_hand_medium-dark_skin_tone": "ðŸ’ðŸ¾\u200d♂ï¸", - "man_tipping_hand_medium-light_skin_tone": "ðŸ’ðŸ¼\u200d♂ï¸", - "man_tipping_hand_medium_skin_tone": "ðŸ’ðŸ½\u200d♂ï¸", - "man_vampire": "🧛\u200d♂ï¸", - "man_vampire_dark_skin_tone": "🧛ðŸ¿\u200d♂ï¸", - "man_vampire_light_skin_tone": "🧛ðŸ»\u200d♂ï¸", - "man_vampire_medium-dark_skin_tone": "🧛ðŸ¾\u200d♂ï¸", - "man_vampire_medium-light_skin_tone": "🧛ðŸ¼\u200d♂ï¸", - "man_vampire_medium_skin_tone": "🧛ðŸ½\u200d♂ï¸", - "man_walking": "🚶\u200d♂ï¸", - "man_walking_dark_skin_tone": "🚶ðŸ¿\u200d♂ï¸", - "man_walking_light_skin_tone": "🚶ðŸ»\u200d♂ï¸", - "man_walking_medium-dark_skin_tone": "🚶ðŸ¾\u200d♂ï¸", - "man_walking_medium-light_skin_tone": "🚶ðŸ¼\u200d♂ï¸", - "man_walking_medium_skin_tone": "🚶ðŸ½\u200d♂ï¸", - "man_wearing_turban": "👳\u200d♂ï¸", - "man_wearing_turban_dark_skin_tone": "👳ðŸ¿\u200d♂ï¸", - "man_wearing_turban_light_skin_tone": "👳ðŸ»\u200d♂ï¸", - "man_wearing_turban_medium-dark_skin_tone": "👳ðŸ¾\u200d♂ï¸", - "man_wearing_turban_medium-light_skin_tone": "👳ðŸ¼\u200d♂ï¸", - "man_wearing_turban_medium_skin_tone": "👳ðŸ½\u200d♂ï¸", - "man_with_probing_cane": "👨\u200d🦯", - "man_with_chinese_cap": "👲", - "man_with_chinese_cap_dark_skin_tone": "👲ðŸ¿", - "man_with_chinese_cap_light_skin_tone": "👲ðŸ»", - "man_with_chinese_cap_medium-dark_skin_tone": "👲ðŸ¾", - "man_with_chinese_cap_medium-light_skin_tone": "👲ðŸ¼", - "man_with_chinese_cap_medium_skin_tone": "👲ðŸ½", - "man_zombie": "🧟\u200d♂ï¸", - "mango": "🥭", - "mantelpiece_clock": "🕰", - "manual_wheelchair": "🦽", - "man’s_shoe": "👞", - "map_of_japan": "🗾", - "maple_leaf": "ðŸ", - "martial_arts_uniform": "🥋", - "mate": "🧉", - "meat_on_bone": "ðŸ–", - "mechanical_arm": "🦾", - "mechanical_leg": "🦿", - "medical_symbol": "âš•", - "megaphone": "📣", - "melon": "ðŸˆ", - "memo": "ðŸ“", - "men_with_bunny_ears": "👯\u200d♂ï¸", - "men_wrestling": "🤼\u200d♂ï¸", - "menorah": "🕎", - "men’s_room": "🚹", - "mermaid": "🧜\u200d♀ï¸", - "mermaid_dark_skin_tone": "🧜ðŸ¿\u200d♀ï¸", - "mermaid_light_skin_tone": "🧜ðŸ»\u200d♀ï¸", - "mermaid_medium-dark_skin_tone": "🧜ðŸ¾\u200d♀ï¸", - "mermaid_medium-light_skin_tone": "🧜ðŸ¼\u200d♀ï¸", - "mermaid_medium_skin_tone": "🧜ðŸ½\u200d♀ï¸", - "merman": "🧜\u200d♂ï¸", - "merman_dark_skin_tone": "🧜ðŸ¿\u200d♂ï¸", - "merman_light_skin_tone": "🧜ðŸ»\u200d♂ï¸", - "merman_medium-dark_skin_tone": "🧜ðŸ¾\u200d♂ï¸", - "merman_medium-light_skin_tone": "🧜ðŸ¼\u200d♂ï¸", - "merman_medium_skin_tone": "🧜ðŸ½\u200d♂ï¸", - "merperson": "🧜", - "merperson_dark_skin_tone": "🧜ðŸ¿", - "merperson_light_skin_tone": "🧜ðŸ»", - "merperson_medium-dark_skin_tone": "🧜ðŸ¾", - "merperson_medium-light_skin_tone": "🧜ðŸ¼", - "merperson_medium_skin_tone": "🧜ðŸ½", - "metro": "🚇", - "microbe": "🦠", - "microphone": "🎤", - "microscope": "🔬", - "middle_finger": "🖕", - "middle_finger_dark_skin_tone": "🖕ðŸ¿", - "middle_finger_light_skin_tone": "🖕ðŸ»", - "middle_finger_medium-dark_skin_tone": "🖕ðŸ¾", - "middle_finger_medium-light_skin_tone": "🖕ðŸ¼", - "middle_finger_medium_skin_tone": "🖕ðŸ½", - "military_medal": "🎖", - "milky_way": "🌌", - "minibus": "ðŸš", - "moai": "🗿", - "mobile_phone": "📱", - "mobile_phone_off": "📴", - "mobile_phone_with_arrow": "📲", - "money-mouth_face": "🤑", - "money_bag": "💰", - "money_with_wings": "💸", - "monkey": "ðŸ’", - "monkey_face": "ðŸµ", - "monorail": "ðŸš", - "moon_cake": "🥮", - "moon_viewing_ceremony": "🎑", - "mosque": "🕌", - "mosquito": "🦟", - "motor_boat": "🛥", - "motor_scooter": "🛵", - "motorcycle": "ðŸ", - "motorized_wheelchair": "🦼", - "motorway": "🛣", - "mount_fuji": "🗻", - "mountain": "â›°", - "mountain_cableway": "🚠", - "mountain_railway": "🚞", - "mouse": "ðŸ­", - "mouse_face": "ðŸ­", - "mouth": "👄", - "movie_camera": "🎥", - "mushroom": "ðŸ„", - "musical_keyboard": "🎹", - "musical_note": "🎵", - "musical_notes": "🎶", - "musical_score": "🎼", - "muted_speaker": "🔇", - "nail_polish": "💅", - "nail_polish_dark_skin_tone": "💅ðŸ¿", - "nail_polish_light_skin_tone": "💅ðŸ»", - "nail_polish_medium-dark_skin_tone": "💅ðŸ¾", - "nail_polish_medium-light_skin_tone": "💅ðŸ¼", - "nail_polish_medium_skin_tone": "💅ðŸ½", - "name_badge": "📛", - "national_park": "ðŸž", - "nauseated_face": "🤢", - "nazar_amulet": "🧿", - "necktie": "👔", - "nerd_face": "🤓", - "neutral_face": "ðŸ˜", - "new_moon": "🌑", - "new_moon_face": "🌚", - "newspaper": "📰", - "next_track_button": "â­", - "night_with_stars": "🌃", - "nine-thirty": "🕤", - "nine_o’clock": "🕘", - "no_bicycles": "🚳", - "no_entry": "â›”", - "no_littering": "🚯", - "no_mobile_phones": "📵", - "no_one_under_eighteen": "🔞", - "no_pedestrians": "🚷", - "no_smoking": "🚭", - "non-potable_water": "🚱", - "nose": "👃", - "nose_dark_skin_tone": "👃ðŸ¿", - "nose_light_skin_tone": "👃ðŸ»", - "nose_medium-dark_skin_tone": "👃ðŸ¾", - "nose_medium-light_skin_tone": "👃ðŸ¼", - "nose_medium_skin_tone": "👃ðŸ½", - "notebook": "📓", - "notebook_with_decorative_cover": "📔", - "nut_and_bolt": "🔩", - "octopus": "ðŸ™", - "oden": "ðŸ¢", - "office_building": "ðŸ¢", - "ogre": "👹", - "oil_drum": "🛢", - "old_key": "ðŸ—", - "old_man": "👴", - "old_man_dark_skin_tone": "👴ðŸ¿", - "old_man_light_skin_tone": "👴ðŸ»", - "old_man_medium-dark_skin_tone": "👴ðŸ¾", - "old_man_medium-light_skin_tone": "👴ðŸ¼", - "old_man_medium_skin_tone": "👴ðŸ½", - "old_woman": "👵", - "old_woman_dark_skin_tone": "👵ðŸ¿", - "old_woman_light_skin_tone": "👵ðŸ»", - "old_woman_medium-dark_skin_tone": "👵ðŸ¾", - "old_woman_medium-light_skin_tone": "👵ðŸ¼", - "old_woman_medium_skin_tone": "👵ðŸ½", - "older_adult": "🧓", - "older_adult_dark_skin_tone": "🧓ðŸ¿", - "older_adult_light_skin_tone": "🧓ðŸ»", - "older_adult_medium-dark_skin_tone": "🧓ðŸ¾", - "older_adult_medium-light_skin_tone": "🧓ðŸ¼", - "older_adult_medium_skin_tone": "🧓ðŸ½", - "om": "🕉", - "oncoming_automobile": "🚘", - "oncoming_bus": "ðŸš", - "oncoming_fist": "👊", - "oncoming_fist_dark_skin_tone": "👊ðŸ¿", - "oncoming_fist_light_skin_tone": "👊ðŸ»", - "oncoming_fist_medium-dark_skin_tone": "👊ðŸ¾", - "oncoming_fist_medium-light_skin_tone": "👊ðŸ¼", - "oncoming_fist_medium_skin_tone": "👊ðŸ½", - "oncoming_police_car": "🚔", - "oncoming_taxi": "🚖", - "one-piece_swimsuit": "🩱", - "one-thirty": "🕜", - "one_o’clock": "ðŸ•", - "onion": "🧅", - "open_book": "📖", - "open_file_folder": "📂", - "open_hands": "ðŸ‘", - "open_hands_dark_skin_tone": "ðŸ‘ðŸ¿", - "open_hands_light_skin_tone": "ðŸ‘ðŸ»", - "open_hands_medium-dark_skin_tone": "ðŸ‘ðŸ¾", - "open_hands_medium-light_skin_tone": "ðŸ‘ðŸ¼", - "open_hands_medium_skin_tone": "ðŸ‘ðŸ½", - "open_mailbox_with_lowered_flag": "📭", - "open_mailbox_with_raised_flag": "📬", - "optical_disk": "💿", - "orange_book": "📙", - "orange_circle": "🟠", - "orange_heart": "🧡", - "orange_square": "🟧", - "orangutan": "🦧", - "orthodox_cross": "☦", - "otter": "🦦", - "outbox_tray": "📤", - "owl": "🦉", - "ox": "ðŸ‚", - "oyster": "🦪", - "package": "📦", - "page_facing_up": "📄", - "page_with_curl": "📃", - "pager": "📟", - "paintbrush": "🖌", - "palm_tree": "🌴", - "palms_up_together": "🤲", - "palms_up_together_dark_skin_tone": "🤲ðŸ¿", - "palms_up_together_light_skin_tone": "🤲ðŸ»", - "palms_up_together_medium-dark_skin_tone": "🤲ðŸ¾", - "palms_up_together_medium-light_skin_tone": "🤲ðŸ¼", - "palms_up_together_medium_skin_tone": "🤲ðŸ½", - "pancakes": "🥞", - "panda_face": "ðŸ¼", - "paperclip": "📎", - "parrot": "🦜", - "part_alternation_mark": "〽", - "party_popper": "🎉", - "partying_face": "🥳", - "passenger_ship": "🛳", - "passport_control": "🛂", - "pause_button": "â¸", - "paw_prints": "ðŸ¾", - "peace_symbol": "☮", - "peach": "ðŸ‘", - "peacock": "🦚", - "peanuts": "🥜", - "pear": "ðŸ", - "pen": "🖊", - "pencil": "ðŸ“", - "penguin": "ðŸ§", - "pensive_face": "😔", - "people_holding_hands": "🧑\u200dðŸ¤\u200d🧑", - "people_with_bunny_ears": "👯", - "people_wrestling": "🤼", - "performing_arts": "🎭", - "persevering_face": "😣", - "person_biking": "🚴", - "person_biking_dark_skin_tone": "🚴ðŸ¿", - "person_biking_light_skin_tone": "🚴ðŸ»", - "person_biking_medium-dark_skin_tone": "🚴ðŸ¾", - "person_biking_medium-light_skin_tone": "🚴ðŸ¼", - "person_biking_medium_skin_tone": "🚴ðŸ½", - "person_bouncing_ball": "⛹", - "person_bouncing_ball_dark_skin_tone": "⛹ðŸ¿", - "person_bouncing_ball_light_skin_tone": "⛹ðŸ»", - "person_bouncing_ball_medium-dark_skin_tone": "⛹ðŸ¾", - "person_bouncing_ball_medium-light_skin_tone": "⛹ðŸ¼", - "person_bouncing_ball_medium_skin_tone": "⛹ðŸ½", - "person_bowing": "🙇", - "person_bowing_dark_skin_tone": "🙇ðŸ¿", - "person_bowing_light_skin_tone": "🙇ðŸ»", - "person_bowing_medium-dark_skin_tone": "🙇ðŸ¾", - "person_bowing_medium-light_skin_tone": "🙇ðŸ¼", - "person_bowing_medium_skin_tone": "🙇ðŸ½", - "person_cartwheeling": "🤸", - "person_cartwheeling_dark_skin_tone": "🤸ðŸ¿", - "person_cartwheeling_light_skin_tone": "🤸ðŸ»", - "person_cartwheeling_medium-dark_skin_tone": "🤸ðŸ¾", - "person_cartwheeling_medium-light_skin_tone": "🤸ðŸ¼", - "person_cartwheeling_medium_skin_tone": "🤸ðŸ½", - "person_climbing": "🧗", - "person_climbing_dark_skin_tone": "🧗ðŸ¿", - "person_climbing_light_skin_tone": "🧗ðŸ»", - "person_climbing_medium-dark_skin_tone": "🧗ðŸ¾", - "person_climbing_medium-light_skin_tone": "🧗ðŸ¼", - "person_climbing_medium_skin_tone": "🧗ðŸ½", - "person_facepalming": "🤦", - "person_facepalming_dark_skin_tone": "🤦ðŸ¿", - "person_facepalming_light_skin_tone": "🤦ðŸ»", - "person_facepalming_medium-dark_skin_tone": "🤦ðŸ¾", - "person_facepalming_medium-light_skin_tone": "🤦ðŸ¼", - "person_facepalming_medium_skin_tone": "🤦ðŸ½", - "person_fencing": "🤺", - "person_frowning": "ðŸ™", - "person_frowning_dark_skin_tone": "ðŸ™ðŸ¿", - "person_frowning_light_skin_tone": "ðŸ™ðŸ»", - "person_frowning_medium-dark_skin_tone": "ðŸ™ðŸ¾", - "person_frowning_medium-light_skin_tone": "ðŸ™ðŸ¼", - "person_frowning_medium_skin_tone": "ðŸ™ðŸ½", - "person_gesturing_no": "🙅", - "person_gesturing_no_dark_skin_tone": "🙅ðŸ¿", - "person_gesturing_no_light_skin_tone": "🙅ðŸ»", - "person_gesturing_no_medium-dark_skin_tone": "🙅ðŸ¾", - "person_gesturing_no_medium-light_skin_tone": "🙅ðŸ¼", - "person_gesturing_no_medium_skin_tone": "🙅ðŸ½", - "person_gesturing_ok": "🙆", - "person_gesturing_ok_dark_skin_tone": "🙆ðŸ¿", - "person_gesturing_ok_light_skin_tone": "🙆ðŸ»", - "person_gesturing_ok_medium-dark_skin_tone": "🙆ðŸ¾", - "person_gesturing_ok_medium-light_skin_tone": "🙆ðŸ¼", - "person_gesturing_ok_medium_skin_tone": "🙆ðŸ½", - "person_getting_haircut": "💇", - "person_getting_haircut_dark_skin_tone": "💇ðŸ¿", - "person_getting_haircut_light_skin_tone": "💇ðŸ»", - "person_getting_haircut_medium-dark_skin_tone": "💇ðŸ¾", - "person_getting_haircut_medium-light_skin_tone": "💇ðŸ¼", - "person_getting_haircut_medium_skin_tone": "💇ðŸ½", - "person_getting_massage": "💆", - "person_getting_massage_dark_skin_tone": "💆ðŸ¿", - "person_getting_massage_light_skin_tone": "💆ðŸ»", - "person_getting_massage_medium-dark_skin_tone": "💆ðŸ¾", - "person_getting_massage_medium-light_skin_tone": "💆ðŸ¼", - "person_getting_massage_medium_skin_tone": "💆ðŸ½", - "person_golfing": "ðŸŒ", - "person_golfing_dark_skin_tone": "ðŸŒðŸ¿", - "person_golfing_light_skin_tone": "ðŸŒðŸ»", - "person_golfing_medium-dark_skin_tone": "ðŸŒðŸ¾", - "person_golfing_medium-light_skin_tone": "ðŸŒðŸ¼", - "person_golfing_medium_skin_tone": "ðŸŒðŸ½", - "person_in_bed": "🛌", - "person_in_bed_dark_skin_tone": "🛌ðŸ¿", - "person_in_bed_light_skin_tone": "🛌ðŸ»", - "person_in_bed_medium-dark_skin_tone": "🛌ðŸ¾", - "person_in_bed_medium-light_skin_tone": "🛌ðŸ¼", - "person_in_bed_medium_skin_tone": "🛌ðŸ½", - "person_in_lotus_position": "🧘", - "person_in_lotus_position_dark_skin_tone": "🧘ðŸ¿", - "person_in_lotus_position_light_skin_tone": "🧘ðŸ»", - "person_in_lotus_position_medium-dark_skin_tone": "🧘ðŸ¾", - "person_in_lotus_position_medium-light_skin_tone": "🧘ðŸ¼", - "person_in_lotus_position_medium_skin_tone": "🧘ðŸ½", - "person_in_steamy_room": "🧖", - "person_in_steamy_room_dark_skin_tone": "🧖ðŸ¿", - "person_in_steamy_room_light_skin_tone": "🧖ðŸ»", - "person_in_steamy_room_medium-dark_skin_tone": "🧖ðŸ¾", - "person_in_steamy_room_medium-light_skin_tone": "🧖ðŸ¼", - "person_in_steamy_room_medium_skin_tone": "🧖ðŸ½", - "person_juggling": "🤹", - "person_juggling_dark_skin_tone": "🤹ðŸ¿", - "person_juggling_light_skin_tone": "🤹ðŸ»", - "person_juggling_medium-dark_skin_tone": "🤹ðŸ¾", - "person_juggling_medium-light_skin_tone": "🤹ðŸ¼", - "person_juggling_medium_skin_tone": "🤹ðŸ½", - "person_kneeling": "🧎", - "person_lifting_weights": "ðŸ‹", - "person_lifting_weights_dark_skin_tone": "ðŸ‹ðŸ¿", - "person_lifting_weights_light_skin_tone": "ðŸ‹ðŸ»", - "person_lifting_weights_medium-dark_skin_tone": "ðŸ‹ðŸ¾", - "person_lifting_weights_medium-light_skin_tone": "ðŸ‹ðŸ¼", - "person_lifting_weights_medium_skin_tone": "ðŸ‹ðŸ½", - "person_mountain_biking": "🚵", - "person_mountain_biking_dark_skin_tone": "🚵ðŸ¿", - "person_mountain_biking_light_skin_tone": "🚵ðŸ»", - "person_mountain_biking_medium-dark_skin_tone": "🚵ðŸ¾", - "person_mountain_biking_medium-light_skin_tone": "🚵ðŸ¼", - "person_mountain_biking_medium_skin_tone": "🚵ðŸ½", - "person_playing_handball": "🤾", - "person_playing_handball_dark_skin_tone": "🤾ðŸ¿", - "person_playing_handball_light_skin_tone": "🤾ðŸ»", - "person_playing_handball_medium-dark_skin_tone": "🤾ðŸ¾", - "person_playing_handball_medium-light_skin_tone": "🤾ðŸ¼", - "person_playing_handball_medium_skin_tone": "🤾ðŸ½", - "person_playing_water_polo": "🤽", - "person_playing_water_polo_dark_skin_tone": "🤽ðŸ¿", - "person_playing_water_polo_light_skin_tone": "🤽ðŸ»", - "person_playing_water_polo_medium-dark_skin_tone": "🤽ðŸ¾", - "person_playing_water_polo_medium-light_skin_tone": "🤽ðŸ¼", - "person_playing_water_polo_medium_skin_tone": "🤽ðŸ½", - "person_pouting": "🙎", - "person_pouting_dark_skin_tone": "🙎ðŸ¿", - "person_pouting_light_skin_tone": "🙎ðŸ»", - "person_pouting_medium-dark_skin_tone": "🙎ðŸ¾", - "person_pouting_medium-light_skin_tone": "🙎ðŸ¼", - "person_pouting_medium_skin_tone": "🙎ðŸ½", - "person_raising_hand": "🙋", - "person_raising_hand_dark_skin_tone": "🙋ðŸ¿", - "person_raising_hand_light_skin_tone": "🙋ðŸ»", - "person_raising_hand_medium-dark_skin_tone": "🙋ðŸ¾", - "person_raising_hand_medium-light_skin_tone": "🙋ðŸ¼", - "person_raising_hand_medium_skin_tone": "🙋ðŸ½", - "person_rowing_boat": "🚣", - "person_rowing_boat_dark_skin_tone": "🚣ðŸ¿", - "person_rowing_boat_light_skin_tone": "🚣ðŸ»", - "person_rowing_boat_medium-dark_skin_tone": "🚣ðŸ¾", - "person_rowing_boat_medium-light_skin_tone": "🚣ðŸ¼", - "person_rowing_boat_medium_skin_tone": "🚣ðŸ½", - "person_running": "ðŸƒ", - "person_running_dark_skin_tone": "ðŸƒðŸ¿", - "person_running_light_skin_tone": "ðŸƒðŸ»", - "person_running_medium-dark_skin_tone": "ðŸƒðŸ¾", - "person_running_medium-light_skin_tone": "ðŸƒðŸ¼", - "person_running_medium_skin_tone": "ðŸƒðŸ½", - "person_shrugging": "🤷", - "person_shrugging_dark_skin_tone": "🤷ðŸ¿", - "person_shrugging_light_skin_tone": "🤷ðŸ»", - "person_shrugging_medium-dark_skin_tone": "🤷ðŸ¾", - "person_shrugging_medium-light_skin_tone": "🤷ðŸ¼", - "person_shrugging_medium_skin_tone": "🤷ðŸ½", - "person_standing": "ðŸ§", - "person_surfing": "ðŸ„", - "person_surfing_dark_skin_tone": "ðŸ„ðŸ¿", - "person_surfing_light_skin_tone": "ðŸ„ðŸ»", - "person_surfing_medium-dark_skin_tone": "ðŸ„ðŸ¾", - "person_surfing_medium-light_skin_tone": "ðŸ„ðŸ¼", - "person_surfing_medium_skin_tone": "ðŸ„ðŸ½", - "person_swimming": "ðŸŠ", - "person_swimming_dark_skin_tone": "ðŸŠðŸ¿", - "person_swimming_light_skin_tone": "ðŸŠðŸ»", - "person_swimming_medium-dark_skin_tone": "ðŸŠðŸ¾", - "person_swimming_medium-light_skin_tone": "ðŸŠðŸ¼", - "person_swimming_medium_skin_tone": "ðŸŠðŸ½", - "person_taking_bath": "🛀", - "person_taking_bath_dark_skin_tone": "🛀ðŸ¿", - "person_taking_bath_light_skin_tone": "🛀ðŸ»", - "person_taking_bath_medium-dark_skin_tone": "🛀ðŸ¾", - "person_taking_bath_medium-light_skin_tone": "🛀ðŸ¼", - "person_taking_bath_medium_skin_tone": "🛀ðŸ½", - "person_tipping_hand": "ðŸ’", - "person_tipping_hand_dark_skin_tone": "ðŸ’ðŸ¿", - "person_tipping_hand_light_skin_tone": "ðŸ’ðŸ»", - "person_tipping_hand_medium-dark_skin_tone": "ðŸ’ðŸ¾", - "person_tipping_hand_medium-light_skin_tone": "ðŸ’ðŸ¼", - "person_tipping_hand_medium_skin_tone": "ðŸ’ðŸ½", - "person_walking": "🚶", - "person_walking_dark_skin_tone": "🚶ðŸ¿", - "person_walking_light_skin_tone": "🚶ðŸ»", - "person_walking_medium-dark_skin_tone": "🚶ðŸ¾", - "person_walking_medium-light_skin_tone": "🚶ðŸ¼", - "person_walking_medium_skin_tone": "🚶ðŸ½", - "person_wearing_turban": "👳", - "person_wearing_turban_dark_skin_tone": "👳ðŸ¿", - "person_wearing_turban_light_skin_tone": "👳ðŸ»", - "person_wearing_turban_medium-dark_skin_tone": "👳ðŸ¾", - "person_wearing_turban_medium-light_skin_tone": "👳ðŸ¼", - "person_wearing_turban_medium_skin_tone": "👳ðŸ½", - "petri_dish": "🧫", - "pick": "â›", - "pie": "🥧", - "pig": "ðŸ·", - "pig_face": "ðŸ·", - "pig_nose": "ðŸ½", - "pile_of_poo": "💩", - "pill": "💊", - "pinching_hand": "ðŸ¤", - "pine_decoration": "ðŸŽ", - "pineapple": "ðŸ", - "ping_pong": "ðŸ“", - "pirate_flag": "ðŸ´\u200d☠ï¸", - "pistol": "🔫", - "pizza": "ðŸ•", - "place_of_worship": "ðŸ›", - "play_button": "â–¶", - "play_or_pause_button": "â¯", - "pleading_face": "🥺", - "police_car": "🚓", - "police_car_light": "🚨", - "police_officer": "👮", - "police_officer_dark_skin_tone": "👮ðŸ¿", - "police_officer_light_skin_tone": "👮ðŸ»", - "police_officer_medium-dark_skin_tone": "👮ðŸ¾", - "police_officer_medium-light_skin_tone": "👮ðŸ¼", - "police_officer_medium_skin_tone": "👮ðŸ½", - "poodle": "ðŸ©", - "pool_8_ball": "🎱", - "popcorn": "ðŸ¿", - "post_office": "ðŸ£", - "postal_horn": "📯", - "postbox": "📮", - "pot_of_food": "ðŸ²", - "potable_water": "🚰", - "potato": "🥔", - "poultry_leg": "ðŸ—", - "pound_banknote": "💷", - "pouting_cat_face": "😾", - "pouting_face": "😡", - "prayer_beads": "📿", - "pregnant_woman": "🤰", - "pregnant_woman_dark_skin_tone": "🤰ðŸ¿", - "pregnant_woman_light_skin_tone": "🤰ðŸ»", - "pregnant_woman_medium-dark_skin_tone": "🤰ðŸ¾", - "pregnant_woman_medium-light_skin_tone": "🤰ðŸ¼", - "pregnant_woman_medium_skin_tone": "🤰ðŸ½", - "pretzel": "🥨", - "probing_cane": "🦯", - "prince": "🤴", - "prince_dark_skin_tone": "🤴ðŸ¿", - "prince_light_skin_tone": "🤴ðŸ»", - "prince_medium-dark_skin_tone": "🤴ðŸ¾", - "prince_medium-light_skin_tone": "🤴ðŸ¼", - "prince_medium_skin_tone": "🤴ðŸ½", - "princess": "👸", - "princess_dark_skin_tone": "👸ðŸ¿", - "princess_light_skin_tone": "👸ðŸ»", - "princess_medium-dark_skin_tone": "👸ðŸ¾", - "princess_medium-light_skin_tone": "👸ðŸ¼", - "princess_medium_skin_tone": "👸ðŸ½", - "printer": "🖨", - "prohibited": "🚫", - "purple_circle": "🟣", - "purple_heart": "💜", - "purple_square": "🟪", - "purse": "👛", - "pushpin": "📌", - "question_mark": "â“", - "rabbit": "ðŸ°", - "rabbit_face": "ðŸ°", - "raccoon": "ðŸ¦", - "racing_car": "ðŸŽ", - "radio": "📻", - "radio_button": "🔘", - "radioactive": "☢", - "railway_car": "🚃", - "railway_track": "🛤", - "rainbow": "🌈", - "rainbow_flag": "ðŸ³ï¸\u200d🌈", - "raised_back_of_hand": "🤚", - "raised_back_of_hand_dark_skin_tone": "🤚ðŸ¿", - "raised_back_of_hand_light_skin_tone": "🤚ðŸ»", - "raised_back_of_hand_medium-dark_skin_tone": "🤚ðŸ¾", - "raised_back_of_hand_medium-light_skin_tone": "🤚ðŸ¼", - "raised_back_of_hand_medium_skin_tone": "🤚ðŸ½", - "raised_fist": "✊", - "raised_fist_dark_skin_tone": "✊ðŸ¿", - "raised_fist_light_skin_tone": "✊ðŸ»", - "raised_fist_medium-dark_skin_tone": "✊ðŸ¾", - "raised_fist_medium-light_skin_tone": "✊ðŸ¼", - "raised_fist_medium_skin_tone": "✊ðŸ½", - "raised_hand": "✋", - "raised_hand_dark_skin_tone": "✋ðŸ¿", - "raised_hand_light_skin_tone": "✋ðŸ»", - "raised_hand_medium-dark_skin_tone": "✋ðŸ¾", - "raised_hand_medium-light_skin_tone": "✋ðŸ¼", - "raised_hand_medium_skin_tone": "✋ðŸ½", - "raising_hands": "🙌", - "raising_hands_dark_skin_tone": "🙌ðŸ¿", - "raising_hands_light_skin_tone": "🙌ðŸ»", - "raising_hands_medium-dark_skin_tone": "🙌ðŸ¾", - "raising_hands_medium-light_skin_tone": "🙌ðŸ¼", - "raising_hands_medium_skin_tone": "🙌ðŸ½", - "ram": "ðŸ", - "rat": "ðŸ€", - "razor": "🪒", - "ringed_planet": "ðŸª", - "receipt": "🧾", - "record_button": "âº", - "recycling_symbol": "â™»", - "red_apple": "ðŸŽ", - "red_circle": "🔴", - "red_envelope": "🧧", - "red_hair": "🦰", - "red-haired_man": "👨\u200d🦰", - "red-haired_woman": "👩\u200d🦰", - "red_heart": "â¤", - "red_paper_lantern": "ðŸ®", - "red_square": "🟥", - "red_triangle_pointed_down": "🔻", - "red_triangle_pointed_up": "🔺", - "registered": "®", - "relieved_face": "😌", - "reminder_ribbon": "🎗", - "repeat_button": "ðŸ”", - "repeat_single_button": "🔂", - "rescue_worker’s_helmet": "⛑", - "restroom": "🚻", - "reverse_button": "â—€", - "revolving_hearts": "💞", - "rhinoceros": "ðŸ¦", - "ribbon": "🎀", - "rice_ball": "ðŸ™", - "rice_cracker": "ðŸ˜", - "right-facing_fist": "🤜", - "right-facing_fist_dark_skin_tone": "🤜ðŸ¿", - "right-facing_fist_light_skin_tone": "🤜ðŸ»", - "right-facing_fist_medium-dark_skin_tone": "🤜ðŸ¾", - "right-facing_fist_medium-light_skin_tone": "🤜ðŸ¼", - "right-facing_fist_medium_skin_tone": "🤜ðŸ½", - "right_anger_bubble": "🗯", - "right_arrow": "âž¡", - "right_arrow_curving_down": "⤵", - "right_arrow_curving_left": "↩", - "right_arrow_curving_up": "⤴", - "ring": "ðŸ’", - "roasted_sweet_potato": "ðŸ ", - "robot_face": "🤖", - "rocket": "🚀", - "roll_of_paper": "🧻", - "rolled-up_newspaper": "🗞", - "roller_coaster": "🎢", - "rolling_on_the_floor_laughing": "🤣", - "rooster": "ðŸ“", - "rose": "🌹", - "rosette": "ðŸµ", - "round_pushpin": "ðŸ“", - "rugby_football": "ðŸ‰", - "running_shirt": "🎽", - "running_shoe": "👟", - "sad_but_relieved_face": "😥", - "safety_pin": "🧷", - "safety_vest": "🦺", - "salt": "🧂", - "sailboat": "⛵", - "sake": "ðŸ¶", - "sandwich": "🥪", - "sari": "🥻", - "satellite": "📡", - "satellite_antenna": "📡", - "sauropod": "🦕", - "saxophone": "🎷", - "scarf": "🧣", - "school": "ðŸ«", - "school_backpack": "🎒", - "scissors": "✂", - "scorpion": "🦂", - "scroll": "📜", - "seat": "💺", - "see-no-evil_monkey": "🙈", - "seedling": "🌱", - "selfie": "🤳", - "selfie_dark_skin_tone": "🤳ðŸ¿", - "selfie_light_skin_tone": "🤳ðŸ»", - "selfie_medium-dark_skin_tone": "🤳ðŸ¾", - "selfie_medium-light_skin_tone": "🤳ðŸ¼", - "selfie_medium_skin_tone": "🤳ðŸ½", - "service_dog": "ðŸ•\u200d🦺", - "seven-thirty": "🕢", - "seven_o’clock": "🕖", - "shallow_pan_of_food": "🥘", - "shamrock": "☘", - "shark": "🦈", - "shaved_ice": "ðŸ§", - "sheaf_of_rice": "🌾", - "shield": "🛡", - "shinto_shrine": "⛩", - "ship": "🚢", - "shooting_star": "🌠", - "shopping_bags": "ðŸ›", - "shopping_cart": "🛒", - "shortcake": "ðŸ°", - "shorts": "🩳", - "shower": "🚿", - "shrimp": "ðŸ¦", - "shuffle_tracks_button": "🔀", - "shushing_face": "🤫", - "sign_of_the_horns": "🤘", - "sign_of_the_horns_dark_skin_tone": "🤘ðŸ¿", - "sign_of_the_horns_light_skin_tone": "🤘ðŸ»", - "sign_of_the_horns_medium-dark_skin_tone": "🤘ðŸ¾", - "sign_of_the_horns_medium-light_skin_tone": "🤘ðŸ¼", - "sign_of_the_horns_medium_skin_tone": "🤘ðŸ½", - "six-thirty": "🕡", - "six_o’clock": "🕕", - "skateboard": "🛹", - "skier": "â›·", - "skis": "🎿", - "skull": "💀", - "skull_and_crossbones": "☠", - "skunk": "🦨", - "sled": "🛷", - "sleeping_face": "😴", - "sleepy_face": "😪", - "slightly_frowning_face": "ðŸ™", - "slightly_smiling_face": "🙂", - "slot_machine": "🎰", - "sloth": "🦥", - "small_airplane": "🛩", - "small_blue_diamond": "🔹", - "small_orange_diamond": "🔸", - "smiling_cat_face_with_heart-eyes": "😻", - "smiling_face": "☺", - "smiling_face_with_halo": "😇", - "smiling_face_with_3_hearts": "🥰", - "smiling_face_with_heart-eyes": "ðŸ˜", - "smiling_face_with_horns": "😈", - "smiling_face_with_smiling_eyes": "😊", - "smiling_face_with_sunglasses": "😎", - "smirking_face": "ðŸ˜", - "snail": "ðŸŒ", - "snake": "ðŸ", - "sneezing_face": "🤧", - "snow-capped_mountain": "ðŸ”", - "snowboarder": "ðŸ‚", - "snowboarder_dark_skin_tone": "ðŸ‚ðŸ¿", - "snowboarder_light_skin_tone": "ðŸ‚ðŸ»", - "snowboarder_medium-dark_skin_tone": "ðŸ‚ðŸ¾", - "snowboarder_medium-light_skin_tone": "ðŸ‚ðŸ¼", - "snowboarder_medium_skin_tone": "ðŸ‚ðŸ½", - "snowflake": "â„", - "snowman": "☃", - "snowman_without_snow": "⛄", - "soap": "🧼", - "soccer_ball": "âš½", - "socks": "🧦", - "softball": "🥎", - "soft_ice_cream": "ðŸ¦", - "spade_suit": "â™ ", - "spaghetti": "ðŸ", - "sparkle": "â‡", - "sparkler": "🎇", - "sparkles": "✨", - "sparkling_heart": "💖", - "speak-no-evil_monkey": "🙊", - "speaker_high_volume": "🔊", - "speaker_low_volume": "🔈", - "speaker_medium_volume": "🔉", - "speaking_head": "🗣", - "speech_balloon": "💬", - "speedboat": "🚤", - "spider": "🕷", - "spider_web": "🕸", - "spiral_calendar": "🗓", - "spiral_notepad": "🗒", - "spiral_shell": "ðŸš", - "spoon": "🥄", - "sponge": "🧽", - "sport_utility_vehicle": "🚙", - "sports_medal": "ðŸ…", - "spouting_whale": "ðŸ³", - "squid": "🦑", - "squinting_face_with_tongue": "ðŸ˜", - "stadium": "ðŸŸ", - "star-struck": "🤩", - "star_and_crescent": "☪", - "star_of_david": "✡", - "station": "🚉", - "steaming_bowl": "ðŸœ", - "stethoscope": "🩺", - "stop_button": "â¹", - "stop_sign": "🛑", - "stopwatch": "â±", - "straight_ruler": "ðŸ“", - "strawberry": "ðŸ“", - "studio_microphone": "🎙", - "stuffed_flatbread": "🥙", - "sun": "☀", - "sun_behind_cloud": "â›…", - "sun_behind_large_cloud": "🌥", - "sun_behind_rain_cloud": "🌦", - "sun_behind_small_cloud": "🌤", - "sun_with_face": "🌞", - "sunflower": "🌻", - "sunglasses": "😎", - "sunrise": "🌅", - "sunrise_over_mountains": "🌄", - "sunset": "🌇", - "superhero": "🦸", - "supervillain": "🦹", - "sushi": "ðŸ£", - "suspension_railway": "🚟", - "swan": "🦢", - "sweat_droplets": "💦", - "synagogue": "ðŸ•", - "syringe": "💉", - "t-shirt": "👕", - "taco": "🌮", - "takeout_box": "🥡", - "tanabata_tree": "🎋", - "tangerine": "ðŸŠ", - "taxi": "🚕", - "teacup_without_handle": "ðŸµ", - "tear-off_calendar": "📆", - "teddy_bear": "🧸", - "telephone": "☎", - "telephone_receiver": "📞", - "telescope": "🔭", - "television": "📺", - "ten-thirty": "🕥", - "ten_o’clock": "🕙", - "tennis": "🎾", - "tent": "⛺", - "test_tube": "🧪", - "thermometer": "🌡", - "thinking_face": "🤔", - "thought_balloon": "💭", - "thread": "🧵", - "three-thirty": "🕞", - "three_o’clock": "🕒", - "thumbs_down": "👎", - "thumbs_down_dark_skin_tone": "👎ðŸ¿", - "thumbs_down_light_skin_tone": "👎ðŸ»", - "thumbs_down_medium-dark_skin_tone": "👎ðŸ¾", - "thumbs_down_medium-light_skin_tone": "👎ðŸ¼", - "thumbs_down_medium_skin_tone": "👎ðŸ½", - "thumbs_up": "ðŸ‘", - "thumbs_up_dark_skin_tone": "ðŸ‘ðŸ¿", - "thumbs_up_light_skin_tone": "ðŸ‘ðŸ»", - "thumbs_up_medium-dark_skin_tone": "ðŸ‘ðŸ¾", - "thumbs_up_medium-light_skin_tone": "ðŸ‘ðŸ¼", - "thumbs_up_medium_skin_tone": "ðŸ‘ðŸ½", - "ticket": "🎫", - "tiger": "ðŸ¯", - "tiger_face": "ðŸ¯", - "timer_clock": "â²", - "tired_face": "😫", - "toolbox": "🧰", - "toilet": "🚽", - "tomato": "ðŸ…", - "tongue": "👅", - "tooth": "🦷", - "top_hat": "🎩", - "tornado": "🌪", - "trackball": "🖲", - "tractor": "🚜", - "trade_mark": "â„¢", - "train": "🚋", - "tram": "🚊", - "tram_car": "🚋", - "triangular_flag": "🚩", - "triangular_ruler": "ðŸ“", - "trident_emblem": "🔱", - "trolleybus": "🚎", - "trophy": "ðŸ†", - "tropical_drink": "ðŸ¹", - "tropical_fish": "ðŸ ", - "trumpet": "🎺", - "tulip": "🌷", - "tumbler_glass": "🥃", - "turtle": "ðŸ¢", - "twelve-thirty": "🕧", - "twelve_o’clock": "🕛", - "two-hump_camel": "ðŸ«", - "two-thirty": "ðŸ•", - "two_hearts": "💕", - "two_men_holding_hands": "👬", - "two_o’clock": "🕑", - "two_women_holding_hands": "👭", - "umbrella": "☂", - "umbrella_on_ground": "â›±", - "umbrella_with_rain_drops": "☔", - "unamused_face": "😒", - "unicorn_face": "🦄", - "unlocked": "🔓", - "up-down_arrow": "↕", - "up-left_arrow": "↖", - "up-right_arrow": "↗", - "up_arrow": "⬆", - "upside-down_face": "🙃", - "upwards_button": "🔼", - "vampire": "🧛", - "vampire_dark_skin_tone": "🧛ðŸ¿", - "vampire_light_skin_tone": "🧛ðŸ»", - "vampire_medium-dark_skin_tone": "🧛ðŸ¾", - "vampire_medium-light_skin_tone": "🧛ðŸ¼", - "vampire_medium_skin_tone": "🧛ðŸ½", - "vertical_traffic_light": "🚦", - "vibration_mode": "📳", - "victory_hand": "✌", - "victory_hand_dark_skin_tone": "✌ðŸ¿", - "victory_hand_light_skin_tone": "✌ðŸ»", - "victory_hand_medium-dark_skin_tone": "✌ðŸ¾", - "victory_hand_medium-light_skin_tone": "✌ðŸ¼", - "victory_hand_medium_skin_tone": "✌ðŸ½", - "video_camera": "📹", - "video_game": "🎮", - "videocassette": "📼", - "violin": "🎻", - "volcano": "🌋", - "volleyball": "ðŸ", - "vulcan_salute": "🖖", - "vulcan_salute_dark_skin_tone": "🖖ðŸ¿", - "vulcan_salute_light_skin_tone": "🖖ðŸ»", - "vulcan_salute_medium-dark_skin_tone": "🖖ðŸ¾", - "vulcan_salute_medium-light_skin_tone": "🖖ðŸ¼", - "vulcan_salute_medium_skin_tone": "🖖ðŸ½", - "waffle": "🧇", - "waning_crescent_moon": "🌘", - "waning_gibbous_moon": "🌖", - "warning": "âš ", - "wastebasket": "🗑", - "watch": "⌚", - "water_buffalo": "ðŸƒ", - "water_closet": "🚾", - "water_wave": "🌊", - "watermelon": "ðŸ‰", - "waving_hand": "👋", - "waving_hand_dark_skin_tone": "👋ðŸ¿", - "waving_hand_light_skin_tone": "👋ðŸ»", - "waving_hand_medium-dark_skin_tone": "👋ðŸ¾", - "waving_hand_medium-light_skin_tone": "👋ðŸ¼", - "waving_hand_medium_skin_tone": "👋ðŸ½", - "wavy_dash": "〰", - "waxing_crescent_moon": "🌒", - "waxing_gibbous_moon": "🌔", - "weary_cat_face": "🙀", - "weary_face": "😩", - "wedding": "💒", - "whale": "ðŸ³", - "wheel_of_dharma": "☸", - "wheelchair_symbol": "♿", - "white_circle": "⚪", - "white_exclamation_mark": "â•", - "white_flag": "ðŸ³", - "white_flower": "💮", - "white_hair": "🦳", - "white-haired_man": "👨\u200d🦳", - "white-haired_woman": "👩\u200d🦳", - "white_heart": "ðŸ¤", - "white_heavy_check_mark": "✅", - "white_large_square": "⬜", - "white_medium-small_square": "â—½", - "white_medium_square": "â—»", - "white_medium_star": "â­", - "white_question_mark": "â”", - "white_small_square": "â–«", - "white_square_button": "🔳", - "wilted_flower": "🥀", - "wind_chime": "ðŸŽ", - "wind_face": "🌬", - "wine_glass": "ðŸ·", - "winking_face": "😉", - "winking_face_with_tongue": "😜", - "wolf_face": "ðŸº", - "woman": "👩", - "woman_artist": "👩\u200d🎨", - "woman_artist_dark_skin_tone": "👩ðŸ¿\u200d🎨", - "woman_artist_light_skin_tone": "👩ðŸ»\u200d🎨", - "woman_artist_medium-dark_skin_tone": "👩ðŸ¾\u200d🎨", - "woman_artist_medium-light_skin_tone": "👩ðŸ¼\u200d🎨", - "woman_artist_medium_skin_tone": "👩ðŸ½\u200d🎨", - "woman_astronaut": "👩\u200d🚀", - "woman_astronaut_dark_skin_tone": "👩ðŸ¿\u200d🚀", - "woman_astronaut_light_skin_tone": "👩ðŸ»\u200d🚀", - "woman_astronaut_medium-dark_skin_tone": "👩ðŸ¾\u200d🚀", - "woman_astronaut_medium-light_skin_tone": "👩ðŸ¼\u200d🚀", - "woman_astronaut_medium_skin_tone": "👩ðŸ½\u200d🚀", - "woman_biking": "🚴\u200d♀ï¸", - "woman_biking_dark_skin_tone": "🚴ðŸ¿\u200d♀ï¸", - "woman_biking_light_skin_tone": "🚴ðŸ»\u200d♀ï¸", - "woman_biking_medium-dark_skin_tone": "🚴ðŸ¾\u200d♀ï¸", - "woman_biking_medium-light_skin_tone": "🚴ðŸ¼\u200d♀ï¸", - "woman_biking_medium_skin_tone": "🚴ðŸ½\u200d♀ï¸", - "woman_bouncing_ball": "⛹ï¸\u200d♀ï¸", - "woman_bouncing_ball_dark_skin_tone": "⛹ðŸ¿\u200d♀ï¸", - "woman_bouncing_ball_light_skin_tone": "⛹ðŸ»\u200d♀ï¸", - "woman_bouncing_ball_medium-dark_skin_tone": "⛹ðŸ¾\u200d♀ï¸", - "woman_bouncing_ball_medium-light_skin_tone": "⛹ðŸ¼\u200d♀ï¸", - "woman_bouncing_ball_medium_skin_tone": "⛹ðŸ½\u200d♀ï¸", - "woman_bowing": "🙇\u200d♀ï¸", - "woman_bowing_dark_skin_tone": "🙇ðŸ¿\u200d♀ï¸", - "woman_bowing_light_skin_tone": "🙇ðŸ»\u200d♀ï¸", - "woman_bowing_medium-dark_skin_tone": "🙇ðŸ¾\u200d♀ï¸", - "woman_bowing_medium-light_skin_tone": "🙇ðŸ¼\u200d♀ï¸", - "woman_bowing_medium_skin_tone": "🙇ðŸ½\u200d♀ï¸", - "woman_cartwheeling": "🤸\u200d♀ï¸", - "woman_cartwheeling_dark_skin_tone": "🤸ðŸ¿\u200d♀ï¸", - "woman_cartwheeling_light_skin_tone": "🤸ðŸ»\u200d♀ï¸", - "woman_cartwheeling_medium-dark_skin_tone": "🤸ðŸ¾\u200d♀ï¸", - "woman_cartwheeling_medium-light_skin_tone": "🤸ðŸ¼\u200d♀ï¸", - "woman_cartwheeling_medium_skin_tone": "🤸ðŸ½\u200d♀ï¸", - "woman_climbing": "🧗\u200d♀ï¸", - "woman_climbing_dark_skin_tone": "🧗ðŸ¿\u200d♀ï¸", - "woman_climbing_light_skin_tone": "🧗ðŸ»\u200d♀ï¸", - "woman_climbing_medium-dark_skin_tone": "🧗ðŸ¾\u200d♀ï¸", - "woman_climbing_medium-light_skin_tone": "🧗ðŸ¼\u200d♀ï¸", - "woman_climbing_medium_skin_tone": "🧗ðŸ½\u200d♀ï¸", - "woman_construction_worker": "👷\u200d♀ï¸", - "woman_construction_worker_dark_skin_tone": "👷ðŸ¿\u200d♀ï¸", - "woman_construction_worker_light_skin_tone": "👷ðŸ»\u200d♀ï¸", - "woman_construction_worker_medium-dark_skin_tone": "👷ðŸ¾\u200d♀ï¸", - "woman_construction_worker_medium-light_skin_tone": "👷ðŸ¼\u200d♀ï¸", - "woman_construction_worker_medium_skin_tone": "👷ðŸ½\u200d♀ï¸", - "woman_cook": "👩\u200dðŸ³", - "woman_cook_dark_skin_tone": "👩ðŸ¿\u200dðŸ³", - "woman_cook_light_skin_tone": "👩ðŸ»\u200dðŸ³", - "woman_cook_medium-dark_skin_tone": "👩ðŸ¾\u200dðŸ³", - "woman_cook_medium-light_skin_tone": "👩ðŸ¼\u200dðŸ³", - "woman_cook_medium_skin_tone": "👩ðŸ½\u200dðŸ³", - "woman_dancing": "💃", - "woman_dancing_dark_skin_tone": "💃ðŸ¿", - "woman_dancing_light_skin_tone": "💃ðŸ»", - "woman_dancing_medium-dark_skin_tone": "💃ðŸ¾", - "woman_dancing_medium-light_skin_tone": "💃ðŸ¼", - "woman_dancing_medium_skin_tone": "💃ðŸ½", - "woman_dark_skin_tone": "👩ðŸ¿", - "woman_detective": "🕵ï¸\u200d♀ï¸", - "woman_detective_dark_skin_tone": "🕵ðŸ¿\u200d♀ï¸", - "woman_detective_light_skin_tone": "🕵ðŸ»\u200d♀ï¸", - "woman_detective_medium-dark_skin_tone": "🕵ðŸ¾\u200d♀ï¸", - "woman_detective_medium-light_skin_tone": "🕵ðŸ¼\u200d♀ï¸", - "woman_detective_medium_skin_tone": "🕵ðŸ½\u200d♀ï¸", - "woman_elf": "ðŸ§\u200d♀ï¸", - "woman_elf_dark_skin_tone": "ðŸ§ðŸ¿\u200d♀ï¸", - "woman_elf_light_skin_tone": "ðŸ§ðŸ»\u200d♀ï¸", - "woman_elf_medium-dark_skin_tone": "ðŸ§ðŸ¾\u200d♀ï¸", - "woman_elf_medium-light_skin_tone": "ðŸ§ðŸ¼\u200d♀ï¸", - "woman_elf_medium_skin_tone": "ðŸ§ðŸ½\u200d♀ï¸", - "woman_facepalming": "🤦\u200d♀ï¸", - "woman_facepalming_dark_skin_tone": "🤦ðŸ¿\u200d♀ï¸", - "woman_facepalming_light_skin_tone": "🤦ðŸ»\u200d♀ï¸", - "woman_facepalming_medium-dark_skin_tone": "🤦ðŸ¾\u200d♀ï¸", - "woman_facepalming_medium-light_skin_tone": "🤦ðŸ¼\u200d♀ï¸", - "woman_facepalming_medium_skin_tone": "🤦ðŸ½\u200d♀ï¸", - "woman_factory_worker": "👩\u200dðŸ­", - "woman_factory_worker_dark_skin_tone": "👩ðŸ¿\u200dðŸ­", - "woman_factory_worker_light_skin_tone": "👩ðŸ»\u200dðŸ­", - "woman_factory_worker_medium-dark_skin_tone": "👩ðŸ¾\u200dðŸ­", - "woman_factory_worker_medium-light_skin_tone": "👩ðŸ¼\u200dðŸ­", - "woman_factory_worker_medium_skin_tone": "👩ðŸ½\u200dðŸ­", - "woman_fairy": "🧚\u200d♀ï¸", - "woman_fairy_dark_skin_tone": "🧚ðŸ¿\u200d♀ï¸", - "woman_fairy_light_skin_tone": "🧚ðŸ»\u200d♀ï¸", - "woman_fairy_medium-dark_skin_tone": "🧚ðŸ¾\u200d♀ï¸", - "woman_fairy_medium-light_skin_tone": "🧚ðŸ¼\u200d♀ï¸", - "woman_fairy_medium_skin_tone": "🧚ðŸ½\u200d♀ï¸", - "woman_farmer": "👩\u200d🌾", - "woman_farmer_dark_skin_tone": "👩ðŸ¿\u200d🌾", - "woman_farmer_light_skin_tone": "👩ðŸ»\u200d🌾", - "woman_farmer_medium-dark_skin_tone": "👩ðŸ¾\u200d🌾", - "woman_farmer_medium-light_skin_tone": "👩ðŸ¼\u200d🌾", - "woman_farmer_medium_skin_tone": "👩ðŸ½\u200d🌾", - "woman_firefighter": "👩\u200d🚒", - "woman_firefighter_dark_skin_tone": "👩ðŸ¿\u200d🚒", - "woman_firefighter_light_skin_tone": "👩ðŸ»\u200d🚒", - "woman_firefighter_medium-dark_skin_tone": "👩ðŸ¾\u200d🚒", - "woman_firefighter_medium-light_skin_tone": "👩ðŸ¼\u200d🚒", - "woman_firefighter_medium_skin_tone": "👩ðŸ½\u200d🚒", - "woman_frowning": "ðŸ™\u200d♀ï¸", - "woman_frowning_dark_skin_tone": "ðŸ™ðŸ¿\u200d♀ï¸", - "woman_frowning_light_skin_tone": "ðŸ™ðŸ»\u200d♀ï¸", - "woman_frowning_medium-dark_skin_tone": "ðŸ™ðŸ¾\u200d♀ï¸", - "woman_frowning_medium-light_skin_tone": "ðŸ™ðŸ¼\u200d♀ï¸", - "woman_frowning_medium_skin_tone": "ðŸ™ðŸ½\u200d♀ï¸", - "woman_genie": "🧞\u200d♀ï¸", - "woman_gesturing_no": "🙅\u200d♀ï¸", - "woman_gesturing_no_dark_skin_tone": "🙅ðŸ¿\u200d♀ï¸", - "woman_gesturing_no_light_skin_tone": "🙅ðŸ»\u200d♀ï¸", - "woman_gesturing_no_medium-dark_skin_tone": "🙅ðŸ¾\u200d♀ï¸", - "woman_gesturing_no_medium-light_skin_tone": "🙅ðŸ¼\u200d♀ï¸", - "woman_gesturing_no_medium_skin_tone": "🙅ðŸ½\u200d♀ï¸", - "woman_gesturing_ok": "🙆\u200d♀ï¸", - "woman_gesturing_ok_dark_skin_tone": "🙆ðŸ¿\u200d♀ï¸", - "woman_gesturing_ok_light_skin_tone": "🙆ðŸ»\u200d♀ï¸", - "woman_gesturing_ok_medium-dark_skin_tone": "🙆ðŸ¾\u200d♀ï¸", - "woman_gesturing_ok_medium-light_skin_tone": "🙆ðŸ¼\u200d♀ï¸", - "woman_gesturing_ok_medium_skin_tone": "🙆ðŸ½\u200d♀ï¸", - "woman_getting_haircut": "💇\u200d♀ï¸", - "woman_getting_haircut_dark_skin_tone": "💇ðŸ¿\u200d♀ï¸", - "woman_getting_haircut_light_skin_tone": "💇ðŸ»\u200d♀ï¸", - "woman_getting_haircut_medium-dark_skin_tone": "💇ðŸ¾\u200d♀ï¸", - "woman_getting_haircut_medium-light_skin_tone": "💇ðŸ¼\u200d♀ï¸", - "woman_getting_haircut_medium_skin_tone": "💇ðŸ½\u200d♀ï¸", - "woman_getting_massage": "💆\u200d♀ï¸", - "woman_getting_massage_dark_skin_tone": "💆ðŸ¿\u200d♀ï¸", - "woman_getting_massage_light_skin_tone": "💆ðŸ»\u200d♀ï¸", - "woman_getting_massage_medium-dark_skin_tone": "💆ðŸ¾\u200d♀ï¸", - "woman_getting_massage_medium-light_skin_tone": "💆ðŸ¼\u200d♀ï¸", - "woman_getting_massage_medium_skin_tone": "💆ðŸ½\u200d♀ï¸", - "woman_golfing": "ðŸŒï¸\u200d♀ï¸", - "woman_golfing_dark_skin_tone": "ðŸŒðŸ¿\u200d♀ï¸", - "woman_golfing_light_skin_tone": "ðŸŒðŸ»\u200d♀ï¸", - "woman_golfing_medium-dark_skin_tone": "ðŸŒðŸ¾\u200d♀ï¸", - "woman_golfing_medium-light_skin_tone": "ðŸŒðŸ¼\u200d♀ï¸", - "woman_golfing_medium_skin_tone": "ðŸŒðŸ½\u200d♀ï¸", - "woman_guard": "💂\u200d♀ï¸", - "woman_guard_dark_skin_tone": "💂ðŸ¿\u200d♀ï¸", - "woman_guard_light_skin_tone": "💂ðŸ»\u200d♀ï¸", - "woman_guard_medium-dark_skin_tone": "💂ðŸ¾\u200d♀ï¸", - "woman_guard_medium-light_skin_tone": "💂ðŸ¼\u200d♀ï¸", - "woman_guard_medium_skin_tone": "💂ðŸ½\u200d♀ï¸", - "woman_health_worker": "👩\u200dâš•ï¸", - "woman_health_worker_dark_skin_tone": "👩ðŸ¿\u200dâš•ï¸", - "woman_health_worker_light_skin_tone": "👩ðŸ»\u200dâš•ï¸", - "woman_health_worker_medium-dark_skin_tone": "👩ðŸ¾\u200dâš•ï¸", - "woman_health_worker_medium-light_skin_tone": "👩ðŸ¼\u200dâš•ï¸", - "woman_health_worker_medium_skin_tone": "👩ðŸ½\u200dâš•ï¸", - "woman_in_lotus_position": "🧘\u200d♀ï¸", - "woman_in_lotus_position_dark_skin_tone": "🧘ðŸ¿\u200d♀ï¸", - "woman_in_lotus_position_light_skin_tone": "🧘ðŸ»\u200d♀ï¸", - "woman_in_lotus_position_medium-dark_skin_tone": "🧘ðŸ¾\u200d♀ï¸", - "woman_in_lotus_position_medium-light_skin_tone": "🧘ðŸ¼\u200d♀ï¸", - "woman_in_lotus_position_medium_skin_tone": "🧘ðŸ½\u200d♀ï¸", - "woman_in_manual_wheelchair": "👩\u200d🦽", - "woman_in_motorized_wheelchair": "👩\u200d🦼", - "woman_in_steamy_room": "🧖\u200d♀ï¸", - "woman_in_steamy_room_dark_skin_tone": "🧖ðŸ¿\u200d♀ï¸", - "woman_in_steamy_room_light_skin_tone": "🧖ðŸ»\u200d♀ï¸", - "woman_in_steamy_room_medium-dark_skin_tone": "🧖ðŸ¾\u200d♀ï¸", - "woman_in_steamy_room_medium-light_skin_tone": "🧖ðŸ¼\u200d♀ï¸", - "woman_in_steamy_room_medium_skin_tone": "🧖ðŸ½\u200d♀ï¸", - "woman_judge": "👩\u200dâš–ï¸", - "woman_judge_dark_skin_tone": "👩ðŸ¿\u200dâš–ï¸", - "woman_judge_light_skin_tone": "👩ðŸ»\u200dâš–ï¸", - "woman_judge_medium-dark_skin_tone": "👩ðŸ¾\u200dâš–ï¸", - "woman_judge_medium-light_skin_tone": "👩ðŸ¼\u200dâš–ï¸", - "woman_judge_medium_skin_tone": "👩ðŸ½\u200dâš–ï¸", - "woman_juggling": "🤹\u200d♀ï¸", - "woman_juggling_dark_skin_tone": "🤹ðŸ¿\u200d♀ï¸", - "woman_juggling_light_skin_tone": "🤹ðŸ»\u200d♀ï¸", - "woman_juggling_medium-dark_skin_tone": "🤹ðŸ¾\u200d♀ï¸", - "woman_juggling_medium-light_skin_tone": "🤹ðŸ¼\u200d♀ï¸", - "woman_juggling_medium_skin_tone": "🤹ðŸ½\u200d♀ï¸", - "woman_lifting_weights": "ðŸ‹ï¸\u200d♀ï¸", - "woman_lifting_weights_dark_skin_tone": "ðŸ‹ðŸ¿\u200d♀ï¸", - "woman_lifting_weights_light_skin_tone": "ðŸ‹ðŸ»\u200d♀ï¸", - "woman_lifting_weights_medium-dark_skin_tone": "ðŸ‹ðŸ¾\u200d♀ï¸", - "woman_lifting_weights_medium-light_skin_tone": "ðŸ‹ðŸ¼\u200d♀ï¸", - "woman_lifting_weights_medium_skin_tone": "ðŸ‹ðŸ½\u200d♀ï¸", - "woman_light_skin_tone": "👩ðŸ»", - "woman_mage": "🧙\u200d♀ï¸", - "woman_mage_dark_skin_tone": "🧙ðŸ¿\u200d♀ï¸", - "woman_mage_light_skin_tone": "🧙ðŸ»\u200d♀ï¸", - "woman_mage_medium-dark_skin_tone": "🧙ðŸ¾\u200d♀ï¸", - "woman_mage_medium-light_skin_tone": "🧙ðŸ¼\u200d♀ï¸", - "woman_mage_medium_skin_tone": "🧙ðŸ½\u200d♀ï¸", - "woman_mechanic": "👩\u200d🔧", - "woman_mechanic_dark_skin_tone": "👩ðŸ¿\u200d🔧", - "woman_mechanic_light_skin_tone": "👩ðŸ»\u200d🔧", - "woman_mechanic_medium-dark_skin_tone": "👩ðŸ¾\u200d🔧", - "woman_mechanic_medium-light_skin_tone": "👩ðŸ¼\u200d🔧", - "woman_mechanic_medium_skin_tone": "👩ðŸ½\u200d🔧", - "woman_medium-dark_skin_tone": "👩ðŸ¾", - "woman_medium-light_skin_tone": "👩ðŸ¼", - "woman_medium_skin_tone": "👩ðŸ½", - "woman_mountain_biking": "🚵\u200d♀ï¸", - "woman_mountain_biking_dark_skin_tone": "🚵ðŸ¿\u200d♀ï¸", - "woman_mountain_biking_light_skin_tone": "🚵ðŸ»\u200d♀ï¸", - "woman_mountain_biking_medium-dark_skin_tone": "🚵ðŸ¾\u200d♀ï¸", - "woman_mountain_biking_medium-light_skin_tone": "🚵ðŸ¼\u200d♀ï¸", - "woman_mountain_biking_medium_skin_tone": "🚵ðŸ½\u200d♀ï¸", - "woman_office_worker": "👩\u200d💼", - "woman_office_worker_dark_skin_tone": "👩ðŸ¿\u200d💼", - "woman_office_worker_light_skin_tone": "👩ðŸ»\u200d💼", - "woman_office_worker_medium-dark_skin_tone": "👩ðŸ¾\u200d💼", - "woman_office_worker_medium-light_skin_tone": "👩ðŸ¼\u200d💼", - "woman_office_worker_medium_skin_tone": "👩ðŸ½\u200d💼", - "woman_pilot": "👩\u200d✈ï¸", - "woman_pilot_dark_skin_tone": "👩ðŸ¿\u200d✈ï¸", - "woman_pilot_light_skin_tone": "👩ðŸ»\u200d✈ï¸", - "woman_pilot_medium-dark_skin_tone": "👩ðŸ¾\u200d✈ï¸", - "woman_pilot_medium-light_skin_tone": "👩ðŸ¼\u200d✈ï¸", - "woman_pilot_medium_skin_tone": "👩ðŸ½\u200d✈ï¸", - "woman_playing_handball": "🤾\u200d♀ï¸", - "woman_playing_handball_dark_skin_tone": "🤾ðŸ¿\u200d♀ï¸", - "woman_playing_handball_light_skin_tone": "🤾ðŸ»\u200d♀ï¸", - "woman_playing_handball_medium-dark_skin_tone": "🤾ðŸ¾\u200d♀ï¸", - "woman_playing_handball_medium-light_skin_tone": "🤾ðŸ¼\u200d♀ï¸", - "woman_playing_handball_medium_skin_tone": "🤾ðŸ½\u200d♀ï¸", - "woman_playing_water_polo": "🤽\u200d♀ï¸", - "woman_playing_water_polo_dark_skin_tone": "🤽ðŸ¿\u200d♀ï¸", - "woman_playing_water_polo_light_skin_tone": "🤽ðŸ»\u200d♀ï¸", - "woman_playing_water_polo_medium-dark_skin_tone": "🤽ðŸ¾\u200d♀ï¸", - "woman_playing_water_polo_medium-light_skin_tone": "🤽ðŸ¼\u200d♀ï¸", - "woman_playing_water_polo_medium_skin_tone": "🤽ðŸ½\u200d♀ï¸", - "woman_police_officer": "👮\u200d♀ï¸", - "woman_police_officer_dark_skin_tone": "👮ðŸ¿\u200d♀ï¸", - "woman_police_officer_light_skin_tone": "👮ðŸ»\u200d♀ï¸", - "woman_police_officer_medium-dark_skin_tone": "👮ðŸ¾\u200d♀ï¸", - "woman_police_officer_medium-light_skin_tone": "👮ðŸ¼\u200d♀ï¸", - "woman_police_officer_medium_skin_tone": "👮ðŸ½\u200d♀ï¸", - "woman_pouting": "🙎\u200d♀ï¸", - "woman_pouting_dark_skin_tone": "🙎ðŸ¿\u200d♀ï¸", - "woman_pouting_light_skin_tone": "🙎ðŸ»\u200d♀ï¸", - "woman_pouting_medium-dark_skin_tone": "🙎ðŸ¾\u200d♀ï¸", - "woman_pouting_medium-light_skin_tone": "🙎ðŸ¼\u200d♀ï¸", - "woman_pouting_medium_skin_tone": "🙎ðŸ½\u200d♀ï¸", - "woman_raising_hand": "🙋\u200d♀ï¸", - "woman_raising_hand_dark_skin_tone": "🙋ðŸ¿\u200d♀ï¸", - "woman_raising_hand_light_skin_tone": "🙋ðŸ»\u200d♀ï¸", - "woman_raising_hand_medium-dark_skin_tone": "🙋ðŸ¾\u200d♀ï¸", - "woman_raising_hand_medium-light_skin_tone": "🙋ðŸ¼\u200d♀ï¸", - "woman_raising_hand_medium_skin_tone": "🙋ðŸ½\u200d♀ï¸", - "woman_rowing_boat": "🚣\u200d♀ï¸", - "woman_rowing_boat_dark_skin_tone": "🚣ðŸ¿\u200d♀ï¸", - "woman_rowing_boat_light_skin_tone": "🚣ðŸ»\u200d♀ï¸", - "woman_rowing_boat_medium-dark_skin_tone": "🚣ðŸ¾\u200d♀ï¸", - "woman_rowing_boat_medium-light_skin_tone": "🚣ðŸ¼\u200d♀ï¸", - "woman_rowing_boat_medium_skin_tone": "🚣ðŸ½\u200d♀ï¸", - "woman_running": "ðŸƒ\u200d♀ï¸", - "woman_running_dark_skin_tone": "ðŸƒðŸ¿\u200d♀ï¸", - "woman_running_light_skin_tone": "ðŸƒðŸ»\u200d♀ï¸", - "woman_running_medium-dark_skin_tone": "ðŸƒðŸ¾\u200d♀ï¸", - "woman_running_medium-light_skin_tone": "ðŸƒðŸ¼\u200d♀ï¸", - "woman_running_medium_skin_tone": "ðŸƒðŸ½\u200d♀ï¸", - "woman_scientist": "👩\u200d🔬", - "woman_scientist_dark_skin_tone": "👩ðŸ¿\u200d🔬", - "woman_scientist_light_skin_tone": "👩ðŸ»\u200d🔬", - "woman_scientist_medium-dark_skin_tone": "👩ðŸ¾\u200d🔬", - "woman_scientist_medium-light_skin_tone": "👩ðŸ¼\u200d🔬", - "woman_scientist_medium_skin_tone": "👩ðŸ½\u200d🔬", - "woman_shrugging": "🤷\u200d♀ï¸", - "woman_shrugging_dark_skin_tone": "🤷ðŸ¿\u200d♀ï¸", - "woman_shrugging_light_skin_tone": "🤷ðŸ»\u200d♀ï¸", - "woman_shrugging_medium-dark_skin_tone": "🤷ðŸ¾\u200d♀ï¸", - "woman_shrugging_medium-light_skin_tone": "🤷ðŸ¼\u200d♀ï¸", - "woman_shrugging_medium_skin_tone": "🤷ðŸ½\u200d♀ï¸", - "woman_singer": "👩\u200d🎤", - "woman_singer_dark_skin_tone": "👩ðŸ¿\u200d🎤", - "woman_singer_light_skin_tone": "👩ðŸ»\u200d🎤", - "woman_singer_medium-dark_skin_tone": "👩ðŸ¾\u200d🎤", - "woman_singer_medium-light_skin_tone": "👩ðŸ¼\u200d🎤", - "woman_singer_medium_skin_tone": "👩ðŸ½\u200d🎤", - "woman_student": "👩\u200d🎓", - "woman_student_dark_skin_tone": "👩ðŸ¿\u200d🎓", - "woman_student_light_skin_tone": "👩ðŸ»\u200d🎓", - "woman_student_medium-dark_skin_tone": "👩ðŸ¾\u200d🎓", - "woman_student_medium-light_skin_tone": "👩ðŸ¼\u200d🎓", - "woman_student_medium_skin_tone": "👩ðŸ½\u200d🎓", - "woman_surfing": "ðŸ„\u200d♀ï¸", - "woman_surfing_dark_skin_tone": "ðŸ„ðŸ¿\u200d♀ï¸", - "woman_surfing_light_skin_tone": "ðŸ„ðŸ»\u200d♀ï¸", - "woman_surfing_medium-dark_skin_tone": "ðŸ„ðŸ¾\u200d♀ï¸", - "woman_surfing_medium-light_skin_tone": "ðŸ„ðŸ¼\u200d♀ï¸", - "woman_surfing_medium_skin_tone": "ðŸ„ðŸ½\u200d♀ï¸", - "woman_swimming": "ðŸŠ\u200d♀ï¸", - "woman_swimming_dark_skin_tone": "ðŸŠðŸ¿\u200d♀ï¸", - "woman_swimming_light_skin_tone": "ðŸŠðŸ»\u200d♀ï¸", - "woman_swimming_medium-dark_skin_tone": "ðŸŠðŸ¾\u200d♀ï¸", - "woman_swimming_medium-light_skin_tone": "ðŸŠðŸ¼\u200d♀ï¸", - "woman_swimming_medium_skin_tone": "ðŸŠðŸ½\u200d♀ï¸", - "woman_teacher": "👩\u200dðŸ«", - "woman_teacher_dark_skin_tone": "👩ðŸ¿\u200dðŸ«", - "woman_teacher_light_skin_tone": "👩ðŸ»\u200dðŸ«", - "woman_teacher_medium-dark_skin_tone": "👩ðŸ¾\u200dðŸ«", - "woman_teacher_medium-light_skin_tone": "👩ðŸ¼\u200dðŸ«", - "woman_teacher_medium_skin_tone": "👩ðŸ½\u200dðŸ«", - "woman_technologist": "👩\u200d💻", - "woman_technologist_dark_skin_tone": "👩ðŸ¿\u200d💻", - "woman_technologist_light_skin_tone": "👩ðŸ»\u200d💻", - "woman_technologist_medium-dark_skin_tone": "👩ðŸ¾\u200d💻", - "woman_technologist_medium-light_skin_tone": "👩ðŸ¼\u200d💻", - "woman_technologist_medium_skin_tone": "👩ðŸ½\u200d💻", - "woman_tipping_hand": "ðŸ’\u200d♀ï¸", - "woman_tipping_hand_dark_skin_tone": "ðŸ’ðŸ¿\u200d♀ï¸", - "woman_tipping_hand_light_skin_tone": "ðŸ’ðŸ»\u200d♀ï¸", - "woman_tipping_hand_medium-dark_skin_tone": "ðŸ’ðŸ¾\u200d♀ï¸", - "woman_tipping_hand_medium-light_skin_tone": "ðŸ’ðŸ¼\u200d♀ï¸", - "woman_tipping_hand_medium_skin_tone": "ðŸ’ðŸ½\u200d♀ï¸", - "woman_vampire": "🧛\u200d♀ï¸", - "woman_vampire_dark_skin_tone": "🧛ðŸ¿\u200d♀ï¸", - "woman_vampire_light_skin_tone": "🧛ðŸ»\u200d♀ï¸", - "woman_vampire_medium-dark_skin_tone": "🧛ðŸ¾\u200d♀ï¸", - "woman_vampire_medium-light_skin_tone": "🧛ðŸ¼\u200d♀ï¸", - "woman_vampire_medium_skin_tone": "🧛ðŸ½\u200d♀ï¸", - "woman_walking": "🚶\u200d♀ï¸", - "woman_walking_dark_skin_tone": "🚶ðŸ¿\u200d♀ï¸", - "woman_walking_light_skin_tone": "🚶ðŸ»\u200d♀ï¸", - "woman_walking_medium-dark_skin_tone": "🚶ðŸ¾\u200d♀ï¸", - "woman_walking_medium-light_skin_tone": "🚶ðŸ¼\u200d♀ï¸", - "woman_walking_medium_skin_tone": "🚶ðŸ½\u200d♀ï¸", - "woman_wearing_turban": "👳\u200d♀ï¸", - "woman_wearing_turban_dark_skin_tone": "👳ðŸ¿\u200d♀ï¸", - "woman_wearing_turban_light_skin_tone": "👳ðŸ»\u200d♀ï¸", - "woman_wearing_turban_medium-dark_skin_tone": "👳ðŸ¾\u200d♀ï¸", - "woman_wearing_turban_medium-light_skin_tone": "👳ðŸ¼\u200d♀ï¸", - "woman_wearing_turban_medium_skin_tone": "👳ðŸ½\u200d♀ï¸", - "woman_with_headscarf": "🧕", - "woman_with_headscarf_dark_skin_tone": "🧕ðŸ¿", - "woman_with_headscarf_light_skin_tone": "🧕ðŸ»", - "woman_with_headscarf_medium-dark_skin_tone": "🧕ðŸ¾", - "woman_with_headscarf_medium-light_skin_tone": "🧕ðŸ¼", - "woman_with_headscarf_medium_skin_tone": "🧕ðŸ½", - "woman_with_probing_cane": "👩\u200d🦯", - "woman_zombie": "🧟\u200d♀ï¸", - "woman’s_boot": "👢", - "woman’s_clothes": "👚", - "woman’s_hat": "👒", - "woman’s_sandal": "👡", - "women_with_bunny_ears": "👯\u200d♀ï¸", - "women_wrestling": "🤼\u200d♀ï¸", - "women’s_room": "🚺", - "woozy_face": "🥴", - "world_map": "🗺", - "worried_face": "😟", - "wrapped_gift": "ðŸŽ", - "wrench": "🔧", - "writing_hand": "âœ", - "writing_hand_dark_skin_tone": "âœðŸ¿", - "writing_hand_light_skin_tone": "âœðŸ»", - "writing_hand_medium-dark_skin_tone": "âœðŸ¾", - "writing_hand_medium-light_skin_tone": "âœðŸ¼", - "writing_hand_medium_skin_tone": "âœðŸ½", - "yarn": "🧶", - "yawning_face": "🥱", - "yellow_circle": "🟡", - "yellow_heart": "💛", - "yellow_square": "🟨", - "yen_banknote": "💴", - "yo-yo": "🪀", - "yin_yang": "☯", - "zany_face": "🤪", - "zebra": "🦓", - "zipper-mouth_face": "ðŸ¤", - "zombie": "🧟", - "zzz": "💤", - "Ã¥land_islands": "🇦🇽", - "keycap_asterisk": "*⃣", - "keycap_digit_eight": "8⃣", - "keycap_digit_five": "5⃣", - "keycap_digit_four": "4⃣", - "keycap_digit_nine": "9⃣", - "keycap_digit_one": "1⃣", - "keycap_digit_seven": "7⃣", - "keycap_digit_six": "6⃣", - "keycap_digit_three": "3⃣", - "keycap_digit_two": "2⃣", - "keycap_digit_zero": "0⃣", - "keycap_number_sign": "#⃣", - "light_skin_tone": "ðŸ»", - "medium_light_skin_tone": "ðŸ¼", - "medium_skin_tone": "ðŸ½", - "medium_dark_skin_tone": "ðŸ¾", - "dark_skin_tone": "ðŸ¿", - "regional_indicator_symbol_letter_a": "🇦", - "regional_indicator_symbol_letter_b": "🇧", - "regional_indicator_symbol_letter_c": "🇨", - "regional_indicator_symbol_letter_d": "🇩", - "regional_indicator_symbol_letter_e": "🇪", - "regional_indicator_symbol_letter_f": "🇫", - "regional_indicator_symbol_letter_g": "🇬", - "regional_indicator_symbol_letter_h": "🇭", - "regional_indicator_symbol_letter_i": "🇮", - "regional_indicator_symbol_letter_j": "🇯", - "regional_indicator_symbol_letter_k": "🇰", - "regional_indicator_symbol_letter_l": "🇱", - "regional_indicator_symbol_letter_m": "🇲", - "regional_indicator_symbol_letter_n": "🇳", - "regional_indicator_symbol_letter_o": "🇴", - "regional_indicator_symbol_letter_p": "🇵", - "regional_indicator_symbol_letter_q": "🇶", - "regional_indicator_symbol_letter_r": "🇷", - "regional_indicator_symbol_letter_s": "🇸", - "regional_indicator_symbol_letter_t": "🇹", - "regional_indicator_symbol_letter_u": "🇺", - "regional_indicator_symbol_letter_v": "🇻", - "regional_indicator_symbol_letter_w": "🇼", - "regional_indicator_symbol_letter_x": "🇽", - "regional_indicator_symbol_letter_y": "🇾", - "regional_indicator_symbol_letter_z": "🇿", - "airplane_arriving": "🛬", - "space_invader": "👾", - "football": "ðŸˆ", - "anger": "💢", - "angry": "😠", - "anguished": "😧", - "signal_strength": "📶", - "arrows_counterclockwise": "🔄", - "arrow_heading_down": "⤵", - "arrow_heading_up": "⤴", - "art": "🎨", - "astonished": "😲", - "athletic_shoe": "👟", - "atm": "ðŸ§", - "car": "🚗", - "red_car": "🚗", - "angel": "👼", - "back": "🔙", - "badminton_racquet_and_shuttlecock": "ðŸ¸", - "dollar": "💵", - "euro": "💶", - "pound": "💷", - "yen": "💴", - "barber": "💈", - "bath": "🛀", - "bear": "ðŸ»", - "heartbeat": "💓", - "beer": "ðŸº", - "no_bell": "🔕", - "bento": "ðŸ±", - "bike": "🚲", - "bicyclist": "🚴", - "8ball": "🎱", - "biohazard_sign": "☣", - "birthday": "🎂", - "black_circle_for_record": "âº", - "clubs": "♣", - "diamonds": "♦", - "arrow_double_down": "â¬", - "hearts": "♥", - "rewind": "âª", - "black_left__pointing_double_triangle_with_vertical_bar": "â®", - "arrow_backward": "â—€", - "black_medium_small_square": "â—¾", - "question": "â“", - "fast_forward": "â©", - "black_right__pointing_double_triangle_with_vertical_bar": "â­", - "arrow_forward": "â–¶", - "black_right__pointing_triangle_with_double_vertical_bar": "â¯", - "arrow_right": "âž¡", - "spades": "â™ ", - "black_square_for_stop": "â¹", - "sunny": "☀", - "phone": "☎", - "recycle": "â™»", - "arrow_double_up": "â«", - "busstop": "ðŸš", - "date": "📅", - "flags": "ðŸŽ", - "cat2": "ðŸˆ", - "joy_cat": "😹", - "smirk_cat": "😼", - "chart_with_downwards_trend": "📉", - "chart_with_upwards_trend": "📈", - "chart": "💹", - "mega": "📣", - "checkered_flag": "ðŸ", - "accept": "🉑", - "ideograph_advantage": "ðŸ‰", - "congratulations": "㊗", - "secret": "㊙", - "m": "â“‚", - "city_sunset": "🌆", - "clapper": "🎬", - "clap": "ðŸ‘", - "beers": "ðŸ»", - "clock830": "🕣", - "clock8": "🕗", - "clock1130": "🕦", - "clock11": "🕚", - "clock530": "🕠", - "clock5": "🕔", - "clock430": "🕟", - "clock4": "🕓", - "clock930": "🕤", - "clock9": "🕘", - "clock130": "🕜", - "clock1": "ðŸ•", - "clock730": "🕢", - "clock7": "🕖", - "clock630": "🕡", - "clock6": "🕕", - "clock1030": "🕥", - "clock10": "🕙", - "clock330": "🕞", - "clock3": "🕒", - "clock1230": "🕧", - "clock12": "🕛", - "clock230": "ðŸ•", - "clock2": "🕑", - "arrows_clockwise": "🔃", - "repeat": "ðŸ”", - "repeat_one": "🔂", - "closed_lock_with_key": "ðŸ”", - "mailbox_closed": "📪", - "mailbox": "📫", - "cloud_with_tornado": "🌪", - "cocktail": "ðŸ¸", - "boom": "💥", - "compression": "🗜", - "confounded": "😖", - "confused": "😕", - "rice": "ðŸš", - "cow2": "ðŸ„", - "cricket_bat_and_ball": "ðŸ", - "x": "âŒ", - "cry": "😢", - "curry": "ðŸ›", - "dagger_knife": "🗡", - "dancer": "💃", - "dark_sunglasses": "🕶", - "dash": "💨", - "truck": "🚚", - "derelict_house_building": "ðŸš", - "diamond_shape_with_a_dot_inside": "💠", - "dart": "🎯", - "disappointed_relieved": "😥", - "disappointed": "😞", - "do_not_litter": "🚯", - "dog2": "ðŸ•", - "flipper": "ðŸ¬", - "loop": "âž¿", - "bangbang": "‼", - "double_vertical_bar": "â¸", - "dove_of_peace": "🕊", - "small_red_triangle_down": "🔻", - "arrow_down_small": "🔽", - "arrow_down": "⬇", - "dromedary_camel": "ðŸª", - "e__mail": "📧", - "corn": "🌽", - "ear_of_rice": "🌾", - "earth_americas": "🌎", - "earth_asia": "ðŸŒ", - "earth_africa": "ðŸŒ", - "eight_pointed_black_star": "✴", - "eight_spoked_asterisk": "✳", - "eject_symbol": "â", - "bulb": "💡", - "emoji_modifier_fitzpatrick_type__1__2": "ðŸ»", - "emoji_modifier_fitzpatrick_type__3": "ðŸ¼", - "emoji_modifier_fitzpatrick_type__4": "ðŸ½", - "emoji_modifier_fitzpatrick_type__5": "ðŸ¾", - "emoji_modifier_fitzpatrick_type__6": "ðŸ¿", - "end": "🔚", - "email": "✉", - "european_castle": "ðŸ°", - "european_post_office": "ðŸ¤", - "interrobang": "â‰", - "expressionless": "😑", - "eyeglasses": "👓", - "massage": "💆", - "yum": "😋", - "scream": "😱", - "kissing_heart": "😘", - "sweat": "😓", - "face_with_head__bandage": "🤕", - "triumph": "😤", - "mask": "😷", - "no_good": "🙅", - "ok_woman": "🙆", - "open_mouth": "😮", - "cold_sweat": "😰", - "stuck_out_tongue": "😛", - "stuck_out_tongue_closed_eyes": "ðŸ˜", - "stuck_out_tongue_winking_eye": "😜", - "joy": "😂", - "no_mouth": "😶", - "santa": "🎅", - "fax": "📠", - "fearful": "😨", - "field_hockey_stick_and_ball": "ðŸ‘", - "first_quarter_moon_with_face": "🌛", - "fish_cake": "ðŸ¥", - "fishing_pole_and_fish": "🎣", - "facepunch": "👊", - "punch": "👊", - "flag_for_afghanistan": "🇦🇫", - "flag_for_albania": "🇦🇱", - "flag_for_algeria": "🇩🇿", - "flag_for_american_samoa": "🇦🇸", - "flag_for_andorra": "🇦🇩", - "flag_for_angola": "🇦🇴", - "flag_for_anguilla": "🇦🇮", - "flag_for_antarctica": "🇦🇶", - "flag_for_antigua_&_barbuda": "🇦🇬", - "flag_for_argentina": "🇦🇷", - "flag_for_armenia": "🇦🇲", - "flag_for_aruba": "🇦🇼", - "flag_for_ascension_island": "🇦🇨", - "flag_for_australia": "🇦🇺", - "flag_for_austria": "🇦🇹", - "flag_for_azerbaijan": "🇦🇿", - "flag_for_bahamas": "🇧🇸", - "flag_for_bahrain": "🇧🇭", - "flag_for_bangladesh": "🇧🇩", - "flag_for_barbados": "🇧🇧", - "flag_for_belarus": "🇧🇾", - "flag_for_belgium": "🇧🇪", - "flag_for_belize": "🇧🇿", - "flag_for_benin": "🇧🇯", - "flag_for_bermuda": "🇧🇲", - "flag_for_bhutan": "🇧🇹", - "flag_for_bolivia": "🇧🇴", - "flag_for_bosnia_&_herzegovina": "🇧🇦", - "flag_for_botswana": "🇧🇼", - "flag_for_bouvet_island": "🇧🇻", - "flag_for_brazil": "🇧🇷", - "flag_for_british_indian_ocean_territory": "🇮🇴", - "flag_for_british_virgin_islands": "🇻🇬", - "flag_for_brunei": "🇧🇳", - "flag_for_bulgaria": "🇧🇬", - "flag_for_burkina_faso": "🇧🇫", - "flag_for_burundi": "🇧🇮", - "flag_for_cambodia": "🇰🇭", - "flag_for_cameroon": "🇨🇲", - "flag_for_canada": "🇨🇦", - "flag_for_canary_islands": "🇮🇨", - "flag_for_cape_verde": "🇨🇻", - "flag_for_caribbean_netherlands": "🇧🇶", - "flag_for_cayman_islands": "🇰🇾", - "flag_for_central_african_republic": "🇨🇫", - "flag_for_ceuta_&_melilla": "🇪🇦", - "flag_for_chad": "🇹🇩", - "flag_for_chile": "🇨🇱", - "flag_for_china": "🇨🇳", - "flag_for_christmas_island": "🇨🇽", - "flag_for_clipperton_island": "🇨🇵", - "flag_for_cocos__islands": "🇨🇨", - "flag_for_colombia": "🇨🇴", - "flag_for_comoros": "🇰🇲", - "flag_for_congo____brazzaville": "🇨🇬", - "flag_for_congo____kinshasa": "🇨🇩", - "flag_for_cook_islands": "🇨🇰", - "flag_for_costa_rica": "🇨🇷", - "flag_for_croatia": "🇭🇷", - "flag_for_cuba": "🇨🇺", - "flag_for_curaçao": "🇨🇼", - "flag_for_cyprus": "🇨🇾", - "flag_for_czech_republic": "🇨🇿", - "flag_for_côte_d’ivoire": "🇨🇮", - "flag_for_denmark": "🇩🇰", - "flag_for_diego_garcia": "🇩🇬", - "flag_for_djibouti": "🇩🇯", - "flag_for_dominica": "🇩🇲", - "flag_for_dominican_republic": "🇩🇴", - "flag_for_ecuador": "🇪🇨", - "flag_for_egypt": "🇪🇬", - "flag_for_el_salvador": "🇸🇻", - "flag_for_equatorial_guinea": "🇬🇶", - "flag_for_eritrea": "🇪🇷", - "flag_for_estonia": "🇪🇪", - "flag_for_ethiopia": "🇪🇹", - "flag_for_european_union": "🇪🇺", - "flag_for_falkland_islands": "🇫🇰", - "flag_for_faroe_islands": "🇫🇴", - "flag_for_fiji": "🇫🇯", - "flag_for_finland": "🇫🇮", - "flag_for_france": "🇫🇷", - "flag_for_french_guiana": "🇬🇫", - "flag_for_french_polynesia": "🇵🇫", - "flag_for_french_southern_territories": "🇹🇫", - "flag_for_gabon": "🇬🇦", - "flag_for_gambia": "🇬🇲", - "flag_for_georgia": "🇬🇪", - "flag_for_germany": "🇩🇪", - "flag_for_ghana": "🇬🇭", - "flag_for_gibraltar": "🇬🇮", - "flag_for_greece": "🇬🇷", - "flag_for_greenland": "🇬🇱", - "flag_for_grenada": "🇬🇩", - "flag_for_guadeloupe": "🇬🇵", - "flag_for_guam": "🇬🇺", - "flag_for_guatemala": "🇬🇹", - "flag_for_guernsey": "🇬🇬", - "flag_for_guinea": "🇬🇳", - "flag_for_guinea__bissau": "🇬🇼", - "flag_for_guyana": "🇬🇾", - "flag_for_haiti": "🇭🇹", - "flag_for_heard_&_mcdonald_islands": "🇭🇲", - "flag_for_honduras": "🇭🇳", - "flag_for_hong_kong": "🇭🇰", - "flag_for_hungary": "🇭🇺", - "flag_for_iceland": "🇮🇸", - "flag_for_india": "🇮🇳", - "flag_for_indonesia": "🇮🇩", - "flag_for_iran": "🇮🇷", - "flag_for_iraq": "🇮🇶", - "flag_for_ireland": "🇮🇪", - "flag_for_isle_of_man": "🇮🇲", - "flag_for_israel": "🇮🇱", - "flag_for_italy": "🇮🇹", - "flag_for_jamaica": "🇯🇲", - "flag_for_japan": "🇯🇵", - "flag_for_jersey": "🇯🇪", - "flag_for_jordan": "🇯🇴", - "flag_for_kazakhstan": "🇰🇿", - "flag_for_kenya": "🇰🇪", - "flag_for_kiribati": "🇰🇮", - "flag_for_kosovo": "🇽🇰", - "flag_for_kuwait": "🇰🇼", - "flag_for_kyrgyzstan": "🇰🇬", - "flag_for_laos": "🇱🇦", - "flag_for_latvia": "🇱🇻", - "flag_for_lebanon": "🇱🇧", - "flag_for_lesotho": "🇱🇸", - "flag_for_liberia": "🇱🇷", - "flag_for_libya": "🇱🇾", - "flag_for_liechtenstein": "🇱🇮", - "flag_for_lithuania": "🇱🇹", - "flag_for_luxembourg": "🇱🇺", - "flag_for_macau": "🇲🇴", - "flag_for_macedonia": "🇲🇰", - "flag_for_madagascar": "🇲🇬", - "flag_for_malawi": "🇲🇼", - "flag_for_malaysia": "🇲🇾", - "flag_for_maldives": "🇲🇻", - "flag_for_mali": "🇲🇱", - "flag_for_malta": "🇲🇹", - "flag_for_marshall_islands": "🇲🇭", - "flag_for_martinique": "🇲🇶", - "flag_for_mauritania": "🇲🇷", - "flag_for_mauritius": "🇲🇺", - "flag_for_mayotte": "🇾🇹", - "flag_for_mexico": "🇲🇽", - "flag_for_micronesia": "🇫🇲", - "flag_for_moldova": "🇲🇩", - "flag_for_monaco": "🇲🇨", - "flag_for_mongolia": "🇲🇳", - "flag_for_montenegro": "🇲🇪", - "flag_for_montserrat": "🇲🇸", - "flag_for_morocco": "🇲🇦", - "flag_for_mozambique": "🇲🇿", - "flag_for_myanmar": "🇲🇲", - "flag_for_namibia": "🇳🇦", - "flag_for_nauru": "🇳🇷", - "flag_for_nepal": "🇳🇵", - "flag_for_netherlands": "🇳🇱", - "flag_for_new_caledonia": "🇳🇨", - "flag_for_new_zealand": "🇳🇿", - "flag_for_nicaragua": "🇳🇮", - "flag_for_niger": "🇳🇪", - "flag_for_nigeria": "🇳🇬", - "flag_for_niue": "🇳🇺", - "flag_for_norfolk_island": "🇳🇫", - "flag_for_north_korea": "🇰🇵", - "flag_for_northern_mariana_islands": "🇲🇵", - "flag_for_norway": "🇳🇴", - "flag_for_oman": "🇴🇲", - "flag_for_pakistan": "🇵🇰", - "flag_for_palau": "🇵🇼", - "flag_for_palestinian_territories": "🇵🇸", - "flag_for_panama": "🇵🇦", - "flag_for_papua_new_guinea": "🇵🇬", - "flag_for_paraguay": "🇵🇾", - "flag_for_peru": "🇵🇪", - "flag_for_philippines": "🇵🇭", - "flag_for_pitcairn_islands": "🇵🇳", - "flag_for_poland": "🇵🇱", - "flag_for_portugal": "🇵🇹", - "flag_for_puerto_rico": "🇵🇷", - "flag_for_qatar": "🇶🇦", - "flag_for_romania": "🇷🇴", - "flag_for_russia": "🇷🇺", - "flag_for_rwanda": "🇷🇼", - "flag_for_réunion": "🇷🇪", - "flag_for_samoa": "🇼🇸", - "flag_for_san_marino": "🇸🇲", - "flag_for_saudi_arabia": "🇸🇦", - "flag_for_senegal": "🇸🇳", - "flag_for_serbia": "🇷🇸", - "flag_for_seychelles": "🇸🇨", - "flag_for_sierra_leone": "🇸🇱", - "flag_for_singapore": "🇸🇬", - "flag_for_sint_maarten": "🇸🇽", - "flag_for_slovakia": "🇸🇰", - "flag_for_slovenia": "🇸🇮", - "flag_for_solomon_islands": "🇸🇧", - "flag_for_somalia": "🇸🇴", - "flag_for_south_africa": "🇿🇦", - "flag_for_south_georgia_&_south_sandwich_islands": "🇬🇸", - "flag_for_south_korea": "🇰🇷", - "flag_for_south_sudan": "🇸🇸", - "flag_for_spain": "🇪🇸", - "flag_for_sri_lanka": "🇱🇰", - "flag_for_st._barthélemy": "🇧🇱", - "flag_for_st._helena": "🇸🇭", - "flag_for_st._kitts_&_nevis": "🇰🇳", - "flag_for_st._lucia": "🇱🇨", - "flag_for_st._martin": "🇲🇫", - "flag_for_st._pierre_&_miquelon": "🇵🇲", - "flag_for_st._vincent_&_grenadines": "🇻🇨", - "flag_for_sudan": "🇸🇩", - "flag_for_suriname": "🇸🇷", - "flag_for_svalbard_&_jan_mayen": "🇸🇯", - "flag_for_swaziland": "🇸🇿", - "flag_for_sweden": "🇸🇪", - "flag_for_switzerland": "🇨🇭", - "flag_for_syria": "🇸🇾", - "flag_for_são_tomé_&_príncipe": "🇸🇹", - "flag_for_taiwan": "🇹🇼", - "flag_for_tajikistan": "🇹🇯", - "flag_for_tanzania": "🇹🇿", - "flag_for_thailand": "🇹🇭", - "flag_for_timor__leste": "🇹🇱", - "flag_for_togo": "🇹🇬", - "flag_for_tokelau": "🇹🇰", - "flag_for_tonga": "🇹🇴", - "flag_for_trinidad_&_tobago": "🇹🇹", - "flag_for_tristan_da_cunha": "🇹🇦", - "flag_for_tunisia": "🇹🇳", - "flag_for_turkey": "🇹🇷", - "flag_for_turkmenistan": "🇹🇲", - "flag_for_turks_&_caicos_islands": "🇹🇨", - "flag_for_tuvalu": "🇹🇻", - "flag_for_u.s._outlying_islands": "🇺🇲", - "flag_for_u.s._virgin_islands": "🇻🇮", - "flag_for_uganda": "🇺🇬", - "flag_for_ukraine": "🇺🇦", - "flag_for_united_arab_emirates": "🇦🇪", - "flag_for_united_kingdom": "🇬🇧", - "flag_for_united_states": "🇺🇸", - "flag_for_uruguay": "🇺🇾", - "flag_for_uzbekistan": "🇺🇿", - "flag_for_vanuatu": "🇻🇺", - "flag_for_vatican_city": "🇻🇦", - "flag_for_venezuela": "🇻🇪", - "flag_for_vietnam": "🇻🇳", - "flag_for_wallis_&_futuna": "🇼🇫", - "flag_for_western_sahara": "🇪🇭", - "flag_for_yemen": "🇾🇪", - "flag_for_zambia": "🇿🇲", - "flag_for_zimbabwe": "🇿🇼", - "flag_for_Ã¥land_islands": "🇦🇽", - "golf": "⛳", - "fleur__de__lis": "âšœ", - "muscle": "💪", - "flushed": "😳", - "frame_with_picture": "🖼", - "fries": "ðŸŸ", - "frog": "ðŸ¸", - "hatched_chick": "ðŸ¥", - "frowning": "😦", - "fuelpump": "⛽", - "full_moon_with_face": "ðŸŒ", - "gem": "💎", - "star2": "🌟", - "golfer": "ðŸŒ", - "mortar_board": "🎓", - "grimacing": "😬", - "smile_cat": "😸", - "grinning": "😀", - "grin": "ðŸ˜", - "heartpulse": "💗", - "guardsman": "💂", - "haircut": "💇", - "hamster": "ðŸ¹", - "raising_hand": "🙋", - "headphones": "🎧", - "hear_no_evil": "🙉", - "cupid": "💘", - "gift_heart": "ðŸ’", - "heart": "â¤", - "exclamation": "â—", - "heavy_exclamation_mark": "â—", - "heavy_heart_exclamation_mark_ornament": "â£", - "o": "â­•", - "helm_symbol": "⎈", - "helmet_with_white_cross": "⛑", - "high_heel": "👠", - "bullettrain_side": "🚄", - "bullettrain_front": "🚅", - "high_brightness": "🔆", - "zap": "âš¡", - "hocho": "🔪", - "knife": "🔪", - "bee": "ðŸ", - "traffic_light": "🚥", - "racehorse": "ðŸŽ", - "coffee": "☕", - "hotsprings": "♨", - "hourglass": "⌛", - "hourglass_flowing_sand": "â³", - "house_buildings": "ðŸ˜", - "100": "💯", - "hushed": "😯", - "ice_hockey_stick_and_puck": "ðŸ’", - "imp": "👿", - "information_desk_person": "ðŸ’", - "information_source": "ℹ", - "capital_abcd": "🔠", - "abc": "🔤", - "abcd": "🔡", - "1234": "🔢", - "symbols": "🔣", - "izakaya_lantern": "ðŸ®", - "lantern": "ðŸ®", - "jack_o_lantern": "🎃", - "dolls": "🎎", - "japanese_goblin": "👺", - "japanese_ogre": "👹", - "beginner": "🔰", - "zero": "0ï¸âƒ£", - "one": "1ï¸âƒ£", - "ten": "🔟", - "two": "2ï¸âƒ£", - "three": "3ï¸âƒ£", - "four": "4ï¸âƒ£", - "five": "5ï¸âƒ£", - "six": "6ï¸âƒ£", - "seven": "7ï¸âƒ£", - "eight": "8ï¸âƒ£", - "nine": "9ï¸âƒ£", - "couplekiss": "ðŸ’", - "kissing_cat": "😽", - "kissing": "😗", - "kissing_closed_eyes": "😚", - "kissing_smiling_eyes": "😙", - "beetle": "ðŸž", - "large_blue_circle": "🔵", - "last_quarter_moon_with_face": "🌜", - "leaves": "ðŸƒ", - "mag": "ðŸ”", - "left_right_arrow": "↔", - "leftwards_arrow_with_hook": "↩", - "arrow_left": "⬅", - "lock": "🔒", - "lock_with_ink_pen": "ðŸ”", - "sob": "😭", - "low_brightness": "🔅", - "lower_left_ballpoint_pen": "🖊", - "lower_left_crayon": "ðŸ–", - "lower_left_fountain_pen": "🖋", - "lower_left_paintbrush": "🖌", - "mahjong": "🀄", - "couple": "👫", - "man_in_business_suit_levitating": "🕴", - "man_with_gua_pi_mao": "👲", - "man_with_turban": "👳", - "mans_shoe": "👞", - "shoe": "👞", - "menorah_with_nine_branches": "🕎", - "mens": "🚹", - "minidisc": "💽", - "iphone": "📱", - "calling": "📲", - "money__mouth_face": "🤑", - "moneybag": "💰", - "rice_scene": "🎑", - "mountain_bicyclist": "🚵", - "mouse2": "ðŸ", - "lips": "👄", - "moyai": "🗿", - "notes": "🎶", - "nail_care": "💅", - "ab": "🆎", - "negative_squared_cross_mark": "âŽ", - "a": "🅰", - "b": "🅱", - "o2": "🅾", - "parking": "🅿", - "new_moon_with_face": "🌚", - "no_entry_sign": "🚫", - "underage": "🔞", - "non__potable_water": "🚱", - "arrow_upper_right": "↗", - "arrow_upper_left": "↖", - "office": "ðŸ¢", - "older_man": "👴", - "older_woman": "👵", - "om_symbol": "🕉", - "on": "🔛", - "book": "📖", - "unlock": "🔓", - "mailbox_with_no_mail": "📭", - "mailbox_with_mail": "📬", - "cd": "💿", - "tada": "🎉", - "feet": "ðŸ¾", - "walking": "🚶", - "pencil2": "âœ", - "pensive": "😔", - "persevere": "😣", - "bow": "🙇", - "raised_hands": "🙌", - "person_with_ball": "⛹", - "person_with_blond_hair": "👱", - "pray": "ðŸ™", - "person_with_pouting_face": "🙎", - "computer": "💻", - "pig2": "ðŸ–", - "hankey": "💩", - "poop": "💩", - "shit": "💩", - "bamboo": "ðŸŽ", - "gun": "🔫", - "black_joker": "ðŸƒ", - "rotating_light": "🚨", - "cop": "👮", - "stew": "ðŸ²", - "pouch": "ðŸ‘", - "pouting_cat": "😾", - "rage": "😡", - "put_litter_in_its_place": "🚮", - "rabbit2": "ðŸ‡", - "racing_motorcycle": "ðŸ", - "radioactive_sign": "☢", - "fist": "✊", - "hand": "✋", - "raised_hand_with_fingers_splayed": "ðŸ–", - "raised_hand_with_part_between_middle_and_ring_fingers": "🖖", - "blue_car": "🚙", - "apple": "ðŸŽ", - "relieved": "😌", - "reversed_hand_with_middle_finger_extended": "🖕", - "mag_right": "🔎", - "arrow_right_hook": "↪", - "sweet_potato": "ðŸ ", - "robot": "🤖", - "rolled__up_newspaper": "🗞", - "rowboat": "🚣", - "runner": "ðŸƒ", - "running": "ðŸƒ", - "running_shirt_with_sash": "🎽", - "boat": "⛵", - "scales": "âš–", - "school_satchel": "🎒", - "scorpius": "â™", - "see_no_evil": "🙈", - "sheep": "ðŸ‘", - "stars": "🌠", - "cake": "ðŸ°", - "six_pointed_star": "🔯", - "ski": "🎿", - "sleeping_accommodation": "🛌", - "sleeping": "😴", - "sleepy": "😪", - "sleuth_or_spy": "🕵", - "heart_eyes_cat": "😻", - "smiley_cat": "😺", - "innocent": "😇", - "heart_eyes": "ðŸ˜", - "smiling_imp": "😈", - "smiley": "😃", - "sweat_smile": "😅", - "smile": "😄", - "laughing": "😆", - "satisfied": "😆", - "blush": "😊", - "smirk": "ðŸ˜", - "smoking": "🚬", - "snow_capped_mountain": "ðŸ”", - "soccer": "âš½", - "icecream": "ðŸ¦", - "soon": "🔜", - "arrow_lower_right": "↘", - "arrow_lower_left": "↙", - "speak_no_evil": "🙊", - "speaker": "🔈", - "mute": "🔇", - "sound": "🔉", - "loud_sound": "🔊", - "speaking_head_in_silhouette": "🗣", - "spiral_calendar_pad": "🗓", - "spiral_note_pad": "🗒", - "shell": "ðŸš", - "sweat_drops": "💦", - "u5272": "🈹", - "u5408": "🈴", - "u55b6": "🈺", - "u6307": "🈯", - "u6708": "🈷", - "u6709": "🈶", - "u6e80": "🈵", - "u7121": "🈚", - "u7533": "🈸", - "u7981": "🈲", - "u7a7a": "🈳", - "cl": "🆑", - "cool": "🆒", - "free": "🆓", - "id": "🆔", - "koko": "ðŸˆ", - "sa": "🈂", - "new": "🆕", - "ng": "🆖", - "ok": "🆗", - "sos": "🆘", - "up": "🆙", - "vs": "🆚", - "steam_locomotive": "🚂", - "ramen": "ðŸœ", - "partly_sunny": "â›…", - "city_sunrise": "🌇", - "surfer": "ðŸ„", - "swimmer": "ðŸŠ", - "shirt": "👕", - "tshirt": "👕", - "table_tennis_paddle_and_ball": "ðŸ“", - "tea": "ðŸµ", - "tv": "📺", - "three_button_mouse": "🖱", - "+1": "ðŸ‘", - "thumbsup": "ðŸ‘", - "__1": "👎", - "-1": "👎", - "thumbsdown": "👎", - "thunder_cloud_and_rain": "⛈", - "tiger2": "ðŸ…", - "tophat": "🎩", - "top": "ðŸ”", - "tm": "â„¢", - "train2": "🚆", - "triangular_flag_on_post": "🚩", - "trident": "🔱", - "twisted_rightwards_arrows": "🔀", - "unamused": "😒", - "small_red_triangle": "🔺", - "arrow_up_small": "🔼", - "arrow_up_down": "↕", - "upside__down_face": "🙃", - "arrow_up": "⬆", - "v": "✌", - "vhs": "📼", - "wc": "🚾", - "ocean": "🌊", - "waving_black_flag": "ðŸ´", - "wave": "👋", - "waving_white_flag": "ðŸ³", - "moon": "🌔", - "scream_cat": "🙀", - "weary": "😩", - "weight_lifter": "ðŸ‹", - "whale2": "ðŸ‹", - "wheelchair": "♿", - "point_down": "👇", - "grey_exclamation": "â•", - "white_frowning_face": "☹", - "white_check_mark": "✅", - "point_left": "👈", - "white_medium_small_square": "â—½", - "star": "â­", - "grey_question": "â”", - "point_right": "👉", - "relaxed": "☺", - "white_sun_behind_cloud": "🌥", - "white_sun_behind_cloud_with_rain": "🌦", - "white_sun_with_small_cloud": "🌤", - "point_up_2": "👆", - "point_up": "â˜", - "wind_blowing_face": "🌬", - "wink": "😉", - "wolf": "ðŸº", - "dancers": "👯", - "boot": "👢", - "womans_clothes": "👚", - "womans_hat": "👒", - "sandal": "👡", - "womens": "🚺", - "worried": "😟", - "gift": "ðŸŽ", - "zipper__mouth_face": "ðŸ¤", - "regional_indicator_a": "🇦", - "regional_indicator_b": "🇧", - "regional_indicator_c": "🇨", - "regional_indicator_d": "🇩", - "regional_indicator_e": "🇪", - "regional_indicator_f": "🇫", - "regional_indicator_g": "🇬", - "regional_indicator_h": "🇭", - "regional_indicator_i": "🇮", - "regional_indicator_j": "🇯", - "regional_indicator_k": "🇰", - "regional_indicator_l": "🇱", - "regional_indicator_m": "🇲", - "regional_indicator_n": "🇳", - "regional_indicator_o": "🇴", - "regional_indicator_p": "🇵", - "regional_indicator_q": "🇶", - "regional_indicator_r": "🇷", - "regional_indicator_s": "🇸", - "regional_indicator_t": "🇹", - "regional_indicator_u": "🇺", - "regional_indicator_v": "🇻", - "regional_indicator_w": "🇼", - "regional_indicator_x": "🇽", - "regional_indicator_y": "🇾", - "regional_indicator_z": "🇿", -} diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py deleted file mode 100644 index bb2cafa..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Callable, Match, Optional -import re - -from ._emoji_codes import EMOJI - - -_ReStringMatch = Match[str] # regex match object -_ReSubCallable = Callable[[_ReStringMatch], str] # Callable invoked by re.sub -_EmojiSubMethod = Callable[[_ReSubCallable, str], str] # Sub method of a compiled re - - -def _emoji_replace( - text: str, - default_variant: Optional[str] = None, - _emoji_sub: _EmojiSubMethod = re.compile(r"(:(\S*?)(?:(?:\-)(emoji|text))?:)").sub, -) -> str: - """Replace emoji code in text.""" - get_emoji = EMOJI.__getitem__ - variants = {"text": "\uFE0E", "emoji": "\uFE0F"} - get_variant = variants.get - default_variant_code = variants.get(default_variant, "") if default_variant else "" - - def do_replace(match: Match[str]) -> str: - emoji_code, emoji_name, variant = match.groups() - try: - return get_emoji(emoji_name.lower()) + get_variant( - variant, default_variant_code - ) - except KeyError: - return emoji_code - - return _emoji_sub(do_replace, text) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py deleted file mode 100644 index 094d2dc..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py +++ /dev/null @@ -1,76 +0,0 @@ -CONSOLE_HTML_FORMAT = """\ - - - - - - - -
{code}
- - -""" - -CONSOLE_SVG_FORMAT = """\ - - - - - - - - - {lines} - - - {chrome} - - {backgrounds} - - {matrix} - - - -""" - -_SVG_FONT_FAMILY = "Rich Fira Code" -_SVG_CLASSES_PREFIX = "rich-svg" diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py deleted file mode 100644 index cbd6da9..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Any - - -def load_ipython_extension(ip: Any) -> None: # pragma: no cover - # prevent circular import - from pip._vendor.rich.pretty import install - from pip._vendor.rich.traceback import install as tr_install - - install() - tr_install() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py deleted file mode 100644 index b17ee65..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import annotations - -from typing import IO, Callable - - -def get_fileno(file_like: IO[str]) -> int | None: - """Get fileno() from a file, accounting for poorly implemented file-like objects. - - Args: - file_like (IO): A file-like object. - - Returns: - int | None: The result of fileno if available, or None if operation failed. - """ - fileno: Callable[[], int] | None = getattr(file_like, "fileno", None) - if fileno is not None: - try: - return fileno() - except Exception: - # `fileno` is documented as potentially raising a OSError - # Alas, from the issues, there are so many poorly implemented file-like objects, - # that `fileno()` can raise just about anything. - return None - return None diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py deleted file mode 100644 index 30446ce..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py +++ /dev/null @@ -1,270 +0,0 @@ -from __future__ import absolute_import - -import inspect -from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature -from typing import Any, Collection, Iterable, Optional, Tuple, Type, Union - -from .console import Group, RenderableType -from .control import escape_control_codes -from .highlighter import ReprHighlighter -from .jupyter import JupyterMixin -from .panel import Panel -from .pretty import Pretty -from .table import Table -from .text import Text, TextType - - -def _first_paragraph(doc: str) -> str: - """Get the first paragraph from a docstring.""" - paragraph, _, _ = doc.partition("\n\n") - return paragraph - - -class Inspect(JupyterMixin): - """A renderable to inspect any Python Object. - - Args: - obj (Any): An object to inspect. - title (str, optional): Title to display over inspect result, or None use type. Defaults to None. - help (bool, optional): Show full help text rather than just first paragraph. Defaults to False. - methods (bool, optional): Enable inspection of callables. Defaults to False. - docs (bool, optional): Also render doc strings. Defaults to True. - private (bool, optional): Show private attributes (beginning with underscore). Defaults to False. - dunder (bool, optional): Show attributes starting with double underscore. Defaults to False. - sort (bool, optional): Sort attributes alphabetically. Defaults to True. - all (bool, optional): Show all attributes. Defaults to False. - value (bool, optional): Pretty print value of object. Defaults to True. - """ - - def __init__( - self, - obj: Any, - *, - title: Optional[TextType] = None, - help: bool = False, - methods: bool = False, - docs: bool = True, - private: bool = False, - dunder: bool = False, - sort: bool = True, - all: bool = True, - value: bool = True, - ) -> None: - self.highlighter = ReprHighlighter() - self.obj = obj - self.title = title or self._make_title(obj) - if all: - methods = private = dunder = True - self.help = help - self.methods = methods - self.docs = docs or help - self.private = private or dunder - self.dunder = dunder - self.sort = sort - self.value = value - - def _make_title(self, obj: Any) -> Text: - """Make a default title.""" - title_str = ( - str(obj) - if (isclass(obj) or callable(obj) or ismodule(obj)) - else str(type(obj)) - ) - title_text = self.highlighter(title_str) - return title_text - - def __rich__(self) -> Panel: - return Panel.fit( - Group(*self._render()), - title=self.title, - border_style="scope.border", - padding=(0, 1), - ) - - def _get_signature(self, name: str, obj: Any) -> Optional[Text]: - """Get a signature for a callable.""" - try: - _signature = str(signature(obj)) + ":" - except ValueError: - _signature = "(...)" - except TypeError: - return None - - source_filename: Optional[str] = None - try: - source_filename = getfile(obj) - except (OSError, TypeError): - # OSError is raised if obj has no source file, e.g. when defined in REPL. - pass - - callable_name = Text(name, style="inspect.callable") - if source_filename: - callable_name.stylize(f"link file://{source_filename}") - signature_text = self.highlighter(_signature) - - qualname = name or getattr(obj, "__qualname__", name) - - # If obj is a module, there may be classes (which are callable) to display - if inspect.isclass(obj): - prefix = "class" - elif inspect.iscoroutinefunction(obj): - prefix = "async def" - else: - prefix = "def" - - qual_signature = Text.assemble( - (f"{prefix} ", f"inspect.{prefix.replace(' ', '_')}"), - (qualname, "inspect.callable"), - signature_text, - ) - - return qual_signature - - def _render(self) -> Iterable[RenderableType]: - """Render object.""" - - def sort_items(item: Tuple[str, Any]) -> Tuple[bool, str]: - key, (_error, value) = item - return (callable(value), key.strip("_").lower()) - - def safe_getattr(attr_name: str) -> Tuple[Any, Any]: - """Get attribute or any exception.""" - try: - return (None, getattr(obj, attr_name)) - except Exception as error: - return (error, None) - - obj = self.obj - keys = dir(obj) - total_items = len(keys) - if not self.dunder: - keys = [key for key in keys if not key.startswith("__")] - if not self.private: - keys = [key for key in keys if not key.startswith("_")] - not_shown_count = total_items - len(keys) - items = [(key, safe_getattr(key)) for key in keys] - if self.sort: - items.sort(key=sort_items) - - items_table = Table.grid(padding=(0, 1), expand=False) - items_table.add_column(justify="right") - add_row = items_table.add_row - highlighter = self.highlighter - - if callable(obj): - signature = self._get_signature("", obj) - if signature is not None: - yield signature - yield "" - - if self.docs: - _doc = self._get_formatted_doc(obj) - if _doc is not None: - doc_text = Text(_doc, style="inspect.help") - doc_text = highlighter(doc_text) - yield doc_text - yield "" - - if self.value and not (isclass(obj) or callable(obj) or ismodule(obj)): - yield Panel( - Pretty(obj, indent_guides=True, max_length=10, max_string=60), - border_style="inspect.value.border", - ) - yield "" - - for key, (error, value) in items: - key_text = Text.assemble( - ( - key, - "inspect.attr.dunder" if key.startswith("__") else "inspect.attr", - ), - (" =", "inspect.equals"), - ) - if error is not None: - warning = key_text.copy() - warning.stylize("inspect.error") - add_row(warning, highlighter(repr(error))) - continue - - if callable(value): - if not self.methods: - continue - - _signature_text = self._get_signature(key, value) - if _signature_text is None: - add_row(key_text, Pretty(value, highlighter=highlighter)) - else: - if self.docs: - docs = self._get_formatted_doc(value) - if docs is not None: - _signature_text.append("\n" if "\n" in docs else " ") - doc = highlighter(docs) - doc.stylize("inspect.doc") - _signature_text.append(doc) - - add_row(key_text, _signature_text) - else: - add_row(key_text, Pretty(value, highlighter=highlighter)) - if items_table.row_count: - yield items_table - elif not_shown_count: - yield Text.from_markup( - f"[b cyan]{not_shown_count}[/][i] attribute(s) not shown.[/i] " - f"Run [b][magenta]inspect[/]([not b]inspect[/])[/b] for options." - ) - - def _get_formatted_doc(self, object_: Any) -> Optional[str]: - """ - Extract the docstring of an object, process it and returns it. - The processing consists in cleaning up the doctring's indentation, - taking only its 1st paragraph if `self.help` is not True, - and escape its control codes. - - Args: - object_ (Any): the object to get the docstring from. - - Returns: - Optional[str]: the processed docstring, or None if no docstring was found. - """ - docs = getdoc(object_) - if docs is None: - return None - docs = cleandoc(docs).strip() - if not self.help: - docs = _first_paragraph(docs) - return escape_control_codes(docs) - - -def get_object_types_mro(obj: Union[object, Type[Any]]) -> Tuple[type, ...]: - """Returns the MRO of an object's class, or of the object itself if it's a class.""" - if not hasattr(obj, "__mro__"): - # N.B. we cannot use `if type(obj) is type` here because it doesn't work with - # some types of classes, such as the ones that use abc.ABCMeta. - obj = type(obj) - return getattr(obj, "__mro__", ()) - - -def get_object_types_mro_as_strings(obj: object) -> Collection[str]: - """ - Returns the MRO of an object's class as full qualified names, or of the object itself if it's a class. - - Examples: - `object_types_mro_as_strings(JSONDecoder)` will return `['json.decoder.JSONDecoder', 'builtins.object']` - """ - return [ - f'{getattr(type_, "__module__", "")}.{getattr(type_, "__qualname__", "")}' - for type_ in get_object_types_mro(obj) - ] - - -def is_object_one_of_types( - obj: object, fully_qualified_types_names: Collection[str] -) -> bool: - """ - Returns `True` if the given object's class (or the object itself, if it's a class) has one of the - fully qualified names in its MRO. - """ - for type_name in get_object_types_mro_as_strings(obj): - if type_name in fully_qualified_types_names: - return True - return False diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py deleted file mode 100644 index fc16c84..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py +++ /dev/null @@ -1,94 +0,0 @@ -from datetime import datetime -from typing import Iterable, List, Optional, TYPE_CHECKING, Union, Callable - - -from .text import Text, TextType - -if TYPE_CHECKING: - from .console import Console, ConsoleRenderable, RenderableType - from .table import Table - -FormatTimeCallable = Callable[[datetime], Text] - - -class LogRender: - def __init__( - self, - show_time: bool = True, - show_level: bool = False, - show_path: bool = True, - time_format: Union[str, FormatTimeCallable] = "[%x %X]", - omit_repeated_times: bool = True, - level_width: Optional[int] = 8, - ) -> None: - self.show_time = show_time - self.show_level = show_level - self.show_path = show_path - self.time_format = time_format - self.omit_repeated_times = omit_repeated_times - self.level_width = level_width - self._last_time: Optional[Text] = None - - def __call__( - self, - console: "Console", - renderables: Iterable["ConsoleRenderable"], - log_time: Optional[datetime] = None, - time_format: Optional[Union[str, FormatTimeCallable]] = None, - level: TextType = "", - path: Optional[str] = None, - line_no: Optional[int] = None, - link_path: Optional[str] = None, - ) -> "Table": - from .containers import Renderables - from .table import Table - - output = Table.grid(padding=(0, 1)) - output.expand = True - if self.show_time: - output.add_column(style="log.time") - if self.show_level: - output.add_column(style="log.level", width=self.level_width) - output.add_column(ratio=1, style="log.message", overflow="fold") - if self.show_path and path: - output.add_column(style="log.path") - row: List["RenderableType"] = [] - if self.show_time: - log_time = log_time or console.get_datetime() - time_format = time_format or self.time_format - if callable(time_format): - log_time_display = time_format(log_time) - else: - log_time_display = Text(log_time.strftime(time_format)) - if log_time_display == self._last_time and self.omit_repeated_times: - row.append(Text(" " * len(log_time_display))) - else: - row.append(log_time_display) - self._last_time = log_time_display - if self.show_level: - row.append(level) - - row.append(Renderables(renderables)) - if self.show_path and path: - path_text = Text() - path_text.append( - path, style=f"link file://{link_path}" if link_path else "" - ) - if line_no: - path_text.append(":") - path_text.append( - f"{line_no}", - style=f"link file://{link_path}#{line_no}" if link_path else "", - ) - row.append(path_text) - - output.add_row(*row) - return output - - -if __name__ == "__main__": # pragma: no cover - from pip._vendor.rich.console import Console - - c = Console() - c.print("[on blue]Hello", justify="right") - c.log("[on blue]hello", justify="right") diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py deleted file mode 100644 index 01c6caf..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py +++ /dev/null @@ -1,43 +0,0 @@ -from typing import Iterable, Tuple, TypeVar - -T = TypeVar("T") - - -def loop_first(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: - """Iterate and generate a tuple with a flag for first value.""" - iter_values = iter(values) - try: - value = next(iter_values) - except StopIteration: - return - yield True, value - for value in iter_values: - yield False, value - - -def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: - """Iterate and generate a tuple with a flag for last value.""" - iter_values = iter(values) - try: - previous_value = next(iter_values) - except StopIteration: - return - for value in iter_values: - yield False, previous_value - previous_value = value - yield True, previous_value - - -def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: - """Iterate and generate a tuple with a flag for first and last value.""" - iter_values = iter(values) - try: - previous_value = next(iter_values) - except StopIteration: - return - first = True - for value in iter_values: - yield first, False, previous_value - first = False - previous_value = value - yield first, True, previous_value diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py deleted file mode 100644 index b659673..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py +++ /dev/null @@ -1,69 +0,0 @@ -from types import TracebackType -from typing import IO, Iterable, Iterator, List, Optional, Type - - -class NullFile(IO[str]): - def close(self) -> None: - pass - - def isatty(self) -> bool: - return False - - def read(self, __n: int = 1) -> str: - return "" - - def readable(self) -> bool: - return False - - def readline(self, __limit: int = 1) -> str: - return "" - - def readlines(self, __hint: int = 1) -> List[str]: - return [] - - def seek(self, __offset: int, __whence: int = 1) -> int: - return 0 - - def seekable(self) -> bool: - return False - - def tell(self) -> int: - return 0 - - def truncate(self, __size: Optional[int] = 1) -> int: - return 0 - - def writable(self) -> bool: - return False - - def writelines(self, __lines: Iterable[str]) -> None: - pass - - def __next__(self) -> str: - return "" - - def __iter__(self) -> Iterator[str]: - return iter([""]) - - def __enter__(self) -> IO[str]: - pass - - def __exit__( - self, - __t: Optional[Type[BaseException]], - __value: Optional[BaseException], - __traceback: Optional[TracebackType], - ) -> None: - pass - - def write(self, text: str) -> int: - return 0 - - def flush(self) -> None: - pass - - def fileno(self) -> int: - return -1 - - -NULL_FILE = NullFile() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py deleted file mode 100644 index 3c748d3..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py +++ /dev/null @@ -1,309 +0,0 @@ -from .palette import Palette - - -# Taken from https://en.wikipedia.org/wiki/ANSI_escape_code (Windows 10 column) -WINDOWS_PALETTE = Palette( - [ - (12, 12, 12), - (197, 15, 31), - (19, 161, 14), - (193, 156, 0), - (0, 55, 218), - (136, 23, 152), - (58, 150, 221), - (204, 204, 204), - (118, 118, 118), - (231, 72, 86), - (22, 198, 12), - (249, 241, 165), - (59, 120, 255), - (180, 0, 158), - (97, 214, 214), - (242, 242, 242), - ] -) - -# # The standard ansi colors (including bright variants) -STANDARD_PALETTE = Palette( - [ - (0, 0, 0), - (170, 0, 0), - (0, 170, 0), - (170, 85, 0), - (0, 0, 170), - (170, 0, 170), - (0, 170, 170), - (170, 170, 170), - (85, 85, 85), - (255, 85, 85), - (85, 255, 85), - (255, 255, 85), - (85, 85, 255), - (255, 85, 255), - (85, 255, 255), - (255, 255, 255), - ] -) - - -# The 256 color palette -EIGHT_BIT_PALETTE = Palette( - [ - (0, 0, 0), - (128, 0, 0), - (0, 128, 0), - (128, 128, 0), - (0, 0, 128), - (128, 0, 128), - (0, 128, 128), - (192, 192, 192), - (128, 128, 128), - (255, 0, 0), - (0, 255, 0), - (255, 255, 0), - (0, 0, 255), - (255, 0, 255), - (0, 255, 255), - (255, 255, 255), - (0, 0, 0), - (0, 0, 95), - (0, 0, 135), - (0, 0, 175), - (0, 0, 215), - (0, 0, 255), - (0, 95, 0), - (0, 95, 95), - (0, 95, 135), - (0, 95, 175), - (0, 95, 215), - (0, 95, 255), - (0, 135, 0), - (0, 135, 95), - (0, 135, 135), - (0, 135, 175), - (0, 135, 215), - (0, 135, 255), - (0, 175, 0), - (0, 175, 95), - (0, 175, 135), - (0, 175, 175), - (0, 175, 215), - (0, 175, 255), - (0, 215, 0), - (0, 215, 95), - (0, 215, 135), - (0, 215, 175), - (0, 215, 215), - (0, 215, 255), - (0, 255, 0), - (0, 255, 95), - (0, 255, 135), - (0, 255, 175), - (0, 255, 215), - (0, 255, 255), - (95, 0, 0), - (95, 0, 95), - (95, 0, 135), - (95, 0, 175), - (95, 0, 215), - (95, 0, 255), - (95, 95, 0), - (95, 95, 95), - (95, 95, 135), - (95, 95, 175), - (95, 95, 215), - (95, 95, 255), - (95, 135, 0), - (95, 135, 95), - (95, 135, 135), - (95, 135, 175), - (95, 135, 215), - (95, 135, 255), - (95, 175, 0), - (95, 175, 95), - (95, 175, 135), - (95, 175, 175), - (95, 175, 215), - (95, 175, 255), - (95, 215, 0), - (95, 215, 95), - (95, 215, 135), - (95, 215, 175), - (95, 215, 215), - (95, 215, 255), - (95, 255, 0), - (95, 255, 95), - (95, 255, 135), - (95, 255, 175), - (95, 255, 215), - (95, 255, 255), - (135, 0, 0), - (135, 0, 95), - (135, 0, 135), - (135, 0, 175), - (135, 0, 215), - (135, 0, 255), - (135, 95, 0), - (135, 95, 95), - (135, 95, 135), - (135, 95, 175), - (135, 95, 215), - (135, 95, 255), - (135, 135, 0), - (135, 135, 95), - (135, 135, 135), - (135, 135, 175), - (135, 135, 215), - (135, 135, 255), - (135, 175, 0), - (135, 175, 95), - (135, 175, 135), - (135, 175, 175), - (135, 175, 215), - (135, 175, 255), - (135, 215, 0), - (135, 215, 95), - (135, 215, 135), - (135, 215, 175), - (135, 215, 215), - (135, 215, 255), - (135, 255, 0), - (135, 255, 95), - (135, 255, 135), - (135, 255, 175), - (135, 255, 215), - (135, 255, 255), - (175, 0, 0), - (175, 0, 95), - (175, 0, 135), - (175, 0, 175), - (175, 0, 215), - (175, 0, 255), - (175, 95, 0), - (175, 95, 95), - (175, 95, 135), - (175, 95, 175), - (175, 95, 215), - (175, 95, 255), - (175, 135, 0), - (175, 135, 95), - (175, 135, 135), - (175, 135, 175), - (175, 135, 215), - (175, 135, 255), - (175, 175, 0), - (175, 175, 95), - (175, 175, 135), - (175, 175, 175), - (175, 175, 215), - (175, 175, 255), - (175, 215, 0), - (175, 215, 95), - (175, 215, 135), - (175, 215, 175), - (175, 215, 215), - (175, 215, 255), - (175, 255, 0), - (175, 255, 95), - (175, 255, 135), - (175, 255, 175), - (175, 255, 215), - (175, 255, 255), - (215, 0, 0), - (215, 0, 95), - (215, 0, 135), - (215, 0, 175), - (215, 0, 215), - (215, 0, 255), - (215, 95, 0), - (215, 95, 95), - (215, 95, 135), - (215, 95, 175), - (215, 95, 215), - (215, 95, 255), - (215, 135, 0), - (215, 135, 95), - (215, 135, 135), - (215, 135, 175), - (215, 135, 215), - (215, 135, 255), - (215, 175, 0), - (215, 175, 95), - (215, 175, 135), - (215, 175, 175), - (215, 175, 215), - (215, 175, 255), - (215, 215, 0), - (215, 215, 95), - (215, 215, 135), - (215, 215, 175), - (215, 215, 215), - (215, 215, 255), - (215, 255, 0), - (215, 255, 95), - (215, 255, 135), - (215, 255, 175), - (215, 255, 215), - (215, 255, 255), - (255, 0, 0), - (255, 0, 95), - (255, 0, 135), - (255, 0, 175), - (255, 0, 215), - (255, 0, 255), - (255, 95, 0), - (255, 95, 95), - (255, 95, 135), - (255, 95, 175), - (255, 95, 215), - (255, 95, 255), - (255, 135, 0), - (255, 135, 95), - (255, 135, 135), - (255, 135, 175), - (255, 135, 215), - (255, 135, 255), - (255, 175, 0), - (255, 175, 95), - (255, 175, 135), - (255, 175, 175), - (255, 175, 215), - (255, 175, 255), - (255, 215, 0), - (255, 215, 95), - (255, 215, 135), - (255, 215, 175), - (255, 215, 215), - (255, 215, 255), - (255, 255, 0), - (255, 255, 95), - (255, 255, 135), - (255, 255, 175), - (255, 255, 215), - (255, 255, 255), - (8, 8, 8), - (18, 18, 18), - (28, 28, 28), - (38, 38, 38), - (48, 48, 48), - (58, 58, 58), - (68, 68, 68), - (78, 78, 78), - (88, 88, 88), - (98, 98, 98), - (108, 108, 108), - (118, 118, 118), - (128, 128, 128), - (138, 138, 138), - (148, 148, 148), - (158, 158, 158), - (168, 168, 168), - (178, 178, 178), - (188, 188, 188), - (198, 198, 198), - (208, 208, 208), - (218, 218, 218), - (228, 228, 228), - (238, 238, 238), - ] -) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py deleted file mode 100644 index 4f6d8b2..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Optional - - -def pick_bool(*values: Optional[bool]) -> bool: - """Pick the first non-none bool or return the last value. - - Args: - *values (bool): Any number of boolean or None values. - - Returns: - bool: First non-none boolean. - """ - assert values, "1 or more values required" - for value in values: - if value is not None: - return value - return bool(value) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py deleted file mode 100644 index e8a3a67..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py +++ /dev/null @@ -1,160 +0,0 @@ -import sys -from fractions import Fraction -from math import ceil -from typing import cast, List, Optional, Sequence - -if sys.version_info >= (3, 8): - from typing import Protocol -else: - from pip._vendor.typing_extensions import Protocol # pragma: no cover - - -class Edge(Protocol): - """Any object that defines an edge (such as Layout).""" - - size: Optional[int] = None - ratio: int = 1 - minimum_size: int = 1 - - -def ratio_resolve(total: int, edges: Sequence[Edge]) -> List[int]: - """Divide total space to satisfy size, ratio, and minimum_size, constraints. - - The returned list of integers should add up to total in most cases, unless it is - impossible to satisfy all the constraints. For instance, if there are two edges - with a minimum size of 20 each and `total` is 30 then the returned list will be - greater than total. In practice, this would mean that a Layout object would - clip the rows that would overflow the screen height. - - Args: - total (int): Total number of characters. - edges (List[Edge]): Edges within total space. - - Returns: - List[int]: Number of characters for each edge. - """ - # Size of edge or None for yet to be determined - sizes = [(edge.size or None) for edge in edges] - - _Fraction = Fraction - - # While any edges haven't been calculated - while None in sizes: - # Get flexible edges and index to map these back on to sizes list - flexible_edges = [ - (index, edge) - for index, (size, edge) in enumerate(zip(sizes, edges)) - if size is None - ] - # Remaining space in total - remaining = total - sum(size or 0 for size in sizes) - if remaining <= 0: - # No room for flexible edges - return [ - ((edge.minimum_size or 1) if size is None else size) - for size, edge in zip(sizes, edges) - ] - # Calculate number of characters in a ratio portion - portion = _Fraction( - remaining, sum((edge.ratio or 1) for _, edge in flexible_edges) - ) - - # If any edges will be less than their minimum, replace size with the minimum - for index, edge in flexible_edges: - if portion * edge.ratio <= edge.minimum_size: - sizes[index] = edge.minimum_size - # New fixed size will invalidate calculations, so we need to repeat the process - break - else: - # Distribute flexible space and compensate for rounding error - # Since edge sizes can only be integers we need to add the remainder - # to the following line - remainder = _Fraction(0) - for index, edge in flexible_edges: - size, remainder = divmod(portion * edge.ratio + remainder, 1) - sizes[index] = size - break - # Sizes now contains integers only - return cast(List[int], sizes) - - -def ratio_reduce( - total: int, ratios: List[int], maximums: List[int], values: List[int] -) -> List[int]: - """Divide an integer total in to parts based on ratios. - - Args: - total (int): The total to divide. - ratios (List[int]): A list of integer ratios. - maximums (List[int]): List of maximums values for each slot. - values (List[int]): List of values - - Returns: - List[int]: A list of integers guaranteed to sum to total. - """ - ratios = [ratio if _max else 0 for ratio, _max in zip(ratios, maximums)] - total_ratio = sum(ratios) - if not total_ratio: - return values[:] - total_remaining = total - result: List[int] = [] - append = result.append - for ratio, maximum, value in zip(ratios, maximums, values): - if ratio and total_ratio > 0: - distributed = min(maximum, round(ratio * total_remaining / total_ratio)) - append(value - distributed) - total_remaining -= distributed - total_ratio -= ratio - else: - append(value) - return result - - -def ratio_distribute( - total: int, ratios: List[int], minimums: Optional[List[int]] = None -) -> List[int]: - """Distribute an integer total in to parts based on ratios. - - Args: - total (int): The total to divide. - ratios (List[int]): A list of integer ratios. - minimums (List[int]): List of minimum values for each slot. - - Returns: - List[int]: A list of integers guaranteed to sum to total. - """ - if minimums: - ratios = [ratio if _min else 0 for ratio, _min in zip(ratios, minimums)] - total_ratio = sum(ratios) - assert total_ratio > 0, "Sum of ratios must be > 0" - - total_remaining = total - distributed_total: List[int] = [] - append = distributed_total.append - if minimums is None: - _minimums = [0] * len(ratios) - else: - _minimums = minimums - for ratio, minimum in zip(ratios, _minimums): - if total_ratio > 0: - distributed = max(minimum, ceil(ratio * total_remaining / total_ratio)) - else: - distributed = total_remaining - append(distributed) - total_ratio -= ratio - total_remaining -= distributed - return distributed_total - - -if __name__ == "__main__": - from dataclasses import dataclass - - @dataclass - class E: - - size: Optional[int] = None - ratio: int = 1 - minimum_size: int = 1 - - resolved = ratio_resolve(110, [E(None, 1, 1), E(None, 1, 1), E(None, 1, 1)]) - print(sum(resolved)) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py deleted file mode 100644 index d0bb1fe..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py +++ /dev/null @@ -1,482 +0,0 @@ -""" -Spinners are from: -* cli-spinners: - MIT License - Copyright (c) Sindre Sorhus (sindresorhus.com) - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. -""" - -SPINNERS = { - "dots": { - "interval": 80, - "frames": "⠋⠙⠹⠸⠼⠴⠦⠧⠇â ", - }, - "dots2": {"interval": 80, "frames": "⣾⣽⣻⢿⡿⣟⣯⣷"}, - "dots3": { - "interval": 80, - "frames": "⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓", - }, - "dots4": { - "interval": 80, - "frames": "⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆", - }, - "dots5": { - "interval": 80, - "frames": "⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒â â â ’â “â ‹", - }, - "dots6": { - "interval": 80, - "frames": "â â ‰â ™â šâ ’⠂⠂⠒⠲⠴⠤⠄⠄⠤⠴⠲⠒⠂⠂⠒⠚⠙⠉â ", - }, - "dots7": { - "interval": 80, - "frames": "⠈⠉⠋⠓⠒â â â ’⠖⠦⠤⠠⠠⠤⠦⠖⠒â â â ’⠓⠋⠉⠈", - }, - "dots8": { - "interval": 80, - "frames": "â â â ‰â ™â šâ ’⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒â â â ’⠓⠋⠉⠈⠈", - }, - "dots9": {"interval": 80, "frames": "⢹⢺⢼⣸⣇⡧⡗â¡"}, - "dots10": {"interval": 80, "frames": "⢄⢂â¢â¡â¡ˆâ¡â¡ "}, - "dots11": {"interval": 100, "frames": "â â ‚⠄⡀⢀⠠â â ˆ"}, - "dots12": { - "interval": 80, - "frames": [ - "⢀⠀", - "⡀⠀", - "â „â €", - "⢂⠀", - "â¡‚â €", - "â …â €", - "⢃⠀", - "⡃⠀", - "â â €", - "⢋⠀", - "â¡‹â €", - "â â ", - "⢋â ", - "â¡‹â ", - "â â ‰", - "â ‹â ‰", - "â ‹â ‰", - "⠉⠙", - "⠉⠙", - "⠉⠩", - "⠈⢙", - "⠈⡙", - "⢈⠩", - "⡀⢙", - "â „â¡™", - "⢂⠩", - "⡂⢘", - "⠅⡘", - "⢃⠨", - "⡃â¢", - "â â¡", - "⢋⠠", - "⡋⢀", - "â â¡", - "⢋â ", - "â¡‹â ", - "â â ‰", - "â ‹â ‰", - "â ‹â ‰", - "⠉⠙", - "⠉⠙", - "⠉⠩", - "⠈⢙", - "⠈⡙", - "⠈⠩", - "⠀⢙", - "⠀⡙", - "⠀⠩", - "⠀⢘", - "⠀⡘", - "⠀⠨", - "â €â¢", - "â €â¡", - "⠀⠠", - "⠀⢀", - "⠀⡀", - ], - }, - "dots8Bit": { - "interval": 80, - "frames": "â €â â ‚⠃⠄⠅⠆⠇⡀â¡â¡‚⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌â â Žâ â¡ˆâ¡‰â¡Šâ¡‹â¡Œâ¡â¡Žâ¡â â ‘⠒⠓⠔⠕⠖⠗â¡â¡‘⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜â â žâ Ÿâ¡˜â¡™" - "⡚⡛⡜â¡â¡žâ¡Ÿâ  â ¡â ¢â £â ¤â ¥â ¦â §â¡ â¡¡â¡¢â¡£â¡¤â¡¥â¡¦â¡§â ¨â ©â ªâ «â ¬â ­â ®â ¯â¡¨â¡©â¡ªâ¡«â¡¬â¡­â¡®â¡¯â °â ±â ²â ³â ´â µâ ¶â ·â¡°â¡±â¡²â¡³â¡´â¡µâ¡¶â¡·â ¸â ¹â ºâ »" - "⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿⢀â¢â¢‚⢃⢄⢅⢆⢇⣀â£â£‚⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌â¢â¢Žâ¢â£ˆâ£‰â£Šâ£‹â£Œâ£â£Žâ£â¢â¢‘⢒⢓⢔⢕⢖⢗â£â£‘⣒⣓⣔⣕" - "⣖⣗⢘⢙⢚⢛⢜â¢â¢žâ¢Ÿâ£˜â£™â£šâ£›â£œâ£â£žâ£Ÿâ¢ â¢¡â¢¢â¢£â¢¤â¢¥â¢¦â¢§â£ â£¡â£¢â££â£¤â£¥â£¦â£§â¢¨â¢©â¢ªâ¢«â¢¬â¢­â¢®â¢¯â£¨â£©â£ªâ£«â£¬â£­â£®â£¯â¢°â¢±â¢²â¢³â¢´â¢µâ¢¶â¢·" - "⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿", - }, - "line": {"interval": 130, "frames": ["-", "\\", "|", "/"]}, - "line2": {"interval": 100, "frames": "â ‚-–—–-"}, - "pipe": {"interval": 100, "frames": "┤┘┴└├┌┬â”"}, - "simpleDots": {"interval": 400, "frames": [". ", ".. ", "...", " "]}, - "simpleDotsScrolling": { - "interval": 200, - "frames": [". ", ".. ", "...", " ..", " .", " "], - }, - "star": {"interval": 70, "frames": "✶✸✹✺✹✷"}, - "star2": {"interval": 80, "frames": "+x*"}, - "flip": { - "interval": 70, - "frames": "___-``'´-___", - }, - "hamburger": {"interval": 100, "frames": "☱☲☴"}, - "growVertical": { - "interval": 120, - "frames": "â–▃▄▅▆▇▆▅▄▃", - }, - "growHorizontal": { - "interval": 120, - "frames": "â–â–Žâ–▌▋▊▉▊▋▌â–â–Ž", - }, - "balloon": {"interval": 140, "frames": " .oO@* "}, - "balloon2": {"interval": 120, "frames": ".oO°Oo."}, - "noise": {"interval": 100, "frames": "â–“â–’â–‘"}, - "bounce": {"interval": 120, "frames": "â â ‚â „â ‚"}, - "boxBounce": {"interval": 120, "frames": "â––â–˜â–â–—"}, - "boxBounce2": {"interval": 100, "frames": "▌▀â–â–„"}, - "triangle": {"interval": 50, "frames": "◢◣◤◥"}, - "arc": {"interval": 100, "frames": "◜◠â—â—žâ—¡â—Ÿ"}, - "circle": {"interval": 120, "frames": "◡⊙◠"}, - "squareCorners": {"interval": 180, "frames": "◰◳◲◱"}, - "circleQuarters": {"interval": 120, "frames": "â—´â—·â—¶â—µ"}, - "circleHalves": {"interval": 50, "frames": "â—â—“â—‘â—’"}, - "squish": {"interval": 100, "frames": "╫╪"}, - "toggle": {"interval": 250, "frames": "⊶⊷"}, - "toggle2": {"interval": 80, "frames": "â–«â–ª"}, - "toggle3": {"interval": 120, "frames": "â–¡â– "}, - "toggle4": {"interval": 100, "frames": "■□▪▫"}, - "toggle5": {"interval": 100, "frames": "▮▯"}, - "toggle6": {"interval": 300, "frames": "á€á€"}, - "toggle7": {"interval": 80, "frames": "⦾⦿"}, - "toggle8": {"interval": 100, "frames": "â—â—Œ"}, - "toggle9": {"interval": 100, "frames": "◉◎"}, - "toggle10": {"interval": 100, "frames": "㊂㊀ãŠ"}, - "toggle11": {"interval": 50, "frames": "⧇⧆"}, - "toggle12": {"interval": 120, "frames": "☗☖"}, - "toggle13": {"interval": 80, "frames": "=*-"}, - "arrow": {"interval": 100, "frames": "â†â†–↑↗→↘↓↙"}, - "arrow2": { - "interval": 80, - "frames": ["â¬†ï¸ ", "â†—ï¸ ", "âž¡ï¸ ", "â†˜ï¸ ", "â¬‡ï¸ ", "â†™ï¸ ", "â¬…ï¸ ", "â†–ï¸ "], - }, - "arrow3": { - "interval": 120, - "frames": ["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸"], - }, - "bouncingBar": { - "interval": 80, - "frames": [ - "[ ]", - "[= ]", - "[== ]", - "[=== ]", - "[ ===]", - "[ ==]", - "[ =]", - "[ ]", - "[ =]", - "[ ==]", - "[ ===]", - "[====]", - "[=== ]", - "[== ]", - "[= ]", - ], - }, - "bouncingBall": { - "interval": 80, - "frames": [ - "( â— )", - "( â— )", - "( â— )", - "( â— )", - "( â—)", - "( â— )", - "( â— )", - "( â— )", - "( â— )", - "(â— )", - ], - }, - "smiley": {"interval": 200, "frames": ["😄 ", "😠"]}, - "monkey": {"interval": 300, "frames": ["🙈 ", "🙈 ", "🙉 ", "🙊 "]}, - "hearts": {"interval": 100, "frames": ["💛 ", "💙 ", "💜 ", "💚 ", "â¤ï¸ "]}, - "clock": { - "interval": 100, - "frames": [ - "🕛 ", - "🕠", - "🕑 ", - "🕒 ", - "🕓 ", - "🕔 ", - "🕕 ", - "🕖 ", - "🕗 ", - "🕘 ", - "🕙 ", - "🕚 ", - ], - }, - "earth": {"interval": 180, "frames": ["🌠", "🌎 ", "🌠"]}, - "material": { - "interval": 17, - "frames": [ - "â–ˆâ–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "██â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "███â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "████â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "██████â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "██████â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "███████â–â–â–â–â–â–â–â–â–â–â–â–â–", - "████████â–â–â–â–â–â–â–â–â–â–â–â–", - "█████████â–â–â–â–â–â–â–â–â–â–â–", - "█████████â–â–â–â–â–â–â–â–â–â–â–", - "██████████â–â–â–â–â–â–â–â–â–â–", - "███████████â–â–â–â–â–â–â–â–â–", - "█████████████â–â–â–â–â–â–â–", - "██████████████â–â–â–â–â–â–", - "██████████████â–â–â–â–â–â–", - "â–██████████████â–â–â–â–â–", - "â–██████████████â–â–â–â–â–", - "â–██████████████â–â–â–â–â–", - "â–â–██████████████â–â–â–â–", - "â–â–â–██████████████â–â–â–", - "â–â–â–â–█████████████â–â–â–", - "â–â–â–â–██████████████â–â–", - "â–â–â–â–██████████████â–â–", - "â–â–â–â–â–██████████████â–", - "â–â–â–â–â–██████████████â–", - "â–â–â–â–â–██████████████â–", - "â–â–â–â–â–â–██████████████", - "â–â–â–â–â–â–██████████████", - "â–â–â–â–â–â–â–█████████████", - "â–â–â–â–â–â–â–█████████████", - "â–â–â–â–â–â–â–â–████████████", - "â–â–â–â–â–â–â–â–████████████", - "â–â–â–â–â–â–â–â–â–███████████", - "â–â–â–â–â–â–â–â–â–███████████", - "â–â–â–â–â–â–â–â–â–â–██████████", - "â–â–â–â–â–â–â–â–â–â–██████████", - "â–â–â–â–â–â–â–â–â–â–â–â–████████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–███████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–██████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–█████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–█████", - "â–ˆâ–â–â–â–â–â–â–â–â–â–â–â–â–â–â–████", - "██â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–███", - "██â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–███", - "███â–â–â–â–â–â–â–â–â–â–â–â–â–â–███", - "████â–â–â–â–â–â–â–â–â–â–â–â–â–â–██", - "█████â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–ˆ", - "█████â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–ˆ", - "██████â–â–â–â–â–â–â–â–â–â–â–â–â–â–ˆ", - "████████â–â–â–â–â–â–â–â–â–â–â–â–", - "█████████â–â–â–â–â–â–â–â–â–â–â–", - "█████████â–â–â–â–â–â–â–â–â–â–â–", - "█████████â–â–â–â–â–â–â–â–â–â–â–", - "█████████â–â–â–â–â–â–â–â–â–â–â–", - "███████████â–â–â–â–â–â–â–â–â–", - "████████████â–â–â–â–â–â–â–â–", - "████████████â–â–â–â–â–â–â–â–", - "██████████████â–â–â–â–â–â–", - "██████████████â–â–â–â–â–â–", - "â–██████████████â–â–â–â–â–", - "â–██████████████â–â–â–â–â–", - "â–â–â–█████████████â–â–â–â–", - "â–â–â–â–â–████████████â–â–â–", - "â–â–â–â–â–████████████â–â–â–", - "â–â–â–â–â–â–███████████â–â–â–", - "â–â–â–â–â–â–â–â–█████████â–â–â–", - "â–â–â–â–â–â–â–â–█████████â–â–â–", - "â–â–â–â–â–â–â–â–â–█████████â–â–", - "â–â–â–â–â–â–â–â–â–█████████â–â–", - "â–â–â–â–â–â–â–â–â–â–█████████â–", - "â–â–â–â–â–â–â–â–â–â–â–████████â–", - "â–â–â–â–â–â–â–â–â–â–â–████████â–", - "â–â–â–â–â–â–â–â–â–â–â–â–███████â–", - "â–â–â–â–â–â–â–â–â–â–â–â–███████â–", - "â–â–â–â–â–â–â–â–â–â–â–â–â–███████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–███████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–█████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–████", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–███", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–███", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–██", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–██", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–██", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–ˆ", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–ˆ", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–ˆ", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - "â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–â–", - ], - }, - "moon": { - "interval": 80, - "frames": ["🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "], - }, - "runner": {"interval": 140, "frames": ["🚶 ", "🃠"]}, - "pong": { - "interval": 80, - "frames": [ - "â–â ‚ â–Œ", - "â–â ˆ â–Œ", - "â– â ‚ â–Œ", - "â– â   â–Œ", - "â– â¡€ â–Œ", - "â– â   â–Œ", - "â– â ‚ â–Œ", - "â– â ˆ â–Œ", - "â– â ‚ â–Œ", - "â– â   â–Œ", - "â– â¡€ â–Œ", - "â– â   â–Œ", - "â– â ‚ â–Œ", - "â– â ˆ â–Œ", - "â– â ‚â–Œ", - "â– â  â–Œ", - "■⡀▌", - "â– â   â–Œ", - "â– â ‚ â–Œ", - "â– â ˆ â–Œ", - "â– â ‚ â–Œ", - "â– â   â–Œ", - "â– â¡€ â–Œ", - "â– â   â–Œ", - "â– â ‚ â–Œ", - "â– â ˆ â–Œ", - "â– â ‚ â–Œ", - "â– â   â–Œ", - "â– â¡€ â–Œ", - "â–â   â–Œ", - ], - }, - "shark": { - "interval": 120, - "frames": [ - "â–|\\____________â–Œ", - "â–_|\\___________â–Œ", - "â–__|\\__________â–Œ", - "â–___|\\_________â–Œ", - "â–____|\\________â–Œ", - "â–_____|\\_______â–Œ", - "â–______|\\______â–Œ", - "â–_______|\\_____â–Œ", - "â–________|\\____â–Œ", - "â–_________|\\___â–Œ", - "â–__________|\\__â–Œ", - "â–___________|\\_â–Œ", - "â–____________|\\â–Œ", - "â–____________/|â–Œ", - "â–___________/|_â–Œ", - "â–__________/|__â–Œ", - "â–_________/|___â–Œ", - "â–________/|____â–Œ", - "â–_______/|_____â–Œ", - "â–______/|______â–Œ", - "â–_____/|_______â–Œ", - "â–____/|________â–Œ", - "â–___/|_________â–Œ", - "â–__/|__________â–Œ", - "â–_/|___________â–Œ", - "â–/|____________â–Œ", - ], - }, - "dqpb": {"interval": 100, "frames": "dqpb"}, - "weather": { - "interval": 100, - "frames": [ - "â˜€ï¸ ", - "â˜€ï¸ ", - "â˜€ï¸ ", - "🌤 ", - "â›…ï¸ ", - "🌥 ", - "â˜ï¸ ", - "🌧 ", - "🌨 ", - "🌧 ", - "🌨 ", - "🌧 ", - "🌨 ", - "⛈ ", - "🌨 ", - "🌧 ", - "🌨 ", - "â˜ï¸ ", - "🌥 ", - "â›…ï¸ ", - "🌤 ", - "â˜€ï¸ ", - "â˜€ï¸ ", - ], - }, - "christmas": {"interval": 400, "frames": "🌲🎄"}, - "grenade": { - "interval": 80, - "frames": [ - "ØŒ ", - "′ ", - " ´ ", - " ‾ ", - " ⸌", - " ⸊", - " |", - " âŽ", - " â•", - " à·´ ", - " â“", - " ", - " ", - " ", - ], - }, - "point": {"interval": 125, "frames": ["∙∙∙", "â—∙∙", "∙â—∙", "∙∙â—", "∙∙∙"]}, - "layer": {"interval": 150, "frames": "-=≡"}, - "betaWave": { - "interval": 80, - "frames": [ - "Ïββββββ", - "βÏβββββ", - "ββÏββββ", - "βββÏβββ", - "ββββÏββ", - "βββββÏβ", - "ββββββÏ", - ], - }, - "aesthetic": { - "interval": 80, - "frames": [ - "▰▱▱▱▱▱▱", - "▰▰▱▱▱▱▱", - "▰▰▰▱▱▱▱", - "▰▰▰▰▱▱▱", - "▰▰▰▰▰▱▱", - "â–°â–°â–°â–°â–°â–°â–±", - "â–°â–°â–°â–°â–°â–°â–°", - "▰▱▱▱▱▱▱", - ], - }, -} diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py deleted file mode 100644 index 194564e..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py +++ /dev/null @@ -1,16 +0,0 @@ -from typing import List, TypeVar - -T = TypeVar("T") - - -class Stack(List[T]): - """A small shim over builtin list.""" - - @property - def top(self) -> T: - """Get top of stack.""" - return self[-1] - - def push(self, item: T) -> None: - """Push an item on to the stack (append in stack nomenclature).""" - self.append(item) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py deleted file mode 100644 index a2ca6be..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Timer context manager, only used in debug. - -""" - -from time import time - -import contextlib -from typing import Generator - - -@contextlib.contextmanager -def timer(subject: str = "time") -> Generator[None, None, None]: - """print the elapsed time. (only used in debugging)""" - start = time() - yield - elapsed = time() - start - elapsed_ms = elapsed * 1000 - print(f"{subject} elapsed {elapsed_ms:.1f}ms") diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py deleted file mode 100644 index 81b1082..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py +++ /dev/null @@ -1,662 +0,0 @@ -"""Light wrapper around the Win32 Console API - this module should only be imported on Windows - -The API that this module wraps is documented at https://docs.microsoft.com/en-us/windows/console/console-functions -""" -import ctypes -import sys -from typing import Any - -windll: Any = None -if sys.platform == "win32": - windll = ctypes.LibraryLoader(ctypes.WinDLL) -else: - raise ImportError(f"{__name__} can only be imported on Windows") - -import time -from ctypes import Structure, byref, wintypes -from typing import IO, NamedTuple, Type, cast - -from pip._vendor.rich.color import ColorSystem -from pip._vendor.rich.style import Style - -STDOUT = -11 -ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4 - -COORD = wintypes._COORD - - -class LegacyWindowsError(Exception): - pass - - -class WindowsCoordinates(NamedTuple): - """Coordinates in the Windows Console API are (y, x), not (x, y). - This class is intended to prevent that confusion. - Rows and columns are indexed from 0. - This class can be used in place of wintypes._COORD in arguments and argtypes. - """ - - row: int - col: int - - @classmethod - def from_param(cls, value: "WindowsCoordinates") -> COORD: - """Converts a WindowsCoordinates into a wintypes _COORD structure. - This classmethod is internally called by ctypes to perform the conversion. - - Args: - value (WindowsCoordinates): The input coordinates to convert. - - Returns: - wintypes._COORD: The converted coordinates struct. - """ - return COORD(value.col, value.row) - - -class CONSOLE_SCREEN_BUFFER_INFO(Structure): - _fields_ = [ - ("dwSize", COORD), - ("dwCursorPosition", COORD), - ("wAttributes", wintypes.WORD), - ("srWindow", wintypes.SMALL_RECT), - ("dwMaximumWindowSize", COORD), - ] - - -class CONSOLE_CURSOR_INFO(ctypes.Structure): - _fields_ = [("dwSize", wintypes.DWORD), ("bVisible", wintypes.BOOL)] - - -_GetStdHandle = windll.kernel32.GetStdHandle -_GetStdHandle.argtypes = [ - wintypes.DWORD, -] -_GetStdHandle.restype = wintypes.HANDLE - - -def GetStdHandle(handle: int = STDOUT) -> wintypes.HANDLE: - """Retrieves a handle to the specified standard device (standard input, standard output, or standard error). - - Args: - handle (int): Integer identifier for the handle. Defaults to -11 (stdout). - - Returns: - wintypes.HANDLE: The handle - """ - return cast(wintypes.HANDLE, _GetStdHandle(handle)) - - -_GetConsoleMode = windll.kernel32.GetConsoleMode -_GetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.LPDWORD] -_GetConsoleMode.restype = wintypes.BOOL - - -def GetConsoleMode(std_handle: wintypes.HANDLE) -> int: - """Retrieves the current input mode of a console's input buffer - or the current output mode of a console screen buffer. - - Args: - std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. - - Raises: - LegacyWindowsError: If any error occurs while calling the Windows console API. - - Returns: - int: Value representing the current console mode as documented at - https://docs.microsoft.com/en-us/windows/console/getconsolemode#parameters - """ - - console_mode = wintypes.DWORD() - success = bool(_GetConsoleMode(std_handle, console_mode)) - if not success: - raise LegacyWindowsError("Unable to get legacy Windows Console Mode") - return console_mode.value - - -_FillConsoleOutputCharacterW = windll.kernel32.FillConsoleOutputCharacterW -_FillConsoleOutputCharacterW.argtypes = [ - wintypes.HANDLE, - ctypes.c_char, - wintypes.DWORD, - cast(Type[COORD], WindowsCoordinates), - ctypes.POINTER(wintypes.DWORD), -] -_FillConsoleOutputCharacterW.restype = wintypes.BOOL - - -def FillConsoleOutputCharacter( - std_handle: wintypes.HANDLE, - char: str, - length: int, - start: WindowsCoordinates, -) -> int: - """Writes a character to the console screen buffer a specified number of times, beginning at the specified coordinates. - - Args: - std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. - char (str): The character to write. Must be a string of length 1. - length (int): The number of times to write the character. - start (WindowsCoordinates): The coordinates to start writing at. - - Returns: - int: The number of characters written. - """ - character = ctypes.c_char(char.encode()) - num_characters = wintypes.DWORD(length) - num_written = wintypes.DWORD(0) - _FillConsoleOutputCharacterW( - std_handle, - character, - num_characters, - start, - byref(num_written), - ) - return num_written.value - - -_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute -_FillConsoleOutputAttribute.argtypes = [ - wintypes.HANDLE, - wintypes.WORD, - wintypes.DWORD, - cast(Type[COORD], WindowsCoordinates), - ctypes.POINTER(wintypes.DWORD), -] -_FillConsoleOutputAttribute.restype = wintypes.BOOL - - -def FillConsoleOutputAttribute( - std_handle: wintypes.HANDLE, - attributes: int, - length: int, - start: WindowsCoordinates, -) -> int: - """Sets the character attributes for a specified number of character cells, - beginning at the specified coordinates in a screen buffer. - - Args: - std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. - attributes (int): Integer value representing the foreground and background colours of the cells. - length (int): The number of cells to set the output attribute of. - start (WindowsCoordinates): The coordinates of the first cell whose attributes are to be set. - - Returns: - int: The number of cells whose attributes were actually set. - """ - num_cells = wintypes.DWORD(length) - style_attrs = wintypes.WORD(attributes) - num_written = wintypes.DWORD(0) - _FillConsoleOutputAttribute( - std_handle, style_attrs, num_cells, start, byref(num_written) - ) - return num_written.value - - -_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute -_SetConsoleTextAttribute.argtypes = [ - wintypes.HANDLE, - wintypes.WORD, -] -_SetConsoleTextAttribute.restype = wintypes.BOOL - - -def SetConsoleTextAttribute( - std_handle: wintypes.HANDLE, attributes: wintypes.WORD -) -> bool: - """Set the colour attributes for all text written after this function is called. - - Args: - std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. - attributes (int): Integer value representing the foreground and background colours. - - - Returns: - bool: True if the attribute was set successfully, otherwise False. - """ - return bool(_SetConsoleTextAttribute(std_handle, attributes)) - - -_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo -_GetConsoleScreenBufferInfo.argtypes = [ - wintypes.HANDLE, - ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO), -] -_GetConsoleScreenBufferInfo.restype = wintypes.BOOL - - -def GetConsoleScreenBufferInfo( - std_handle: wintypes.HANDLE, -) -> CONSOLE_SCREEN_BUFFER_INFO: - """Retrieves information about the specified console screen buffer. - - Args: - std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. - - Returns: - CONSOLE_SCREEN_BUFFER_INFO: A CONSOLE_SCREEN_BUFFER_INFO ctype struct contain information about - screen size, cursor position, colour attributes, and more.""" - console_screen_buffer_info = CONSOLE_SCREEN_BUFFER_INFO() - _GetConsoleScreenBufferInfo(std_handle, byref(console_screen_buffer_info)) - return console_screen_buffer_info - - -_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition -_SetConsoleCursorPosition.argtypes = [ - wintypes.HANDLE, - cast(Type[COORD], WindowsCoordinates), -] -_SetConsoleCursorPosition.restype = wintypes.BOOL - - -def SetConsoleCursorPosition( - std_handle: wintypes.HANDLE, coords: WindowsCoordinates -) -> bool: - """Set the position of the cursor in the console screen - - Args: - std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. - coords (WindowsCoordinates): The coordinates to move the cursor to. - - Returns: - bool: True if the function succeeds, otherwise False. - """ - return bool(_SetConsoleCursorPosition(std_handle, coords)) - - -_GetConsoleCursorInfo = windll.kernel32.GetConsoleCursorInfo -_GetConsoleCursorInfo.argtypes = [ - wintypes.HANDLE, - ctypes.POINTER(CONSOLE_CURSOR_INFO), -] -_GetConsoleCursorInfo.restype = wintypes.BOOL - - -def GetConsoleCursorInfo( - std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO -) -> bool: - """Get the cursor info - used to get cursor visibility and width - - Args: - std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. - cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct that receives information - about the console's cursor. - - Returns: - bool: True if the function succeeds, otherwise False. - """ - return bool(_GetConsoleCursorInfo(std_handle, byref(cursor_info))) - - -_SetConsoleCursorInfo = windll.kernel32.SetConsoleCursorInfo -_SetConsoleCursorInfo.argtypes = [ - wintypes.HANDLE, - ctypes.POINTER(CONSOLE_CURSOR_INFO), -] -_SetConsoleCursorInfo.restype = wintypes.BOOL - - -def SetConsoleCursorInfo( - std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO -) -> bool: - """Set the cursor info - used for adjusting cursor visibility and width - - Args: - std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer. - cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct containing the new cursor info. - - Returns: - bool: True if the function succeeds, otherwise False. - """ - return bool(_SetConsoleCursorInfo(std_handle, byref(cursor_info))) - - -_SetConsoleTitle = windll.kernel32.SetConsoleTitleW -_SetConsoleTitle.argtypes = [wintypes.LPCWSTR] -_SetConsoleTitle.restype = wintypes.BOOL - - -def SetConsoleTitle(title: str) -> bool: - """Sets the title of the current console window - - Args: - title (str): The new title of the console window. - - Returns: - bool: True if the function succeeds, otherwise False. - """ - return bool(_SetConsoleTitle(title)) - - -class LegacyWindowsTerm: - """This class allows interaction with the legacy Windows Console API. It should only be used in the context - of environments where virtual terminal processing is not available. However, if it is used in a Windows environment, - the entire API should work. - - Args: - file (IO[str]): The file which the Windows Console API HANDLE is retrieved from, defaults to sys.stdout. - """ - - BRIGHT_BIT = 8 - - # Indices are ANSI color numbers, values are the corresponding Windows Console API color numbers - ANSI_TO_WINDOWS = [ - 0, # black The Windows colours are defined in wincon.h as follows: - 4, # red define FOREGROUND_BLUE 0x0001 -- 0000 0001 - 2, # green define FOREGROUND_GREEN 0x0002 -- 0000 0010 - 6, # yellow define FOREGROUND_RED 0x0004 -- 0000 0100 - 1, # blue define FOREGROUND_INTENSITY 0x0008 -- 0000 1000 - 5, # magenta define BACKGROUND_BLUE 0x0010 -- 0001 0000 - 3, # cyan define BACKGROUND_GREEN 0x0020 -- 0010 0000 - 7, # white define BACKGROUND_RED 0x0040 -- 0100 0000 - 8, # bright black (grey) define BACKGROUND_INTENSITY 0x0080 -- 1000 0000 - 12, # bright red - 10, # bright green - 14, # bright yellow - 9, # bright blue - 13, # bright magenta - 11, # bright cyan - 15, # bright white - ] - - def __init__(self, file: "IO[str]") -> None: - handle = GetStdHandle(STDOUT) - self._handle = handle - default_text = GetConsoleScreenBufferInfo(handle).wAttributes - self._default_text = default_text - - self._default_fore = default_text & 7 - self._default_back = (default_text >> 4) & 7 - self._default_attrs = self._default_fore | (self._default_back << 4) - - self._file = file - self.write = file.write - self.flush = file.flush - - @property - def cursor_position(self) -> WindowsCoordinates: - """Returns the current position of the cursor (0-based) - - Returns: - WindowsCoordinates: The current cursor position. - """ - coord: COORD = GetConsoleScreenBufferInfo(self._handle).dwCursorPosition - return WindowsCoordinates(row=cast(int, coord.Y), col=cast(int, coord.X)) - - @property - def screen_size(self) -> WindowsCoordinates: - """Returns the current size of the console screen buffer, in character columns and rows - - Returns: - WindowsCoordinates: The width and height of the screen as WindowsCoordinates. - """ - screen_size: COORD = GetConsoleScreenBufferInfo(self._handle).dwSize - return WindowsCoordinates( - row=cast(int, screen_size.Y), col=cast(int, screen_size.X) - ) - - def write_text(self, text: str) -> None: - """Write text directly to the terminal without any modification of styles - - Args: - text (str): The text to write to the console - """ - self.write(text) - self.flush() - - def write_styled(self, text: str, style: Style) -> None: - """Write styled text to the terminal. - - Args: - text (str): The text to write - style (Style): The style of the text - """ - color = style.color - bgcolor = style.bgcolor - if style.reverse: - color, bgcolor = bgcolor, color - - if color: - fore = color.downgrade(ColorSystem.WINDOWS).number - fore = fore if fore is not None else 7 # Default to ANSI 7: White - if style.bold: - fore = fore | self.BRIGHT_BIT - if style.dim: - fore = fore & ~self.BRIGHT_BIT - fore = self.ANSI_TO_WINDOWS[fore] - else: - fore = self._default_fore - - if bgcolor: - back = bgcolor.downgrade(ColorSystem.WINDOWS).number - back = back if back is not None else 0 # Default to ANSI 0: Black - back = self.ANSI_TO_WINDOWS[back] - else: - back = self._default_back - - assert fore is not None - assert back is not None - - SetConsoleTextAttribute( - self._handle, attributes=ctypes.c_ushort(fore | (back << 4)) - ) - self.write_text(text) - SetConsoleTextAttribute(self._handle, attributes=self._default_text) - - def move_cursor_to(self, new_position: WindowsCoordinates) -> None: - """Set the position of the cursor - - Args: - new_position (WindowsCoordinates): The WindowsCoordinates representing the new position of the cursor. - """ - if new_position.col < 0 or new_position.row < 0: - return - SetConsoleCursorPosition(self._handle, coords=new_position) - - def erase_line(self) -> None: - """Erase all content on the line the cursor is currently located at""" - screen_size = self.screen_size - cursor_position = self.cursor_position - cells_to_erase = screen_size.col - start_coordinates = WindowsCoordinates(row=cursor_position.row, col=0) - FillConsoleOutputCharacter( - self._handle, " ", length=cells_to_erase, start=start_coordinates - ) - FillConsoleOutputAttribute( - self._handle, - self._default_attrs, - length=cells_to_erase, - start=start_coordinates, - ) - - def erase_end_of_line(self) -> None: - """Erase all content from the cursor position to the end of that line""" - cursor_position = self.cursor_position - cells_to_erase = self.screen_size.col - cursor_position.col - FillConsoleOutputCharacter( - self._handle, " ", length=cells_to_erase, start=cursor_position - ) - FillConsoleOutputAttribute( - self._handle, - self._default_attrs, - length=cells_to_erase, - start=cursor_position, - ) - - def erase_start_of_line(self) -> None: - """Erase all content from the cursor position to the start of that line""" - row, col = self.cursor_position - start = WindowsCoordinates(row, 0) - FillConsoleOutputCharacter(self._handle, " ", length=col, start=start) - FillConsoleOutputAttribute( - self._handle, self._default_attrs, length=col, start=start - ) - - def move_cursor_up(self) -> None: - """Move the cursor up a single cell""" - cursor_position = self.cursor_position - SetConsoleCursorPosition( - self._handle, - coords=WindowsCoordinates( - row=cursor_position.row - 1, col=cursor_position.col - ), - ) - - def move_cursor_down(self) -> None: - """Move the cursor down a single cell""" - cursor_position = self.cursor_position - SetConsoleCursorPosition( - self._handle, - coords=WindowsCoordinates( - row=cursor_position.row + 1, - col=cursor_position.col, - ), - ) - - def move_cursor_forward(self) -> None: - """Move the cursor forward a single cell. Wrap to the next line if required.""" - row, col = self.cursor_position - if col == self.screen_size.col - 1: - row += 1 - col = 0 - else: - col += 1 - SetConsoleCursorPosition( - self._handle, coords=WindowsCoordinates(row=row, col=col) - ) - - def move_cursor_to_column(self, column: int) -> None: - """Move cursor to the column specified by the zero-based column index, staying on the same row - - Args: - column (int): The zero-based column index to move the cursor to. - """ - row, _ = self.cursor_position - SetConsoleCursorPosition(self._handle, coords=WindowsCoordinates(row, column)) - - def move_cursor_backward(self) -> None: - """Move the cursor backward a single cell. Wrap to the previous line if required.""" - row, col = self.cursor_position - if col == 0: - row -= 1 - col = self.screen_size.col - 1 - else: - col -= 1 - SetConsoleCursorPosition( - self._handle, coords=WindowsCoordinates(row=row, col=col) - ) - - def hide_cursor(self) -> None: - """Hide the cursor""" - current_cursor_size = self._get_cursor_size() - invisible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=0) - SetConsoleCursorInfo(self._handle, cursor_info=invisible_cursor) - - def show_cursor(self) -> None: - """Show the cursor""" - current_cursor_size = self._get_cursor_size() - visible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=1) - SetConsoleCursorInfo(self._handle, cursor_info=visible_cursor) - - def set_title(self, title: str) -> None: - """Set the title of the terminal window - - Args: - title (str): The new title of the console window - """ - assert len(title) < 255, "Console title must be less than 255 characters" - SetConsoleTitle(title) - - def _get_cursor_size(self) -> int: - """Get the percentage of the character cell that is filled by the cursor""" - cursor_info = CONSOLE_CURSOR_INFO() - GetConsoleCursorInfo(self._handle, cursor_info=cursor_info) - return int(cursor_info.dwSize) - - -if __name__ == "__main__": - handle = GetStdHandle() - - from pip._vendor.rich.console import Console - - console = Console() - - term = LegacyWindowsTerm(sys.stdout) - term.set_title("Win32 Console Examples") - - style = Style(color="black", bgcolor="red") - - heading = Style.parse("black on green") - - # Check colour output - console.rule("Checking colour output") - console.print("[on red]on red!") - console.print("[blue]blue!") - console.print("[yellow]yellow!") - console.print("[bold yellow]bold yellow!") - console.print("[bright_yellow]bright_yellow!") - console.print("[dim bright_yellow]dim bright_yellow!") - console.print("[italic cyan]italic cyan!") - console.print("[bold white on blue]bold white on blue!") - console.print("[reverse bold white on blue]reverse bold white on blue!") - console.print("[bold black on cyan]bold black on cyan!") - console.print("[black on green]black on green!") - console.print("[blue on green]blue on green!") - console.print("[white on black]white on black!") - console.print("[black on white]black on white!") - console.print("[#1BB152 on #DA812D]#1BB152 on #DA812D!") - - # Check cursor movement - console.rule("Checking cursor movement") - console.print() - term.move_cursor_backward() - term.move_cursor_backward() - term.write_text("went back and wrapped to prev line") - time.sleep(1) - term.move_cursor_up() - term.write_text("we go up") - time.sleep(1) - term.move_cursor_down() - term.write_text("and down") - time.sleep(1) - term.move_cursor_up() - term.move_cursor_backward() - term.move_cursor_backward() - term.write_text("we went up and back 2") - time.sleep(1) - term.move_cursor_down() - term.move_cursor_backward() - term.move_cursor_backward() - term.write_text("we went down and back 2") - time.sleep(1) - - # Check erasing of lines - term.hide_cursor() - console.print() - console.rule("Checking line erasing") - console.print("\n...Deleting to the start of the line...") - term.write_text("The red arrow shows the cursor location, and direction of erase") - time.sleep(1) - term.move_cursor_to_column(16) - term.write_styled("<", Style.parse("black on red")) - term.move_cursor_backward() - time.sleep(1) - term.erase_start_of_line() - time.sleep(1) - - console.print("\n\n...And to the end of the line...") - term.write_text("The red arrow shows the cursor location, and direction of erase") - time.sleep(1) - - term.move_cursor_to_column(16) - term.write_styled(">", Style.parse("black on red")) - time.sleep(1) - term.erase_end_of_line() - time.sleep(1) - - console.print("\n\n...Now the whole line will be erased...") - term.write_styled("I'm going to disappear!", style=Style.parse("black on cyan")) - time.sleep(1) - term.erase_line() - - term.show_cursor() - print("\n") diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py deleted file mode 100644 index 10fc0d7..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py +++ /dev/null @@ -1,72 +0,0 @@ -import sys -from dataclasses import dataclass - - -@dataclass -class WindowsConsoleFeatures: - """Windows features available.""" - - vt: bool = False - """The console supports VT codes.""" - truecolor: bool = False - """The console supports truecolor.""" - - -try: - import ctypes - from ctypes import LibraryLoader - - if sys.platform == "win32": - windll = LibraryLoader(ctypes.WinDLL) - else: - windll = None - raise ImportError("Not windows") - - from pip._vendor.rich._win32_console import ( - ENABLE_VIRTUAL_TERMINAL_PROCESSING, - GetConsoleMode, - GetStdHandle, - LegacyWindowsError, - ) - -except (AttributeError, ImportError, ValueError): - - # Fallback if we can't load the Windows DLL - def get_windows_console_features() -> WindowsConsoleFeatures: - features = WindowsConsoleFeatures() - return features - -else: - - def get_windows_console_features() -> WindowsConsoleFeatures: - """Get windows console features. - - Returns: - WindowsConsoleFeatures: An instance of WindowsConsoleFeatures. - """ - handle = GetStdHandle() - try: - console_mode = GetConsoleMode(handle) - success = True - except LegacyWindowsError: - console_mode = 0 - success = False - vt = bool(success and console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) - truecolor = False - if vt: - win_version = sys.getwindowsversion() - truecolor = win_version.major > 10 or ( - win_version.major == 10 and win_version.build >= 15063 - ) - features = WindowsConsoleFeatures(vt=vt, truecolor=truecolor) - return features - - -if __name__ == "__main__": - import platform - - features = get_windows_console_features() - from pip._vendor.rich import print - - print(f'platform="{platform.system()}"') - print(repr(features)) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py deleted file mode 100644 index 5ece056..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py +++ /dev/null @@ -1,56 +0,0 @@ -from typing import Iterable, Sequence, Tuple, cast - -from pip._vendor.rich._win32_console import LegacyWindowsTerm, WindowsCoordinates -from pip._vendor.rich.segment import ControlCode, ControlType, Segment - - -def legacy_windows_render(buffer: Iterable[Segment], term: LegacyWindowsTerm) -> None: - """Makes appropriate Windows Console API calls based on the segments in the buffer. - - Args: - buffer (Iterable[Segment]): Iterable of Segments to convert to Win32 API calls. - term (LegacyWindowsTerm): Used to call the Windows Console API. - """ - for text, style, control in buffer: - if not control: - if style: - term.write_styled(text, style) - else: - term.write_text(text) - else: - control_codes: Sequence[ControlCode] = control - for control_code in control_codes: - control_type = control_code[0] - if control_type == ControlType.CURSOR_MOVE_TO: - _, x, y = cast(Tuple[ControlType, int, int], control_code) - term.move_cursor_to(WindowsCoordinates(row=y - 1, col=x - 1)) - elif control_type == ControlType.CARRIAGE_RETURN: - term.write_text("\r") - elif control_type == ControlType.HOME: - term.move_cursor_to(WindowsCoordinates(0, 0)) - elif control_type == ControlType.CURSOR_UP: - term.move_cursor_up() - elif control_type == ControlType.CURSOR_DOWN: - term.move_cursor_down() - elif control_type == ControlType.CURSOR_FORWARD: - term.move_cursor_forward() - elif control_type == ControlType.CURSOR_BACKWARD: - term.move_cursor_backward() - elif control_type == ControlType.CURSOR_MOVE_TO_COLUMN: - _, column = cast(Tuple[ControlType, int], control_code) - term.move_cursor_to_column(column - 1) - elif control_type == ControlType.HIDE_CURSOR: - term.hide_cursor() - elif control_type == ControlType.SHOW_CURSOR: - term.show_cursor() - elif control_type == ControlType.ERASE_IN_LINE: - _, mode = cast(Tuple[ControlType, int], control_code) - if mode == 0: - term.erase_end_of_line() - elif mode == 1: - term.erase_start_of_line() - elif mode == 2: - term.erase_line() - elif control_type == ControlType.SET_WINDOW_TITLE: - _, title = cast(Tuple[ControlType, str], control_code) - term.set_title(title) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py deleted file mode 100644 index c45f193..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py +++ /dev/null @@ -1,56 +0,0 @@ -import re -from typing import Iterable, List, Tuple - -from ._loop import loop_last -from .cells import cell_len, chop_cells - -re_word = re.compile(r"\s*\S+\s*") - - -def words(text: str) -> Iterable[Tuple[int, int, str]]: - position = 0 - word_match = re_word.match(text, position) - while word_match is not None: - start, end = word_match.span() - word = word_match.group(0) - yield start, end, word - word_match = re_word.match(text, end) - - -def divide_line(text: str, width: int, fold: bool = True) -> List[int]: - divides: List[int] = [] - append = divides.append - line_position = 0 - _cell_len = cell_len - for start, _end, word in words(text): - word_length = _cell_len(word.rstrip()) - if line_position + word_length > width: - if word_length > width: - if fold: - chopped_words = chop_cells(word, max_size=width, position=0) - for last, line in loop_last(chopped_words): - if start: - append(start) - - if last: - line_position = _cell_len(line) - else: - start += len(line) - else: - if start: - append(start) - line_position = _cell_len(word) - elif line_position and start: - append(start) - line_position = _cell_len(word) - else: - line_position += _cell_len(word) - return divides - - -if __name__ == "__main__": # pragma: no cover - from .console import Console - - console = Console(width=10) - console.print("12345 abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ 12345") - print(chop_cells("abcdefghijklmnopqrstuvwxyz", 10, position=2)) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/abc.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/abc.py deleted file mode 100644 index e6e498e..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/abc.py +++ /dev/null @@ -1,33 +0,0 @@ -from abc import ABC - - -class RichRenderable(ABC): - """An abstract base class for Rich renderables. - - Note that there is no need to extend this class, the intended use is to check if an - object supports the Rich renderable protocol. For example:: - - if isinstance(my_object, RichRenderable): - console.print(my_object) - - """ - - @classmethod - def __subclasshook__(cls, other: type) -> bool: - """Check if this class supports the rich render protocol.""" - return hasattr(other, "__rich_console__") or hasattr(other, "__rich__") - - -if __name__ == "__main__": # pragma: no cover - from pip._vendor.rich.text import Text - - t = Text() - print(isinstance(Text, RichRenderable)) - print(isinstance(t, RichRenderable)) - - class Foo: - pass - - f = Foo() - print(isinstance(f, RichRenderable)) - print(isinstance("", RichRenderable)) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/align.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/align.py deleted file mode 100644 index c310b66..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/align.py +++ /dev/null @@ -1,311 +0,0 @@ -import sys -from itertools import chain -from typing import TYPE_CHECKING, Iterable, Optional - -if sys.version_info >= (3, 8): - from typing import Literal -else: - from pip._vendor.typing_extensions import Literal # pragma: no cover - -from .constrain import Constrain -from .jupyter import JupyterMixin -from .measure import Measurement -from .segment import Segment -from .style import StyleType - -if TYPE_CHECKING: - from .console import Console, ConsoleOptions, RenderableType, RenderResult - -AlignMethod = Literal["left", "center", "right"] -VerticalAlignMethod = Literal["top", "middle", "bottom"] - - -class Align(JupyterMixin): - """Align a renderable by adding spaces if necessary. - - Args: - renderable (RenderableType): A console renderable. - align (AlignMethod): One of "left", "center", or "right"" - style (StyleType, optional): An optional style to apply to the background. - vertical (Optional[VerticalAlginMethod], optional): Optional vertical align, one of "top", "middle", or "bottom". Defaults to None. - pad (bool, optional): Pad the right with spaces. Defaults to True. - width (int, optional): Restrict contents to given width, or None to use default width. Defaults to None. - height (int, optional): Set height of align renderable, or None to fit to contents. Defaults to None. - - Raises: - ValueError: if ``align`` is not one of the expected values. - """ - - def __init__( - self, - renderable: "RenderableType", - align: AlignMethod = "left", - style: Optional[StyleType] = None, - *, - vertical: Optional[VerticalAlignMethod] = None, - pad: bool = True, - width: Optional[int] = None, - height: Optional[int] = None, - ) -> None: - if align not in ("left", "center", "right"): - raise ValueError( - f'invalid value for align, expected "left", "center", or "right" (not {align!r})' - ) - if vertical is not None and vertical not in ("top", "middle", "bottom"): - raise ValueError( - f'invalid value for vertical, expected "top", "middle", or "bottom" (not {vertical!r})' - ) - self.renderable = renderable - self.align = align - self.style = style - self.vertical = vertical - self.pad = pad - self.width = width - self.height = height - - def __repr__(self) -> str: - return f"Align({self.renderable!r}, {self.align!r})" - - @classmethod - def left( - cls, - renderable: "RenderableType", - style: Optional[StyleType] = None, - *, - vertical: Optional[VerticalAlignMethod] = None, - pad: bool = True, - width: Optional[int] = None, - height: Optional[int] = None, - ) -> "Align": - """Align a renderable to the left.""" - return cls( - renderable, - "left", - style=style, - vertical=vertical, - pad=pad, - width=width, - height=height, - ) - - @classmethod - def center( - cls, - renderable: "RenderableType", - style: Optional[StyleType] = None, - *, - vertical: Optional[VerticalAlignMethod] = None, - pad: bool = True, - width: Optional[int] = None, - height: Optional[int] = None, - ) -> "Align": - """Align a renderable to the center.""" - return cls( - renderable, - "center", - style=style, - vertical=vertical, - pad=pad, - width=width, - height=height, - ) - - @classmethod - def right( - cls, - renderable: "RenderableType", - style: Optional[StyleType] = None, - *, - vertical: Optional[VerticalAlignMethod] = None, - pad: bool = True, - width: Optional[int] = None, - height: Optional[int] = None, - ) -> "Align": - """Align a renderable to the right.""" - return cls( - renderable, - "right", - style=style, - vertical=vertical, - pad=pad, - width=width, - height=height, - ) - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> "RenderResult": - align = self.align - width = console.measure(self.renderable, options=options).maximum - rendered = console.render( - Constrain( - self.renderable, width if self.width is None else min(width, self.width) - ), - options.update(height=None), - ) - lines = list(Segment.split_lines(rendered)) - width, height = Segment.get_shape(lines) - lines = Segment.set_shape(lines, width, height) - new_line = Segment.line() - excess_space = options.max_width - width - style = console.get_style(self.style) if self.style is not None else None - - def generate_segments() -> Iterable[Segment]: - if excess_space <= 0: - # Exact fit - for line in lines: - yield from line - yield new_line - - elif align == "left": - # Pad on the right - pad = Segment(" " * excess_space, style) if self.pad else None - for line in lines: - yield from line - if pad: - yield pad - yield new_line - - elif align == "center": - # Pad left and right - left = excess_space // 2 - pad = Segment(" " * left, style) - pad_right = ( - Segment(" " * (excess_space - left), style) if self.pad else None - ) - for line in lines: - if left: - yield pad - yield from line - if pad_right: - yield pad_right - yield new_line - - elif align == "right": - # Padding on left - pad = Segment(" " * excess_space, style) - for line in lines: - yield pad - yield from line - yield new_line - - blank_line = ( - Segment(f"{' ' * (self.width or options.max_width)}\n", style) - if self.pad - else Segment("\n") - ) - - def blank_lines(count: int) -> Iterable[Segment]: - if count > 0: - for _ in range(count): - yield blank_line - - vertical_height = self.height or options.height - iter_segments: Iterable[Segment] - if self.vertical and vertical_height is not None: - if self.vertical == "top": - bottom_space = vertical_height - height - iter_segments = chain(generate_segments(), blank_lines(bottom_space)) - elif self.vertical == "middle": - top_space = (vertical_height - height) // 2 - bottom_space = vertical_height - top_space - height - iter_segments = chain( - blank_lines(top_space), - generate_segments(), - blank_lines(bottom_space), - ) - else: # self.vertical == "bottom": - top_space = vertical_height - height - iter_segments = chain(blank_lines(top_space), generate_segments()) - else: - iter_segments = generate_segments() - if self.style: - style = console.get_style(self.style) - iter_segments = Segment.apply_style(iter_segments, style) - yield from iter_segments - - def __rich_measure__( - self, console: "Console", options: "ConsoleOptions" - ) -> Measurement: - measurement = Measurement.get(console, options, self.renderable) - return measurement - - -class VerticalCenter(JupyterMixin): - """Vertically aligns a renderable. - - Warn: - This class is deprecated and may be removed in a future version. Use Align class with - `vertical="middle"`. - - Args: - renderable (RenderableType): A renderable object. - """ - - def __init__( - self, - renderable: "RenderableType", - style: Optional[StyleType] = None, - ) -> None: - self.renderable = renderable - self.style = style - - def __repr__(self) -> str: - return f"VerticalCenter({self.renderable!r})" - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> "RenderResult": - style = console.get_style(self.style) if self.style is not None else None - lines = console.render_lines( - self.renderable, options.update(height=None), pad=False - ) - width, _height = Segment.get_shape(lines) - new_line = Segment.line() - height = options.height or options.size.height - top_space = (height - len(lines)) // 2 - bottom_space = height - top_space - len(lines) - blank_line = Segment(f"{' ' * width}", style) - - def blank_lines(count: int) -> Iterable[Segment]: - for _ in range(count): - yield blank_line - yield new_line - - if top_space > 0: - yield from blank_lines(top_space) - for line in lines: - yield from line - yield new_line - if bottom_space > 0: - yield from blank_lines(bottom_space) - - def __rich_measure__( - self, console: "Console", options: "ConsoleOptions" - ) -> Measurement: - measurement = Measurement.get(console, options, self.renderable) - return measurement - - -if __name__ == "__main__": # pragma: no cover - from pip._vendor.rich.console import Console, Group - from pip._vendor.rich.highlighter import ReprHighlighter - from pip._vendor.rich.panel import Panel - - highlighter = ReprHighlighter() - console = Console() - - panel = Panel( - Group( - Align.left(highlighter("align='left'")), - Align.center(highlighter("align='center'")), - Align.right(highlighter("align='right'")), - ), - width=60, - style="on dark_blue", - title="Align", - ) - - console.print( - Align.center(panel, vertical="middle", style="on red", height=console.height) - ) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py deleted file mode 100644 index 66365e6..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py +++ /dev/null @@ -1,240 +0,0 @@ -import re -import sys -from contextlib import suppress -from typing import Iterable, NamedTuple, Optional - -from .color import Color -from .style import Style -from .text import Text - -re_ansi = re.compile( - r""" -(?:\x1b\](.*?)\x1b\\)| -(?:\x1b([(@-Z\\-_]|\[[0-?]*[ -/]*[@-~])) -""", - re.VERBOSE, -) - - -class _AnsiToken(NamedTuple): - """Result of ansi tokenized string.""" - - plain: str = "" - sgr: Optional[str] = "" - osc: Optional[str] = "" - - -def _ansi_tokenize(ansi_text: str) -> Iterable[_AnsiToken]: - """Tokenize a string in to plain text and ANSI codes. - - Args: - ansi_text (str): A String containing ANSI codes. - - Yields: - AnsiToken: A named tuple of (plain, sgr, osc) - """ - - position = 0 - sgr: Optional[str] - osc: Optional[str] - for match in re_ansi.finditer(ansi_text): - start, end = match.span(0) - osc, sgr = match.groups() - if start > position: - yield _AnsiToken(ansi_text[position:start]) - if sgr: - if sgr == "(": - position = end + 1 - continue - if sgr.endswith("m"): - yield _AnsiToken("", sgr[1:-1], osc) - else: - yield _AnsiToken("", sgr, osc) - position = end - if position < len(ansi_text): - yield _AnsiToken(ansi_text[position:]) - - -SGR_STYLE_MAP = { - 1: "bold", - 2: "dim", - 3: "italic", - 4: "underline", - 5: "blink", - 6: "blink2", - 7: "reverse", - 8: "conceal", - 9: "strike", - 21: "underline2", - 22: "not dim not bold", - 23: "not italic", - 24: "not underline", - 25: "not blink", - 26: "not blink2", - 27: "not reverse", - 28: "not conceal", - 29: "not strike", - 30: "color(0)", - 31: "color(1)", - 32: "color(2)", - 33: "color(3)", - 34: "color(4)", - 35: "color(5)", - 36: "color(6)", - 37: "color(7)", - 39: "default", - 40: "on color(0)", - 41: "on color(1)", - 42: "on color(2)", - 43: "on color(3)", - 44: "on color(4)", - 45: "on color(5)", - 46: "on color(6)", - 47: "on color(7)", - 49: "on default", - 51: "frame", - 52: "encircle", - 53: "overline", - 54: "not frame not encircle", - 55: "not overline", - 90: "color(8)", - 91: "color(9)", - 92: "color(10)", - 93: "color(11)", - 94: "color(12)", - 95: "color(13)", - 96: "color(14)", - 97: "color(15)", - 100: "on color(8)", - 101: "on color(9)", - 102: "on color(10)", - 103: "on color(11)", - 104: "on color(12)", - 105: "on color(13)", - 106: "on color(14)", - 107: "on color(15)", -} - - -class AnsiDecoder: - """Translate ANSI code in to styled Text.""" - - def __init__(self) -> None: - self.style = Style.null() - - def decode(self, terminal_text: str) -> Iterable[Text]: - """Decode ANSI codes in an iterable of lines. - - Args: - lines (Iterable[str]): An iterable of lines of terminal output. - - Yields: - Text: Marked up Text. - """ - for line in terminal_text.splitlines(): - yield self.decode_line(line) - - def decode_line(self, line: str) -> Text: - """Decode a line containing ansi codes. - - Args: - line (str): A line of terminal output. - - Returns: - Text: A Text instance marked up according to ansi codes. - """ - from_ansi = Color.from_ansi - from_rgb = Color.from_rgb - _Style = Style - text = Text() - append = text.append - line = line.rsplit("\r", 1)[-1] - for plain_text, sgr, osc in _ansi_tokenize(line): - if plain_text: - append(plain_text, self.style or None) - elif osc is not None: - if osc.startswith("8;"): - _params, semicolon, link = osc[2:].partition(";") - if semicolon: - self.style = self.style.update_link(link or None) - elif sgr is not None: - # Translate in to semi-colon separated codes - # Ignore invalid codes, because we want to be lenient - codes = [ - min(255, int(_code) if _code else 0) - for _code in sgr.split(";") - if _code.isdigit() or _code == "" - ] - iter_codes = iter(codes) - for code in iter_codes: - if code == 0: - # reset - self.style = _Style.null() - elif code in SGR_STYLE_MAP: - # styles - self.style += _Style.parse(SGR_STYLE_MAP[code]) - elif code == 38: - #  Foreground - with suppress(StopIteration): - color_type = next(iter_codes) - if color_type == 5: - self.style += _Style.from_color( - from_ansi(next(iter_codes)) - ) - elif color_type == 2: - self.style += _Style.from_color( - from_rgb( - next(iter_codes), - next(iter_codes), - next(iter_codes), - ) - ) - elif code == 48: - # Background - with suppress(StopIteration): - color_type = next(iter_codes) - if color_type == 5: - self.style += _Style.from_color( - None, from_ansi(next(iter_codes)) - ) - elif color_type == 2: - self.style += _Style.from_color( - None, - from_rgb( - next(iter_codes), - next(iter_codes), - next(iter_codes), - ), - ) - - return text - - -if sys.platform != "win32" and __name__ == "__main__": # pragma: no cover - import io - import os - import pty - import sys - - decoder = AnsiDecoder() - - stdout = io.BytesIO() - - def read(fd: int) -> bytes: - data = os.read(fd, 1024) - stdout.write(data) - return data - - pty.spawn(sys.argv[1:], read) - - from .console import Console - - console = Console(record=True) - - stdout_result = stdout.getvalue().decode("utf-8") - print(stdout_result) - - for line in decoder.decode(stdout_result): - console.print(line) - - console.save_html("stdout.html") diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/bar.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/bar.py deleted file mode 100644 index ed86a55..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/bar.py +++ /dev/null @@ -1,94 +0,0 @@ -from typing import Optional, Union - -from .color import Color -from .console import Console, ConsoleOptions, RenderResult -from .jupyter import JupyterMixin -from .measure import Measurement -from .segment import Segment -from .style import Style - -# There are left-aligned characters for 1/8 to 7/8, but -# the right-aligned characters exist only for 1/8 and 4/8. -BEGIN_BLOCK_ELEMENTS = ["â–ˆ", "â–ˆ", "â–ˆ", "â–", "â–", "â–", "â–•", "â–•"] -END_BLOCK_ELEMENTS = [" ", "â–", "â–Ž", "â–", "â–Œ", "â–‹", "â–Š", "â–‰"] -FULL_BLOCK = "â–ˆ" - - -class Bar(JupyterMixin): - """Renders a solid block bar. - - Args: - size (float): Value for the end of the bar. - begin (float): Begin point (between 0 and size, inclusive). - end (float): End point (between 0 and size, inclusive). - width (int, optional): Width of the bar, or ``None`` for maximum width. Defaults to None. - color (Union[Color, str], optional): Color of the bar. Defaults to "default". - bgcolor (Union[Color, str], optional): Color of bar background. Defaults to "default". - """ - - def __init__( - self, - size: float, - begin: float, - end: float, - *, - width: Optional[int] = None, - color: Union[Color, str] = "default", - bgcolor: Union[Color, str] = "default", - ): - self.size = size - self.begin = max(begin, 0) - self.end = min(end, size) - self.width = width - self.style = Style(color=color, bgcolor=bgcolor) - - def __repr__(self) -> str: - return f"Bar({self.size}, {self.begin}, {self.end})" - - def __rich_console__( - self, console: Console, options: ConsoleOptions - ) -> RenderResult: - - width = min( - self.width if self.width is not None else options.max_width, - options.max_width, - ) - - if self.begin >= self.end: - yield Segment(" " * width, self.style) - yield Segment.line() - return - - prefix_complete_eights = int(width * 8 * self.begin / self.size) - prefix_bar_count = prefix_complete_eights // 8 - prefix_eights_count = prefix_complete_eights % 8 - - body_complete_eights = int(width * 8 * self.end / self.size) - body_bar_count = body_complete_eights // 8 - body_eights_count = body_complete_eights % 8 - - # When start and end fall into the same cell, we ideally should render - # a symbol that's "center-aligned", but there is no good symbol in Unicode. - # In this case, we fall back to right-aligned block symbol for simplicity. - - prefix = " " * prefix_bar_count - if prefix_eights_count: - prefix += BEGIN_BLOCK_ELEMENTS[prefix_eights_count] - - body = FULL_BLOCK * body_bar_count - if body_eights_count: - body += END_BLOCK_ELEMENTS[body_eights_count] - - suffix = " " * (width - len(body)) - - yield Segment(prefix + body[len(prefix) :] + suffix, self.style) - yield Segment.line() - - def __rich_measure__( - self, console: Console, options: ConsoleOptions - ) -> Measurement: - return ( - Measurement(self.width, self.width) - if self.width is not None - else Measurement(4, options.max_width) - ) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/box.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/box.py deleted file mode 100644 index 97d2a94..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/box.py +++ /dev/null @@ -1,517 +0,0 @@ -import sys -from typing import TYPE_CHECKING, Iterable, List - -if sys.version_info >= (3, 8): - from typing import Literal -else: - from pip._vendor.typing_extensions import Literal # pragma: no cover - - -from ._loop import loop_last - -if TYPE_CHECKING: - from pip._vendor.rich.console import ConsoleOptions - - -class Box: - """Defines characters to render boxes. - - ┌─┬┠top - │ ││ head - ├─┼┤ head_row - │ ││ mid - ├─┼┤ row - ├─┼┤ foot_row - │ ││ foot - └─┴┘ bottom - - Args: - box (str): Characters making up box. - ascii (bool, optional): True if this box uses ascii characters only. Default is False. - """ - - def __init__(self, box: str, *, ascii: bool = False) -> None: - self._box = box - self.ascii = ascii - line1, line2, line3, line4, line5, line6, line7, line8 = box.splitlines() - # top - self.top_left, self.top, self.top_divider, self.top_right = iter(line1) - # head - self.head_left, _, self.head_vertical, self.head_right = iter(line2) - # head_row - ( - self.head_row_left, - self.head_row_horizontal, - self.head_row_cross, - self.head_row_right, - ) = iter(line3) - - # mid - self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4) - # row - self.row_left, self.row_horizontal, self.row_cross, self.row_right = iter(line5) - # foot_row - ( - self.foot_row_left, - self.foot_row_horizontal, - self.foot_row_cross, - self.foot_row_right, - ) = iter(line6) - # foot - self.foot_left, _, self.foot_vertical, self.foot_right = iter(line7) - # bottom - self.bottom_left, self.bottom, self.bottom_divider, self.bottom_right = iter( - line8 - ) - - def __repr__(self) -> str: - return "Box(...)" - - def __str__(self) -> str: - return self._box - - def substitute(self, options: "ConsoleOptions", safe: bool = True) -> "Box": - """Substitute this box for another if it won't render due to platform issues. - - Args: - options (ConsoleOptions): Console options used in rendering. - safe (bool, optional): Substitute this for another Box if there are known problems - displaying on the platform (currently only relevant on Windows). Default is True. - - Returns: - Box: A different Box or the same Box. - """ - box = self - if options.legacy_windows and safe: - box = LEGACY_WINDOWS_SUBSTITUTIONS.get(box, box) - if options.ascii_only and not box.ascii: - box = ASCII - return box - - def get_plain_headed_box(self) -> "Box": - """If this box uses special characters for the borders of the header, then - return the equivalent box that does not. - - Returns: - Box: The most similar Box that doesn't use header-specific box characters. - If the current Box already satisfies this criterion, then it's returned. - """ - return PLAIN_HEADED_SUBSTITUTIONS.get(self, self) - - def get_top(self, widths: Iterable[int]) -> str: - """Get the top of a simple box. - - Args: - widths (List[int]): Widths of columns. - - Returns: - str: A string of box characters. - """ - - parts: List[str] = [] - append = parts.append - append(self.top_left) - for last, width in loop_last(widths): - append(self.top * width) - if not last: - append(self.top_divider) - append(self.top_right) - return "".join(parts) - - def get_row( - self, - widths: Iterable[int], - level: Literal["head", "row", "foot", "mid"] = "row", - edge: bool = True, - ) -> str: - """Get the top of a simple box. - - Args: - width (List[int]): Widths of columns. - - Returns: - str: A string of box characters. - """ - if level == "head": - left = self.head_row_left - horizontal = self.head_row_horizontal - cross = self.head_row_cross - right = self.head_row_right - elif level == "row": - left = self.row_left - horizontal = self.row_horizontal - cross = self.row_cross - right = self.row_right - elif level == "mid": - left = self.mid_left - horizontal = " " - cross = self.mid_vertical - right = self.mid_right - elif level == "foot": - left = self.foot_row_left - horizontal = self.foot_row_horizontal - cross = self.foot_row_cross - right = self.foot_row_right - else: - raise ValueError("level must be 'head', 'row' or 'foot'") - - parts: List[str] = [] - append = parts.append - if edge: - append(left) - for last, width in loop_last(widths): - append(horizontal * width) - if not last: - append(cross) - if edge: - append(right) - return "".join(parts) - - def get_bottom(self, widths: Iterable[int]) -> str: - """Get the bottom of a simple box. - - Args: - widths (List[int]): Widths of columns. - - Returns: - str: A string of box characters. - """ - - parts: List[str] = [] - append = parts.append - append(self.bottom_left) - for last, width in loop_last(widths): - append(self.bottom * width) - if not last: - append(self.bottom_divider) - append(self.bottom_right) - return "".join(parts) - - -ASCII: Box = Box( - """\ -+--+ -| || -|-+| -| || -|-+| -|-+| -| || -+--+ -""", - ascii=True, -) - -ASCII2: Box = Box( - """\ -+-++ -| || -+-++ -| || -+-++ -+-++ -| || -+-++ -""", - ascii=True, -) - -ASCII_DOUBLE_HEAD: Box = Box( - """\ -+-++ -| || -+=++ -| || -+-++ -+-++ -| || -+-++ -""", - ascii=True, -) - -SQUARE: Box = Box( - """\ -┌─┬┠-│ ││ -├─┼┤ -│ ││ -├─┼┤ -├─┼┤ -│ ││ -└─┴┘ -""" -) - -SQUARE_DOUBLE_HEAD: Box = Box( - """\ -┌─┬┠-│ ││ -╞â•╪╡ -│ ││ -├─┼┤ -├─┼┤ -│ ││ -└─┴┘ -""" -) - -MINIMAL: Box = Box( - """\ - â•· - │ -╶─┼╴ - │ -╶─┼╴ -╶─┼╴ - │ - ╵ -""" -) - - -MINIMAL_HEAVY_HEAD: Box = Box( - """\ - â•· - │ -╺â”┿╸ - │ -╶─┼╴ -╶─┼╴ - │ - ╵ -""" -) - -MINIMAL_DOUBLE_HEAD: Box = Box( - """\ - â•· - │ - â•╪ - │ - ─┼ - ─┼ - │ - ╵ -""" -) - - -SIMPLE: Box = Box( - """\ - - - ── - - - ── - - -""" -) - -SIMPLE_HEAD: Box = Box( - """\ - - - ── - - - - - -""" -) - - -SIMPLE_HEAVY: Box = Box( - """\ - - - â”â” - - - â”â” - - -""" -) - - -HORIZONTALS: Box = Box( - """\ - ── - - ── - - ── - ── - - ── -""" -) - -ROUNDED: Box = Box( - """\ -╭─┬╮ -│ ││ -├─┼┤ -│ ││ -├─┼┤ -├─┼┤ -│ ││ -╰─┴╯ -""" -) - -HEAVY: Box = Box( - """\ -â”â”┳┓ -┃ ┃┃ -┣â”╋┫ -┃ ┃┃ -┣â”╋┫ -┣â”╋┫ -┃ ┃┃ -â”—â”┻┛ -""" -) - -HEAVY_EDGE: Box = Box( - """\ -â”â”┯┓ -┃ │┃ -┠─┼┨ -┃ │┃ -┠─┼┨ -┠─┼┨ -┃ │┃ -â”—â”â”·â”› -""" -) - -HEAVY_HEAD: Box = Box( - """\ -â”â”┳┓ -┃ ┃┃ -┡â”╇┩ -│ ││ -├─┼┤ -├─┼┤ -│ ││ -└─┴┘ -""" -) - -DOUBLE: Box = Box( - """\ -â•”â•╦╗ -â•‘ â•‘â•‘ -â• â•╬╣ -â•‘ â•‘â•‘ -â• â•╬╣ -â• â•╬╣ -â•‘ â•‘â•‘ -╚â•â•©â• -""" -) - -DOUBLE_EDGE: Box = Box( - """\ -â•”â•╤╗ -â•‘ │║ -╟─┼╢ -â•‘ │║ -╟─┼╢ -╟─┼╢ -â•‘ │║ -╚â•â•§â• -""" -) - -MARKDOWN: Box = Box( - """\ - -| || -|-|| -| || -|-|| -|-|| -| || - -""", - ascii=True, -) - -# Map Boxes that don't render with raster fonts on to equivalent that do -LEGACY_WINDOWS_SUBSTITUTIONS = { - ROUNDED: SQUARE, - MINIMAL_HEAVY_HEAD: MINIMAL, - SIMPLE_HEAVY: SIMPLE, - HEAVY: SQUARE, - HEAVY_EDGE: SQUARE, - HEAVY_HEAD: SQUARE, -} - -# Map headed boxes to their headerless equivalents -PLAIN_HEADED_SUBSTITUTIONS = { - HEAVY_HEAD: SQUARE, - SQUARE_DOUBLE_HEAD: SQUARE, - MINIMAL_DOUBLE_HEAD: MINIMAL, - MINIMAL_HEAVY_HEAD: MINIMAL, - ASCII_DOUBLE_HEAD: ASCII2, -} - - -if __name__ == "__main__": # pragma: no cover - - from pip._vendor.rich.columns import Columns - from pip._vendor.rich.panel import Panel - - from . import box as box - from .console import Console - from .table import Table - from .text import Text - - console = Console(record=True) - - BOXES = [ - "ASCII", - "ASCII2", - "ASCII_DOUBLE_HEAD", - "SQUARE", - "SQUARE_DOUBLE_HEAD", - "MINIMAL", - "MINIMAL_HEAVY_HEAD", - "MINIMAL_DOUBLE_HEAD", - "SIMPLE", - "SIMPLE_HEAD", - "SIMPLE_HEAVY", - "HORIZONTALS", - "ROUNDED", - "HEAVY", - "HEAVY_EDGE", - "HEAVY_HEAD", - "DOUBLE", - "DOUBLE_EDGE", - "MARKDOWN", - ] - - console.print(Panel("[bold green]Box Constants", style="green"), justify="center") - console.print() - - columns = Columns(expand=True, padding=2) - for box_name in sorted(BOXES): - table = Table( - show_footer=True, style="dim", border_style="not dim", expand=True - ) - table.add_column("Header 1", "Footer 1") - table.add_column("Header 2", "Footer 2") - table.add_row("Cell", "Cell") - table.add_row("Cell", "Cell") - table.box = getattr(box, box_name) - table.title = Text(f"box.{box_name}", style="magenta") - columns.add_renderable(table) - console.print(columns) - - # console.save_svg("box.svg") diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/cells.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/cells.py deleted file mode 100644 index 9354f9e..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/cells.py +++ /dev/null @@ -1,154 +0,0 @@ -import re -from functools import lru_cache -from typing import Callable, List - -from ._cell_widths import CELL_WIDTHS - -# Regex to match sequence of the most common character ranges -_is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match - - -@lru_cache(4096) -def cached_cell_len(text: str) -> int: - """Get the number of cells required to display text. - - This method always caches, which may use up a lot of memory. It is recommended to use - `cell_len` over this method. - - Args: - text (str): Text to display. - - Returns: - int: Get the number of cells required to display text. - """ - _get_size = get_character_cell_size - total_size = sum(_get_size(character) for character in text) - return total_size - - -def cell_len(text: str, _cell_len: Callable[[str], int] = cached_cell_len) -> int: - """Get the number of cells required to display text. - - Args: - text (str): Text to display. - - Returns: - int: Get the number of cells required to display text. - """ - if len(text) < 512: - return _cell_len(text) - _get_size = get_character_cell_size - total_size = sum(_get_size(character) for character in text) - return total_size - - -@lru_cache(maxsize=4096) -def get_character_cell_size(character: str) -> int: - """Get the cell size of a character. - - Args: - character (str): A single character. - - Returns: - int: Number of cells (0, 1 or 2) occupied by that character. - """ - return _get_codepoint_cell_size(ord(character)) - - -@lru_cache(maxsize=4096) -def _get_codepoint_cell_size(codepoint: int) -> int: - """Get the cell size of a character. - - Args: - codepoint (int): Codepoint of a character. - - Returns: - int: Number of cells (0, 1 or 2) occupied by that character. - """ - - _table = CELL_WIDTHS - lower_bound = 0 - upper_bound = len(_table) - 1 - index = (lower_bound + upper_bound) // 2 - while True: - start, end, width = _table[index] - if codepoint < start: - upper_bound = index - 1 - elif codepoint > end: - lower_bound = index + 1 - else: - return 0 if width == -1 else width - if upper_bound < lower_bound: - break - index = (lower_bound + upper_bound) // 2 - return 1 - - -def set_cell_size(text: str, total: int) -> str: - """Set the length of a string to fit within given number of cells.""" - - if _is_single_cell_widths(text): - size = len(text) - if size < total: - return text + " " * (total - size) - return text[:total] - - if total <= 0: - return "" - cell_size = cell_len(text) - if cell_size == total: - return text - if cell_size < total: - return text + " " * (total - cell_size) - - start = 0 - end = len(text) - - # Binary search until we find the right size - while True: - pos = (start + end) // 2 - before = text[: pos + 1] - before_len = cell_len(before) - if before_len == total + 1 and cell_len(before[-1]) == 2: - return before[:-1] + " " - if before_len == total: - return before - if before_len > total: - end = pos - else: - start = pos - - -# TODO: This is inefficient -# TODO: This might not work with CWJ type characters -def chop_cells(text: str, max_size: int, position: int = 0) -> List[str]: - """Break text in to equal (cell) length strings, returning the characters in reverse - order""" - _get_character_cell_size = get_character_cell_size - characters = [ - (character, _get_character_cell_size(character)) for character in text - ] - total_size = position - lines: List[List[str]] = [[]] - append = lines[-1].append - - for character, size in reversed(characters): - if total_size + size > max_size: - lines.append([character]) - append = lines[-1].append - total_size = size - else: - total_size += size - append(character) - - return ["".join(line) for line in lines] - - -if __name__ == "__main__": # pragma: no cover - - print(get_character_cell_size("😽")) - for line in chop_cells("""这是对亚洲语言支æŒçš„æµ‹è¯•。é¢å¯¹æ¨¡æ£±ä¸¤å¯çš„æƒ³æ³•,拒ç»çŒœæµ‹çš„诱惑。""", 8): - print(line) - for n in range(80, 1, -1): - print(set_cell_size("""这是对亚洲语言支æŒçš„æµ‹è¯•。é¢å¯¹æ¨¡æ£±ä¸¤å¯çš„æƒ³æ³•,拒ç»çŒœæµ‹çš„诱惑。""", n) + "|") - print("x" * n) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/color.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/color.py deleted file mode 100644 index dfe4559..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/color.py +++ /dev/null @@ -1,622 +0,0 @@ -import platform -import re -from colorsys import rgb_to_hls -from enum import IntEnum -from functools import lru_cache -from typing import TYPE_CHECKING, NamedTuple, Optional, Tuple - -from ._palettes import EIGHT_BIT_PALETTE, STANDARD_PALETTE, WINDOWS_PALETTE -from .color_triplet import ColorTriplet -from .repr import Result, rich_repr -from .terminal_theme import DEFAULT_TERMINAL_THEME - -if TYPE_CHECKING: # pragma: no cover - from .terminal_theme import TerminalTheme - from .text import Text - - -WINDOWS = platform.system() == "Windows" - - -class ColorSystem(IntEnum): - """One of the 3 color system supported by terminals.""" - - STANDARD = 1 - EIGHT_BIT = 2 - TRUECOLOR = 3 - WINDOWS = 4 - - def __repr__(self) -> str: - return f"ColorSystem.{self.name}" - - def __str__(self) -> str: - return repr(self) - - -class ColorType(IntEnum): - """Type of color stored in Color class.""" - - DEFAULT = 0 - STANDARD = 1 - EIGHT_BIT = 2 - TRUECOLOR = 3 - WINDOWS = 4 - - def __repr__(self) -> str: - return f"ColorType.{self.name}" - - -ANSI_COLOR_NAMES = { - "black": 0, - "red": 1, - "green": 2, - "yellow": 3, - "blue": 4, - "magenta": 5, - "cyan": 6, - "white": 7, - "bright_black": 8, - "bright_red": 9, - "bright_green": 10, - "bright_yellow": 11, - "bright_blue": 12, - "bright_magenta": 13, - "bright_cyan": 14, - "bright_white": 15, - "grey0": 16, - "gray0": 16, - "navy_blue": 17, - "dark_blue": 18, - "blue3": 20, - "blue1": 21, - "dark_green": 22, - "deep_sky_blue4": 25, - "dodger_blue3": 26, - "dodger_blue2": 27, - "green4": 28, - "spring_green4": 29, - "turquoise4": 30, - "deep_sky_blue3": 32, - "dodger_blue1": 33, - "green3": 40, - "spring_green3": 41, - "dark_cyan": 36, - "light_sea_green": 37, - "deep_sky_blue2": 38, - "deep_sky_blue1": 39, - "spring_green2": 47, - "cyan3": 43, - "dark_turquoise": 44, - "turquoise2": 45, - "green1": 46, - "spring_green1": 48, - "medium_spring_green": 49, - "cyan2": 50, - "cyan1": 51, - "dark_red": 88, - "deep_pink4": 125, - "purple4": 55, - "purple3": 56, - "blue_violet": 57, - "orange4": 94, - "grey37": 59, - "gray37": 59, - "medium_purple4": 60, - "slate_blue3": 62, - "royal_blue1": 63, - "chartreuse4": 64, - "dark_sea_green4": 71, - "pale_turquoise4": 66, - "steel_blue": 67, - "steel_blue3": 68, - "cornflower_blue": 69, - "chartreuse3": 76, - "cadet_blue": 73, - "sky_blue3": 74, - "steel_blue1": 81, - "pale_green3": 114, - "sea_green3": 78, - "aquamarine3": 79, - "medium_turquoise": 80, - "chartreuse2": 112, - "sea_green2": 83, - "sea_green1": 85, - "aquamarine1": 122, - "dark_slate_gray2": 87, - "dark_magenta": 91, - "dark_violet": 128, - "purple": 129, - "light_pink4": 95, - "plum4": 96, - "medium_purple3": 98, - "slate_blue1": 99, - "yellow4": 106, - "wheat4": 101, - "grey53": 102, - "gray53": 102, - "light_slate_grey": 103, - "light_slate_gray": 103, - "medium_purple": 104, - "light_slate_blue": 105, - "dark_olive_green3": 149, - "dark_sea_green": 108, - "light_sky_blue3": 110, - "sky_blue2": 111, - "dark_sea_green3": 150, - "dark_slate_gray3": 116, - "sky_blue1": 117, - "chartreuse1": 118, - "light_green": 120, - "pale_green1": 156, - "dark_slate_gray1": 123, - "red3": 160, - "medium_violet_red": 126, - "magenta3": 164, - "dark_orange3": 166, - "indian_red": 167, - "hot_pink3": 168, - "medium_orchid3": 133, - "medium_orchid": 134, - "medium_purple2": 140, - "dark_goldenrod": 136, - "light_salmon3": 173, - "rosy_brown": 138, - "grey63": 139, - "gray63": 139, - "medium_purple1": 141, - "gold3": 178, - "dark_khaki": 143, - "navajo_white3": 144, - "grey69": 145, - "gray69": 145, - "light_steel_blue3": 146, - "light_steel_blue": 147, - "yellow3": 184, - "dark_sea_green2": 157, - "light_cyan3": 152, - "light_sky_blue1": 153, - "green_yellow": 154, - "dark_olive_green2": 155, - "dark_sea_green1": 193, - "pale_turquoise1": 159, - "deep_pink3": 162, - "magenta2": 200, - "hot_pink2": 169, - "orchid": 170, - "medium_orchid1": 207, - "orange3": 172, - "light_pink3": 174, - "pink3": 175, - "plum3": 176, - "violet": 177, - "light_goldenrod3": 179, - "tan": 180, - "misty_rose3": 181, - "thistle3": 182, - "plum2": 183, - "khaki3": 185, - "light_goldenrod2": 222, - "light_yellow3": 187, - "grey84": 188, - "gray84": 188, - "light_steel_blue1": 189, - "yellow2": 190, - "dark_olive_green1": 192, - "honeydew2": 194, - "light_cyan1": 195, - "red1": 196, - "deep_pink2": 197, - "deep_pink1": 199, - "magenta1": 201, - "orange_red1": 202, - "indian_red1": 204, - "hot_pink": 206, - "dark_orange": 208, - "salmon1": 209, - "light_coral": 210, - "pale_violet_red1": 211, - "orchid2": 212, - "orchid1": 213, - "orange1": 214, - "sandy_brown": 215, - "light_salmon1": 216, - "light_pink1": 217, - "pink1": 218, - "plum1": 219, - "gold1": 220, - "navajo_white1": 223, - "misty_rose1": 224, - "thistle1": 225, - "yellow1": 226, - "light_goldenrod1": 227, - "khaki1": 228, - "wheat1": 229, - "cornsilk1": 230, - "grey100": 231, - "gray100": 231, - "grey3": 232, - "gray3": 232, - "grey7": 233, - "gray7": 233, - "grey11": 234, - "gray11": 234, - "grey15": 235, - "gray15": 235, - "grey19": 236, - "gray19": 236, - "grey23": 237, - "gray23": 237, - "grey27": 238, - "gray27": 238, - "grey30": 239, - "gray30": 239, - "grey35": 240, - "gray35": 240, - "grey39": 241, - "gray39": 241, - "grey42": 242, - "gray42": 242, - "grey46": 243, - "gray46": 243, - "grey50": 244, - "gray50": 244, - "grey54": 245, - "gray54": 245, - "grey58": 246, - "gray58": 246, - "grey62": 247, - "gray62": 247, - "grey66": 248, - "gray66": 248, - "grey70": 249, - "gray70": 249, - "grey74": 250, - "gray74": 250, - "grey78": 251, - "gray78": 251, - "grey82": 252, - "gray82": 252, - "grey85": 253, - "gray85": 253, - "grey89": 254, - "gray89": 254, - "grey93": 255, - "gray93": 255, -} - - -class ColorParseError(Exception): - """The color could not be parsed.""" - - -RE_COLOR = re.compile( - r"""^ -\#([0-9a-f]{6})$| -color\(([0-9]{1,3})\)$| -rgb\(([\d\s,]+)\)$ -""", - re.VERBOSE, -) - - -@rich_repr -class Color(NamedTuple): - """Terminal color definition.""" - - name: str - """The name of the color (typically the input to Color.parse).""" - type: ColorType - """The type of the color.""" - number: Optional[int] = None - """The color number, if a standard color, or None.""" - triplet: Optional[ColorTriplet] = None - """A triplet of color components, if an RGB color.""" - - def __rich__(self) -> "Text": - """Displays the actual color if Rich printed.""" - from .style import Style - from .text import Text - - return Text.assemble( - f"", - ) - - def __rich_repr__(self) -> Result: - yield self.name - yield self.type - yield "number", self.number, None - yield "triplet", self.triplet, None - - @property - def system(self) -> ColorSystem: - """Get the native color system for this color.""" - if self.type == ColorType.DEFAULT: - return ColorSystem.STANDARD - return ColorSystem(int(self.type)) - - @property - def is_system_defined(self) -> bool: - """Check if the color is ultimately defined by the system.""" - return self.system not in (ColorSystem.EIGHT_BIT, ColorSystem.TRUECOLOR) - - @property - def is_default(self) -> bool: - """Check if the color is a default color.""" - return self.type == ColorType.DEFAULT - - def get_truecolor( - self, theme: Optional["TerminalTheme"] = None, foreground: bool = True - ) -> ColorTriplet: - """Get an equivalent color triplet for this color. - - Args: - theme (TerminalTheme, optional): Optional terminal theme, or None to use default. Defaults to None. - foreground (bool, optional): True for a foreground color, or False for background. Defaults to True. - - Returns: - ColorTriplet: A color triplet containing RGB components. - """ - - if theme is None: - theme = DEFAULT_TERMINAL_THEME - if self.type == ColorType.TRUECOLOR: - assert self.triplet is not None - return self.triplet - elif self.type == ColorType.EIGHT_BIT: - assert self.number is not None - return EIGHT_BIT_PALETTE[self.number] - elif self.type == ColorType.STANDARD: - assert self.number is not None - return theme.ansi_colors[self.number] - elif self.type == ColorType.WINDOWS: - assert self.number is not None - return WINDOWS_PALETTE[self.number] - else: # self.type == ColorType.DEFAULT: - assert self.number is None - return theme.foreground_color if foreground else theme.background_color - - @classmethod - def from_ansi(cls, number: int) -> "Color": - """Create a Color number from it's 8-bit ansi number. - - Args: - number (int): A number between 0-255 inclusive. - - Returns: - Color: A new Color instance. - """ - return cls( - name=f"color({number})", - type=(ColorType.STANDARD if number < 16 else ColorType.EIGHT_BIT), - number=number, - ) - - @classmethod - def from_triplet(cls, triplet: "ColorTriplet") -> "Color": - """Create a truecolor RGB color from a triplet of values. - - Args: - triplet (ColorTriplet): A color triplet containing red, green and blue components. - - Returns: - Color: A new color object. - """ - return cls(name=triplet.hex, type=ColorType.TRUECOLOR, triplet=triplet) - - @classmethod - def from_rgb(cls, red: float, green: float, blue: float) -> "Color": - """Create a truecolor from three color components in the range(0->255). - - Args: - red (float): Red component in range 0-255. - green (float): Green component in range 0-255. - blue (float): Blue component in range 0-255. - - Returns: - Color: A new color object. - """ - return cls.from_triplet(ColorTriplet(int(red), int(green), int(blue))) - - @classmethod - def default(cls) -> "Color": - """Get a Color instance representing the default color. - - Returns: - Color: Default color. - """ - return cls(name="default", type=ColorType.DEFAULT) - - @classmethod - @lru_cache(maxsize=1024) - def parse(cls, color: str) -> "Color": - """Parse a color definition.""" - original_color = color - color = color.lower().strip() - - if color == "default": - return cls(color, type=ColorType.DEFAULT) - - color_number = ANSI_COLOR_NAMES.get(color) - if color_number is not None: - return cls( - color, - type=(ColorType.STANDARD if color_number < 16 else ColorType.EIGHT_BIT), - number=color_number, - ) - - color_match = RE_COLOR.match(color) - if color_match is None: - raise ColorParseError(f"{original_color!r} is not a valid color") - - color_24, color_8, color_rgb = color_match.groups() - if color_24: - triplet = ColorTriplet( - int(color_24[0:2], 16), int(color_24[2:4], 16), int(color_24[4:6], 16) - ) - return cls(color, ColorType.TRUECOLOR, triplet=triplet) - - elif color_8: - number = int(color_8) - if number > 255: - raise ColorParseError(f"color number must be <= 255 in {color!r}") - return cls( - color, - type=(ColorType.STANDARD if number < 16 else ColorType.EIGHT_BIT), - number=number, - ) - - else: # color_rgb: - components = color_rgb.split(",") - if len(components) != 3: - raise ColorParseError( - f"expected three components in {original_color!r}" - ) - red, green, blue = components - triplet = ColorTriplet(int(red), int(green), int(blue)) - if not all(component <= 255 for component in triplet): - raise ColorParseError( - f"color components must be <= 255 in {original_color!r}" - ) - return cls(color, ColorType.TRUECOLOR, triplet=triplet) - - @lru_cache(maxsize=1024) - def get_ansi_codes(self, foreground: bool = True) -> Tuple[str, ...]: - """Get the ANSI escape codes for this color.""" - _type = self.type - if _type == ColorType.DEFAULT: - return ("39" if foreground else "49",) - - elif _type == ColorType.WINDOWS: - number = self.number - assert number is not None - fore, back = (30, 40) if number < 8 else (82, 92) - return (str(fore + number if foreground else back + number),) - - elif _type == ColorType.STANDARD: - number = self.number - assert number is not None - fore, back = (30, 40) if number < 8 else (82, 92) - return (str(fore + number if foreground else back + number),) - - elif _type == ColorType.EIGHT_BIT: - assert self.number is not None - return ("38" if foreground else "48", "5", str(self.number)) - - else: # self.standard == ColorStandard.TRUECOLOR: - assert self.triplet is not None - red, green, blue = self.triplet - return ("38" if foreground else "48", "2", str(red), str(green), str(blue)) - - @lru_cache(maxsize=1024) - def downgrade(self, system: ColorSystem) -> "Color": - """Downgrade a color system to a system with fewer colors.""" - - if self.type in (ColorType.DEFAULT, system): - return self - # Convert to 8-bit color from truecolor color - if system == ColorSystem.EIGHT_BIT and self.system == ColorSystem.TRUECOLOR: - assert self.triplet is not None - _h, l, s = rgb_to_hls(*self.triplet.normalized) - # If saturation is under 15% assume it is grayscale - if s < 0.15: - gray = round(l * 25.0) - if gray == 0: - color_number = 16 - elif gray == 25: - color_number = 231 - else: - color_number = 231 + gray - return Color(self.name, ColorType.EIGHT_BIT, number=color_number) - - red, green, blue = self.triplet - six_red = red / 95 if red < 95 else 1 + (red - 95) / 40 - six_green = green / 95 if green < 95 else 1 + (green - 95) / 40 - six_blue = blue / 95 if blue < 95 else 1 + (blue - 95) / 40 - - color_number = ( - 16 + 36 * round(six_red) + 6 * round(six_green) + round(six_blue) - ) - return Color(self.name, ColorType.EIGHT_BIT, number=color_number) - - # Convert to standard from truecolor or 8-bit - elif system == ColorSystem.STANDARD: - if self.system == ColorSystem.TRUECOLOR: - assert self.triplet is not None - triplet = self.triplet - else: # self.system == ColorSystem.EIGHT_BIT - assert self.number is not None - triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) - - color_number = STANDARD_PALETTE.match(triplet) - return Color(self.name, ColorType.STANDARD, number=color_number) - - elif system == ColorSystem.WINDOWS: - if self.system == ColorSystem.TRUECOLOR: - assert self.triplet is not None - triplet = self.triplet - else: # self.system == ColorSystem.EIGHT_BIT - assert self.number is not None - if self.number < 16: - return Color(self.name, ColorType.WINDOWS, number=self.number) - triplet = ColorTriplet(*EIGHT_BIT_PALETTE[self.number]) - - color_number = WINDOWS_PALETTE.match(triplet) - return Color(self.name, ColorType.WINDOWS, number=color_number) - - return self - - -def parse_rgb_hex(hex_color: str) -> ColorTriplet: - """Parse six hex characters in to RGB triplet.""" - assert len(hex_color) == 6, "must be 6 characters" - color = ColorTriplet( - int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16) - ) - return color - - -def blend_rgb( - color1: ColorTriplet, color2: ColorTriplet, cross_fade: float = 0.5 -) -> ColorTriplet: - """Blend one RGB color in to another.""" - r1, g1, b1 = color1 - r2, g2, b2 = color2 - new_color = ColorTriplet( - int(r1 + (r2 - r1) * cross_fade), - int(g1 + (g2 - g1) * cross_fade), - int(b1 + (b2 - b1) * cross_fade), - ) - return new_color - - -if __name__ == "__main__": # pragma: no cover - - from .console import Console - from .table import Table - from .text import Text - - console = Console() - - table = Table(show_footer=False, show_edge=True) - table.add_column("Color", width=10, overflow="ellipsis") - table.add_column("Number", justify="right", style="yellow") - table.add_column("Name", style="green") - table.add_column("Hex", style="blue") - table.add_column("RGB", style="magenta") - - colors = sorted((v, k) for k, v in ANSI_COLOR_NAMES.items()) - for color_number, name in colors: - if "grey" in name: - continue - color_cell = Text(" " * 10, style=f"on {name}") - if color_number < 16: - table.add_row(color_cell, f"{color_number}", Text(f'"{name}"')) - else: - color = EIGHT_BIT_PALETTE[color_number] # type: ignore[has-type] - table.add_row( - color_cell, str(color_number), Text(f'"{name}"'), color.hex, color.rgb - ) - - console.print(table) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py deleted file mode 100644 index 02cab32..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py +++ /dev/null @@ -1,38 +0,0 @@ -from typing import NamedTuple, Tuple - - -class ColorTriplet(NamedTuple): - """The red, green, and blue components of a color.""" - - red: int - """Red component in 0 to 255 range.""" - green: int - """Green component in 0 to 255 range.""" - blue: int - """Blue component in 0 to 255 range.""" - - @property - def hex(self) -> str: - """get the color triplet in CSS style.""" - red, green, blue = self - return f"#{red:02x}{green:02x}{blue:02x}" - - @property - def rgb(self) -> str: - """The color in RGB format. - - Returns: - str: An rgb color, e.g. ``"rgb(100,23,255)"``. - """ - red, green, blue = self - return f"rgb({red},{green},{blue})" - - @property - def normalized(self) -> Tuple[float, float, float]: - """Convert components into floats between 0 and 1. - - Returns: - Tuple[float, float, float]: A tuple of three normalized colour components. - """ - red, green, blue = self - return red / 255.0, green / 255.0, blue / 255.0 diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/columns.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/columns.py deleted file mode 100644 index 669a3a7..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/columns.py +++ /dev/null @@ -1,187 +0,0 @@ -from collections import defaultdict -from itertools import chain -from operator import itemgetter -from typing import Dict, Iterable, List, Optional, Tuple - -from .align import Align, AlignMethod -from .console import Console, ConsoleOptions, RenderableType, RenderResult -from .constrain import Constrain -from .measure import Measurement -from .padding import Padding, PaddingDimensions -from .table import Table -from .text import TextType -from .jupyter import JupyterMixin - - -class Columns(JupyterMixin): - """Display renderables in neat columns. - - Args: - renderables (Iterable[RenderableType]): Any number of Rich renderables (including str). - width (int, optional): The desired width of the columns, or None to auto detect. Defaults to None. - padding (PaddingDimensions, optional): Optional padding around cells. Defaults to (0, 1). - expand (bool, optional): Expand columns to full width. Defaults to False. - equal (bool, optional): Arrange in to equal sized columns. Defaults to False. - column_first (bool, optional): Align items from top to bottom (rather than left to right). Defaults to False. - right_to_left (bool, optional): Start column from right hand side. Defaults to False. - align (str, optional): Align value ("left", "right", or "center") or None for default. Defaults to None. - title (TextType, optional): Optional title for Columns. - """ - - def __init__( - self, - renderables: Optional[Iterable[RenderableType]] = None, - padding: PaddingDimensions = (0, 1), - *, - width: Optional[int] = None, - expand: bool = False, - equal: bool = False, - column_first: bool = False, - right_to_left: bool = False, - align: Optional[AlignMethod] = None, - title: Optional[TextType] = None, - ) -> None: - self.renderables = list(renderables or []) - self.width = width - self.padding = padding - self.expand = expand - self.equal = equal - self.column_first = column_first - self.right_to_left = right_to_left - self.align: Optional[AlignMethod] = align - self.title = title - - def add_renderable(self, renderable: RenderableType) -> None: - """Add a renderable to the columns. - - Args: - renderable (RenderableType): Any renderable object. - """ - self.renderables.append(renderable) - - def __rich_console__( - self, console: Console, options: ConsoleOptions - ) -> RenderResult: - render_str = console.render_str - renderables = [ - render_str(renderable) if isinstance(renderable, str) else renderable - for renderable in self.renderables - ] - if not renderables: - return - _top, right, _bottom, left = Padding.unpack(self.padding) - width_padding = max(left, right) - max_width = options.max_width - widths: Dict[int, int] = defaultdict(int) - column_count = len(renderables) - - get_measurement = Measurement.get - renderable_widths = [ - get_measurement(console, options, renderable).maximum - for renderable in renderables - ] - if self.equal: - renderable_widths = [max(renderable_widths)] * len(renderable_widths) - - def iter_renderables( - column_count: int, - ) -> Iterable[Tuple[int, Optional[RenderableType]]]: - item_count = len(renderables) - if self.column_first: - width_renderables = list(zip(renderable_widths, renderables)) - - column_lengths: List[int] = [item_count // column_count] * column_count - for col_no in range(item_count % column_count): - column_lengths[col_no] += 1 - - row_count = (item_count + column_count - 1) // column_count - cells = [[-1] * column_count for _ in range(row_count)] - row = col = 0 - for index in range(item_count): - cells[row][col] = index - column_lengths[col] -= 1 - if column_lengths[col]: - row += 1 - else: - col += 1 - row = 0 - for index in chain.from_iterable(cells): - if index == -1: - break - yield width_renderables[index] - else: - yield from zip(renderable_widths, renderables) - # Pad odd elements with spaces - if item_count % column_count: - for _ in range(column_count - (item_count % column_count)): - yield 0, None - - table = Table.grid(padding=self.padding, collapse_padding=True, pad_edge=False) - table.expand = self.expand - table.title = self.title - - if self.width is not None: - column_count = (max_width) // (self.width + width_padding) - for _ in range(column_count): - table.add_column(width=self.width) - else: - while column_count > 1: - widths.clear() - column_no = 0 - for renderable_width, _ in iter_renderables(column_count): - widths[column_no] = max(widths[column_no], renderable_width) - total_width = sum(widths.values()) + width_padding * ( - len(widths) - 1 - ) - if total_width > max_width: - column_count = len(widths) - 1 - break - else: - column_no = (column_no + 1) % column_count - else: - break - - get_renderable = itemgetter(1) - _renderables = [ - get_renderable(_renderable) - for _renderable in iter_renderables(column_count) - ] - if self.equal: - _renderables = [ - None - if renderable is None - else Constrain(renderable, renderable_widths[0]) - for renderable in _renderables - ] - if self.align: - align = self.align - _Align = Align - _renderables = [ - None if renderable is None else _Align(renderable, align) - for renderable in _renderables - ] - - right_to_left = self.right_to_left - add_row = table.add_row - for start in range(0, len(_renderables), column_count): - row = _renderables[start : start + column_count] - if right_to_left: - row = row[::-1] - add_row(*row) - yield table - - -if __name__ == "__main__": # pragma: no cover - import os - - console = Console() - - files = [f"{i} {s}" for i, s in enumerate(sorted(os.listdir()))] - columns = Columns(files, padding=(0, 1), expand=False, equal=False) - console.print(columns) - console.rule() - columns.column_first = True - console.print(columns) - columns.right_to_left = True - console.rule() - console.print(columns) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/console.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/console.py deleted file mode 100644 index e559cbb..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/console.py +++ /dev/null @@ -1,2633 +0,0 @@ -import inspect -import os -import platform -import sys -import threading -import zlib -from abc import ABC, abstractmethod -from dataclasses import dataclass, field -from datetime import datetime -from functools import wraps -from getpass import getpass -from html import escape -from inspect import isclass -from itertools import islice -from math import ceil -from time import monotonic -from types import FrameType, ModuleType, TracebackType -from typing import ( - IO, - TYPE_CHECKING, - Any, - Callable, - Dict, - Iterable, - List, - Mapping, - NamedTuple, - Optional, - TextIO, - Tuple, - Type, - Union, - cast, -) - -from pip._vendor.rich._null_file import NULL_FILE - -if sys.version_info >= (3, 8): - from typing import Literal, Protocol, runtime_checkable -else: - from pip._vendor.typing_extensions import ( - Literal, - Protocol, - runtime_checkable, - ) # pragma: no cover - -from . import errors, themes -from ._emoji_replace import _emoji_replace -from ._export_format import CONSOLE_HTML_FORMAT, CONSOLE_SVG_FORMAT -from ._fileno import get_fileno -from ._log_render import FormatTimeCallable, LogRender -from .align import Align, AlignMethod -from .color import ColorSystem, blend_rgb -from .control import Control -from .emoji import EmojiVariant -from .highlighter import NullHighlighter, ReprHighlighter -from .markup import render as render_markup -from .measure import Measurement, measure_renderables -from .pager import Pager, SystemPager -from .pretty import Pretty, is_expandable -from .protocol import rich_cast -from .region import Region -from .scope import render_scope -from .screen import Screen -from .segment import Segment -from .style import Style, StyleType -from .styled import Styled -from .terminal_theme import DEFAULT_TERMINAL_THEME, SVG_EXPORT_THEME, TerminalTheme -from .text import Text, TextType -from .theme import Theme, ThemeStack - -if TYPE_CHECKING: - from ._windows import WindowsConsoleFeatures - from .live import Live - from .status import Status - -JUPYTER_DEFAULT_COLUMNS = 115 -JUPYTER_DEFAULT_LINES = 100 -WINDOWS = platform.system() == "Windows" - -HighlighterType = Callable[[Union[str, "Text"]], "Text"] -JustifyMethod = Literal["default", "left", "center", "right", "full"] -OverflowMethod = Literal["fold", "crop", "ellipsis", "ignore"] - - -class NoChange: - pass - - -NO_CHANGE = NoChange() - -try: - _STDIN_FILENO = sys.__stdin__.fileno() -except Exception: - _STDIN_FILENO = 0 -try: - _STDOUT_FILENO = sys.__stdout__.fileno() -except Exception: - _STDOUT_FILENO = 1 -try: - _STDERR_FILENO = sys.__stderr__.fileno() -except Exception: - _STDERR_FILENO = 2 - -_STD_STREAMS = (_STDIN_FILENO, _STDOUT_FILENO, _STDERR_FILENO) -_STD_STREAMS_OUTPUT = (_STDOUT_FILENO, _STDERR_FILENO) - - -_TERM_COLORS = { - "kitty": ColorSystem.EIGHT_BIT, - "256color": ColorSystem.EIGHT_BIT, - "16color": ColorSystem.STANDARD, -} - - -class ConsoleDimensions(NamedTuple): - """Size of the terminal.""" - - width: int - """The width of the console in 'cells'.""" - height: int - """The height of the console in lines.""" - - -@dataclass -class ConsoleOptions: - """Options for __rich_console__ method.""" - - size: ConsoleDimensions - """Size of console.""" - legacy_windows: bool - """legacy_windows: flag for legacy windows.""" - min_width: int - """Minimum width of renderable.""" - max_width: int - """Maximum width of renderable.""" - is_terminal: bool - """True if the target is a terminal, otherwise False.""" - encoding: str - """Encoding of terminal.""" - max_height: int - """Height of container (starts as terminal)""" - justify: Optional[JustifyMethod] = None - """Justify value override for renderable.""" - overflow: Optional[OverflowMethod] = None - """Overflow value override for renderable.""" - no_wrap: Optional[bool] = False - """Disable wrapping for text.""" - highlight: Optional[bool] = None - """Highlight override for render_str.""" - markup: Optional[bool] = None - """Enable markup when rendering strings.""" - height: Optional[int] = None - - @property - def ascii_only(self) -> bool: - """Check if renderables should use ascii only.""" - return not self.encoding.startswith("utf") - - def copy(self) -> "ConsoleOptions": - """Return a copy of the options. - - Returns: - ConsoleOptions: a copy of self. - """ - options: ConsoleOptions = ConsoleOptions.__new__(ConsoleOptions) - options.__dict__ = self.__dict__.copy() - return options - - def update( - self, - *, - width: Union[int, NoChange] = NO_CHANGE, - min_width: Union[int, NoChange] = NO_CHANGE, - max_width: Union[int, NoChange] = NO_CHANGE, - justify: Union[Optional[JustifyMethod], NoChange] = NO_CHANGE, - overflow: Union[Optional[OverflowMethod], NoChange] = NO_CHANGE, - no_wrap: Union[Optional[bool], NoChange] = NO_CHANGE, - highlight: Union[Optional[bool], NoChange] = NO_CHANGE, - markup: Union[Optional[bool], NoChange] = NO_CHANGE, - height: Union[Optional[int], NoChange] = NO_CHANGE, - ) -> "ConsoleOptions": - """Update values, return a copy.""" - options = self.copy() - if not isinstance(width, NoChange): - options.min_width = options.max_width = max(0, width) - if not isinstance(min_width, NoChange): - options.min_width = min_width - if not isinstance(max_width, NoChange): - options.max_width = max_width - if not isinstance(justify, NoChange): - options.justify = justify - if not isinstance(overflow, NoChange): - options.overflow = overflow - if not isinstance(no_wrap, NoChange): - options.no_wrap = no_wrap - if not isinstance(highlight, NoChange): - options.highlight = highlight - if not isinstance(markup, NoChange): - options.markup = markup - if not isinstance(height, NoChange): - if height is not None: - options.max_height = height - options.height = None if height is None else max(0, height) - return options - - def update_width(self, width: int) -> "ConsoleOptions": - """Update just the width, return a copy. - - Args: - width (int): New width (sets both min_width and max_width) - - Returns: - ~ConsoleOptions: New console options instance. - """ - options = self.copy() - options.min_width = options.max_width = max(0, width) - return options - - def update_height(self, height: int) -> "ConsoleOptions": - """Update the height, and return a copy. - - Args: - height (int): New height - - Returns: - ~ConsoleOptions: New Console options instance. - """ - options = self.copy() - options.max_height = options.height = height - return options - - def reset_height(self) -> "ConsoleOptions": - """Return a copy of the options with height set to ``None``. - - Returns: - ~ConsoleOptions: New console options instance. - """ - options = self.copy() - options.height = None - return options - - def update_dimensions(self, width: int, height: int) -> "ConsoleOptions": - """Update the width and height, and return a copy. - - Args: - width (int): New width (sets both min_width and max_width). - height (int): New height. - - Returns: - ~ConsoleOptions: New console options instance. - """ - options = self.copy() - options.min_width = options.max_width = max(0, width) - options.height = options.max_height = height - return options - - -@runtime_checkable -class RichCast(Protocol): - """An object that may be 'cast' to a console renderable.""" - - def __rich__( - self, - ) -> Union["ConsoleRenderable", "RichCast", str]: # pragma: no cover - ... - - -@runtime_checkable -class ConsoleRenderable(Protocol): - """An object that supports the console protocol.""" - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> "RenderResult": # pragma: no cover - ... - - -# A type that may be rendered by Console. -RenderableType = Union[ConsoleRenderable, RichCast, str] - -# The result of calling a __rich_console__ method. -RenderResult = Iterable[Union[RenderableType, Segment]] - -_null_highlighter = NullHighlighter() - - -class CaptureError(Exception): - """An error in the Capture context manager.""" - - -class NewLine: - """A renderable to generate new line(s)""" - - def __init__(self, count: int = 1) -> None: - self.count = count - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> Iterable[Segment]: - yield Segment("\n" * self.count) - - -class ScreenUpdate: - """Render a list of lines at a given offset.""" - - def __init__(self, lines: List[List[Segment]], x: int, y: int) -> None: - self._lines = lines - self.x = x - self.y = y - - def __rich_console__( - self, console: "Console", options: ConsoleOptions - ) -> RenderResult: - x = self.x - move_to = Control.move_to - for offset, line in enumerate(self._lines, self.y): - yield move_to(x, offset) - yield from line - - -class Capture: - """Context manager to capture the result of printing to the console. - See :meth:`~rich.console.Console.capture` for how to use. - - Args: - console (Console): A console instance to capture output. - """ - - def __init__(self, console: "Console") -> None: - self._console = console - self._result: Optional[str] = None - - def __enter__(self) -> "Capture": - self._console.begin_capture() - return self - - def __exit__( - self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], - ) -> None: - self._result = self._console.end_capture() - - def get(self) -> str: - """Get the result of the capture.""" - if self._result is None: - raise CaptureError( - "Capture result is not available until context manager exits." - ) - return self._result - - -class ThemeContext: - """A context manager to use a temporary theme. See :meth:`~rich.console.Console.use_theme` for usage.""" - - def __init__(self, console: "Console", theme: Theme, inherit: bool = True) -> None: - self.console = console - self.theme = theme - self.inherit = inherit - - def __enter__(self) -> "ThemeContext": - self.console.push_theme(self.theme) - return self - - def __exit__( - self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], - ) -> None: - self.console.pop_theme() - - -class PagerContext: - """A context manager that 'pages' content. See :meth:`~rich.console.Console.pager` for usage.""" - - def __init__( - self, - console: "Console", - pager: Optional[Pager] = None, - styles: bool = False, - links: bool = False, - ) -> None: - self._console = console - self.pager = SystemPager() if pager is None else pager - self.styles = styles - self.links = links - - def __enter__(self) -> "PagerContext": - self._console._enter_buffer() - return self - - def __exit__( - self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], - ) -> None: - if exc_type is None: - with self._console._lock: - buffer: List[Segment] = self._console._buffer[:] - del self._console._buffer[:] - segments: Iterable[Segment] = buffer - if not self.styles: - segments = Segment.strip_styles(segments) - elif not self.links: - segments = Segment.strip_links(segments) - content = self._console._render_buffer(segments) - self.pager.show(content) - self._console._exit_buffer() - - -class ScreenContext: - """A context manager that enables an alternative screen. See :meth:`~rich.console.Console.screen` for usage.""" - - def __init__( - self, console: "Console", hide_cursor: bool, style: StyleType = "" - ) -> None: - self.console = console - self.hide_cursor = hide_cursor - self.screen = Screen(style=style) - self._changed = False - - def update( - self, *renderables: RenderableType, style: Optional[StyleType] = None - ) -> None: - """Update the screen. - - Args: - renderable (RenderableType, optional): Optional renderable to replace current renderable, - or None for no change. Defaults to None. - style: (Style, optional): Replacement style, or None for no change. Defaults to None. - """ - if renderables: - self.screen.renderable = ( - Group(*renderables) if len(renderables) > 1 else renderables[0] - ) - if style is not None: - self.screen.style = style - self.console.print(self.screen, end="") - - def __enter__(self) -> "ScreenContext": - self._changed = self.console.set_alt_screen(True) - if self._changed and self.hide_cursor: - self.console.show_cursor(False) - return self - - def __exit__( - self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], - ) -> None: - if self._changed: - self.console.set_alt_screen(False) - if self.hide_cursor: - self.console.show_cursor(True) - - -class Group: - """Takes a group of renderables and returns a renderable object that renders the group. - - Args: - renderables (Iterable[RenderableType]): An iterable of renderable objects. - fit (bool, optional): Fit dimension of group to contents, or fill available space. Defaults to True. - """ - - def __init__(self, *renderables: "RenderableType", fit: bool = True) -> None: - self._renderables = renderables - self.fit = fit - self._render: Optional[List[RenderableType]] = None - - @property - def renderables(self) -> List["RenderableType"]: - if self._render is None: - self._render = list(self._renderables) - return self._render - - def __rich_measure__( - self, console: "Console", options: "ConsoleOptions" - ) -> "Measurement": - if self.fit: - return measure_renderables(console, options, self.renderables) - else: - return Measurement(options.max_width, options.max_width) - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> RenderResult: - yield from self.renderables - - -def group(fit: bool = True) -> Callable[..., Callable[..., Group]]: - """A decorator that turns an iterable of renderables in to a group. - - Args: - fit (bool, optional): Fit dimension of group to contents, or fill available space. Defaults to True. - """ - - def decorator( - method: Callable[..., Iterable[RenderableType]] - ) -> Callable[..., Group]: - """Convert a method that returns an iterable of renderables in to a Group.""" - - @wraps(method) - def _replace(*args: Any, **kwargs: Any) -> Group: - renderables = method(*args, **kwargs) - return Group(*renderables, fit=fit) - - return _replace - - return decorator - - -def _is_jupyter() -> bool: # pragma: no cover - """Check if we're running in a Jupyter notebook.""" - try: - get_ipython # type: ignore[name-defined] - except NameError: - return False - ipython = get_ipython() # type: ignore[name-defined] - shell = ipython.__class__.__name__ - if ( - "google.colab" in str(ipython.__class__) - or os.getenv("DATABRICKS_RUNTIME_VERSION") - or shell == "ZMQInteractiveShell" - ): - return True # Jupyter notebook or qtconsole - elif shell == "TerminalInteractiveShell": - return False # Terminal running IPython - else: - return False # Other type (?) - - -COLOR_SYSTEMS = { - "standard": ColorSystem.STANDARD, - "256": ColorSystem.EIGHT_BIT, - "truecolor": ColorSystem.TRUECOLOR, - "windows": ColorSystem.WINDOWS, -} - -_COLOR_SYSTEMS_NAMES = {system: name for name, system in COLOR_SYSTEMS.items()} - - -@dataclass -class ConsoleThreadLocals(threading.local): - """Thread local values for Console context.""" - - theme_stack: ThemeStack - buffer: List[Segment] = field(default_factory=list) - buffer_index: int = 0 - - -class RenderHook(ABC): - """Provides hooks in to the render process.""" - - @abstractmethod - def process_renderables( - self, renderables: List[ConsoleRenderable] - ) -> List[ConsoleRenderable]: - """Called with a list of objects to render. - - This method can return a new list of renderables, or modify and return the same list. - - Args: - renderables (List[ConsoleRenderable]): A number of renderable objects. - - Returns: - List[ConsoleRenderable]: A replacement list of renderables. - """ - - -_windows_console_features: Optional["WindowsConsoleFeatures"] = None - - -def get_windows_console_features() -> "WindowsConsoleFeatures": # pragma: no cover - global _windows_console_features - if _windows_console_features is not None: - return _windows_console_features - from ._windows import get_windows_console_features - - _windows_console_features = get_windows_console_features() - return _windows_console_features - - -def detect_legacy_windows() -> bool: - """Detect legacy Windows.""" - return WINDOWS and not get_windows_console_features().vt - - -class Console: - """A high level console interface. - - Args: - color_system (str, optional): The color system supported by your terminal, - either ``"standard"``, ``"256"`` or ``"truecolor"``. Leave as ``"auto"`` to autodetect. - force_terminal (Optional[bool], optional): Enable/disable terminal control codes, or None to auto-detect terminal. Defaults to None. - force_jupyter (Optional[bool], optional): Enable/disable Jupyter rendering, or None to auto-detect Jupyter. Defaults to None. - force_interactive (Optional[bool], optional): Enable/disable interactive mode, or None to auto detect. Defaults to None. - soft_wrap (Optional[bool], optional): Set soft wrap default on print method. Defaults to False. - theme (Theme, optional): An optional style theme object, or ``None`` for default theme. - stderr (bool, optional): Use stderr rather than stdout if ``file`` is not specified. Defaults to False. - file (IO, optional): A file object where the console should write to. Defaults to stdout. - quiet (bool, Optional): Boolean to suppress all output. Defaults to False. - width (int, optional): The width of the terminal. Leave as default to auto-detect width. - height (int, optional): The height of the terminal. Leave as default to auto-detect height. - style (StyleType, optional): Style to apply to all output, or None for no style. Defaults to None. - no_color (Optional[bool], optional): Enabled no color mode, or None to auto detect. Defaults to None. - tab_size (int, optional): Number of spaces used to replace a tab character. Defaults to 8. - record (bool, optional): Boolean to enable recording of terminal output, - required to call :meth:`export_html`, :meth:`export_svg`, and :meth:`export_text`. Defaults to False. - markup (bool, optional): Boolean to enable :ref:`console_markup`. Defaults to True. - emoji (bool, optional): Enable emoji code. Defaults to True. - emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None. - highlight (bool, optional): Enable automatic highlighting. Defaults to True. - log_time (bool, optional): Boolean to enable logging of time by :meth:`log` methods. Defaults to True. - log_path (bool, optional): Boolean to enable the logging of the caller by :meth:`log`. Defaults to True. - log_time_format (Union[str, TimeFormatterCallable], optional): If ``log_time`` is enabled, either string for strftime or callable that formats the time. Defaults to "[%X] ". - highlighter (HighlighterType, optional): Default highlighter. - legacy_windows (bool, optional): Enable legacy Windows mode, or ``None`` to auto detect. Defaults to ``None``. - safe_box (bool, optional): Restrict box options that don't render on legacy Windows. - get_datetime (Callable[[], datetime], optional): Callable that gets the current time as a datetime.datetime object (used by Console.log), - or None for datetime.now. - get_time (Callable[[], time], optional): Callable that gets the current time in seconds, default uses time.monotonic. - """ - - _environ: Mapping[str, str] = os.environ - - def __init__( - self, - *, - color_system: Optional[ - Literal["auto", "standard", "256", "truecolor", "windows"] - ] = "auto", - force_terminal: Optional[bool] = None, - force_jupyter: Optional[bool] = None, - force_interactive: Optional[bool] = None, - soft_wrap: bool = False, - theme: Optional[Theme] = None, - stderr: bool = False, - file: Optional[IO[str]] = None, - quiet: bool = False, - width: Optional[int] = None, - height: Optional[int] = None, - style: Optional[StyleType] = None, - no_color: Optional[bool] = None, - tab_size: int = 8, - record: bool = False, - markup: bool = True, - emoji: bool = True, - emoji_variant: Optional[EmojiVariant] = None, - highlight: bool = True, - log_time: bool = True, - log_path: bool = True, - log_time_format: Union[str, FormatTimeCallable] = "[%X]", - highlighter: Optional["HighlighterType"] = ReprHighlighter(), - legacy_windows: Optional[bool] = None, - safe_box: bool = True, - get_datetime: Optional[Callable[[], datetime]] = None, - get_time: Optional[Callable[[], float]] = None, - _environ: Optional[Mapping[str, str]] = None, - ): - # Copy of os.environ allows us to replace it for testing - if _environ is not None: - self._environ = _environ - - self.is_jupyter = _is_jupyter() if force_jupyter is None else force_jupyter - if self.is_jupyter: - if width is None: - jupyter_columns = self._environ.get("JUPYTER_COLUMNS") - if jupyter_columns is not None and jupyter_columns.isdigit(): - width = int(jupyter_columns) - else: - width = JUPYTER_DEFAULT_COLUMNS - if height is None: - jupyter_lines = self._environ.get("JUPYTER_LINES") - if jupyter_lines is not None and jupyter_lines.isdigit(): - height = int(jupyter_lines) - else: - height = JUPYTER_DEFAULT_LINES - - self.tab_size = tab_size - self.record = record - self._markup = markup - self._emoji = emoji - self._emoji_variant: Optional[EmojiVariant] = emoji_variant - self._highlight = highlight - self.legacy_windows: bool = ( - (detect_legacy_windows() and not self.is_jupyter) - if legacy_windows is None - else legacy_windows - ) - - if width is None: - columns = self._environ.get("COLUMNS") - if columns is not None and columns.isdigit(): - width = int(columns) - self.legacy_windows - if height is None: - lines = self._environ.get("LINES") - if lines is not None and lines.isdigit(): - height = int(lines) - - self.soft_wrap = soft_wrap - self._width = width - self._height = height - - self._color_system: Optional[ColorSystem] - - self._force_terminal = None - if force_terminal is not None: - self._force_terminal = force_terminal - - self._file = file - self.quiet = quiet - self.stderr = stderr - - if color_system is None: - self._color_system = None - elif color_system == "auto": - self._color_system = self._detect_color_system() - else: - self._color_system = COLOR_SYSTEMS[color_system] - - self._lock = threading.RLock() - self._log_render = LogRender( - show_time=log_time, - show_path=log_path, - time_format=log_time_format, - ) - self.highlighter: HighlighterType = highlighter or _null_highlighter - self.safe_box = safe_box - self.get_datetime = get_datetime or datetime.now - self.get_time = get_time or monotonic - self.style = style - self.no_color = ( - no_color if no_color is not None else "NO_COLOR" in self._environ - ) - self.is_interactive = ( - (self.is_terminal and not self.is_dumb_terminal) - if force_interactive is None - else force_interactive - ) - - self._record_buffer_lock = threading.RLock() - self._thread_locals = ConsoleThreadLocals( - theme_stack=ThemeStack(themes.DEFAULT if theme is None else theme) - ) - self._record_buffer: List[Segment] = [] - self._render_hooks: List[RenderHook] = [] - self._live: Optional["Live"] = None - self._is_alt_screen = False - - def __repr__(self) -> str: - return f"" - - @property - def file(self) -> IO[str]: - """Get the file object to write to.""" - file = self._file or (sys.stderr if self.stderr else sys.stdout) - file = getattr(file, "rich_proxied_file", file) - if file is None: - file = NULL_FILE - return file - - @file.setter - def file(self, new_file: IO[str]) -> None: - """Set a new file object.""" - self._file = new_file - - @property - def _buffer(self) -> List[Segment]: - """Get a thread local buffer.""" - return self._thread_locals.buffer - - @property - def _buffer_index(self) -> int: - """Get a thread local buffer.""" - return self._thread_locals.buffer_index - - @_buffer_index.setter - def _buffer_index(self, value: int) -> None: - self._thread_locals.buffer_index = value - - @property - def _theme_stack(self) -> ThemeStack: - """Get the thread local theme stack.""" - return self._thread_locals.theme_stack - - def _detect_color_system(self) -> Optional[ColorSystem]: - """Detect color system from env vars.""" - if self.is_jupyter: - return ColorSystem.TRUECOLOR - if not self.is_terminal or self.is_dumb_terminal: - return None - if WINDOWS: # pragma: no cover - if self.legacy_windows: # pragma: no cover - return ColorSystem.WINDOWS - windows_console_features = get_windows_console_features() - return ( - ColorSystem.TRUECOLOR - if windows_console_features.truecolor - else ColorSystem.EIGHT_BIT - ) - else: - color_term = self._environ.get("COLORTERM", "").strip().lower() - if color_term in ("truecolor", "24bit"): - return ColorSystem.TRUECOLOR - term = self._environ.get("TERM", "").strip().lower() - _term_name, _hyphen, colors = term.rpartition("-") - color_system = _TERM_COLORS.get(colors, ColorSystem.STANDARD) - return color_system - - def _enter_buffer(self) -> None: - """Enter in to a buffer context, and buffer all output.""" - self._buffer_index += 1 - - def _exit_buffer(self) -> None: - """Leave buffer context, and render content if required.""" - self._buffer_index -= 1 - self._check_buffer() - - def set_live(self, live: "Live") -> None: - """Set Live instance. Used by Live context manager. - - Args: - live (Live): Live instance using this Console. - - Raises: - errors.LiveError: If this Console has a Live context currently active. - """ - with self._lock: - if self._live is not None: - raise errors.LiveError("Only one live display may be active at once") - self._live = live - - def clear_live(self) -> None: - """Clear the Live instance.""" - with self._lock: - self._live = None - - def push_render_hook(self, hook: RenderHook) -> None: - """Add a new render hook to the stack. - - Args: - hook (RenderHook): Render hook instance. - """ - with self._lock: - self._render_hooks.append(hook) - - def pop_render_hook(self) -> None: - """Pop the last renderhook from the stack.""" - with self._lock: - self._render_hooks.pop() - - def __enter__(self) -> "Console": - """Own context manager to enter buffer context.""" - self._enter_buffer() - return self - - def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: - """Exit buffer context.""" - self._exit_buffer() - - def begin_capture(self) -> None: - """Begin capturing console output. Call :meth:`end_capture` to exit capture mode and return output.""" - self._enter_buffer() - - def end_capture(self) -> str: - """End capture mode and return captured string. - - Returns: - str: Console output. - """ - render_result = self._render_buffer(self._buffer) - del self._buffer[:] - self._exit_buffer() - return render_result - - def push_theme(self, theme: Theme, *, inherit: bool = True) -> None: - """Push a new theme on to the top of the stack, replacing the styles from the previous theme. - Generally speaking, you should call :meth:`~rich.console.Console.use_theme` to get a context manager, rather - than calling this method directly. - - Args: - theme (Theme): A theme instance. - inherit (bool, optional): Inherit existing styles. Defaults to True. - """ - self._theme_stack.push_theme(theme, inherit=inherit) - - def pop_theme(self) -> None: - """Remove theme from top of stack, restoring previous theme.""" - self._theme_stack.pop_theme() - - def use_theme(self, theme: Theme, *, inherit: bool = True) -> ThemeContext: - """Use a different theme for the duration of the context manager. - - Args: - theme (Theme): Theme instance to user. - inherit (bool, optional): Inherit existing console styles. Defaults to True. - - Returns: - ThemeContext: [description] - """ - return ThemeContext(self, theme, inherit) - - @property - def color_system(self) -> Optional[str]: - """Get color system string. - - Returns: - Optional[str]: "standard", "256" or "truecolor". - """ - - if self._color_system is not None: - return _COLOR_SYSTEMS_NAMES[self._color_system] - else: - return None - - @property - def encoding(self) -> str: - """Get the encoding of the console file, e.g. ``"utf-8"``. - - Returns: - str: A standard encoding string. - """ - return (getattr(self.file, "encoding", "utf-8") or "utf-8").lower() - - @property - def is_terminal(self) -> bool: - """Check if the console is writing to a terminal. - - Returns: - bool: True if the console writing to a device capable of - understanding terminal codes, otherwise False. - """ - if self._force_terminal is not None: - return self._force_terminal - - if hasattr(sys.stdin, "__module__") and sys.stdin.__module__.startswith( - "idlelib" - ): - # Return False for Idle which claims to be a tty but can't handle ansi codes - return False - - if self.is_jupyter: - # return False for Jupyter, which may have FORCE_COLOR set - return False - - # If FORCE_COLOR env var has any value at all, we assume a terminal. - force_color = self._environ.get("FORCE_COLOR") - if force_color is not None: - self._force_terminal = True - return True - - isatty: Optional[Callable[[], bool]] = getattr(self.file, "isatty", None) - try: - return False if isatty is None else isatty() - except ValueError: - # in some situation (at the end of a pytest run for example) isatty() can raise - # ValueError: I/O operation on closed file - # return False because we aren't in a terminal anymore - return False - - @property - def is_dumb_terminal(self) -> bool: - """Detect dumb terminal. - - Returns: - bool: True if writing to a dumb terminal, otherwise False. - - """ - _term = self._environ.get("TERM", "") - is_dumb = _term.lower() in ("dumb", "unknown") - return self.is_terminal and is_dumb - - @property - def options(self) -> ConsoleOptions: - """Get default console options.""" - return ConsoleOptions( - max_height=self.size.height, - size=self.size, - legacy_windows=self.legacy_windows, - min_width=1, - max_width=self.width, - encoding=self.encoding, - is_terminal=self.is_terminal, - ) - - @property - def size(self) -> ConsoleDimensions: - """Get the size of the console. - - Returns: - ConsoleDimensions: A named tuple containing the dimensions. - """ - - if self._width is not None and self._height is not None: - return ConsoleDimensions(self._width - self.legacy_windows, self._height) - - if self.is_dumb_terminal: - return ConsoleDimensions(80, 25) - - width: Optional[int] = None - height: Optional[int] = None - - if WINDOWS: # pragma: no cover - try: - width, height = os.get_terminal_size() - except (AttributeError, ValueError, OSError): # Probably not a terminal - pass - else: - for file_descriptor in _STD_STREAMS: - try: - width, height = os.get_terminal_size(file_descriptor) - except (AttributeError, ValueError, OSError): - pass - else: - break - - columns = self._environ.get("COLUMNS") - if columns is not None and columns.isdigit(): - width = int(columns) - lines = self._environ.get("LINES") - if lines is not None and lines.isdigit(): - height = int(lines) - - # get_terminal_size can report 0, 0 if run from pseudo-terminal - width = width or 80 - height = height or 25 - return ConsoleDimensions( - width - self.legacy_windows if self._width is None else self._width, - height if self._height is None else self._height, - ) - - @size.setter - def size(self, new_size: Tuple[int, int]) -> None: - """Set a new size for the terminal. - - Args: - new_size (Tuple[int, int]): New width and height. - """ - width, height = new_size - self._width = width - self._height = height - - @property - def width(self) -> int: - """Get the width of the console. - - Returns: - int: The width (in characters) of the console. - """ - return self.size.width - - @width.setter - def width(self, width: int) -> None: - """Set width. - - Args: - width (int): New width. - """ - self._width = width - - @property - def height(self) -> int: - """Get the height of the console. - - Returns: - int: The height (in lines) of the console. - """ - return self.size.height - - @height.setter - def height(self, height: int) -> None: - """Set height. - - Args: - height (int): new height. - """ - self._height = height - - def bell(self) -> None: - """Play a 'bell' sound (if supported by the terminal).""" - self.control(Control.bell()) - - def capture(self) -> Capture: - """A context manager to *capture* the result of print() or log() in a string, - rather than writing it to the console. - - Example: - >>> from rich.console import Console - >>> console = Console() - >>> with console.capture() as capture: - ... console.print("[bold magenta]Hello World[/]") - >>> print(capture.get()) - - Returns: - Capture: Context manager with disables writing to the terminal. - """ - capture = Capture(self) - return capture - - def pager( - self, pager: Optional[Pager] = None, styles: bool = False, links: bool = False - ) -> PagerContext: - """A context manager to display anything printed within a "pager". The pager application - is defined by the system and will typically support at least pressing a key to scroll. - - Args: - pager (Pager, optional): A pager object, or None to use :class:`~rich.pager.SystemPager`. Defaults to None. - styles (bool, optional): Show styles in pager. Defaults to False. - links (bool, optional): Show links in pager. Defaults to False. - - Example: - >>> from rich.console import Console - >>> from rich.__main__ import make_test_card - >>> console = Console() - >>> with console.pager(): - console.print(make_test_card()) - - Returns: - PagerContext: A context manager. - """ - return PagerContext(self, pager=pager, styles=styles, links=links) - - def line(self, count: int = 1) -> None: - """Write new line(s). - - Args: - count (int, optional): Number of new lines. Defaults to 1. - """ - - assert count >= 0, "count must be >= 0" - self.print(NewLine(count)) - - def clear(self, home: bool = True) -> None: - """Clear the screen. - - Args: - home (bool, optional): Also move the cursor to 'home' position. Defaults to True. - """ - if home: - self.control(Control.clear(), Control.home()) - else: - self.control(Control.clear()) - - def status( - self, - status: RenderableType, - *, - spinner: str = "dots", - spinner_style: StyleType = "status.spinner", - speed: float = 1.0, - refresh_per_second: float = 12.5, - ) -> "Status": - """Display a status and spinner. - - Args: - status (RenderableType): A status renderable (str or Text typically). - spinner (str, optional): Name of spinner animation (see python -m rich.spinner). Defaults to "dots". - spinner_style (StyleType, optional): Style of spinner. Defaults to "status.spinner". - speed (float, optional): Speed factor for spinner animation. Defaults to 1.0. - refresh_per_second (float, optional): Number of refreshes per second. Defaults to 12.5. - - Returns: - Status: A Status object that may be used as a context manager. - """ - from .status import Status - - status_renderable = Status( - status, - console=self, - spinner=spinner, - spinner_style=spinner_style, - speed=speed, - refresh_per_second=refresh_per_second, - ) - return status_renderable - - def show_cursor(self, show: bool = True) -> bool: - """Show or hide the cursor. - - Args: - show (bool, optional): Set visibility of the cursor. - """ - if self.is_terminal: - self.control(Control.show_cursor(show)) - return True - return False - - def set_alt_screen(self, enable: bool = True) -> bool: - """Enables alternative screen mode. - - Note, if you enable this mode, you should ensure that is disabled before - the application exits. See :meth:`~rich.Console.screen` for a context manager - that handles this for you. - - Args: - enable (bool, optional): Enable (True) or disable (False) alternate screen. Defaults to True. - - Returns: - bool: True if the control codes were written. - - """ - changed = False - if self.is_terminal and not self.legacy_windows: - self.control(Control.alt_screen(enable)) - changed = True - self._is_alt_screen = enable - return changed - - @property - def is_alt_screen(self) -> bool: - """Check if the alt screen was enabled. - - Returns: - bool: True if the alt screen was enabled, otherwise False. - """ - return self._is_alt_screen - - def set_window_title(self, title: str) -> bool: - """Set the title of the console terminal window. - - Warning: There is no means within Rich of "resetting" the window title to its - previous value, meaning the title you set will persist even after your application - exits. - - ``fish`` shell resets the window title before and after each command by default, - negating this issue. Windows Terminal and command prompt will also reset the title for you. - Most other shells and terminals, however, do not do this. - - Some terminals may require configuration changes before you can set the title. - Some terminals may not support setting the title at all. - - Other software (including the terminal itself, the shell, custom prompts, plugins, etc.) - may also set the terminal window title. This could result in whatever value you write - using this method being overwritten. - - Args: - title (str): The new title of the terminal window. - - Returns: - bool: True if the control code to change the terminal title was - written, otherwise False. Note that a return value of True - does not guarantee that the window title has actually changed, - since the feature may be unsupported/disabled in some terminals. - """ - if self.is_terminal: - self.control(Control.title(title)) - return True - return False - - def screen( - self, hide_cursor: bool = True, style: Optional[StyleType] = None - ) -> "ScreenContext": - """Context manager to enable and disable 'alternative screen' mode. - - Args: - hide_cursor (bool, optional): Also hide the cursor. Defaults to False. - style (Style, optional): Optional style for screen. Defaults to None. - - Returns: - ~ScreenContext: Context which enables alternate screen on enter, and disables it on exit. - """ - return ScreenContext(self, hide_cursor=hide_cursor, style=style or "") - - def measure( - self, renderable: RenderableType, *, options: Optional[ConsoleOptions] = None - ) -> Measurement: - """Measure a renderable. Returns a :class:`~rich.measure.Measurement` object which contains - information regarding the number of characters required to print the renderable. - - Args: - renderable (RenderableType): Any renderable or string. - options (Optional[ConsoleOptions], optional): Options to use when measuring, or None - to use default options. Defaults to None. - - Returns: - Measurement: A measurement of the renderable. - """ - measurement = Measurement.get(self, options or self.options, renderable) - return measurement - - def render( - self, renderable: RenderableType, options: Optional[ConsoleOptions] = None - ) -> Iterable[Segment]: - """Render an object in to an iterable of `Segment` instances. - - This method contains the logic for rendering objects with the console protocol. - You are unlikely to need to use it directly, unless you are extending the library. - - Args: - renderable (RenderableType): An object supporting the console protocol, or - an object that may be converted to a string. - options (ConsoleOptions, optional): An options object, or None to use self.options. Defaults to None. - - Returns: - Iterable[Segment]: An iterable of segments that may be rendered. - """ - - _options = options or self.options - if _options.max_width < 1: - # No space to render anything. This prevents potential recursion errors. - return - render_iterable: RenderResult - - renderable = rich_cast(renderable) - if hasattr(renderable, "__rich_console__") and not isclass(renderable): - render_iterable = renderable.__rich_console__(self, _options) # type: ignore[union-attr] - elif isinstance(renderable, str): - text_renderable = self.render_str( - renderable, highlight=_options.highlight, markup=_options.markup - ) - render_iterable = text_renderable.__rich_console__(self, _options) - else: - raise errors.NotRenderableError( - f"Unable to render {renderable!r}; " - "A str, Segment or object with __rich_console__ method is required" - ) - - try: - iter_render = iter(render_iterable) - except TypeError: - raise errors.NotRenderableError( - f"object {render_iterable!r} is not renderable" - ) - _Segment = Segment - _options = _options.reset_height() - for render_output in iter_render: - if isinstance(render_output, _Segment): - yield render_output - else: - yield from self.render(render_output, _options) - - def render_lines( - self, - renderable: RenderableType, - options: Optional[ConsoleOptions] = None, - *, - style: Optional[Style] = None, - pad: bool = True, - new_lines: bool = False, - ) -> List[List[Segment]]: - """Render objects in to a list of lines. - - The output of render_lines is useful when further formatting of rendered console text - is required, such as the Panel class which draws a border around any renderable object. - - Args: - renderable (RenderableType): Any object renderable in the console. - options (Optional[ConsoleOptions], optional): Console options, or None to use self.options. Default to ``None``. - style (Style, optional): Optional style to apply to renderables. Defaults to ``None``. - pad (bool, optional): Pad lines shorter than render width. Defaults to ``True``. - new_lines (bool, optional): Include "\n" characters at end of lines. - - Returns: - List[List[Segment]]: A list of lines, where a line is a list of Segment objects. - """ - with self._lock: - render_options = options or self.options - _rendered = self.render(renderable, render_options) - if style: - _rendered = Segment.apply_style(_rendered, style) - - render_height = render_options.height - if render_height is not None: - render_height = max(0, render_height) - - lines = list( - islice( - Segment.split_and_crop_lines( - _rendered, - render_options.max_width, - include_new_lines=new_lines, - pad=pad, - style=style, - ), - None, - render_height, - ) - ) - if render_options.height is not None: - extra_lines = render_options.height - len(lines) - if extra_lines > 0: - pad_line = [ - [Segment(" " * render_options.max_width, style), Segment("\n")] - if new_lines - else [Segment(" " * render_options.max_width, style)] - ] - lines.extend(pad_line * extra_lines) - - return lines - - def render_str( - self, - text: str, - *, - style: Union[str, Style] = "", - justify: Optional[JustifyMethod] = None, - overflow: Optional[OverflowMethod] = None, - emoji: Optional[bool] = None, - markup: Optional[bool] = None, - highlight: Optional[bool] = None, - highlighter: Optional[HighlighterType] = None, - ) -> "Text": - """Convert a string to a Text instance. This is called automatically if - you print or log a string. - - Args: - text (str): Text to render. - style (Union[str, Style], optional): Style to apply to rendered text. - justify (str, optional): Justify method: "default", "left", "center", "full", or "right". Defaults to ``None``. - overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to ``None``. - emoji (Optional[bool], optional): Enable emoji, or ``None`` to use Console default. - markup (Optional[bool], optional): Enable markup, or ``None`` to use Console default. - highlight (Optional[bool], optional): Enable highlighting, or ``None`` to use Console default. - highlighter (HighlighterType, optional): Optional highlighter to apply. - Returns: - ConsoleRenderable: Renderable object. - - """ - emoji_enabled = emoji or (emoji is None and self._emoji) - markup_enabled = markup or (markup is None and self._markup) - highlight_enabled = highlight or (highlight is None and self._highlight) - - if markup_enabled: - rich_text = render_markup( - text, - style=style, - emoji=emoji_enabled, - emoji_variant=self._emoji_variant, - ) - rich_text.justify = justify - rich_text.overflow = overflow - else: - rich_text = Text( - _emoji_replace(text, default_variant=self._emoji_variant) - if emoji_enabled - else text, - justify=justify, - overflow=overflow, - style=style, - ) - - _highlighter = (highlighter or self.highlighter) if highlight_enabled else None - if _highlighter is not None: - highlight_text = _highlighter(str(rich_text)) - highlight_text.copy_styles(rich_text) - return highlight_text - - return rich_text - - def get_style( - self, name: Union[str, Style], *, default: Optional[Union[Style, str]] = None - ) -> Style: - """Get a Style instance by its theme name or parse a definition. - - Args: - name (str): The name of a style or a style definition. - - Returns: - Style: A Style object. - - Raises: - MissingStyle: If no style could be parsed from name. - - """ - if isinstance(name, Style): - return name - - try: - style = self._theme_stack.get(name) - if style is None: - style = Style.parse(name) - return style.copy() if style.link else style - except errors.StyleSyntaxError as error: - if default is not None: - return self.get_style(default) - raise errors.MissingStyle( - f"Failed to get style {name!r}; {error}" - ) from None - - def _collect_renderables( - self, - objects: Iterable[Any], - sep: str, - end: str, - *, - justify: Optional[JustifyMethod] = None, - emoji: Optional[bool] = None, - markup: Optional[bool] = None, - highlight: Optional[bool] = None, - ) -> List[ConsoleRenderable]: - """Combine a number of renderables and text into one renderable. - - Args: - objects (Iterable[Any]): Anything that Rich can render. - sep (str): String to write between print data. - end (str): String to write at end of print data. - justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``. - emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. - markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. - highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. - - Returns: - List[ConsoleRenderable]: A list of things to render. - """ - renderables: List[ConsoleRenderable] = [] - _append = renderables.append - text: List[Text] = [] - append_text = text.append - - append = _append - if justify in ("left", "center", "right"): - - def align_append(renderable: RenderableType) -> None: - _append(Align(renderable, cast(AlignMethod, justify))) - - append = align_append - - _highlighter: HighlighterType = _null_highlighter - if highlight or (highlight is None and self._highlight): - _highlighter = self.highlighter - - def check_text() -> None: - if text: - sep_text = Text(sep, justify=justify, end=end) - append(sep_text.join(text)) - text.clear() - - for renderable in objects: - renderable = rich_cast(renderable) - if isinstance(renderable, str): - append_text( - self.render_str( - renderable, emoji=emoji, markup=markup, highlighter=_highlighter - ) - ) - elif isinstance(renderable, Text): - append_text(renderable) - elif isinstance(renderable, ConsoleRenderable): - check_text() - append(renderable) - elif is_expandable(renderable): - check_text() - append(Pretty(renderable, highlighter=_highlighter)) - else: - append_text(_highlighter(str(renderable))) - - check_text() - - if self.style is not None: - style = self.get_style(self.style) - renderables = [Styled(renderable, style) for renderable in renderables] - - return renderables - - def rule( - self, - title: TextType = "", - *, - characters: str = "─", - style: Union[str, Style] = "rule.line", - align: AlignMethod = "center", - ) -> None: - """Draw a line with optional centered title. - - Args: - title (str, optional): Text to render over the rule. Defaults to "". - characters (str, optional): Character(s) to form the line. Defaults to "─". - style (str, optional): Style of line. Defaults to "rule.line". - align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center". - """ - from .rule import Rule - - rule = Rule(title=title, characters=characters, style=style, align=align) - self.print(rule) - - def control(self, *control: Control) -> None: - """Insert non-printing control codes. - - Args: - control_codes (str): Control codes, such as those that may move the cursor. - """ - if not self.is_dumb_terminal: - with self: - self._buffer.extend(_control.segment for _control in control) - - def out( - self, - *objects: Any, - sep: str = " ", - end: str = "\n", - style: Optional[Union[str, Style]] = None, - highlight: Optional[bool] = None, - ) -> None: - """Output to the terminal. This is a low-level way of writing to the terminal which unlike - :meth:`~rich.console.Console.print` won't pretty print, wrap text, or apply markup, but will - optionally apply highlighting and a basic style. - - Args: - sep (str, optional): String to write between print data. Defaults to " ". - end (str, optional): String to write at end of print data. Defaults to "\\\\n". - style (Union[str, Style], optional): A style to apply to output. Defaults to None. - highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use - console default. Defaults to ``None``. - """ - raw_output: str = sep.join(str(_object) for _object in objects) - self.print( - raw_output, - style=style, - highlight=highlight, - emoji=False, - markup=False, - no_wrap=True, - overflow="ignore", - crop=False, - end=end, - ) - - def print( - self, - *objects: Any, - sep: str = " ", - end: str = "\n", - style: Optional[Union[str, Style]] = None, - justify: Optional[JustifyMethod] = None, - overflow: Optional[OverflowMethod] = None, - no_wrap: Optional[bool] = None, - emoji: Optional[bool] = None, - markup: Optional[bool] = None, - highlight: Optional[bool] = None, - width: Optional[int] = None, - height: Optional[int] = None, - crop: bool = True, - soft_wrap: Optional[bool] = None, - new_line_start: bool = False, - ) -> None: - """Print to the console. - - Args: - objects (positional args): Objects to log to the terminal. - sep (str, optional): String to write between print data. Defaults to " ". - end (str, optional): String to write at end of print data. Defaults to "\\\\n". - style (Union[str, Style], optional): A style to apply to output. Defaults to None. - justify (str, optional): Justify method: "default", "left", "right", "center", or "full". Defaults to ``None``. - overflow (str, optional): Overflow method: "ignore", "crop", "fold", or "ellipsis". Defaults to None. - no_wrap (Optional[bool], optional): Disable word wrapping. Defaults to None. - emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to ``None``. - markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to ``None``. - highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to ``None``. - width (Optional[int], optional): Width of output, or ``None`` to auto-detect. Defaults to ``None``. - crop (Optional[bool], optional): Crop output to width of terminal. Defaults to True. - soft_wrap (bool, optional): Enable soft wrap mode which disables word wrapping and cropping of text or ``None`` for - Console default. Defaults to ``None``. - new_line_start (bool, False): Insert a new line at the start if the output contains more than one line. Defaults to ``False``. - """ - if not objects: - objects = (NewLine(),) - - if soft_wrap is None: - soft_wrap = self.soft_wrap - if soft_wrap: - if no_wrap is None: - no_wrap = True - if overflow is None: - overflow = "ignore" - crop = False - render_hooks = self._render_hooks[:] - with self: - renderables = self._collect_renderables( - objects, - sep, - end, - justify=justify, - emoji=emoji, - markup=markup, - highlight=highlight, - ) - for hook in render_hooks: - renderables = hook.process_renderables(renderables) - render_options = self.options.update( - justify=justify, - overflow=overflow, - width=min(width, self.width) if width is not None else NO_CHANGE, - height=height, - no_wrap=no_wrap, - markup=markup, - highlight=highlight, - ) - - new_segments: List[Segment] = [] - extend = new_segments.extend - render = self.render - if style is None: - for renderable in renderables: - extend(render(renderable, render_options)) - else: - for renderable in renderables: - extend( - Segment.apply_style( - render(renderable, render_options), self.get_style(style) - ) - ) - if new_line_start: - if ( - len("".join(segment.text for segment in new_segments).splitlines()) - > 1 - ): - new_segments.insert(0, Segment.line()) - if crop: - buffer_extend = self._buffer.extend - for line in Segment.split_and_crop_lines( - new_segments, self.width, pad=False - ): - buffer_extend(line) - else: - self._buffer.extend(new_segments) - - def print_json( - self, - json: Optional[str] = None, - *, - data: Any = None, - indent: Union[None, int, str] = 2, - highlight: bool = True, - skip_keys: bool = False, - ensure_ascii: bool = False, - check_circular: bool = True, - allow_nan: bool = True, - default: Optional[Callable[[Any], Any]] = None, - sort_keys: bool = False, - ) -> None: - """Pretty prints JSON. Output will be valid JSON. - - Args: - json (Optional[str]): A string containing JSON. - data (Any): If json is not supplied, then encode this data. - indent (Union[None, int, str], optional): Number of spaces to indent. Defaults to 2. - highlight (bool, optional): Enable highlighting of output: Defaults to True. - skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False. - ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False. - check_circular (bool, optional): Check for circular references. Defaults to True. - allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True. - default (Callable, optional): A callable that converts values that can not be encoded - in to something that can be JSON encoded. Defaults to None. - sort_keys (bool, optional): Sort dictionary keys. Defaults to False. - """ - from pip._vendor.rich.json import JSON - - if json is None: - json_renderable = JSON.from_data( - data, - indent=indent, - highlight=highlight, - skip_keys=skip_keys, - ensure_ascii=ensure_ascii, - check_circular=check_circular, - allow_nan=allow_nan, - default=default, - sort_keys=sort_keys, - ) - else: - if not isinstance(json, str): - raise TypeError( - f"json must be str. Did you mean print_json(data={json!r}) ?" - ) - json_renderable = JSON( - json, - indent=indent, - highlight=highlight, - skip_keys=skip_keys, - ensure_ascii=ensure_ascii, - check_circular=check_circular, - allow_nan=allow_nan, - default=default, - sort_keys=sort_keys, - ) - self.print(json_renderable, soft_wrap=True) - - def update_screen( - self, - renderable: RenderableType, - *, - region: Optional[Region] = None, - options: Optional[ConsoleOptions] = None, - ) -> None: - """Update the screen at a given offset. - - Args: - renderable (RenderableType): A Rich renderable. - region (Region, optional): Region of screen to update, or None for entire screen. Defaults to None. - x (int, optional): x offset. Defaults to 0. - y (int, optional): y offset. Defaults to 0. - - Raises: - errors.NoAltScreen: If the Console isn't in alt screen mode. - - """ - if not self.is_alt_screen: - raise errors.NoAltScreen("Alt screen must be enabled to call update_screen") - render_options = options or self.options - if region is None: - x = y = 0 - render_options = render_options.update_dimensions( - render_options.max_width, render_options.height or self.height - ) - else: - x, y, width, height = region - render_options = render_options.update_dimensions(width, height) - - lines = self.render_lines(renderable, options=render_options) - self.update_screen_lines(lines, x, y) - - def update_screen_lines( - self, lines: List[List[Segment]], x: int = 0, y: int = 0 - ) -> None: - """Update lines of the screen at a given offset. - - Args: - lines (List[List[Segment]]): Rendered lines (as produced by :meth:`~rich.Console.render_lines`). - x (int, optional): x offset (column no). Defaults to 0. - y (int, optional): y offset (column no). Defaults to 0. - - Raises: - errors.NoAltScreen: If the Console isn't in alt screen mode. - """ - if not self.is_alt_screen: - raise errors.NoAltScreen("Alt screen must be enabled to call update_screen") - screen_update = ScreenUpdate(lines, x, y) - segments = self.render(screen_update) - self._buffer.extend(segments) - self._check_buffer() - - def print_exception( - self, - *, - width: Optional[int] = 100, - extra_lines: int = 3, - theme: Optional[str] = None, - word_wrap: bool = False, - show_locals: bool = False, - suppress: Iterable[Union[str, ModuleType]] = (), - max_frames: int = 100, - ) -> None: - """Prints a rich render of the last exception and traceback. - - Args: - width (Optional[int], optional): Number of characters used to render code. Defaults to 100. - extra_lines (int, optional): Additional lines of code to render. Defaults to 3. - theme (str, optional): Override pygments theme used in traceback - word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. - show_locals (bool, optional): Enable display of local variables. Defaults to False. - suppress (Iterable[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. - max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100. - """ - from .traceback import Traceback - - traceback = Traceback( - width=width, - extra_lines=extra_lines, - theme=theme, - word_wrap=word_wrap, - show_locals=show_locals, - suppress=suppress, - max_frames=max_frames, - ) - self.print(traceback) - - @staticmethod - def _caller_frame_info( - offset: int, - currentframe: Callable[[], Optional[FrameType]] = inspect.currentframe, - ) -> Tuple[str, int, Dict[str, Any]]: - """Get caller frame information. - - Args: - offset (int): the caller offset within the current frame stack. - currentframe (Callable[[], Optional[FrameType]], optional): the callable to use to - retrieve the current frame. Defaults to ``inspect.currentframe``. - - Returns: - Tuple[str, int, Dict[str, Any]]: A tuple containing the filename, the line number and - the dictionary of local variables associated with the caller frame. - - Raises: - RuntimeError: If the stack offset is invalid. - """ - # Ignore the frame of this local helper - offset += 1 - - frame = currentframe() - if frame is not None: - # Use the faster currentframe where implemented - while offset and frame is not None: - frame = frame.f_back - offset -= 1 - assert frame is not None - return frame.f_code.co_filename, frame.f_lineno, frame.f_locals - else: - # Fallback to the slower stack - frame_info = inspect.stack()[offset] - return frame_info.filename, frame_info.lineno, frame_info.frame.f_locals - - def log( - self, - *objects: Any, - sep: str = " ", - end: str = "\n", - style: Optional[Union[str, Style]] = None, - justify: Optional[JustifyMethod] = None, - emoji: Optional[bool] = None, - markup: Optional[bool] = None, - highlight: Optional[bool] = None, - log_locals: bool = False, - _stack_offset: int = 1, - ) -> None: - """Log rich content to the terminal. - - Args: - objects (positional args): Objects to log to the terminal. - sep (str, optional): String to write between print data. Defaults to " ". - end (str, optional): String to write at end of print data. Defaults to "\\\\n". - style (Union[str, Style], optional): A style to apply to output. Defaults to None. - justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``. - overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None. - emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to None. - markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to None. - highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to None. - log_locals (bool, optional): Boolean to enable logging of locals where ``log()`` - was called. Defaults to False. - _stack_offset (int, optional): Offset of caller from end of call stack. Defaults to 1. - """ - if not objects: - objects = (NewLine(),) - - render_hooks = self._render_hooks[:] - - with self: - renderables = self._collect_renderables( - objects, - sep, - end, - justify=justify, - emoji=emoji, - markup=markup, - highlight=highlight, - ) - if style is not None: - renderables = [Styled(renderable, style) for renderable in renderables] - - filename, line_no, locals = self._caller_frame_info(_stack_offset) - link_path = None if filename.startswith("<") else os.path.abspath(filename) - path = filename.rpartition(os.sep)[-1] - if log_locals: - locals_map = { - key: value - for key, value in locals.items() - if not key.startswith("__") - } - renderables.append(render_scope(locals_map, title="[i]locals")) - - renderables = [ - self._log_render( - self, - renderables, - log_time=self.get_datetime(), - path=path, - line_no=line_no, - link_path=link_path, - ) - ] - for hook in render_hooks: - renderables = hook.process_renderables(renderables) - new_segments: List[Segment] = [] - extend = new_segments.extend - render = self.render - render_options = self.options - for renderable in renderables: - extend(render(renderable, render_options)) - buffer_extend = self._buffer.extend - for line in Segment.split_and_crop_lines( - new_segments, self.width, pad=False - ): - buffer_extend(line) - - def _check_buffer(self) -> None: - """Check if the buffer may be rendered. Render it if it can (e.g. Console.quiet is False) - Rendering is supported on Windows, Unix and Jupyter environments. For - legacy Windows consoles, the win32 API is called directly. - This method will also record what it renders if recording is enabled via Console.record. - """ - if self.quiet: - del self._buffer[:] - return - with self._lock: - if self.record: - with self._record_buffer_lock: - self._record_buffer.extend(self._buffer[:]) - - if self._buffer_index == 0: - if self.is_jupyter: # pragma: no cover - from .jupyter import display - - display(self._buffer, self._render_buffer(self._buffer[:])) - del self._buffer[:] - else: - if WINDOWS: - use_legacy_windows_render = False - if self.legacy_windows: - fileno = get_fileno(self.file) - if fileno is not None: - use_legacy_windows_render = ( - fileno in _STD_STREAMS_OUTPUT - ) - - if use_legacy_windows_render: - from pip._vendor.rich._win32_console import LegacyWindowsTerm - from pip._vendor.rich._windows_renderer import legacy_windows_render - - buffer = self._buffer[:] - if self.no_color and self._color_system: - buffer = list(Segment.remove_color(buffer)) - - legacy_windows_render(buffer, LegacyWindowsTerm(self.file)) - else: - # Either a non-std stream on legacy Windows, or modern Windows. - text = self._render_buffer(self._buffer[:]) - # https://bugs.python.org/issue37871 - # https://github.com/python/cpython/issues/82052 - # We need to avoid writing more than 32Kb in a single write, due to the above bug - write = self.file.write - # Worse case scenario, every character is 4 bytes of utf-8 - MAX_WRITE = 32 * 1024 // 4 - try: - if len(text) <= MAX_WRITE: - write(text) - else: - batch: List[str] = [] - batch_append = batch.append - size = 0 - for line in text.splitlines(True): - if size + len(line) > MAX_WRITE and batch: - write("".join(batch)) - batch.clear() - size = 0 - batch_append(line) - size += len(line) - if batch: - write("".join(batch)) - batch.clear() - except UnicodeEncodeError as error: - error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***" - raise - else: - text = self._render_buffer(self._buffer[:]) - try: - self.file.write(text) - except UnicodeEncodeError as error: - error.reason = f"{error.reason}\n*** You may need to add PYTHONIOENCODING=utf-8 to your environment ***" - raise - - self.file.flush() - del self._buffer[:] - - def _render_buffer(self, buffer: Iterable[Segment]) -> str: - """Render buffered output, and clear buffer.""" - output: List[str] = [] - append = output.append - color_system = self._color_system - legacy_windows = self.legacy_windows - not_terminal = not self.is_terminal - if self.no_color and color_system: - buffer = Segment.remove_color(buffer) - for text, style, control in buffer: - if style: - append( - style.render( - text, - color_system=color_system, - legacy_windows=legacy_windows, - ) - ) - elif not (not_terminal and control): - append(text) - - rendered = "".join(output) - return rendered - - def input( - self, - prompt: TextType = "", - *, - markup: bool = True, - emoji: bool = True, - password: bool = False, - stream: Optional[TextIO] = None, - ) -> str: - """Displays a prompt and waits for input from the user. The prompt may contain color / style. - - It works in the same way as Python's builtin :func:`input` function and provides elaborate line editing and history features if Python's builtin :mod:`readline` module is previously loaded. - - Args: - prompt (Union[str, Text]): Text to render in the prompt. - markup (bool, optional): Enable console markup (requires a str prompt). Defaults to True. - emoji (bool, optional): Enable emoji (requires a str prompt). Defaults to True. - password: (bool, optional): Hide typed text. Defaults to False. - stream: (TextIO, optional): Optional file to read input from (rather than stdin). Defaults to None. - - Returns: - str: Text read from stdin. - """ - if prompt: - self.print(prompt, markup=markup, emoji=emoji, end="") - if password: - result = getpass("", stream=stream) - else: - if stream: - result = stream.readline() - else: - result = input() - return result - - def export_text(self, *, clear: bool = True, styles: bool = False) -> str: - """Generate text from console contents (requires record=True argument in constructor). - - Args: - clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. - styles (bool, optional): If ``True``, ansi escape codes will be included. ``False`` for plain text. - Defaults to ``False``. - - Returns: - str: String containing console contents. - - """ - assert ( - self.record - ), "To export console contents set record=True in the constructor or instance" - - with self._record_buffer_lock: - if styles: - text = "".join( - (style.render(text) if style else text) - for text, style, _ in self._record_buffer - ) - else: - text = "".join( - segment.text - for segment in self._record_buffer - if not segment.control - ) - if clear: - del self._record_buffer[:] - return text - - def save_text(self, path: str, *, clear: bool = True, styles: bool = False) -> None: - """Generate text from console and save to a given location (requires record=True argument in constructor). - - Args: - path (str): Path to write text files. - clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. - styles (bool, optional): If ``True``, ansi style codes will be included. ``False`` for plain text. - Defaults to ``False``. - - """ - text = self.export_text(clear=clear, styles=styles) - with open(path, "wt", encoding="utf-8") as write_file: - write_file.write(text) - - def export_html( - self, - *, - theme: Optional[TerminalTheme] = None, - clear: bool = True, - code_format: Optional[str] = None, - inline_styles: bool = False, - ) -> str: - """Generate HTML from console contents (requires record=True argument in constructor). - - Args: - theme (TerminalTheme, optional): TerminalTheme object containing console colors. - clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. - code_format (str, optional): Format string to render HTML. In addition to '{foreground}', - '{background}', and '{code}', should contain '{stylesheet}' if inline_styles is ``False``. - inline_styles (bool, optional): If ``True`` styles will be inlined in to spans, which makes files - larger but easier to cut and paste markup. If ``False``, styles will be embedded in a style tag. - Defaults to False. - - Returns: - str: String containing console contents as HTML. - """ - assert ( - self.record - ), "To export console contents set record=True in the constructor or instance" - fragments: List[str] = [] - append = fragments.append - _theme = theme or DEFAULT_TERMINAL_THEME - stylesheet = "" - - render_code_format = CONSOLE_HTML_FORMAT if code_format is None else code_format - - with self._record_buffer_lock: - if inline_styles: - for text, style, _ in Segment.filter_control( - Segment.simplify(self._record_buffer) - ): - text = escape(text) - if style: - rule = style.get_html_style(_theme) - if style.link: - text = f'{text}' - text = f'{text}' if rule else text - append(text) - else: - styles: Dict[str, int] = {} - for text, style, _ in Segment.filter_control( - Segment.simplify(self._record_buffer) - ): - text = escape(text) - if style: - rule = style.get_html_style(_theme) - style_number = styles.setdefault(rule, len(styles) + 1) - if style.link: - text = f'{text}' - else: - text = f'{text}' - append(text) - stylesheet_rules: List[str] = [] - stylesheet_append = stylesheet_rules.append - for style_rule, style_number in styles.items(): - if style_rule: - stylesheet_append(f".r{style_number} {{{style_rule}}}") - stylesheet = "\n".join(stylesheet_rules) - - rendered_code = render_code_format.format( - code="".join(fragments), - stylesheet=stylesheet, - foreground=_theme.foreground_color.hex, - background=_theme.background_color.hex, - ) - if clear: - del self._record_buffer[:] - return rendered_code - - def save_html( - self, - path: str, - *, - theme: Optional[TerminalTheme] = None, - clear: bool = True, - code_format: str = CONSOLE_HTML_FORMAT, - inline_styles: bool = False, - ) -> None: - """Generate HTML from console contents and write to a file (requires record=True argument in constructor). - - Args: - path (str): Path to write html file. - theme (TerminalTheme, optional): TerminalTheme object containing console colors. - clear (bool, optional): Clear record buffer after exporting. Defaults to ``True``. - code_format (str, optional): Format string to render HTML. In addition to '{foreground}', - '{background}', and '{code}', should contain '{stylesheet}' if inline_styles is ``False``. - inline_styles (bool, optional): If ``True`` styles will be inlined in to spans, which makes files - larger but easier to cut and paste markup. If ``False``, styles will be embedded in a style tag. - Defaults to False. - - """ - html = self.export_html( - theme=theme, - clear=clear, - code_format=code_format, - inline_styles=inline_styles, - ) - with open(path, "wt", encoding="utf-8") as write_file: - write_file.write(html) - - def export_svg( - self, - *, - title: str = "Rich", - theme: Optional[TerminalTheme] = None, - clear: bool = True, - code_format: str = CONSOLE_SVG_FORMAT, - font_aspect_ratio: float = 0.61, - unique_id: Optional[str] = None, - ) -> str: - """ - Generate an SVG from the console contents (requires record=True in Console constructor). - - Args: - title (str, optional): The title of the tab in the output image - theme (TerminalTheme, optional): The ``TerminalTheme`` object to use to style the terminal - clear (bool, optional): Clear record buffer after exporting. Defaults to ``True`` - code_format (str, optional): Format string used to generate the SVG. Rich will inject a number of variables - into the string in order to form the final SVG output. The default template used and the variables - injected by Rich can be found by inspecting the ``console.CONSOLE_SVG_FORMAT`` variable. - font_aspect_ratio (float, optional): The width to height ratio of the font used in the ``code_format`` - string. Defaults to 0.61, which is the width to height ratio of Fira Code (the default font). - If you aren't specifying a different font inside ``code_format``, you probably don't need this. - unique_id (str, optional): unique id that is used as the prefix for various elements (CSS styles, node - ids). If not set, this defaults to a computed value based on the recorded content. - """ - - from pip._vendor.rich.cells import cell_len - - style_cache: Dict[Style, str] = {} - - def get_svg_style(style: Style) -> str: - """Convert a Style to CSS rules for SVG.""" - if style in style_cache: - return style_cache[style] - css_rules = [] - color = ( - _theme.foreground_color - if (style.color is None or style.color.is_default) - else style.color.get_truecolor(_theme) - ) - bgcolor = ( - _theme.background_color - if (style.bgcolor is None or style.bgcolor.is_default) - else style.bgcolor.get_truecolor(_theme) - ) - if style.reverse: - color, bgcolor = bgcolor, color - if style.dim: - color = blend_rgb(color, bgcolor, 0.4) - css_rules.append(f"fill: {color.hex}") - if style.bold: - css_rules.append("font-weight: bold") - if style.italic: - css_rules.append("font-style: italic;") - if style.underline: - css_rules.append("text-decoration: underline;") - if style.strike: - css_rules.append("text-decoration: line-through;") - - css = ";".join(css_rules) - style_cache[style] = css - return css - - _theme = theme or SVG_EXPORT_THEME - - width = self.width - char_height = 20 - char_width = char_height * font_aspect_ratio - line_height = char_height * 1.22 - - margin_top = 1 - margin_right = 1 - margin_bottom = 1 - margin_left = 1 - - padding_top = 40 - padding_right = 8 - padding_bottom = 8 - padding_left = 8 - - padding_width = padding_left + padding_right - padding_height = padding_top + padding_bottom - margin_width = margin_left + margin_right - margin_height = margin_top + margin_bottom - - text_backgrounds: List[str] = [] - text_group: List[str] = [] - classes: Dict[str, int] = {} - style_no = 1 - - def escape_text(text: str) -> str: - """HTML escape text and replace spaces with nbsp.""" - return escape(text).replace(" ", " ") - - def make_tag( - name: str, content: Optional[str] = None, **attribs: object - ) -> str: - """Make a tag from name, content, and attributes.""" - - def stringify(value: object) -> str: - if isinstance(value, (float)): - return format(value, "g") - return str(value) - - tag_attribs = " ".join( - f'{k.lstrip("_").replace("_", "-")}="{stringify(v)}"' - for k, v in attribs.items() - ) - return ( - f"<{name} {tag_attribs}>{content}" - if content - else f"<{name} {tag_attribs}/>" - ) - - with self._record_buffer_lock: - segments = list(Segment.filter_control(self._record_buffer)) - if clear: - self._record_buffer.clear() - - if unique_id is None: - unique_id = "terminal-" + str( - zlib.adler32( - ("".join(repr(segment) for segment in segments)).encode( - "utf-8", - "ignore", - ) - + title.encode("utf-8", "ignore") - ) - ) - y = 0 - for y, line in enumerate(Segment.split_and_crop_lines(segments, length=width)): - x = 0 - for text, style, _control in line: - style = style or Style() - rules = get_svg_style(style) - if rules not in classes: - classes[rules] = style_no - style_no += 1 - class_name = f"r{classes[rules]}" - - if style.reverse: - has_background = True - background = ( - _theme.foreground_color.hex - if style.color is None - else style.color.get_truecolor(_theme).hex - ) - else: - bgcolor = style.bgcolor - has_background = bgcolor is not None and not bgcolor.is_default - background = ( - _theme.background_color.hex - if style.bgcolor is None - else style.bgcolor.get_truecolor(_theme).hex - ) - - text_length = cell_len(text) - if has_background: - text_backgrounds.append( - make_tag( - "rect", - fill=background, - x=x * char_width, - y=y * line_height + 1.5, - width=char_width * text_length, - height=line_height + 0.25, - shape_rendering="crispEdges", - ) - ) - - if text != " " * len(text): - text_group.append( - make_tag( - "text", - escape_text(text), - _class=f"{unique_id}-{class_name}", - x=x * char_width, - y=y * line_height + char_height, - textLength=char_width * len(text), - clip_path=f"url(#{unique_id}-line-{y})", - ) - ) - x += cell_len(text) - - line_offsets = [line_no * line_height + 1.5 for line_no in range(y)] - lines = "\n".join( - f""" - {make_tag("rect", x=0, y=offset, width=char_width * width, height=line_height + 0.25)} - """ - for line_no, offset in enumerate(line_offsets) - ) - - styles = "\n".join( - f".{unique_id}-r{rule_no} {{ {css} }}" for css, rule_no in classes.items() - ) - backgrounds = "".join(text_backgrounds) - matrix = "".join(text_group) - - terminal_width = ceil(width * char_width + padding_width) - terminal_height = (y + 1) * line_height + padding_height - chrome = make_tag( - "rect", - fill=_theme.background_color.hex, - stroke="rgba(255,255,255,0.35)", - stroke_width="1", - x=margin_left, - y=margin_top, - width=terminal_width, - height=terminal_height, - rx=8, - ) - - title_color = _theme.foreground_color.hex - if title: - chrome += make_tag( - "text", - escape_text(title), - _class=f"{unique_id}-title", - fill=title_color, - text_anchor="middle", - x=terminal_width // 2, - y=margin_top + char_height + 6, - ) - chrome += f""" - - - - - - """ - - svg = code_format.format( - unique_id=unique_id, - char_width=char_width, - char_height=char_height, - line_height=line_height, - terminal_width=char_width * width - 1, - terminal_height=(y + 1) * line_height - 1, - width=terminal_width + margin_width, - height=terminal_height + margin_height, - terminal_x=margin_left + padding_left, - terminal_y=margin_top + padding_top, - styles=styles, - chrome=chrome, - backgrounds=backgrounds, - matrix=matrix, - lines=lines, - ) - return svg - - def save_svg( - self, - path: str, - *, - title: str = "Rich", - theme: Optional[TerminalTheme] = None, - clear: bool = True, - code_format: str = CONSOLE_SVG_FORMAT, - font_aspect_ratio: float = 0.61, - unique_id: Optional[str] = None, - ) -> None: - """Generate an SVG file from the console contents (requires record=True in Console constructor). - - Args: - path (str): The path to write the SVG to. - title (str, optional): The title of the tab in the output image - theme (TerminalTheme, optional): The ``TerminalTheme`` object to use to style the terminal - clear (bool, optional): Clear record buffer after exporting. Defaults to ``True`` - code_format (str, optional): Format string used to generate the SVG. Rich will inject a number of variables - into the string in order to form the final SVG output. The default template used and the variables - injected by Rich can be found by inspecting the ``console.CONSOLE_SVG_FORMAT`` variable. - font_aspect_ratio (float, optional): The width to height ratio of the font used in the ``code_format`` - string. Defaults to 0.61, which is the width to height ratio of Fira Code (the default font). - If you aren't specifying a different font inside ``code_format``, you probably don't need this. - unique_id (str, optional): unique id that is used as the prefix for various elements (CSS styles, node - ids). If not set, this defaults to a computed value based on the recorded content. - """ - svg = self.export_svg( - title=title, - theme=theme, - clear=clear, - code_format=code_format, - font_aspect_ratio=font_aspect_ratio, - unique_id=unique_id, - ) - with open(path, "wt", encoding="utf-8") as write_file: - write_file.write(svg) - - -def _svg_hash(svg_main_code: str) -> str: - """Returns a unique hash for the given SVG main code. - - Args: - svg_main_code (str): The content we're going to inject in the SVG envelope. - - Returns: - str: a hash of the given content - """ - return str(zlib.adler32(svg_main_code.encode())) - - -if __name__ == "__main__": # pragma: no cover - console = Console(record=True) - - console.log( - "JSONRPC [i]request[/i]", - 5, - 1.3, - True, - False, - None, - { - "jsonrpc": "2.0", - "method": "subtract", - "params": {"minuend": 42, "subtrahend": 23}, - "id": 3, - }, - ) - - console.log("Hello, World!", "{'a': 1}", repr(console)) - - console.print( - { - "name": None, - "empty": [], - "quiz": { - "sport": { - "answered": True, - "q1": { - "question": "Which one is correct team name in NBA?", - "options": [ - "New York Bulls", - "Los Angeles Kings", - "Golden State Warriors", - "Huston Rocket", - ], - "answer": "Huston Rocket", - }, - }, - "maths": { - "answered": False, - "q1": { - "question": "5 + 7 = ?", - "options": [10, 11, 12, 13], - "answer": 12, - }, - "q2": { - "question": "12 - 8 = ?", - "options": [1, 2, 3, 4], - "answer": 4, - }, - }, - }, - } - ) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py deleted file mode 100644 index 65fdf56..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py +++ /dev/null @@ -1,37 +0,0 @@ -from typing import Optional, TYPE_CHECKING - -from .jupyter import JupyterMixin -from .measure import Measurement - -if TYPE_CHECKING: - from .console import Console, ConsoleOptions, RenderableType, RenderResult - - -class Constrain(JupyterMixin): - """Constrain the width of a renderable to a given number of characters. - - Args: - renderable (RenderableType): A renderable object. - width (int, optional): The maximum width (in characters) to render. Defaults to 80. - """ - - def __init__(self, renderable: "RenderableType", width: Optional[int] = 80) -> None: - self.renderable = renderable - self.width = width - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> "RenderResult": - if self.width is None: - yield self.renderable - else: - child_options = options.update_width(min(self.width, options.max_width)) - yield from console.render(self.renderable, child_options) - - def __rich_measure__( - self, console: "Console", options: "ConsoleOptions" - ) -> "Measurement": - if self.width is not None: - options = options.update_width(self.width) - measurement = Measurement.get(console, options, self.renderable) - return measurement diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/containers.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/containers.py deleted file mode 100644 index e29cf36..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/containers.py +++ /dev/null @@ -1,167 +0,0 @@ -from itertools import zip_longest -from typing import ( - Iterator, - Iterable, - List, - Optional, - Union, - overload, - TypeVar, - TYPE_CHECKING, -) - -if TYPE_CHECKING: - from .console import ( - Console, - ConsoleOptions, - JustifyMethod, - OverflowMethod, - RenderResult, - RenderableType, - ) - from .text import Text - -from .cells import cell_len -from .measure import Measurement - -T = TypeVar("T") - - -class Renderables: - """A list subclass which renders its contents to the console.""" - - def __init__( - self, renderables: Optional[Iterable["RenderableType"]] = None - ) -> None: - self._renderables: List["RenderableType"] = ( - list(renderables) if renderables is not None else [] - ) - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> "RenderResult": - """Console render method to insert line-breaks.""" - yield from self._renderables - - def __rich_measure__( - self, console: "Console", options: "ConsoleOptions" - ) -> "Measurement": - dimensions = [ - Measurement.get(console, options, renderable) - for renderable in self._renderables - ] - if not dimensions: - return Measurement(1, 1) - _min = max(dimension.minimum for dimension in dimensions) - _max = max(dimension.maximum for dimension in dimensions) - return Measurement(_min, _max) - - def append(self, renderable: "RenderableType") -> None: - self._renderables.append(renderable) - - def __iter__(self) -> Iterable["RenderableType"]: - return iter(self._renderables) - - -class Lines: - """A list subclass which can render to the console.""" - - def __init__(self, lines: Iterable["Text"] = ()) -> None: - self._lines: List["Text"] = list(lines) - - def __repr__(self) -> str: - return f"Lines({self._lines!r})" - - def __iter__(self) -> Iterator["Text"]: - return iter(self._lines) - - @overload - def __getitem__(self, index: int) -> "Text": - ... - - @overload - def __getitem__(self, index: slice) -> List["Text"]: - ... - - def __getitem__(self, index: Union[slice, int]) -> Union["Text", List["Text"]]: - return self._lines[index] - - def __setitem__(self, index: int, value: "Text") -> "Lines": - self._lines[index] = value - return self - - def __len__(self) -> int: - return self._lines.__len__() - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> "RenderResult": - """Console render method to insert line-breaks.""" - yield from self._lines - - def append(self, line: "Text") -> None: - self._lines.append(line) - - def extend(self, lines: Iterable["Text"]) -> None: - self._lines.extend(lines) - - def pop(self, index: int = -1) -> "Text": - return self._lines.pop(index) - - def justify( - self, - console: "Console", - width: int, - justify: "JustifyMethod" = "left", - overflow: "OverflowMethod" = "fold", - ) -> None: - """Justify and overflow text to a given width. - - Args: - console (Console): Console instance. - width (int): Number of characters per line. - justify (str, optional): Default justify method for text: "left", "center", "full" or "right". Defaults to "left". - overflow (str, optional): Default overflow for text: "crop", "fold", or "ellipsis". Defaults to "fold". - - """ - from .text import Text - - if justify == "left": - for line in self._lines: - line.truncate(width, overflow=overflow, pad=True) - elif justify == "center": - for line in self._lines: - line.rstrip() - line.truncate(width, overflow=overflow) - line.pad_left((width - cell_len(line.plain)) // 2) - line.pad_right(width - cell_len(line.plain)) - elif justify == "right": - for line in self._lines: - line.rstrip() - line.truncate(width, overflow=overflow) - line.pad_left(width - cell_len(line.plain)) - elif justify == "full": - for line_index, line in enumerate(self._lines): - if line_index == len(self._lines) - 1: - break - words = line.split(" ") - words_size = sum(cell_len(word.plain) for word in words) - num_spaces = len(words) - 1 - spaces = [1 for _ in range(num_spaces)] - index = 0 - if spaces: - while words_size + num_spaces < width: - spaces[len(spaces) - index - 1] += 1 - num_spaces += 1 - index = (index + 1) % len(spaces) - tokens: List[Text] = [] - for index, (word, next_word) in enumerate( - zip_longest(words, words[1:]) - ): - tokens.append(word) - if index < len(spaces): - style = word.get_style_at_offset(console, -1) - next_style = next_word.get_style_at_offset(console, 0) - space_style = style if style == next_style else line.style - tokens.append(Text(" " * spaces[index], style=space_style)) - self[line_index] = Text("").join(tokens) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/control.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/control.py deleted file mode 100644 index 88fcb92..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/control.py +++ /dev/null @@ -1,225 +0,0 @@ -import sys -import time -from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Union - -if sys.version_info >= (3, 8): - from typing import Final -else: - from pip._vendor.typing_extensions import Final # pragma: no cover - -from .segment import ControlCode, ControlType, Segment - -if TYPE_CHECKING: - from .console import Console, ConsoleOptions, RenderResult - -STRIP_CONTROL_CODES: Final = [ - 7, # Bell - 8, # Backspace - 11, # Vertical tab - 12, # Form feed - 13, # Carriage return -] -_CONTROL_STRIP_TRANSLATE: Final = { - _codepoint: None for _codepoint in STRIP_CONTROL_CODES -} - -CONTROL_ESCAPE: Final = { - 7: "\\a", - 8: "\\b", - 11: "\\v", - 12: "\\f", - 13: "\\r", -} - -CONTROL_CODES_FORMAT: Dict[int, Callable[..., str]] = { - ControlType.BELL: lambda: "\x07", - ControlType.CARRIAGE_RETURN: lambda: "\r", - ControlType.HOME: lambda: "\x1b[H", - ControlType.CLEAR: lambda: "\x1b[2J", - ControlType.ENABLE_ALT_SCREEN: lambda: "\x1b[?1049h", - ControlType.DISABLE_ALT_SCREEN: lambda: "\x1b[?1049l", - ControlType.SHOW_CURSOR: lambda: "\x1b[?25h", - ControlType.HIDE_CURSOR: lambda: "\x1b[?25l", - ControlType.CURSOR_UP: lambda param: f"\x1b[{param}A", - ControlType.CURSOR_DOWN: lambda param: f"\x1b[{param}B", - ControlType.CURSOR_FORWARD: lambda param: f"\x1b[{param}C", - ControlType.CURSOR_BACKWARD: lambda param: f"\x1b[{param}D", - ControlType.CURSOR_MOVE_TO_COLUMN: lambda param: f"\x1b[{param+1}G", - ControlType.ERASE_IN_LINE: lambda param: f"\x1b[{param}K", - ControlType.CURSOR_MOVE_TO: lambda x, y: f"\x1b[{y+1};{x+1}H", - ControlType.SET_WINDOW_TITLE: lambda title: f"\x1b]0;{title}\x07", -} - - -class Control: - """A renderable that inserts a control code (non printable but may move cursor). - - Args: - *codes (str): Positional arguments are either a :class:`~rich.segment.ControlType` enum or a - tuple of ControlType and an integer parameter - """ - - __slots__ = ["segment"] - - def __init__(self, *codes: Union[ControlType, ControlCode]) -> None: - control_codes: List[ControlCode] = [ - (code,) if isinstance(code, ControlType) else code for code in codes - ] - _format_map = CONTROL_CODES_FORMAT - rendered_codes = "".join( - _format_map[code](*parameters) for code, *parameters in control_codes - ) - self.segment = Segment(rendered_codes, None, control_codes) - - @classmethod - def bell(cls) -> "Control": - """Ring the 'bell'.""" - return cls(ControlType.BELL) - - @classmethod - def home(cls) -> "Control": - """Move cursor to 'home' position.""" - return cls(ControlType.HOME) - - @classmethod - def move(cls, x: int = 0, y: int = 0) -> "Control": - """Move cursor relative to current position. - - Args: - x (int): X offset. - y (int): Y offset. - - Returns: - ~Control: Control object. - - """ - - def get_codes() -> Iterable[ControlCode]: - control = ControlType - if x: - yield ( - control.CURSOR_FORWARD if x > 0 else control.CURSOR_BACKWARD, - abs(x), - ) - if y: - yield ( - control.CURSOR_DOWN if y > 0 else control.CURSOR_UP, - abs(y), - ) - - control = cls(*get_codes()) - return control - - @classmethod - def move_to_column(cls, x: int, y: int = 0) -> "Control": - """Move to the given column, optionally add offset to row. - - Returns: - x (int): absolute x (column) - y (int): optional y offset (row) - - Returns: - ~Control: Control object. - """ - - return ( - cls( - (ControlType.CURSOR_MOVE_TO_COLUMN, x), - ( - ControlType.CURSOR_DOWN if y > 0 else ControlType.CURSOR_UP, - abs(y), - ), - ) - if y - else cls((ControlType.CURSOR_MOVE_TO_COLUMN, x)) - ) - - @classmethod - def move_to(cls, x: int, y: int) -> "Control": - """Move cursor to absolute position. - - Args: - x (int): x offset (column) - y (int): y offset (row) - - Returns: - ~Control: Control object. - """ - return cls((ControlType.CURSOR_MOVE_TO, x, y)) - - @classmethod - def clear(cls) -> "Control": - """Clear the screen.""" - return cls(ControlType.CLEAR) - - @classmethod - def show_cursor(cls, show: bool) -> "Control": - """Show or hide the cursor.""" - return cls(ControlType.SHOW_CURSOR if show else ControlType.HIDE_CURSOR) - - @classmethod - def alt_screen(cls, enable: bool) -> "Control": - """Enable or disable alt screen.""" - if enable: - return cls(ControlType.ENABLE_ALT_SCREEN, ControlType.HOME) - else: - return cls(ControlType.DISABLE_ALT_SCREEN) - - @classmethod - def title(cls, title: str) -> "Control": - """Set the terminal window title - - Args: - title (str): The new terminal window title - """ - return cls((ControlType.SET_WINDOW_TITLE, title)) - - def __str__(self) -> str: - return self.segment.text - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> "RenderResult": - if self.segment.text: - yield self.segment - - -def strip_control_codes( - text: str, _translate_table: Dict[int, None] = _CONTROL_STRIP_TRANSLATE -) -> str: - """Remove control codes from text. - - Args: - text (str): A string possibly contain control codes. - - Returns: - str: String with control codes removed. - """ - return text.translate(_translate_table) - - -def escape_control_codes( - text: str, - _translate_table: Dict[int, str] = CONTROL_ESCAPE, -) -> str: - """Replace control codes with their "escaped" equivalent in the given text. - (e.g. "\b" becomes "\\b") - - Args: - text (str): A string possibly containing control codes. - - Returns: - str: String with control codes replaced with their escaped version. - """ - return text.translate(_translate_table) - - -if __name__ == "__main__": # pragma: no cover - from pip._vendor.rich.console import Console - - console = Console() - console.print("Look at the title of your terminal window ^") - # console.print(Control((ControlType.SET_WINDOW_TITLE, "Hello, world!"))) - for i in range(10): - console.set_window_title("🚀 Loading" + "." * i) - time.sleep(0.5) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py deleted file mode 100644 index dca3719..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py +++ /dev/null @@ -1,190 +0,0 @@ -from typing import Dict - -from .style import Style - -DEFAULT_STYLES: Dict[str, Style] = { - "none": Style.null(), - "reset": Style( - color="default", - bgcolor="default", - dim=False, - bold=False, - italic=False, - underline=False, - blink=False, - blink2=False, - reverse=False, - conceal=False, - strike=False, - ), - "dim": Style(dim=True), - "bright": Style(dim=False), - "bold": Style(bold=True), - "strong": Style(bold=True), - "code": Style(reverse=True, bold=True), - "italic": Style(italic=True), - "emphasize": Style(italic=True), - "underline": Style(underline=True), - "blink": Style(blink=True), - "blink2": Style(blink2=True), - "reverse": Style(reverse=True), - "strike": Style(strike=True), - "black": Style(color="black"), - "red": Style(color="red"), - "green": Style(color="green"), - "yellow": Style(color="yellow"), - "magenta": Style(color="magenta"), - "cyan": Style(color="cyan"), - "white": Style(color="white"), - "inspect.attr": Style(color="yellow", italic=True), - "inspect.attr.dunder": Style(color="yellow", italic=True, dim=True), - "inspect.callable": Style(bold=True, color="red"), - "inspect.async_def": Style(italic=True, color="bright_cyan"), - "inspect.def": Style(italic=True, color="bright_cyan"), - "inspect.class": Style(italic=True, color="bright_cyan"), - "inspect.error": Style(bold=True, color="red"), - "inspect.equals": Style(), - "inspect.help": Style(color="cyan"), - "inspect.doc": Style(dim=True), - "inspect.value.border": Style(color="green"), - "live.ellipsis": Style(bold=True, color="red"), - "layout.tree.row": Style(dim=False, color="red"), - "layout.tree.column": Style(dim=False, color="blue"), - "logging.keyword": Style(bold=True, color="yellow"), - "logging.level.notset": Style(dim=True), - "logging.level.debug": Style(color="green"), - "logging.level.info": Style(color="blue"), - "logging.level.warning": Style(color="red"), - "logging.level.error": Style(color="red", bold=True), - "logging.level.critical": Style(color="red", bold=True, reverse=True), - "log.level": Style.null(), - "log.time": Style(color="cyan", dim=True), - "log.message": Style.null(), - "log.path": Style(dim=True), - "repr.ellipsis": Style(color="yellow"), - "repr.indent": Style(color="green", dim=True), - "repr.error": Style(color="red", bold=True), - "repr.str": Style(color="green", italic=False, bold=False), - "repr.brace": Style(bold=True), - "repr.comma": Style(bold=True), - "repr.ipv4": Style(bold=True, color="bright_green"), - "repr.ipv6": Style(bold=True, color="bright_green"), - "repr.eui48": Style(bold=True, color="bright_green"), - "repr.eui64": Style(bold=True, color="bright_green"), - "repr.tag_start": Style(bold=True), - "repr.tag_name": Style(color="bright_magenta", bold=True), - "repr.tag_contents": Style(color="default"), - "repr.tag_end": Style(bold=True), - "repr.attrib_name": Style(color="yellow", italic=False), - "repr.attrib_equal": Style(bold=True), - "repr.attrib_value": Style(color="magenta", italic=False), - "repr.number": Style(color="cyan", bold=True, italic=False), - "repr.number_complex": Style(color="cyan", bold=True, italic=False), # same - "repr.bool_true": Style(color="bright_green", italic=True), - "repr.bool_false": Style(color="bright_red", italic=True), - "repr.none": Style(color="magenta", italic=True), - "repr.url": Style(underline=True, color="bright_blue", italic=False, bold=False), - "repr.uuid": Style(color="bright_yellow", bold=False), - "repr.call": Style(color="magenta", bold=True), - "repr.path": Style(color="magenta"), - "repr.filename": Style(color="bright_magenta"), - "rule.line": Style(color="bright_green"), - "rule.text": Style.null(), - "json.brace": Style(bold=True), - "json.bool_true": Style(color="bright_green", italic=True), - "json.bool_false": Style(color="bright_red", italic=True), - "json.null": Style(color="magenta", italic=True), - "json.number": Style(color="cyan", bold=True, italic=False), - "json.str": Style(color="green", italic=False, bold=False), - "json.key": Style(color="blue", bold=True), - "prompt": Style.null(), - "prompt.choices": Style(color="magenta", bold=True), - "prompt.default": Style(color="cyan", bold=True), - "prompt.invalid": Style(color="red"), - "prompt.invalid.choice": Style(color="red"), - "pretty": Style.null(), - "scope.border": Style(color="blue"), - "scope.key": Style(color="yellow", italic=True), - "scope.key.special": Style(color="yellow", italic=True, dim=True), - "scope.equals": Style(color="red"), - "table.header": Style(bold=True), - "table.footer": Style(bold=True), - "table.cell": Style.null(), - "table.title": Style(italic=True), - "table.caption": Style(italic=True, dim=True), - "traceback.error": Style(color="red", italic=True), - "traceback.border.syntax_error": Style(color="bright_red"), - "traceback.border": Style(color="red"), - "traceback.text": Style.null(), - "traceback.title": Style(color="red", bold=True), - "traceback.exc_type": Style(color="bright_red", bold=True), - "traceback.exc_value": Style.null(), - "traceback.offset": Style(color="bright_red", bold=True), - "bar.back": Style(color="grey23"), - "bar.complete": Style(color="rgb(249,38,114)"), - "bar.finished": Style(color="rgb(114,156,31)"), - "bar.pulse": Style(color="rgb(249,38,114)"), - "progress.description": Style.null(), - "progress.filesize": Style(color="green"), - "progress.filesize.total": Style(color="green"), - "progress.download": Style(color="green"), - "progress.elapsed": Style(color="yellow"), - "progress.percentage": Style(color="magenta"), - "progress.remaining": Style(color="cyan"), - "progress.data.speed": Style(color="red"), - "progress.spinner": Style(color="green"), - "status.spinner": Style(color="green"), - "tree": Style(), - "tree.line": Style(), - "markdown.paragraph": Style(), - "markdown.text": Style(), - "markdown.em": Style(italic=True), - "markdown.emph": Style(italic=True), # For commonmark backwards compatibility - "markdown.strong": Style(bold=True), - "markdown.code": Style(bold=True, color="cyan", bgcolor="black"), - "markdown.code_block": Style(color="cyan", bgcolor="black"), - "markdown.block_quote": Style(color="magenta"), - "markdown.list": Style(color="cyan"), - "markdown.item": Style(), - "markdown.item.bullet": Style(color="yellow", bold=True), - "markdown.item.number": Style(color="yellow", bold=True), - "markdown.hr": Style(color="yellow"), - "markdown.h1.border": Style(), - "markdown.h1": Style(bold=True), - "markdown.h2": Style(bold=True, underline=True), - "markdown.h3": Style(bold=True), - "markdown.h4": Style(bold=True, dim=True), - "markdown.h5": Style(underline=True), - "markdown.h6": Style(italic=True), - "markdown.h7": Style(italic=True, dim=True), - "markdown.link": Style(color="bright_blue"), - "markdown.link_url": Style(color="blue", underline=True), - "markdown.s": Style(strike=True), - "iso8601.date": Style(color="blue"), - "iso8601.time": Style(color="magenta"), - "iso8601.timezone": Style(color="yellow"), -} - - -if __name__ == "__main__": # pragma: no cover - import argparse - import io - - from pip._vendor.rich.console import Console - from pip._vendor.rich.table import Table - from pip._vendor.rich.text import Text - - parser = argparse.ArgumentParser() - parser.add_argument("--html", action="store_true", help="Export as HTML table") - args = parser.parse_args() - html: bool = args.html - console = Console(record=True, width=70, file=io.StringIO()) if html else Console() - - table = Table("Name", "Styling") - - for style_name, style in DEFAULT_STYLES.items(): - table.add_row(Text(style_name, style=style), str(style)) - - console.print(table) - if html: - print(console.export_html(inline_styles=True)) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py deleted file mode 100644 index ad36183..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py +++ /dev/null @@ -1,37 +0,0 @@ -import os -import platform - -from pip._vendor.rich import inspect -from pip._vendor.rich.console import Console, get_windows_console_features -from pip._vendor.rich.panel import Panel -from pip._vendor.rich.pretty import Pretty - - -def report() -> None: # pragma: no cover - """Print a report to the terminal with debugging information""" - console = Console() - inspect(console) - features = get_windows_console_features() - inspect(features) - - env_names = ( - "TERM", - "COLORTERM", - "CLICOLOR", - "NO_COLOR", - "TERM_PROGRAM", - "COLUMNS", - "LINES", - "JUPYTER_COLUMNS", - "JUPYTER_LINES", - "JPY_PARENT_PID", - "VSCODE_VERBOSE_LOGGING", - ) - env = {name: os.getenv(name) for name in env_names} - console.print(Panel.fit((Pretty(env)), title="[b]Environment Variables")) - - console.print(f'platform="{platform.system()}"') - - -if __name__ == "__main__": # pragma: no cover - report() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py deleted file mode 100644 index 791f046..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py +++ /dev/null @@ -1,96 +0,0 @@ -import sys -from typing import TYPE_CHECKING, Optional, Union - -from .jupyter import JupyterMixin -from .segment import Segment -from .style import Style -from ._emoji_codes import EMOJI -from ._emoji_replace import _emoji_replace - -if sys.version_info >= (3, 8): - from typing import Literal -else: - from pip._vendor.typing_extensions import Literal # pragma: no cover - - -if TYPE_CHECKING: - from .console import Console, ConsoleOptions, RenderResult - - -EmojiVariant = Literal["emoji", "text"] - - -class NoEmoji(Exception): - """No emoji by that name.""" - - -class Emoji(JupyterMixin): - __slots__ = ["name", "style", "_char", "variant"] - - VARIANTS = {"text": "\uFE0E", "emoji": "\uFE0F"} - - def __init__( - self, - name: str, - style: Union[str, Style] = "none", - variant: Optional[EmojiVariant] = None, - ) -> None: - """A single emoji character. - - Args: - name (str): Name of emoji. - style (Union[str, Style], optional): Optional style. Defaults to None. - - Raises: - NoEmoji: If the emoji doesn't exist. - """ - self.name = name - self.style = style - self.variant = variant - try: - self._char = EMOJI[name] - except KeyError: - raise NoEmoji(f"No emoji called {name!r}") - if variant is not None: - self._char += self.VARIANTS.get(variant, "") - - @classmethod - def replace(cls, text: str) -> str: - """Replace emoji markup with corresponding unicode characters. - - Args: - text (str): A string with emojis codes, e.g. "Hello :smiley:!" - - Returns: - str: A string with emoji codes replaces with actual emoji. - """ - return _emoji_replace(text) - - def __repr__(self) -> str: - return f"" - - def __str__(self) -> str: - return self._char - - def __rich_console__( - self, console: "Console", options: "ConsoleOptions" - ) -> "RenderResult": - yield Segment(self._char, console.get_style(self.style)) - - -if __name__ == "__main__": # pragma: no cover - import sys - - from pip._vendor.rich.columns import Columns - from pip._vendor.rich.console import Console - - console = Console(record=True) - - columns = Columns( - (f":{name}: {name}" for name in sorted(EMOJI.keys()) if "\u200D" not in name), - column_first=True, - ) - - console.print(columns) - if len(sys.argv) > 1: - console.save_html(sys.argv[1]) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/errors.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/errors.py deleted file mode 100644 index 0bcbe53..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/errors.py +++ /dev/null @@ -1,34 +0,0 @@ -class ConsoleError(Exception): - """An error in console operation.""" - - -class StyleError(Exception): - """An error in styles.""" - - -class StyleSyntaxError(ConsoleError): - """Style was badly formatted.""" - - -class MissingStyle(StyleError): - """No such style.""" - - -class StyleStackError(ConsoleError): - """Style stack is invalid.""" - - -class NotRenderableError(ConsoleError): - """Object is not renderable.""" - - -class MarkupError(ConsoleError): - """Markup was badly formatted.""" - - -class LiveError(ConsoleError): - """Error related to Live display.""" - - -class NoAltScreen(ConsoleError): - """Alt screen mode was required.""" diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py deleted file mode 100644 index 4b0b0da..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py +++ /dev/null @@ -1,57 +0,0 @@ -import io -from typing import IO, TYPE_CHECKING, Any, List - -from .ansi import AnsiDecoder -from .text import Text - -if TYPE_CHECKING: - from .console import Console - - -class FileProxy(io.TextIOBase): - """Wraps a file (e.g. sys.stdout) and redirects writes to a console.""" - - def __init__(self, console: "Console", file: IO[str]) -> None: - self.__console = console - self.__file = file - self.__buffer: List[str] = [] - self.__ansi_decoder = AnsiDecoder() - - @property - def rich_proxied_file(self) -> IO[str]: - """Get proxied file.""" - return self.__file - - def __getattr__(self, name: str) -> Any: - return getattr(self.__file, name) - - def write(self, text: str) -> int: - if not isinstance(text, str): - raise TypeError(f"write() argument must be str, not {type(text).__name__}") - buffer = self.__buffer - lines: List[str] = [] - while text: - line, new_line, text = text.partition("\n") - if new_line: - lines.append("".join(buffer) + line) - buffer.clear() - else: - buffer.append(line) - break - if lines: - console = self.__console - with console: - output = Text("\n").join( - self.__ansi_decoder.decode_line(line) for line in lines - ) - console.print(output) - return len(text) - - def flush(self) -> None: - output = "".join(self.__buffer) - if output: - self.__console.print(output) - del self.__buffer[:] - - def fileno(self) -> int: - return self.__file.fileno() diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py deleted file mode 100644 index 99f118e..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py +++ /dev/null @@ -1,89 +0,0 @@ -# coding: utf-8 -"""Functions for reporting filesizes. Borrowed from https://github.com/PyFilesystem/pyfilesystem2 - -The functions declared in this module should cover the different -use cases needed to generate a string representation of a file size -using several different units. Since there are many standards regarding -file size units, three different functions have been implemented. - -See Also: - * `Wikipedia: Binary prefix `_ - -""" - -__all__ = ["decimal"] - -from typing import Iterable, List, Optional, Tuple - - -def _to_str( - size: int, - suffixes: Iterable[str], - base: int, - *, - precision: Optional[int] = 1, - separator: Optional[str] = " ", -) -> str: - if size == 1: - return "1 byte" - elif size < base: - return "{:,} bytes".format(size) - - for i, suffix in enumerate(suffixes, 2): # noqa: B007 - unit = base**i - if size < unit: - break - return "{:,.{precision}f}{separator}{}".format( - (base * size / unit), - suffix, - precision=precision, - separator=separator, - ) - - -def pick_unit_and_suffix(size: int, suffixes: List[str], base: int) -> Tuple[int, str]: - """Pick a suffix and base for the given size.""" - for i, suffix in enumerate(suffixes): - unit = base**i - if size < unit * base: - break - return unit, suffix - - -def decimal( - size: int, - *, - precision: Optional[int] = 1, - separator: Optional[str] = " ", -) -> str: - """Convert a filesize in to a string (powers of 1000, SI prefixes). - - In this convention, ``1000 B = 1 kB``. - - This is typically the format used to advertise the storage - capacity of USB flash drives and the like (*256 MB* meaning - actually a storage capacity of more than *256 000 000 B*), - or used by **Mac OS X** since v10.6 to report file sizes. - - Arguments: - int (size): A file size. - int (precision): The number of decimal places to include (default = 1). - str (separator): The string to separate the value from the units (default = " "). - - Returns: - `str`: A string containing a abbreviated file size and units. - - Example: - >>> filesize.decimal(30000) - '30.0 kB' - >>> filesize.decimal(30000, precision=2, separator="") - '30.00kB' - - """ - return _to_str( - size, - ("kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"), - 1000, - precision=precision, - separator=separator, - ) diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py deleted file mode 100644 index c264679..0000000 --- a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py +++ /dev/null @@ -1,232 +0,0 @@ -import re -from abc import ABC, abstractmethod -from typing import List, Union - -from .text import Span, Text - - -def _combine_regex(*regexes: str) -> str: - """Combine a number of regexes in to a single regex. - - Returns: - str: New regex with all regexes ORed together. - """ - return "|".join(regexes) - - -class Highlighter(ABC): - """Abstract base class for highlighters.""" - - def __call__(self, text: Union[str, Text]) -> Text: - """Highlight a str or Text instance. - - Args: - text (Union[str, ~Text]): Text to highlight. - - Raises: - TypeError: If not called with text or str. - - Returns: - Text: A test instance with highlighting applied. - """ - if isinstance(text, str): - highlight_text = Text(text) - elif isinstance(text, Text): - highlight_text = text.copy() - else: - raise TypeError(f"str or Text instance required, not {text!r}") - self.highlight(highlight_text) - return highlight_text - - @abstractmethod - def highlight(self, text: Text) -> None: - """Apply highlighting in place to text. - - Args: - text (~Text): A text object highlight. - """ - - -class NullHighlighter(Highlighter): - """A highlighter object that doesn't highlight. - - May be used to disable highlighting entirely. - - """ - - def highlight(self, text: Text) -> None: - """Nothing to do""" - - -class RegexHighlighter(Highlighter): - """Applies highlighting from a list of regular expressions.""" - - highlights: List[str] = [] - base_style: str = "" - - def highlight(self, text: Text) -> None: - """Highlight :class:`rich.text.Text` using regular expressions. - - Args: - text (~Text): Text to highlighted. - - """ - - highlight_regex = text.highlight_regex - for re_highlight in self.highlights: - highlight_regex(re_highlight, style_prefix=self.base_style) - - -class ReprHighlighter(RegexHighlighter): - """Highlights the text typically produced from ``__repr__`` methods.""" - - base_style = "repr." - highlights = [ - r"(?P<)(?P[-\w.:|]*)(?P[\w\W]*)(?P>)", - r'(?P[\w_]{1,50})=(?P"?[\w_]+"?)?', - r"(?P[][{}()])", - _combine_regex( - r"(?P[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})", - r"(?P([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})", - r"(?P(?:[0-9A-Fa-f]{1,2}-){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){3}[0-9A-Fa-f]{4})", - r"(?P(?:[0-9A-Fa-f]{1,2}-){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})", - r"(?P[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})", - r"(?P[\w.]*?)\(", - r"\b(?PTrue)\b|\b(?PFalse)\b|\b(?PNone)\b", - r"(?P\.\.\.)", - r"(?P(?(?\B(/[-\w._+]+)*\/)(?P[-\w._+]*)?", - r"(?b?'''.*?(?(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#]*)", - ), - ] - - -class JSONHighlighter(RegexHighlighter): - """Highlights JSON""" - - # Captures the start and end of JSON strings, handling escaped quotes - JSON_STR = r"(?b?\".*?(?[\{\[\(\)\]\}])", - r"\b(?Ptrue)\b|\b(?Pfalse)\b|\b(?Pnull)\b", - r"(?P(? None: - super().highlight(text) - - # Additional work to handle highlighting JSON keys - plain = text.plain - append = text.spans.append - whitespace = self.JSON_WHITESPACE - for match in re.finditer(self.JSON_STR, plain): - start, end = match.span() - cursor = end - while cursor < len(plain): - char = plain[cursor] - cursor += 1 - if char == ":": - append(Span(start, end, "json.key")) - elif char in whitespace: - continue - break - - -class ISO8601Highlighter(RegexHighlighter): - """Highlights the ISO8601 date time strings. - Regex reference: https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s07.html - """ - - base_style = "iso8601." - highlights = [ - # - # Dates - # - # Calendar month (e.g. 2008-08). The hyphen is required - r"^(?P[0-9]{4})-(?P1[0-2]|0[1-9])$", - # Calendar date w/o hyphens (e.g. 20080830) - r"^(?P(?P[0-9]{4})(?P1[0-2]|0[1-9])(?P3[01]|0[1-9]|[12][0-9]))$", - # Ordinal date (e.g. 2008-243). The hyphen is optional - r"^(?P(?P[0-9]{4})-?(?P36[0-6]|3[0-5][0-9]|[12][0-9]{2}|0[1-9][0-9]|00[1-9]))$", - # - # Weeks - # - # Week of the year (e.g., 2008-W35). The hyphen is optional - r"^(?P(?P[0-9]{4})-?W(?P5[0-3]|[1-4][0-9]|0[1-9]))$", - # Week date (e.g., 2008-W35-6). The hyphens are optional - r"^(?P(?P[0-9]{4})-?W(?P5[0-3]|[1-4][0-9]|0[1-9])-?(?P[1-7]))$", - # - # Times - # - # Hours and minutes (e.g., 17:21). The colon is optional - r"^(?P