Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/ceval.pxd +8 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/conversion.pxd +36 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/descr.pxd +26 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/getargs.pxd +12 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/instance.pxd +25 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/longintrepr.pxd +19 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/marshal.pxd +66 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/module.pxd +208 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/number.pxd +265 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/pythread.pxd +53 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/string.pxd +196 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__init__.py +55 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/exceptions.py +48 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/ext.py +168 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/fallback.py +951 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__init__.py +177 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__pycache__/control.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/_fileno.py +24 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/_null_file.py +69 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/_pick.py +17 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/_windows_renderer.py +56 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/ansi.py +240 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/columns.py +187 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/containers.py +167 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/default_styles.py +190 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/diagnose.py +37 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/emoji.py +96 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/live_render.py +112 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/measure.py +151 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/padding.py +141 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/pager.py +34 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/pretty.py +995 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/progress.py +1699 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/rule.py +130 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/scope.py +86 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/status.py +131 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/text.py +1357 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__init__.py +11 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/_parser.py +691 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/_re.py +107 -0
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/ceval.pxd
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
cdef extern from "Python.h":
|
| 3 |
+
|
| 4 |
+
void PyEval_InitThreads()
|
| 5 |
+
# Initialize and acquire the global interpreter lock.
|
| 6 |
+
|
| 7 |
+
int PyEval_ThreadsInitialized()
|
| 8 |
+
# Returns a non-zero value if PyEval_InitThreads() has been called.
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/conversion.pxd
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# From https://docs.python.org/3/c-api/conversion.html
|
| 2 |
+
|
| 3 |
+
from .object cimport PyObject
|
| 4 |
+
|
| 5 |
+
cdef extern from "Python.h":
|
| 6 |
+
ctypedef struct va_list
|
| 7 |
+
|
| 8 |
+
int PyOS_snprintf(char *str, size_t size, const char *format, ...)
|
| 9 |
+
# Output not more than size bytes to str according to the format
|
| 10 |
+
# string format and the extra arguments. See the Unix man page snprintf(2).
|
| 11 |
+
|
| 12 |
+
int PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
|
| 13 |
+
# Output not more than size bytes to str according to the format
|
| 14 |
+
# string format and the variable argument list va. Unix man page vsnprintf(2).
|
| 15 |
+
|
| 16 |
+
double PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception) except? -1.0
|
| 17 |
+
# Convert a string s to a double, raising a Python exception on failure. The set of
|
| 18 |
+
# accepted strings corresponds to the set of strings accepted by Python’s float()
|
| 19 |
+
# constructor, except that s must not have leading or trailing whitespace.
|
| 20 |
+
# The conversion is independent of the current locale.
|
| 21 |
+
|
| 22 |
+
enum:
|
| 23 |
+
Py_DTSF_SIGN
|
| 24 |
+
Py_DTSF_ADD_DOT_0
|
| 25 |
+
Py_DTSF_ALT
|
| 26 |
+
|
| 27 |
+
char* PyOS_double_to_string(double val, char format_code, int precision, int flags, int *ptype) except NULL
|
| 28 |
+
# Convert a double val to a string using supplied format_code, precision, and flags.
|
| 29 |
+
|
| 30 |
+
int PyOS_stricmp(const char *s1, const char *s2)
|
| 31 |
+
# Case insensitive comparison of strings. The function works almost identically
|
| 32 |
+
# to strcmp() except that it ignores the case.
|
| 33 |
+
|
| 34 |
+
int PyOS_strnicmp(const char *s1, const char *s2, Py_ssize_t size)
|
| 35 |
+
# Case insensitive comparison of strings. The function works almost identically
|
| 36 |
+
# to strncmp() except that it ignores the case.
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/descr.pxd
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .object cimport PyObject, PyTypeObject
|
| 2 |
+
|
| 3 |
+
cdef extern from "Python.h":
|
| 4 |
+
ctypedef object (*wrapperfunc)(self, args, void* wrapped)
|
| 5 |
+
ctypedef object (*wrapperfunc_kwds)(self, args, void* wrapped, kwds)
|
| 6 |
+
|
| 7 |
+
struct wrapperbase:
|
| 8 |
+
char* name
|
| 9 |
+
int offset
|
| 10 |
+
void* function
|
| 11 |
+
wrapperfunc wrapper
|
| 12 |
+
char* doc
|
| 13 |
+
int flags
|
| 14 |
+
PyObject* name_strobj
|
| 15 |
+
|
| 16 |
+
int PyWrapperFlag_KEYWORDS
|
| 17 |
+
|
| 18 |
+
ctypedef class __builtin__.wrapper_descriptor [object PyWrapperDescrObject]:
|
| 19 |
+
cdef type d_type
|
| 20 |
+
cdef d_name
|
| 21 |
+
cdef wrapperbase* d_base
|
| 22 |
+
cdef void* d_wrapped
|
| 23 |
+
|
| 24 |
+
object PyDescr_NewWrapper(PyTypeObject* cls, wrapperbase* wrapper, void* wrapped)
|
| 25 |
+
|
| 26 |
+
int PyDescr_IsData(descr)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/getargs.pxd
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
cdef extern from "Python.h":
|
| 3 |
+
#####################################################################
|
| 4 |
+
# 5.5 Parsing arguments and building values
|
| 5 |
+
#####################################################################
|
| 6 |
+
ctypedef struct va_list
|
| 7 |
+
int PyArg_ParseTuple(object args, char *format, ...) except 0
|
| 8 |
+
int PyArg_VaParse(object args, char *format, va_list vargs) except 0
|
| 9 |
+
int PyArg_ParseTupleAndKeywords(object args, object kw, char *format, char *keywords[], ...) except 0
|
| 10 |
+
int PyArg_VaParseTupleAndKeywords(object args, object kw, char *format, char *keywords[], va_list vargs) except 0
|
| 11 |
+
int PyArg_Parse(object args, char *format, ...) except 0
|
| 12 |
+
int PyArg_UnpackTuple(object args, char *name, Py_ssize_t min, Py_ssize_t max, ...) except 0
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/instance.pxd
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cdef extern from "Python.h":
|
| 2 |
+
|
| 3 |
+
############################################################################
|
| 4 |
+
# 7.5.2 Instance Objects
|
| 5 |
+
############################################################################
|
| 6 |
+
|
| 7 |
+
# PyTypeObject PyInstance_Type
|
| 8 |
+
#
|
| 9 |
+
# Type object for class instances.
|
| 10 |
+
|
| 11 |
+
int PyInstance_Check(object obj)
|
| 12 |
+
# Return true if obj is an instance.
|
| 13 |
+
|
| 14 |
+
object PyInstance_New(object cls, object arg, object kw)
|
| 15 |
+
# Return value: New reference.
|
| 16 |
+
# Create a new instance of a specific class. The parameters arg
|
| 17 |
+
# and kw are used as the positional and keyword parameters to the
|
| 18 |
+
# object's constructor.
|
| 19 |
+
|
| 20 |
+
object PyInstance_NewRaw(object cls, object dict)
|
| 21 |
+
# Return value: New reference.
|
| 22 |
+
# Create a new instance of a specific class without calling its
|
| 23 |
+
# constructor. class is the class of new object. The dict
|
| 24 |
+
# parameter will be used as the object's __dict__; if NULL, a new
|
| 25 |
+
# dictionary will be created for the instance.
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/longintrepr.pxd
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Internals of the "long" type (Python 2) or "int" type (Python 3).
|
| 2 |
+
|
| 3 |
+
cdef extern from "Python.h":
|
| 4 |
+
"""
|
| 5 |
+
#if PY_MAJOR_VERSION < 3
|
| 6 |
+
#include "longintrepr.h"
|
| 7 |
+
#endif
|
| 8 |
+
"""
|
| 9 |
+
ctypedef unsigned int digit
|
| 10 |
+
ctypedef int sdigit # Python >= 2.7 only
|
| 11 |
+
|
| 12 |
+
ctypedef class __builtin__.py_long [object PyLongObject]:
|
| 13 |
+
cdef digit* ob_digit
|
| 14 |
+
|
| 15 |
+
cdef py_long _PyLong_New(Py_ssize_t s)
|
| 16 |
+
|
| 17 |
+
cdef long PyLong_SHIFT
|
| 18 |
+
cdef digit PyLong_BASE
|
| 19 |
+
cdef digit PyLong_MASK
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/marshal.pxd
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from libc.stdio cimport FILE
|
| 2 |
+
|
| 3 |
+
cdef extern from "Python.h":
|
| 4 |
+
|
| 5 |
+
###########################################################################
|
| 6 |
+
# Data marshalling support
|
| 7 |
+
###########################################################################
|
| 8 |
+
|
| 9 |
+
const int Py_MARSHAL_VERSION
|
| 10 |
+
|
| 11 |
+
void PyMarshal_WriteLongToFile(long value, FILE *file, int version)
|
| 12 |
+
# Marshal a long integer, value, to file. This will only write the
|
| 13 |
+
# least-significant 32 bits of value, regardless of the size of the native
|
| 14 |
+
# long type. version indicates the file format.
|
| 15 |
+
|
| 16 |
+
void PyMarshal_WriteObjectToFile(object value, FILE *file, int version)
|
| 17 |
+
# Marshal a Python object, value, to file. version indicates the file
|
| 18 |
+
# format.
|
| 19 |
+
|
| 20 |
+
bytes PyMarshal_WriteObjectToString(object value, int version)
|
| 21 |
+
# Return value: New reference.
|
| 22 |
+
# Return a bytes object containing the marshalled representation of value.
|
| 23 |
+
# version indicates the file format.
|
| 24 |
+
|
| 25 |
+
long PyMarshal_ReadLongFromFile(FILE *file) except? -1
|
| 26 |
+
# Return a C long from the data stream in a FILE* opened for reading. Only
|
| 27 |
+
# a 32-bit value can be read in using this function, regardless of the
|
| 28 |
+
# native size of long.
|
| 29 |
+
|
| 30 |
+
# On error, sets the appropriate exception (EOFError) and returns -1.
|
| 31 |
+
|
| 32 |
+
int PyMarshal_ReadShortFromFile(FILE *file) except? -1
|
| 33 |
+
# Return a C short from the data stream in a FILE* opened for reading. Only
|
| 34 |
+
# a 16-bit value can be read in using this function, regardless of the
|
| 35 |
+
# native size of short.
|
| 36 |
+
|
| 37 |
+
# On error, sets the appropriate exception (EOFError) and returns -1.
|
| 38 |
+
|
| 39 |
+
object PyMarshal_ReadObjectFromFile(FILE *file)
|
| 40 |
+
# Return value: New reference.
|
| 41 |
+
# Return a Python object from the data stream in a FILE* opened for
|
| 42 |
+
# reading.
|
| 43 |
+
|
| 44 |
+
# On error, sets the appropriate exception (EOFError, ValueError or
|
| 45 |
+
# TypeError) and returns NULL.
|
| 46 |
+
|
| 47 |
+
object PyMarshal_ReadLastObjectFromFile(FILE *file)
|
| 48 |
+
# Return value: New reference.
|
| 49 |
+
# Return a Python object from the data stream in a FILE* opened for
|
| 50 |
+
# reading. Unlike PyMarshal_ReadObjectFromFile(), this function assumes
|
| 51 |
+
# that no further objects will be read from the file, allowing it to
|
| 52 |
+
# aggressively load file data into memory so that the de-serialization can
|
| 53 |
+
# operate from data in memory, rather than reading a byte at a time from the
|
| 54 |
+
# file. Only use these variant if you are certain that you won’t be reading
|
| 55 |
+
# anything else from the file.
|
| 56 |
+
|
| 57 |
+
# On error, sets the appropriate exception (EOFError, ValueError or
|
| 58 |
+
# TypeError) and returns NULL.
|
| 59 |
+
|
| 60 |
+
object PyMarshal_ReadObjectFromString(const char *data, Py_ssize_t len)
|
| 61 |
+
# Return value: New reference.
|
| 62 |
+
# Return a Python object from the data stream in a byte buffer containing
|
| 63 |
+
# len bytes pointed to by data.
|
| 64 |
+
|
| 65 |
+
# On error, sets the appropriate exception (EOFError, ValueError or
|
| 66 |
+
# TypeError) and returns NULL.
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/module.pxd
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .object cimport PyObject
|
| 2 |
+
|
| 3 |
+
cdef extern from "Python.h":
|
| 4 |
+
ctypedef struct _inittab
|
| 5 |
+
|
| 6 |
+
#####################################################################
|
| 7 |
+
# 5.3 Importing Modules
|
| 8 |
+
#####################################################################
|
| 9 |
+
object PyImport_ImportModule(const char *name)
|
| 10 |
+
# Return value: New reference.
|
| 11 |
+
# This is a simplified interface to PyImport_ImportModuleEx()
|
| 12 |
+
# below, leaving the globals and locals arguments set to
|
| 13 |
+
# NULL. When the name argument contains a dot (when it specifies a
|
| 14 |
+
# submodule of a package), the fromlist argument is set to the
|
| 15 |
+
# list ['*'] so that the return value is the named module rather
|
| 16 |
+
# than the top-level package containing it as would otherwise be
|
| 17 |
+
# the case. (Unfortunately, this has an additional side effect
|
| 18 |
+
# when name in fact specifies a subpackage instead of a submodule:
|
| 19 |
+
# the submodules specified in the package's __all__ variable are
|
| 20 |
+
# loaded.) Return a new reference to the imported module, or NULL
|
| 21 |
+
# with an exception set on failure.
|
| 22 |
+
|
| 23 |
+
object PyImport_ImportModuleEx(const char *name, object globals, object locals, object fromlist)
|
| 24 |
+
# Return value: New reference.
|
| 25 |
+
|
| 26 |
+
# Import a module. This is best described by referring to the
|
| 27 |
+
# built-in Python function __import__(), as the standard
|
| 28 |
+
# __import__() function calls this function directly.
|
| 29 |
+
|
| 30 |
+
# The return value is a new reference to the imported module or
|
| 31 |
+
# top-level package, or NULL with an exception set on failure
|
| 32 |
+
# (before Python 2.4, the module may still be created in this
|
| 33 |
+
# case). Like for __import__(), the return value when a submodule
|
| 34 |
+
# of a package was requested is normally the top-level package,
|
| 35 |
+
# unless a non-empty fromlist was given. Changed in version 2.4:
|
| 36 |
+
# failing imports remove incomplete module objects.
|
| 37 |
+
|
| 38 |
+
object PyImport_ImportModuleLevel(char *name, object globals, object locals, object fromlist, int level)
|
| 39 |
+
# Return value: New reference.
|
| 40 |
+
|
| 41 |
+
# Import a module. This is best described by referring to the
|
| 42 |
+
# built-in Python function __import__(), as the standard
|
| 43 |
+
# __import__() function calls this function directly.
|
| 44 |
+
|
| 45 |
+
# The return value is a new reference to the imported module or
|
| 46 |
+
# top-level package, or NULL with an exception set on failure. Like
|
| 47 |
+
# for __import__(), the return value when a submodule of a package
|
| 48 |
+
# was requested is normally the top-level package, unless a
|
| 49 |
+
# non-empty fromlist was given.
|
| 50 |
+
|
| 51 |
+
object PyImport_Import(object name)
|
| 52 |
+
# Return value: New reference.
|
| 53 |
+
# This is a higher-level interface that calls the current ``import
|
| 54 |
+
# hook function''. It invokes the __import__() function from the
|
| 55 |
+
# __builtins__ of the current globals. This means that the import
|
| 56 |
+
# is done using whatever import hooks are installed in the current
|
| 57 |
+
# environment, e.g. by rexec or ihooks.
|
| 58 |
+
|
| 59 |
+
object PyImport_ReloadModule(object m)
|
| 60 |
+
# Return value: New reference.
|
| 61 |
+
# Reload a module. This is best described by referring to the
|
| 62 |
+
# built-in Python function reload(), as the standard reload()
|
| 63 |
+
# function calls this function directly. Return a new reference to
|
| 64 |
+
# the reloaded module, or NULL with an exception set on failure
|
| 65 |
+
# (the module still exists in this case).
|
| 66 |
+
|
| 67 |
+
PyObject* PyImport_AddModule(const char *name) except NULL
|
| 68 |
+
# Return value: Borrowed reference.
|
| 69 |
+
# Return the module object corresponding to a module name. The
|
| 70 |
+
# name argument may be of the form package.module. First check the
|
| 71 |
+
# modules dictionary if there's one there, and if not, create a
|
| 72 |
+
# new one and insert it in the modules dictionary. Return NULL
|
| 73 |
+
# with an exception set on failure. Note: This function does not
|
| 74 |
+
# load or import the module; if the module wasn't already loaded,
|
| 75 |
+
# you will get an empty module object. Use PyImport_ImportModule()
|
| 76 |
+
# or one of its variants to import a module. Package structures
|
| 77 |
+
# implied by a dotted name for name are not created if not already
|
| 78 |
+
# present.
|
| 79 |
+
|
| 80 |
+
object PyImport_ExecCodeModule(char *name, object co)
|
| 81 |
+
# Return value: New reference.
|
| 82 |
+
# Given a module name (possibly of the form package.module) and a
|
| 83 |
+
# code object read from a Python bytecode file or obtained from
|
| 84 |
+
# the built-in function compile(), load the module. Return a new
|
| 85 |
+
# reference to the module object, or NULL with an exception set if
|
| 86 |
+
# an error occurred. Name is removed from sys.modules in error
|
| 87 |
+
# cases, and even if name was already in sys.modules on entry to
|
| 88 |
+
# PyImport_ExecCodeModule(). Leaving incompletely initialized
|
| 89 |
+
# modules in sys.modules is dangerous, as imports of such modules
|
| 90 |
+
# have no way to know that the module object is an unknown (and
|
| 91 |
+
# probably damaged with respect to the module author's intents)
|
| 92 |
+
# state.
|
| 93 |
+
# This function will reload the module if it was already
|
| 94 |
+
# imported. See PyImport_ReloadModule() for the intended way to
|
| 95 |
+
# reload a module.
|
| 96 |
+
# If name points to a dotted name of the form package.module, any
|
| 97 |
+
# package structures not already created will still not be
|
| 98 |
+
# created.
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
long PyImport_GetMagicNumber()
|
| 102 |
+
# Return the magic number for Python bytecode files (a.k.a. .pyc
|
| 103 |
+
# and .pyo files). The magic number should be present in the first
|
| 104 |
+
# four bytes of the bytecode file, in little-endian byte order.
|
| 105 |
+
|
| 106 |
+
PyObject* PyImport_GetModuleDict() except NULL
|
| 107 |
+
# Return value: Borrowed reference.
|
| 108 |
+
# Return the dictionary used for the module administration
|
| 109 |
+
# (a.k.a. sys.modules). Note that this is a per-interpreter
|
| 110 |
+
# variable.
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
int PyImport_ImportFrozenModule(char *name) except -1
|
| 114 |
+
# Load a frozen module named name. Return 1 for success, 0 if the
|
| 115 |
+
# module is not found, and -1 with an exception set if the
|
| 116 |
+
# initialization failed. To access the imported module on a
|
| 117 |
+
# successful load, use PyImport_ImportModule(). (Note the misnomer
|
| 118 |
+
# -- this function would reload the module if it was already
|
| 119 |
+
# imported.)
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
int PyImport_ExtendInittab(_inittab *newtab) except -1
|
| 123 |
+
# Add a collection of modules to the table of built-in
|
| 124 |
+
# modules. The newtab array must end with a sentinel entry which
|
| 125 |
+
# contains NULL for the name field; failure to provide the
|
| 126 |
+
# sentinel value can result in a memory fault. Returns 0 on
|
| 127 |
+
# success or -1 if insufficient memory could be allocated to
|
| 128 |
+
# extend the internal table. In the event of failure, no modules
|
| 129 |
+
# are added to the internal table. This should be called before
|
| 130 |
+
# Py_Initialize().
|
| 131 |
+
|
| 132 |
+
#####################################################################
|
| 133 |
+
# 7.5.5 Module Objects
|
| 134 |
+
#####################################################################
|
| 135 |
+
|
| 136 |
+
# PyTypeObject PyModule_Type
|
| 137 |
+
#
|
| 138 |
+
# This instance of PyTypeObject represents the Python module
|
| 139 |
+
# type. This is exposed to Python programs as types.ModuleType.
|
| 140 |
+
|
| 141 |
+
bint PyModule_Check(object p)
|
| 142 |
+
# Return true if p is a module object, or a subtype of a module
|
| 143 |
+
# object.
|
| 144 |
+
|
| 145 |
+
bint PyModule_CheckExact(object p)
|
| 146 |
+
# Return true if p is a module object, but not a subtype of PyModule_Type.
|
| 147 |
+
|
| 148 |
+
object PyModule_NewObject(object name)
|
| 149 |
+
# Return a new module object with the __name__ attribute set to name.
|
| 150 |
+
# The module’s __name__, __doc__, __package__, and __loader__
|
| 151 |
+
# attributes are filled in (all but __name__ are set to None); the caller
|
| 152 |
+
# is responsible for providing a __file__ attribute.
|
| 153 |
+
|
| 154 |
+
object PyModule_New(const char *name)
|
| 155 |
+
# Return value: New reference.
|
| 156 |
+
# Return a new module object with the __name__ attribute set to
|
| 157 |
+
# name. Only the module's __doc__ and __name__ attributes are
|
| 158 |
+
# filled in; the caller is responsible for providing a __file__
|
| 159 |
+
# attribute.
|
| 160 |
+
|
| 161 |
+
PyObject* PyModule_GetDict(object module) except NULL
|
| 162 |
+
# Return value: Borrowed reference.
|
| 163 |
+
# Return the dictionary object that implements module's namespace;
|
| 164 |
+
# this object is the same as the __dict__ attribute of the module
|
| 165 |
+
# object. This function never fails. It is recommended extensions
|
| 166 |
+
# use other PyModule_*() and PyObject_*() functions rather than
|
| 167 |
+
# directly manipulate a module's __dict__.
|
| 168 |
+
|
| 169 |
+
object PyModule_GetNameObject(object module)
|
| 170 |
+
# Return module’s __name__ value. If the module does not provide one, or if
|
| 171 |
+
# it is not a string, SystemError is raised and NULL is returned.
|
| 172 |
+
|
| 173 |
+
char* PyModule_GetName(object module) except NULL
|
| 174 |
+
# Similar to PyModule_GetNameObject() but return the name encoded
|
| 175 |
+
# to 'utf-8'.
|
| 176 |
+
|
| 177 |
+
void* PyModule_GetState(object module)
|
| 178 |
+
# Return the “state” of the module, that is, a pointer to the block of
|
| 179 |
+
# memory allocated at module creation time, or NULL.
|
| 180 |
+
# See PyModuleDef.m_size.
|
| 181 |
+
|
| 182 |
+
object PyModule_GetFilenameObject(object module)
|
| 183 |
+
# Return the name of the file from which module was loaded using module’s
|
| 184 |
+
# __file__ attribute. If this is not defined, or if it is not a unicode
|
| 185 |
+
# string, raise SystemError and return NULL; otherwise return a reference
|
| 186 |
+
# to a Unicode object.
|
| 187 |
+
|
| 188 |
+
char* PyModule_GetFilename(object module) except NULL
|
| 189 |
+
# Similar to PyModule_GetFilenameObject() but return the filename encoded
|
| 190 |
+
# to ‘utf-8’.
|
| 191 |
+
|
| 192 |
+
int PyModule_AddObject(object module, const char *name, object value) except -1
|
| 193 |
+
# Add an object to module as name. This is a convenience function
|
| 194 |
+
# which can be used from the module's initialization function.
|
| 195 |
+
# Return -1 on error, 0 on success.
|
| 196 |
+
#
|
| 197 |
+
# WARNING: This _steals_ a reference to value.
|
| 198 |
+
|
| 199 |
+
int PyModule_AddIntConstant(object module, const char *name, long value) except -1
|
| 200 |
+
# Add an integer constant to module as name. This convenience
|
| 201 |
+
# function can be used from the module's initialization
|
| 202 |
+
# function. Return -1 on error, 0 on success.
|
| 203 |
+
|
| 204 |
+
int PyModule_AddStringConstant(object module, const char *name, const char *value) except -1
|
| 205 |
+
# Add a string constant to module as name. This convenience
|
| 206 |
+
# function can be used from the module's initialization
|
| 207 |
+
# function. The string value must be null-terminated. Return -1 on
|
| 208 |
+
# error, 0 on success.
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/number.pxd
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .object cimport PyObject
|
| 2 |
+
|
| 3 |
+
cdef extern from "Python.h":
|
| 4 |
+
|
| 5 |
+
#####################################################################
|
| 6 |
+
# 6.2 Number Protocol
|
| 7 |
+
#####################################################################
|
| 8 |
+
|
| 9 |
+
bint PyNumber_Check(object o)
|
| 10 |
+
# Returns 1 if the object o provides numeric protocols, and false
|
| 11 |
+
# otherwise. This function always succeeds.
|
| 12 |
+
|
| 13 |
+
object PyNumber_Add(object o1, object o2)
|
| 14 |
+
# Return value: New reference.
|
| 15 |
+
# Returns the result of adding o1 and o2, or NULL on failure. This
|
| 16 |
+
# is the equivalent of the Python expression "o1 + o2".
|
| 17 |
+
|
| 18 |
+
object PyNumber_Subtract(object o1, object o2)
|
| 19 |
+
# Return value: New reference.
|
| 20 |
+
# Returns the result of subtracting o2 from o1, or NULL on
|
| 21 |
+
# failure. This is the equivalent of the Python expression "o1 -
|
| 22 |
+
# o2".
|
| 23 |
+
|
| 24 |
+
object PyNumber_Multiply(object o1, object o2)
|
| 25 |
+
# Return value: New reference.
|
| 26 |
+
# Returns the result of multiplying o1 and o2, or NULL on
|
| 27 |
+
# failure. This is the equivalent of the Python expression "o1 *
|
| 28 |
+
# o2".
|
| 29 |
+
|
| 30 |
+
object PyNumber_MatrixMultiply(object o1, object o2)
|
| 31 |
+
# Return value: New reference.
|
| 32 |
+
# Returns the result of matrix multiplication on o1 and o2, or
|
| 33 |
+
# NULL on failure. This is the equivalent of the Python
|
| 34 |
+
# expression "o1 @ o2".
|
| 35 |
+
# New in version 3.5.
|
| 36 |
+
|
| 37 |
+
object PyNumber_Divide(object o1, object o2)
|
| 38 |
+
# Return value: New reference.
|
| 39 |
+
# Returns the result of dividing o1 by o2, or NULL on
|
| 40 |
+
# failure. This is the equivalent of the Python expression "o1 /
|
| 41 |
+
# o2".
|
| 42 |
+
|
| 43 |
+
object PyNumber_FloorDivide(object o1, object o2)
|
| 44 |
+
# Return value: New reference.
|
| 45 |
+
# Return the floor of o1 divided by o2, or NULL on failure. This
|
| 46 |
+
# is equivalent to the ``classic'' division of integers.
|
| 47 |
+
|
| 48 |
+
object PyNumber_TrueDivide(object o1, object o2)
|
| 49 |
+
# Return value: New reference.
|
| 50 |
+
# Return a reasonable approximation for the mathematical value of
|
| 51 |
+
# o1 divided by o2, or NULL on failure. The return value is
|
| 52 |
+
# ``approximate'' because binary floating point numbers are
|
| 53 |
+
# approximate; it is not possible to represent all real numbers in
|
| 54 |
+
# base two. This function can return a floating point value when
|
| 55 |
+
# passed two integers.
|
| 56 |
+
|
| 57 |
+
object PyNumber_Remainder(object o1, object o2)
|
| 58 |
+
# Return value: New reference.
|
| 59 |
+
# Returns the remainder of dividing o1 by o2, or NULL on
|
| 60 |
+
# failure. This is the equivalent of the Python expression "o1 %
|
| 61 |
+
# o2".
|
| 62 |
+
|
| 63 |
+
object PyNumber_Divmod(object o1, object o2)
|
| 64 |
+
# Return value: New reference.
|
| 65 |
+
# See the built-in function divmod(). Returns NULL on
|
| 66 |
+
# failure. This is the equivalent of the Python expression
|
| 67 |
+
# "divmod(o1, o2)".
|
| 68 |
+
|
| 69 |
+
object PyNumber_Power(object o1, object o2, object o3)
|
| 70 |
+
# Return value: New reference.
|
| 71 |
+
# See the built-in function pow(). Returns NULL on failure. This
|
| 72 |
+
# is the equivalent of the Python expression "pow(o1, o2, o3)",
|
| 73 |
+
# where o3 is optional. If o3 is to be ignored, pass Py_None in
|
| 74 |
+
# its place (passing NULL for o3 would cause an illegal memory
|
| 75 |
+
# access).
|
| 76 |
+
|
| 77 |
+
object PyNumber_Negative(object o)
|
| 78 |
+
# Return value: New reference.
|
| 79 |
+
# Returns the negation of o on success, or NULL on failure. This
|
| 80 |
+
# is the equivalent of the Python expression "-o".
|
| 81 |
+
|
| 82 |
+
object PyNumber_Positive(object o)
|
| 83 |
+
# Return value: New reference.
|
| 84 |
+
# Returns o on success, or NULL on failure. This is the equivalent
|
| 85 |
+
# of the Python expression "+o".
|
| 86 |
+
|
| 87 |
+
object PyNumber_Absolute(object o)
|
| 88 |
+
# Return value: New reference.
|
| 89 |
+
# Returns the absolute value of o, or NULL on failure. This is the
|
| 90 |
+
# equivalent of the Python expression "abs(o)".
|
| 91 |
+
|
| 92 |
+
object PyNumber_Invert(object o)
|
| 93 |
+
# Return value: New reference.
|
| 94 |
+
# Returns the bitwise negation of o on success, or NULL on
|
| 95 |
+
# failure. This is the equivalent of the Python expression "~o".
|
| 96 |
+
|
| 97 |
+
object PyNumber_Lshift(object o1, object o2)
|
| 98 |
+
# Return value: New reference.
|
| 99 |
+
# Returns the result of left shifting o1 by o2 on success, or NULL
|
| 100 |
+
# on failure. This is the equivalent of the Python expression "o1
|
| 101 |
+
# << o2".
|
| 102 |
+
|
| 103 |
+
object PyNumber_Rshift(object o1, object o2)
|
| 104 |
+
# Return value: New reference.
|
| 105 |
+
# Returns the result of right shifting o1 by o2 on success, or
|
| 106 |
+
# NULL on failure. This is the equivalent of the Python expression
|
| 107 |
+
# "o1 >> o2".
|
| 108 |
+
|
| 109 |
+
object PyNumber_And(object o1, object o2)
|
| 110 |
+
# Return value: New reference.
|
| 111 |
+
# Returns the ``bitwise and'' of o1 and o2 on success and NULL on
|
| 112 |
+
# failure. This is the equivalent of the Python expression "o1 &
|
| 113 |
+
# o2".
|
| 114 |
+
|
| 115 |
+
object PyNumber_Xor(object o1, object o2)
|
| 116 |
+
# Return value: New reference.
|
| 117 |
+
# Returns the ``bitwise exclusive or'' of o1 by o2 on success, or
|
| 118 |
+
# NULL on failure. This is the equivalent of the Python expression
|
| 119 |
+
# "o1 ^ o2".
|
| 120 |
+
|
| 121 |
+
object PyNumber_Or(object o1, object o2)
|
| 122 |
+
# Return value: New reference.
|
| 123 |
+
# Returns the ``bitwise or'' of o1 and o2 on success, or NULL on failure. This is the equivalent of the Python expression "o1 | o2".
|
| 124 |
+
|
| 125 |
+
object PyNumber_InPlaceAdd(object o1, object o2)
|
| 126 |
+
# Return value: New reference.
|
| 127 |
+
# Returns the result of adding o1 and o2, or NULL on failure. The
|
| 128 |
+
# operation is done in-place when o1 supports it. This is the
|
| 129 |
+
# equivalent of the Python statement "o1 += o2".
|
| 130 |
+
|
| 131 |
+
object PyNumber_InPlaceSubtract(object o1, object o2)
|
| 132 |
+
# Return value: New reference.
|
| 133 |
+
# Returns the result of subtracting o2 from o1, or NULL on
|
| 134 |
+
# failure. The operation is done in-place when o1 supports
|
| 135 |
+
# it. This is the equivalent of the Python statement "o1 -= o2".
|
| 136 |
+
|
| 137 |
+
object PyNumber_InPlaceMultiply(object o1, object o2)
|
| 138 |
+
# Return value: New reference.
|
| 139 |
+
# Returns the result of multiplying o1 and o2, or NULL on
|
| 140 |
+
# failure. The operation is done in-place when o1 supports
|
| 141 |
+
# it. This is the equivalent of the Python statement "o1 *= o2".
|
| 142 |
+
|
| 143 |
+
object PyNumber_InPlaceMatrixMultiply(object o1, object o2)
|
| 144 |
+
# Return value: New reference.
|
| 145 |
+
# Returns the result of matrix multiplication on o1 and o2, or
|
| 146 |
+
# NULL on failure. The operation is done in-place when o1 supports
|
| 147 |
+
# it. This is the equivalent of the Python statement "o1 @= o2".
|
| 148 |
+
# New in version 3.5.
|
| 149 |
+
|
| 150 |
+
object PyNumber_InPlaceDivide(object o1, object o2)
|
| 151 |
+
# Return value: New reference.
|
| 152 |
+
# Returns the result of dividing o1 by o2, or NULL on failure. The
|
| 153 |
+
# operation is done in-place when o1 supports it. This is the
|
| 154 |
+
# equivalent of the Python statement "o1 /= o2".
|
| 155 |
+
|
| 156 |
+
object PyNumber_InPlaceFloorDivide(object o1, object o2)
|
| 157 |
+
# Return value: New reference.
|
| 158 |
+
# Returns the mathematical floor of dividing o1 by o2, or NULL on
|
| 159 |
+
# failure. The operation is done in-place when o1 supports
|
| 160 |
+
# it. This is the equivalent of the Python statement "o1 //=
|
| 161 |
+
# o2".
|
| 162 |
+
|
| 163 |
+
object PyNumber_InPlaceTrueDivide(object o1, object o2)
|
| 164 |
+
# Return value: New reference.
|
| 165 |
+
# Return a reasonable approximation for the mathematical value of
|
| 166 |
+
# o1 divided by o2, or NULL on failure. The return value is
|
| 167 |
+
# ``approximate'' because binary floating point numbers are
|
| 168 |
+
# approximate; it is not possible to represent all real numbers in
|
| 169 |
+
# base two. This function can return a floating point value when
|
| 170 |
+
# passed two integers. The operation is done in-place when o1
|
| 171 |
+
# supports it.
|
| 172 |
+
|
| 173 |
+
object PyNumber_InPlaceRemainder(object o1, object o2)
|
| 174 |
+
# Return value: New reference.
|
| 175 |
+
# Returns the remainder of dividing o1 by o2, or NULL on
|
| 176 |
+
# failure. The operation is done in-place when o1 supports
|
| 177 |
+
# it. This is the equivalent of the Python statement "o1 %= o2".
|
| 178 |
+
|
| 179 |
+
object PyNumber_InPlacePower(object o1, object o2, object o3)
|
| 180 |
+
# Return value: New reference.
|
| 181 |
+
# See the built-in function pow(). Returns NULL on failure. The
|
| 182 |
+
# operation is done in-place when o1 supports it. This is the
|
| 183 |
+
# equivalent of the Python statement "o1 **= o2" when o3 is
|
| 184 |
+
# Py_None, or an in-place variant of "pow(o1, o2, o3)"
|
| 185 |
+
# otherwise. If o3 is to be ignored, pass Py_None in its place
|
| 186 |
+
# (passing NULL for o3 would cause an illegal memory access).
|
| 187 |
+
|
| 188 |
+
object PyNumber_InPlaceLshift(object o1, object o2)
|
| 189 |
+
# Return value: New reference.
|
| 190 |
+
# Returns the result of left shifting o1 by o2 on success, or NULL
|
| 191 |
+
# on failure. The operation is done in-place when o1 supports
|
| 192 |
+
# it. This is the equivalent of the Python statement "o1 <<= o2".
|
| 193 |
+
|
| 194 |
+
object PyNumber_InPlaceRshift(object o1, object o2)
|
| 195 |
+
# Return value: New reference.
|
| 196 |
+
# Returns the result of right shifting o1 by o2 on success, or
|
| 197 |
+
# NULL on failure. The operation is done in-place when o1 supports
|
| 198 |
+
# it. This is the equivalent of the Python statement "o1 >>= o2".
|
| 199 |
+
|
| 200 |
+
object PyNumber_InPlaceAnd(object o1, object o2)
|
| 201 |
+
# Return value: New reference.
|
| 202 |
+
# Returns the ``bitwise and'' of o1 and o2 on success and NULL on
|
| 203 |
+
# failure. The operation is done in-place when o1 supports
|
| 204 |
+
# it. This is the equivalent of the Python statement "o1 &= o2".
|
| 205 |
+
|
| 206 |
+
object PyNumber_InPlaceXor(object o1, object o2)
|
| 207 |
+
# Return value: New reference.
|
| 208 |
+
# Returns the ``bitwise exclusive or'' of o1 by o2 on success, or
|
| 209 |
+
# NULL on failure. The operation is done in-place when o1 supports
|
| 210 |
+
# it. This is the equivalent of the Python statement "o1 ^= o2".
|
| 211 |
+
|
| 212 |
+
object PyNumber_InPlaceOr(object o1, object o2)
|
| 213 |
+
# Return value: New reference.
|
| 214 |
+
# Returns the ``bitwise or'' of o1 and o2 on success, or NULL on
|
| 215 |
+
# failure. The operation is done in-place when o1 supports
|
| 216 |
+
# it. This is the equivalent of the Python statement "o1 |= o2".
|
| 217 |
+
|
| 218 |
+
int PyNumber_Coerce(PyObject **p1, PyObject **p2) except -1
|
| 219 |
+
# This function takes the addresses of two variables of type
|
| 220 |
+
# PyObject*. If the objects pointed to by *p1 and *p2 have the
|
| 221 |
+
# same type, increment their reference count and return 0
|
| 222 |
+
# (success). If the objects can be converted to a common numeric
|
| 223 |
+
# type, replace *p1 and *p2 by their converted value (with 'new'
|
| 224 |
+
# reference counts), and return 0. If no conversion is possible,
|
| 225 |
+
# or if some other error occurs, return -1 (failure) and don't
|
| 226 |
+
# increment the reference counts. The call PyNumber_Coerce(&o1,
|
| 227 |
+
# &o2) is equivalent to the Python statement "o1, o2 = coerce(o1,
|
| 228 |
+
# o2)".
|
| 229 |
+
|
| 230 |
+
object PyNumber_Int(object o)
|
| 231 |
+
# Return value: New reference.
|
| 232 |
+
# Returns the o converted to an integer object on success, or NULL
|
| 233 |
+
# on failure. If the argument is outside the integer range a long
|
| 234 |
+
# object will be returned instead. This is the equivalent of the
|
| 235 |
+
# Python expression "int(o)".
|
| 236 |
+
|
| 237 |
+
object PyNumber_Long(object o)
|
| 238 |
+
# Return value: New reference.
|
| 239 |
+
# Returns the o converted to a long integer object on success, or
|
| 240 |
+
# NULL on failure. This is the equivalent of the Python expression
|
| 241 |
+
# "long(o)".
|
| 242 |
+
|
| 243 |
+
object PyNumber_Float(object o)
|
| 244 |
+
# Return value: New reference.
|
| 245 |
+
# Returns the o converted to a float object on success, or NULL on
|
| 246 |
+
# failure. This is the equivalent of the Python expression
|
| 247 |
+
# "float(o)".
|
| 248 |
+
|
| 249 |
+
object PyNumber_Index(object o)
|
| 250 |
+
# Returns the o converted to a Python int or long on success or
|
| 251 |
+
# NULL with a TypeError exception raised on failure.
|
| 252 |
+
|
| 253 |
+
Py_ssize_t PyNumber_AsSsize_t(object o, object exc) except? -1
|
| 254 |
+
# Returns o converted to a Py_ssize_t value if o can be
|
| 255 |
+
# interpreted as an integer. If o can be converted to a Python int
|
| 256 |
+
# or long but the attempt to convert to a Py_ssize_t value would
|
| 257 |
+
# raise an OverflowError, then the exc argument is the type of
|
| 258 |
+
# exception that will be raised (usually IndexError or
|
| 259 |
+
# OverflowError). If exc is NULL, then the exception is cleared
|
| 260 |
+
# and the value is clipped to PY_SSIZE_T_MIN for a negative
|
| 261 |
+
# integer or PY_SSIZE_T_MAX for a positive integer.
|
| 262 |
+
|
| 263 |
+
bint PyIndex_Check(object)
|
| 264 |
+
# Returns True if o is an index integer (has the nb_index slot of
|
| 265 |
+
# the tp_as_number structure filled in).
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/pythread.pxd
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
|
| 3 |
+
cdef extern from "pythread.h":
|
| 4 |
+
|
| 5 |
+
ctypedef void *PyThread_type_lock
|
| 6 |
+
ctypedef void *PyThread_type_sema
|
| 7 |
+
|
| 8 |
+
void PyThread_init_thread()
|
| 9 |
+
long PyThread_start_new_thread(void (*)(void *), void *) # FIXME: legacy
|
| 10 |
+
#unsigned long PyThread_start_new_thread(void (*)(void *), void *) # returned 'long' before Py3.7
|
| 11 |
+
void PyThread_exit_thread()
|
| 12 |
+
long PyThread_get_thread_ident() # FIXME: legacy
|
| 13 |
+
#unsigned long PyThread_get_thread_ident() # returned 'long' before Py3.7
|
| 14 |
+
|
| 15 |
+
PyThread_type_lock PyThread_allocate_lock()
|
| 16 |
+
void PyThread_free_lock(PyThread_type_lock)
|
| 17 |
+
int PyThread_acquire_lock(PyThread_type_lock, int mode) nogil
|
| 18 |
+
void PyThread_release_lock(PyThread_type_lock) nogil
|
| 19 |
+
|
| 20 |
+
enum:
|
| 21 |
+
# 'mode' in PyThread_acquire_lock()
|
| 22 |
+
WAIT_LOCK # 1
|
| 23 |
+
NOWAIT_LOCK # 0
|
| 24 |
+
|
| 25 |
+
ctypedef enum PyLockStatus:
|
| 26 |
+
# return values of PyThread_acquire_lock() in CPython 3.2+
|
| 27 |
+
PY_LOCK_FAILURE = 0
|
| 28 |
+
PY_LOCK_ACQUIRED = 1
|
| 29 |
+
PY_LOCK_INTR
|
| 30 |
+
|
| 31 |
+
size_t PyThread_get_stacksize()
|
| 32 |
+
int PyThread_set_stacksize(size_t)
|
| 33 |
+
|
| 34 |
+
# Thread Local Storage (TLS) API deprecated in CPython 3.7+
|
| 35 |
+
int PyThread_create_key()
|
| 36 |
+
void PyThread_delete_key(int)
|
| 37 |
+
int PyThread_set_key_value(int, void *)
|
| 38 |
+
void * PyThread_get_key_value(int)
|
| 39 |
+
void PyThread_delete_key_value(int key)
|
| 40 |
+
|
| 41 |
+
# Cleanup after a fork
|
| 42 |
+
void PyThread_ReInitTLS()
|
| 43 |
+
|
| 44 |
+
# Thread Specific Storage (TSS) API in CPython 3.7+ (also backported)
|
| 45 |
+
#ctypedef struct Py_tss_t: pass # Cython built-in type
|
| 46 |
+
Py_tss_t Py_tss_NEEDS_INIT # Not normally useful: Cython auto-initialises declared "Py_tss_t" variables.
|
| 47 |
+
Py_tss_t * PyThread_tss_alloc()
|
| 48 |
+
void PyThread_tss_free(Py_tss_t *key)
|
| 49 |
+
int PyThread_tss_is_created(Py_tss_t *key)
|
| 50 |
+
int PyThread_tss_create(Py_tss_t *key)
|
| 51 |
+
void PyThread_tss_delete(Py_tss_t *key)
|
| 52 |
+
int PyThread_tss_set(Py_tss_t *key, void *value)
|
| 53 |
+
void * PyThread_tss_get(Py_tss_t *key)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Includes/cpython/string.pxd
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .object cimport PyObject
|
| 2 |
+
|
| 3 |
+
cdef extern from "Python.h":
|
| 4 |
+
ctypedef struct va_list
|
| 5 |
+
|
| 6 |
+
############################################################################
|
| 7 |
+
# 7.3.1 String Objects
|
| 8 |
+
############################################################################
|
| 9 |
+
|
| 10 |
+
# These functions raise TypeError when expecting a string
|
| 11 |
+
# parameter and are called with a non-string parameter.
|
| 12 |
+
# PyStringObject
|
| 13 |
+
# This subtype of PyObject represents a Python string object.
|
| 14 |
+
# PyTypeObject PyString_Type
|
| 15 |
+
# This instance of PyTypeObject represents the Python string type;
|
| 16 |
+
# it is the same object as str and types.StringType in the Python
|
| 17 |
+
# layer.
|
| 18 |
+
|
| 19 |
+
bint PyString_Check(object o)
|
| 20 |
+
# Return true if the object o is a string object or an instance of
|
| 21 |
+
# a subtype of the string type.
|
| 22 |
+
|
| 23 |
+
bint PyString_CheckExact(object o)
|
| 24 |
+
# Return true if the object o is a string object, but not an instance of a subtype of the string type.
|
| 25 |
+
|
| 26 |
+
object PyString_FromString(char *v)
|
| 27 |
+
# Return value: New reference.
|
| 28 |
+
# Return a new string object with the value v on success, and NULL
|
| 29 |
+
# on failure. The parameter v must not be NULL; it will not be
|
| 30 |
+
# checked.
|
| 31 |
+
|
| 32 |
+
object PyString_FromStringAndSize(char *v, Py_ssize_t len)
|
| 33 |
+
# Return value: New reference.
|
| 34 |
+
# Return a new string object with the value v and length len on
|
| 35 |
+
# success, and NULL on failure. If v is NULL, the contents of the
|
| 36 |
+
# string are uninitialized.
|
| 37 |
+
|
| 38 |
+
object PyString_FromFormat(char *format, ...)
|
| 39 |
+
# Return value: New reference.
|
| 40 |
+
# Take a C printf()-style format string and a variable number of
|
| 41 |
+
# arguments, calculate the size of the resulting Python string and
|
| 42 |
+
# return a string with the values formatted into it. The variable
|
| 43 |
+
# arguments must be C types and must correspond exactly to the
|
| 44 |
+
# format characters in the format string. The following format
|
| 45 |
+
# characters are allowed:
|
| 46 |
+
# Format Characters Type Comment
|
| 47 |
+
# %% n/a The literal % character.
|
| 48 |
+
# %c int A single character, represented as an C int.
|
| 49 |
+
# %d int Exactly equivalent to printf("%d").
|
| 50 |
+
# %u unsigned int Exactly equivalent to printf("%u").
|
| 51 |
+
# %ld long Exactly equivalent to printf("%ld").
|
| 52 |
+
# %lu unsigned long Exactly equivalent to printf("%lu").
|
| 53 |
+
# %zd Py_ssize_t Exactly equivalent to printf("%zd").
|
| 54 |
+
# %zu size_t Exactly equivalent to printf("%zu").
|
| 55 |
+
# %i int Exactly equivalent to printf("%i").
|
| 56 |
+
# %x int Exactly equivalent to printf("%x").
|
| 57 |
+
# %s char* A null-terminated C character array.
|
| 58 |
+
|
| 59 |
+
# %p void* The hex representation of a C pointer.
|
| 60 |
+
# Mostly equivalent to printf("%p") except that it is guaranteed to
|
| 61 |
+
# start with the literal 0x regardless of what the platform's printf
|
| 62 |
+
# yields.
|
| 63 |
+
# An unrecognized format character causes all the rest of the
|
| 64 |
+
# format string to be copied as-is to the result string, and any
|
| 65 |
+
# extra arguments discarded.
|
| 66 |
+
|
| 67 |
+
object PyString_FromFormatV(char *format, va_list vargs)
|
| 68 |
+
# Return value: New reference.
|
| 69 |
+
# Identical to PyString_FromFormat() except that it takes exactly two arguments.
|
| 70 |
+
|
| 71 |
+
Py_ssize_t PyString_Size(object string) except -1
|
| 72 |
+
# Return the length of the string in string object string.
|
| 73 |
+
|
| 74 |
+
Py_ssize_t PyString_GET_SIZE(object string)
|
| 75 |
+
# Macro form of PyString_Size() but without error checking.
|
| 76 |
+
|
| 77 |
+
char* PyString_AsString(object string) except NULL
|
| 78 |
+
# Return a NUL-terminated representation of the contents of
|
| 79 |
+
# string. The pointer refers to the internal buffer of string, not
|
| 80 |
+
# a copy. The data must not be modified in any way, unless the
|
| 81 |
+
# string was just created using PyString_FromStringAndSize(NULL,
|
| 82 |
+
# size). It must not be deallocated. If string is a Unicode
|
| 83 |
+
# object, this function computes the default encoding of string
|
| 84 |
+
# and operates on that. If string is not a string object at all,
|
| 85 |
+
# PyString_AsString() returns NULL and raises TypeError.
|
| 86 |
+
|
| 87 |
+
char* PyString_AS_STRING(object string)
|
| 88 |
+
# Macro form of PyString_AsString() but without error
|
| 89 |
+
# checking. Only string objects are supported; no Unicode objects
|
| 90 |
+
# should be passed.
|
| 91 |
+
|
| 92 |
+
int PyString_AsStringAndSize(object obj, char **buffer, Py_ssize_t *length) except -1
|
| 93 |
+
# Return a NULL-terminated representation of the contents of the
|
| 94 |
+
# object obj through the output variables buffer and length.
|
| 95 |
+
#
|
| 96 |
+
# The function accepts both string and Unicode objects as
|
| 97 |
+
# input. For Unicode objects it returns the default encoded
|
| 98 |
+
# version of the object. If length is NULL, the resulting buffer
|
| 99 |
+
# may not contain NUL characters; if it does, the function returns
|
| 100 |
+
# -1 and a TypeError is raised.
|
| 101 |
+
|
| 102 |
+
# The buffer refers to an internal string buffer of obj, not a
|
| 103 |
+
# copy. The data must not be modified in any way, unless the
|
| 104 |
+
# string was just created using PyString_FromStringAndSize(NULL,
|
| 105 |
+
# size). It must not be deallocated. If string is a Unicode
|
| 106 |
+
# object, this function computes the default encoding of string
|
| 107 |
+
# and operates on that. If string is not a string object at all,
|
| 108 |
+
# PyString_AsStringAndSize() returns -1 and raises TypeError.
|
| 109 |
+
|
| 110 |
+
void PyString_Concat(PyObject **string, object newpart)
|
| 111 |
+
# Create a new string object in *string containing the contents of
|
| 112 |
+
# newpart appended to string; the caller will own the new
|
| 113 |
+
# reference. The reference to the old value of string will be
|
| 114 |
+
# stolen. If the new string cannot be created, the old reference
|
| 115 |
+
# to string will still be discarded and the value of *string will
|
| 116 |
+
# be set to NULL; the appropriate exception will be set.
|
| 117 |
+
|
| 118 |
+
void PyString_ConcatAndDel(PyObject **string, object newpart)
|
| 119 |
+
# Create a new string object in *string containing the contents of
|
| 120 |
+
# newpart appended to string. This version decrements the
|
| 121 |
+
# reference count of newpart.
|
| 122 |
+
|
| 123 |
+
int _PyString_Resize(PyObject **string, Py_ssize_t newsize) except -1
|
| 124 |
+
# A way to resize a string object even though it is
|
| 125 |
+
# ``immutable''. Only use this to build up a brand new string
|
| 126 |
+
# object; don't use this if the string may already be known in
|
| 127 |
+
# other parts of the code. It is an error to call this function if
|
| 128 |
+
# the refcount on the input string object is not one. Pass the
|
| 129 |
+
# address of an existing string object as an lvalue (it may be
|
| 130 |
+
# written into), and the new size desired. On success, *string
|
| 131 |
+
# holds the resized string object and 0 is returned; the address
|
| 132 |
+
# in *string may differ from its input value. If the reallocation
|
| 133 |
+
# fails, the original string object at *string is deallocated,
|
| 134 |
+
# *string is set to NULL, a memory exception is set, and -1 is
|
| 135 |
+
# returned.
|
| 136 |
+
|
| 137 |
+
object PyString_Format(object format, object args)
|
| 138 |
+
# Return value: New reference. Return a new string object from
|
| 139 |
+
# format and args. Analogous to format % args. The args argument
|
| 140 |
+
# must be a tuple.
|
| 141 |
+
|
| 142 |
+
void PyString_InternInPlace(PyObject **string)
|
| 143 |
+
# Intern the argument *string in place. The argument must be the
|
| 144 |
+
# address of a pointer variable pointing to a Python string
|
| 145 |
+
# object. If there is an existing interned string that is the same
|
| 146 |
+
# as *string, it sets *string to it (decrementing the reference
|
| 147 |
+
# count of the old string object and incrementing the reference
|
| 148 |
+
# count of the interned string object), otherwise it leaves
|
| 149 |
+
# *string alone and interns it (incrementing its reference
|
| 150 |
+
# count). (Clarification: even though there is a lot of talk about
|
| 151 |
+
# reference counts, think of this function as
|
| 152 |
+
# reference-count-neutral; you own the object after the call if
|
| 153 |
+
# and only if you owned it before the call.)
|
| 154 |
+
|
| 155 |
+
object PyString_InternFromString(char *v)
|
| 156 |
+
# Return value: New reference.
|
| 157 |
+
# A combination of PyString_FromString() and
|
| 158 |
+
# PyString_InternInPlace(), returning either a new string object
|
| 159 |
+
# that has been interned, or a new (``owned'') reference to an
|
| 160 |
+
# earlier interned string object with the same value.
|
| 161 |
+
|
| 162 |
+
object PyString_Decode(char *s, Py_ssize_t size, char *encoding, char *errors)
|
| 163 |
+
# Return value: New reference.
|
| 164 |
+
# Create an object by decoding size bytes of the encoded buffer s
|
| 165 |
+
# using the codec registered for encoding. encoding and errors
|
| 166 |
+
# have the same meaning as the parameters of the same name in the
|
| 167 |
+
# unicode() built-in function. The codec to be used is looked up
|
| 168 |
+
# using the Python codec registry. Return NULL if an exception was
|
| 169 |
+
# raised by the codec.
|
| 170 |
+
|
| 171 |
+
object PyString_AsDecodedObject(object str, char *encoding, char *errors)
|
| 172 |
+
# Return value: New reference.
|
| 173 |
+
# Decode a string object by passing it to the codec registered for
|
| 174 |
+
# encoding and return the result as Python object. encoding and
|
| 175 |
+
# errors have the same meaning as the parameters of the same name
|
| 176 |
+
# in the string encode() method. The codec to be used is looked up
|
| 177 |
+
# using the Python codec registry. Return NULL if an exception was
|
| 178 |
+
# raised by the codec.
|
| 179 |
+
|
| 180 |
+
object PyString_Encode(char *s, Py_ssize_t size, char *encoding, char *errors)
|
| 181 |
+
# Return value: New reference.
|
| 182 |
+
# Encode the char buffer of the given size by passing it to the
|
| 183 |
+
# codec registered for encoding and return a Python
|
| 184 |
+
# object. encoding and errors have the same meaning as the
|
| 185 |
+
# parameters of the same name in the string encode() method. The
|
| 186 |
+
# codec to be used is looked up using the Python codec
|
| 187 |
+
# registry. Return NULL if an exception was raised by the codec.
|
| 188 |
+
|
| 189 |
+
object PyString_AsEncodedObject(object str, char *encoding, char *errors)
|
| 190 |
+
# Return value: New reference.
|
| 191 |
+
# Encode a string object using the codec registered for encoding
|
| 192 |
+
# and return the result as Python object. encoding and errors have
|
| 193 |
+
# the same meaning as the parameters of the same name in the
|
| 194 |
+
# string encode() method. The codec to be used is looked up using
|
| 195 |
+
# the Python codec registry. Return NULL if an exception was
|
| 196 |
+
# raised by the codec.
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (5.45 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__init__.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .exceptions import *
|
| 2 |
+
from .ext import ExtType, Timestamp
|
| 3 |
+
|
| 4 |
+
import os
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
version = (1, 0, 8)
|
| 8 |
+
__version__ = "1.0.8"
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
if os.environ.get("MSGPACK_PUREPYTHON"):
|
| 12 |
+
from .fallback import Packer, unpackb, Unpacker
|
| 13 |
+
else:
|
| 14 |
+
try:
|
| 15 |
+
from ._cmsgpack import Packer, unpackb, Unpacker
|
| 16 |
+
except ImportError:
|
| 17 |
+
from .fallback import Packer, unpackb, Unpacker
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def pack(o, stream, **kwargs):
|
| 21 |
+
"""
|
| 22 |
+
Pack object `o` and write it to `stream`
|
| 23 |
+
|
| 24 |
+
See :class:`Packer` for options.
|
| 25 |
+
"""
|
| 26 |
+
packer = Packer(**kwargs)
|
| 27 |
+
stream.write(packer.pack(o))
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def packb(o, **kwargs):
|
| 31 |
+
"""
|
| 32 |
+
Pack object `o` and return packed bytes
|
| 33 |
+
|
| 34 |
+
See :class:`Packer` for options.
|
| 35 |
+
"""
|
| 36 |
+
return Packer(**kwargs).pack(o)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def unpack(stream, **kwargs):
|
| 40 |
+
"""
|
| 41 |
+
Unpack an object from `stream`.
|
| 42 |
+
|
| 43 |
+
Raises `ExtraData` when `stream` contains extra bytes.
|
| 44 |
+
See :class:`Unpacker` for options.
|
| 45 |
+
"""
|
| 46 |
+
data = stream.read()
|
| 47 |
+
return unpackb(data, **kwargs)
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# alias for compatibility to simplejson/marshal/pickle.
|
| 51 |
+
load = unpack
|
| 52 |
+
loads = unpackb
|
| 53 |
+
|
| 54 |
+
dump = pack
|
| 55 |
+
dumps = packb
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (2 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-311.pyc
ADDED
|
Binary file (2.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-311.pyc
ADDED
|
Binary file (8.65 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-311.pyc
ADDED
|
Binary file (45.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/exceptions.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class UnpackException(Exception):
|
| 2 |
+
"""Base class for some exceptions raised while unpacking.
|
| 3 |
+
|
| 4 |
+
NOTE: unpack may raise exception other than subclass of
|
| 5 |
+
UnpackException. If you want to catch all error, catch
|
| 6 |
+
Exception instead.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class BufferFull(UnpackException):
|
| 11 |
+
pass
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class OutOfData(UnpackException):
|
| 15 |
+
pass
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class FormatError(ValueError, UnpackException):
|
| 19 |
+
"""Invalid msgpack format"""
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class StackError(ValueError, UnpackException):
|
| 23 |
+
"""Too nested"""
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
# Deprecated. Use ValueError instead
|
| 27 |
+
UnpackValueError = ValueError
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class ExtraData(UnpackValueError):
|
| 31 |
+
"""ExtraData is raised when there is trailing data.
|
| 32 |
+
|
| 33 |
+
This exception is raised while only one-shot (not streaming)
|
| 34 |
+
unpack.
|
| 35 |
+
"""
|
| 36 |
+
|
| 37 |
+
def __init__(self, unpacked, extra):
|
| 38 |
+
self.unpacked = unpacked
|
| 39 |
+
self.extra = extra
|
| 40 |
+
|
| 41 |
+
def __str__(self):
|
| 42 |
+
return "unpack(b) received extra data."
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
# Deprecated. Use Exception instead to catch all exception during packing.
|
| 46 |
+
PackException = Exception
|
| 47 |
+
PackValueError = ValueError
|
| 48 |
+
PackOverflowError = OverflowError
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/ext.py
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections import namedtuple
|
| 2 |
+
import datetime
|
| 3 |
+
import struct
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class ExtType(namedtuple("ExtType", "code data")):
|
| 7 |
+
"""ExtType represents ext type in msgpack."""
|
| 8 |
+
|
| 9 |
+
def __new__(cls, code, data):
|
| 10 |
+
if not isinstance(code, int):
|
| 11 |
+
raise TypeError("code must be int")
|
| 12 |
+
if not isinstance(data, bytes):
|
| 13 |
+
raise TypeError("data must be bytes")
|
| 14 |
+
if not 0 <= code <= 127:
|
| 15 |
+
raise ValueError("code must be 0~127")
|
| 16 |
+
return super().__new__(cls, code, data)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class Timestamp:
|
| 20 |
+
"""Timestamp represents the Timestamp extension type in msgpack.
|
| 21 |
+
|
| 22 |
+
When built with Cython, msgpack uses C methods to pack and unpack `Timestamp`.
|
| 23 |
+
When using pure-Python msgpack, :func:`to_bytes` and :func:`from_bytes` are used to pack and
|
| 24 |
+
unpack `Timestamp`.
|
| 25 |
+
|
| 26 |
+
This class is immutable: Do not override seconds and nanoseconds.
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
__slots__ = ["seconds", "nanoseconds"]
|
| 30 |
+
|
| 31 |
+
def __init__(self, seconds, nanoseconds=0):
|
| 32 |
+
"""Initialize a Timestamp object.
|
| 33 |
+
|
| 34 |
+
:param int seconds:
|
| 35 |
+
Number of seconds since the UNIX epoch (00:00:00 UTC Jan 1 1970, minus leap seconds).
|
| 36 |
+
May be negative.
|
| 37 |
+
|
| 38 |
+
:param int nanoseconds:
|
| 39 |
+
Number of nanoseconds to add to `seconds` to get fractional time.
|
| 40 |
+
Maximum is 999_999_999. Default is 0.
|
| 41 |
+
|
| 42 |
+
Note: Negative times (before the UNIX epoch) are represented as neg. seconds + pos. ns.
|
| 43 |
+
"""
|
| 44 |
+
if not isinstance(seconds, int):
|
| 45 |
+
raise TypeError("seconds must be an integer")
|
| 46 |
+
if not isinstance(nanoseconds, int):
|
| 47 |
+
raise TypeError("nanoseconds must be an integer")
|
| 48 |
+
if not (0 <= nanoseconds < 10**9):
|
| 49 |
+
raise ValueError("nanoseconds must be a non-negative integer less than 999999999.")
|
| 50 |
+
self.seconds = seconds
|
| 51 |
+
self.nanoseconds = nanoseconds
|
| 52 |
+
|
| 53 |
+
def __repr__(self):
|
| 54 |
+
"""String representation of Timestamp."""
|
| 55 |
+
return f"Timestamp(seconds={self.seconds}, nanoseconds={self.nanoseconds})"
|
| 56 |
+
|
| 57 |
+
def __eq__(self, other):
|
| 58 |
+
"""Check for equality with another Timestamp object"""
|
| 59 |
+
if type(other) is self.__class__:
|
| 60 |
+
return self.seconds == other.seconds and self.nanoseconds == other.nanoseconds
|
| 61 |
+
return False
|
| 62 |
+
|
| 63 |
+
def __ne__(self, other):
|
| 64 |
+
"""not-equals method (see :func:`__eq__()`)"""
|
| 65 |
+
return not self.__eq__(other)
|
| 66 |
+
|
| 67 |
+
def __hash__(self):
|
| 68 |
+
return hash((self.seconds, self.nanoseconds))
|
| 69 |
+
|
| 70 |
+
@staticmethod
|
| 71 |
+
def from_bytes(b):
|
| 72 |
+
"""Unpack bytes into a `Timestamp` object.
|
| 73 |
+
|
| 74 |
+
Used for pure-Python msgpack unpacking.
|
| 75 |
+
|
| 76 |
+
:param b: Payload from msgpack ext message with code -1
|
| 77 |
+
:type b: bytes
|
| 78 |
+
|
| 79 |
+
:returns: Timestamp object unpacked from msgpack ext payload
|
| 80 |
+
:rtype: Timestamp
|
| 81 |
+
"""
|
| 82 |
+
if len(b) == 4:
|
| 83 |
+
seconds = struct.unpack("!L", b)[0]
|
| 84 |
+
nanoseconds = 0
|
| 85 |
+
elif len(b) == 8:
|
| 86 |
+
data64 = struct.unpack("!Q", b)[0]
|
| 87 |
+
seconds = data64 & 0x00000003FFFFFFFF
|
| 88 |
+
nanoseconds = data64 >> 34
|
| 89 |
+
elif len(b) == 12:
|
| 90 |
+
nanoseconds, seconds = struct.unpack("!Iq", b)
|
| 91 |
+
else:
|
| 92 |
+
raise ValueError(
|
| 93 |
+
"Timestamp type can only be created from 32, 64, or 96-bit byte objects"
|
| 94 |
+
)
|
| 95 |
+
return Timestamp(seconds, nanoseconds)
|
| 96 |
+
|
| 97 |
+
def to_bytes(self):
|
| 98 |
+
"""Pack this Timestamp object into bytes.
|
| 99 |
+
|
| 100 |
+
Used for pure-Python msgpack packing.
|
| 101 |
+
|
| 102 |
+
:returns data: Payload for EXT message with code -1 (timestamp type)
|
| 103 |
+
:rtype: bytes
|
| 104 |
+
"""
|
| 105 |
+
if (self.seconds >> 34) == 0: # seconds is non-negative and fits in 34 bits
|
| 106 |
+
data64 = self.nanoseconds << 34 | self.seconds
|
| 107 |
+
if data64 & 0xFFFFFFFF00000000 == 0:
|
| 108 |
+
# nanoseconds is zero and seconds < 2**32, so timestamp 32
|
| 109 |
+
data = struct.pack("!L", data64)
|
| 110 |
+
else:
|
| 111 |
+
# timestamp 64
|
| 112 |
+
data = struct.pack("!Q", data64)
|
| 113 |
+
else:
|
| 114 |
+
# timestamp 96
|
| 115 |
+
data = struct.pack("!Iq", self.nanoseconds, self.seconds)
|
| 116 |
+
return data
|
| 117 |
+
|
| 118 |
+
@staticmethod
|
| 119 |
+
def from_unix(unix_sec):
|
| 120 |
+
"""Create a Timestamp from posix timestamp in seconds.
|
| 121 |
+
|
| 122 |
+
:param unix_float: Posix timestamp in seconds.
|
| 123 |
+
:type unix_float: int or float
|
| 124 |
+
"""
|
| 125 |
+
seconds = int(unix_sec // 1)
|
| 126 |
+
nanoseconds = int((unix_sec % 1) * 10**9)
|
| 127 |
+
return Timestamp(seconds, nanoseconds)
|
| 128 |
+
|
| 129 |
+
def to_unix(self):
|
| 130 |
+
"""Get the timestamp as a floating-point value.
|
| 131 |
+
|
| 132 |
+
:returns: posix timestamp
|
| 133 |
+
:rtype: float
|
| 134 |
+
"""
|
| 135 |
+
return self.seconds + self.nanoseconds / 1e9
|
| 136 |
+
|
| 137 |
+
@staticmethod
|
| 138 |
+
def from_unix_nano(unix_ns):
|
| 139 |
+
"""Create a Timestamp from posix timestamp in nanoseconds.
|
| 140 |
+
|
| 141 |
+
:param int unix_ns: Posix timestamp in nanoseconds.
|
| 142 |
+
:rtype: Timestamp
|
| 143 |
+
"""
|
| 144 |
+
return Timestamp(*divmod(unix_ns, 10**9))
|
| 145 |
+
|
| 146 |
+
def to_unix_nano(self):
|
| 147 |
+
"""Get the timestamp as a unixtime in nanoseconds.
|
| 148 |
+
|
| 149 |
+
:returns: posix timestamp in nanoseconds
|
| 150 |
+
:rtype: int
|
| 151 |
+
"""
|
| 152 |
+
return self.seconds * 10**9 + self.nanoseconds
|
| 153 |
+
|
| 154 |
+
def to_datetime(self):
|
| 155 |
+
"""Get the timestamp as a UTC datetime.
|
| 156 |
+
|
| 157 |
+
:rtype: `datetime.datetime`
|
| 158 |
+
"""
|
| 159 |
+
utc = datetime.timezone.utc
|
| 160 |
+
return datetime.datetime.fromtimestamp(0, utc) + datetime.timedelta(seconds=self.to_unix())
|
| 161 |
+
|
| 162 |
+
@staticmethod
|
| 163 |
+
def from_datetime(dt):
|
| 164 |
+
"""Create a Timestamp from datetime with tzinfo.
|
| 165 |
+
|
| 166 |
+
:rtype: Timestamp
|
| 167 |
+
"""
|
| 168 |
+
return Timestamp.from_unix(dt.timestamp())
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/fallback.py
ADDED
|
@@ -0,0 +1,951 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Fallback pure Python implementation of msgpack"""
|
| 2 |
+
from datetime import datetime as _DateTime
|
| 3 |
+
import sys
|
| 4 |
+
import struct
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
if hasattr(sys, "pypy_version_info"):
|
| 8 |
+
# StringIO is slow on PyPy, StringIO is faster. However: PyPy's own
|
| 9 |
+
# StringBuilder is fastest.
|
| 10 |
+
from __pypy__ import newlist_hint
|
| 11 |
+
|
| 12 |
+
try:
|
| 13 |
+
from __pypy__.builders import BytesBuilder as StringBuilder
|
| 14 |
+
except ImportError:
|
| 15 |
+
from __pypy__.builders import StringBuilder
|
| 16 |
+
USING_STRINGBUILDER = True
|
| 17 |
+
|
| 18 |
+
class StringIO:
|
| 19 |
+
def __init__(self, s=b""):
|
| 20 |
+
if s:
|
| 21 |
+
self.builder = StringBuilder(len(s))
|
| 22 |
+
self.builder.append(s)
|
| 23 |
+
else:
|
| 24 |
+
self.builder = StringBuilder()
|
| 25 |
+
|
| 26 |
+
def write(self, s):
|
| 27 |
+
if isinstance(s, memoryview):
|
| 28 |
+
s = s.tobytes()
|
| 29 |
+
elif isinstance(s, bytearray):
|
| 30 |
+
s = bytes(s)
|
| 31 |
+
self.builder.append(s)
|
| 32 |
+
|
| 33 |
+
def getvalue(self):
|
| 34 |
+
return self.builder.build()
|
| 35 |
+
|
| 36 |
+
else:
|
| 37 |
+
USING_STRINGBUILDER = False
|
| 38 |
+
from io import BytesIO as StringIO
|
| 39 |
+
|
| 40 |
+
newlist_hint = lambda size: []
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
from .exceptions import BufferFull, OutOfData, ExtraData, FormatError, StackError
|
| 44 |
+
|
| 45 |
+
from .ext import ExtType, Timestamp
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
EX_SKIP = 0
|
| 49 |
+
EX_CONSTRUCT = 1
|
| 50 |
+
EX_READ_ARRAY_HEADER = 2
|
| 51 |
+
EX_READ_MAP_HEADER = 3
|
| 52 |
+
|
| 53 |
+
TYPE_IMMEDIATE = 0
|
| 54 |
+
TYPE_ARRAY = 1
|
| 55 |
+
TYPE_MAP = 2
|
| 56 |
+
TYPE_RAW = 3
|
| 57 |
+
TYPE_BIN = 4
|
| 58 |
+
TYPE_EXT = 5
|
| 59 |
+
|
| 60 |
+
DEFAULT_RECURSE_LIMIT = 511
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def _check_type_strict(obj, t, type=type, tuple=tuple):
|
| 64 |
+
if type(t) is tuple:
|
| 65 |
+
return type(obj) in t
|
| 66 |
+
else:
|
| 67 |
+
return type(obj) is t
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _get_data_from_buffer(obj):
|
| 71 |
+
view = memoryview(obj)
|
| 72 |
+
if view.itemsize != 1:
|
| 73 |
+
raise ValueError("cannot unpack from multi-byte object")
|
| 74 |
+
return view
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def unpackb(packed, **kwargs):
|
| 78 |
+
"""
|
| 79 |
+
Unpack an object from `packed`.
|
| 80 |
+
|
| 81 |
+
Raises ``ExtraData`` when *packed* contains extra bytes.
|
| 82 |
+
Raises ``ValueError`` when *packed* is incomplete.
|
| 83 |
+
Raises ``FormatError`` when *packed* is not valid msgpack.
|
| 84 |
+
Raises ``StackError`` when *packed* contains too nested.
|
| 85 |
+
Other exceptions can be raised during unpacking.
|
| 86 |
+
|
| 87 |
+
See :class:`Unpacker` for options.
|
| 88 |
+
"""
|
| 89 |
+
unpacker = Unpacker(None, max_buffer_size=len(packed), **kwargs)
|
| 90 |
+
unpacker.feed(packed)
|
| 91 |
+
try:
|
| 92 |
+
ret = unpacker._unpack()
|
| 93 |
+
except OutOfData:
|
| 94 |
+
raise ValueError("Unpack failed: incomplete input")
|
| 95 |
+
except RecursionError:
|
| 96 |
+
raise StackError
|
| 97 |
+
if unpacker._got_extradata():
|
| 98 |
+
raise ExtraData(ret, unpacker._get_extradata())
|
| 99 |
+
return ret
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
_NO_FORMAT_USED = ""
|
| 103 |
+
_MSGPACK_HEADERS = {
|
| 104 |
+
0xC4: (1, _NO_FORMAT_USED, TYPE_BIN),
|
| 105 |
+
0xC5: (2, ">H", TYPE_BIN),
|
| 106 |
+
0xC6: (4, ">I", TYPE_BIN),
|
| 107 |
+
0xC7: (2, "Bb", TYPE_EXT),
|
| 108 |
+
0xC8: (3, ">Hb", TYPE_EXT),
|
| 109 |
+
0xC9: (5, ">Ib", TYPE_EXT),
|
| 110 |
+
0xCA: (4, ">f"),
|
| 111 |
+
0xCB: (8, ">d"),
|
| 112 |
+
0xCC: (1, _NO_FORMAT_USED),
|
| 113 |
+
0xCD: (2, ">H"),
|
| 114 |
+
0xCE: (4, ">I"),
|
| 115 |
+
0xCF: (8, ">Q"),
|
| 116 |
+
0xD0: (1, "b"),
|
| 117 |
+
0xD1: (2, ">h"),
|
| 118 |
+
0xD2: (4, ">i"),
|
| 119 |
+
0xD3: (8, ">q"),
|
| 120 |
+
0xD4: (1, "b1s", TYPE_EXT),
|
| 121 |
+
0xD5: (2, "b2s", TYPE_EXT),
|
| 122 |
+
0xD6: (4, "b4s", TYPE_EXT),
|
| 123 |
+
0xD7: (8, "b8s", TYPE_EXT),
|
| 124 |
+
0xD8: (16, "b16s", TYPE_EXT),
|
| 125 |
+
0xD9: (1, _NO_FORMAT_USED, TYPE_RAW),
|
| 126 |
+
0xDA: (2, ">H", TYPE_RAW),
|
| 127 |
+
0xDB: (4, ">I", TYPE_RAW),
|
| 128 |
+
0xDC: (2, ">H", TYPE_ARRAY),
|
| 129 |
+
0xDD: (4, ">I", TYPE_ARRAY),
|
| 130 |
+
0xDE: (2, ">H", TYPE_MAP),
|
| 131 |
+
0xDF: (4, ">I", TYPE_MAP),
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
class Unpacker:
|
| 136 |
+
"""Streaming unpacker.
|
| 137 |
+
|
| 138 |
+
Arguments:
|
| 139 |
+
|
| 140 |
+
:param file_like:
|
| 141 |
+
File-like object having `.read(n)` method.
|
| 142 |
+
If specified, unpacker reads serialized data from it and `.feed()` is not usable.
|
| 143 |
+
|
| 144 |
+
:param int read_size:
|
| 145 |
+
Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`)
|
| 146 |
+
|
| 147 |
+
:param bool use_list:
|
| 148 |
+
If true, unpack msgpack array to Python list.
|
| 149 |
+
Otherwise, unpack to Python tuple. (default: True)
|
| 150 |
+
|
| 151 |
+
:param bool raw:
|
| 152 |
+
If true, unpack msgpack raw to Python bytes.
|
| 153 |
+
Otherwise, unpack to Python str by decoding with UTF-8 encoding (default).
|
| 154 |
+
|
| 155 |
+
:param int timestamp:
|
| 156 |
+
Control how timestamp type is unpacked:
|
| 157 |
+
|
| 158 |
+
0 - Timestamp
|
| 159 |
+
1 - float (Seconds from the EPOCH)
|
| 160 |
+
2 - int (Nanoseconds from the EPOCH)
|
| 161 |
+
3 - datetime.datetime (UTC).
|
| 162 |
+
|
| 163 |
+
:param bool strict_map_key:
|
| 164 |
+
If true (default), only str or bytes are accepted for map (dict) keys.
|
| 165 |
+
|
| 166 |
+
:param object_hook:
|
| 167 |
+
When specified, it should be callable.
|
| 168 |
+
Unpacker calls it with a dict argument after unpacking msgpack map.
|
| 169 |
+
(See also simplejson)
|
| 170 |
+
|
| 171 |
+
:param object_pairs_hook:
|
| 172 |
+
When specified, it should be callable.
|
| 173 |
+
Unpacker calls it with a list of key-value pairs after unpacking msgpack map.
|
| 174 |
+
(See also simplejson)
|
| 175 |
+
|
| 176 |
+
:param str unicode_errors:
|
| 177 |
+
The error handler for decoding unicode. (default: 'strict')
|
| 178 |
+
This option should be used only when you have msgpack data which
|
| 179 |
+
contains invalid UTF-8 string.
|
| 180 |
+
|
| 181 |
+
:param int max_buffer_size:
|
| 182 |
+
Limits size of data waiting unpacked. 0 means 2**32-1.
|
| 183 |
+
The default value is 100*1024*1024 (100MiB).
|
| 184 |
+
Raises `BufferFull` exception when it is insufficient.
|
| 185 |
+
You should set this parameter when unpacking data from untrusted source.
|
| 186 |
+
|
| 187 |
+
:param int max_str_len:
|
| 188 |
+
Deprecated, use *max_buffer_size* instead.
|
| 189 |
+
Limits max length of str. (default: max_buffer_size)
|
| 190 |
+
|
| 191 |
+
:param int max_bin_len:
|
| 192 |
+
Deprecated, use *max_buffer_size* instead.
|
| 193 |
+
Limits max length of bin. (default: max_buffer_size)
|
| 194 |
+
|
| 195 |
+
:param int max_array_len:
|
| 196 |
+
Limits max length of array.
|
| 197 |
+
(default: max_buffer_size)
|
| 198 |
+
|
| 199 |
+
:param int max_map_len:
|
| 200 |
+
Limits max length of map.
|
| 201 |
+
(default: max_buffer_size//2)
|
| 202 |
+
|
| 203 |
+
:param int max_ext_len:
|
| 204 |
+
Deprecated, use *max_buffer_size* instead.
|
| 205 |
+
Limits max size of ext type. (default: max_buffer_size)
|
| 206 |
+
|
| 207 |
+
Example of streaming deserialize from file-like object::
|
| 208 |
+
|
| 209 |
+
unpacker = Unpacker(file_like)
|
| 210 |
+
for o in unpacker:
|
| 211 |
+
process(o)
|
| 212 |
+
|
| 213 |
+
Example of streaming deserialize from socket::
|
| 214 |
+
|
| 215 |
+
unpacker = Unpacker()
|
| 216 |
+
while True:
|
| 217 |
+
buf = sock.recv(1024**2)
|
| 218 |
+
if not buf:
|
| 219 |
+
break
|
| 220 |
+
unpacker.feed(buf)
|
| 221 |
+
for o in unpacker:
|
| 222 |
+
process(o)
|
| 223 |
+
|
| 224 |
+
Raises ``ExtraData`` when *packed* contains extra bytes.
|
| 225 |
+
Raises ``OutOfData`` when *packed* is incomplete.
|
| 226 |
+
Raises ``FormatError`` when *packed* is not valid msgpack.
|
| 227 |
+
Raises ``StackError`` when *packed* contains too nested.
|
| 228 |
+
Other exceptions can be raised during unpacking.
|
| 229 |
+
"""
|
| 230 |
+
|
| 231 |
+
def __init__(
|
| 232 |
+
self,
|
| 233 |
+
file_like=None,
|
| 234 |
+
read_size=0,
|
| 235 |
+
use_list=True,
|
| 236 |
+
raw=False,
|
| 237 |
+
timestamp=0,
|
| 238 |
+
strict_map_key=True,
|
| 239 |
+
object_hook=None,
|
| 240 |
+
object_pairs_hook=None,
|
| 241 |
+
list_hook=None,
|
| 242 |
+
unicode_errors=None,
|
| 243 |
+
max_buffer_size=100 * 1024 * 1024,
|
| 244 |
+
ext_hook=ExtType,
|
| 245 |
+
max_str_len=-1,
|
| 246 |
+
max_bin_len=-1,
|
| 247 |
+
max_array_len=-1,
|
| 248 |
+
max_map_len=-1,
|
| 249 |
+
max_ext_len=-1,
|
| 250 |
+
):
|
| 251 |
+
if unicode_errors is None:
|
| 252 |
+
unicode_errors = "strict"
|
| 253 |
+
|
| 254 |
+
if file_like is None:
|
| 255 |
+
self._feeding = True
|
| 256 |
+
else:
|
| 257 |
+
if not callable(file_like.read):
|
| 258 |
+
raise TypeError("`file_like.read` must be callable")
|
| 259 |
+
self.file_like = file_like
|
| 260 |
+
self._feeding = False
|
| 261 |
+
|
| 262 |
+
#: array of bytes fed.
|
| 263 |
+
self._buffer = bytearray()
|
| 264 |
+
#: Which position we currently reads
|
| 265 |
+
self._buff_i = 0
|
| 266 |
+
|
| 267 |
+
# When Unpacker is used as an iterable, between the calls to next(),
|
| 268 |
+
# the buffer is not "consumed" completely, for efficiency sake.
|
| 269 |
+
# Instead, it is done sloppily. To make sure we raise BufferFull at
|
| 270 |
+
# the correct moments, we have to keep track of how sloppy we were.
|
| 271 |
+
# Furthermore, when the buffer is incomplete (that is: in the case
|
| 272 |
+
# we raise an OutOfData) we need to rollback the buffer to the correct
|
| 273 |
+
# state, which _buf_checkpoint records.
|
| 274 |
+
self._buf_checkpoint = 0
|
| 275 |
+
|
| 276 |
+
if not max_buffer_size:
|
| 277 |
+
max_buffer_size = 2**31 - 1
|
| 278 |
+
if max_str_len == -1:
|
| 279 |
+
max_str_len = max_buffer_size
|
| 280 |
+
if max_bin_len == -1:
|
| 281 |
+
max_bin_len = max_buffer_size
|
| 282 |
+
if max_array_len == -1:
|
| 283 |
+
max_array_len = max_buffer_size
|
| 284 |
+
if max_map_len == -1:
|
| 285 |
+
max_map_len = max_buffer_size // 2
|
| 286 |
+
if max_ext_len == -1:
|
| 287 |
+
max_ext_len = max_buffer_size
|
| 288 |
+
|
| 289 |
+
self._max_buffer_size = max_buffer_size
|
| 290 |
+
if read_size > self._max_buffer_size:
|
| 291 |
+
raise ValueError("read_size must be smaller than max_buffer_size")
|
| 292 |
+
self._read_size = read_size or min(self._max_buffer_size, 16 * 1024)
|
| 293 |
+
self._raw = bool(raw)
|
| 294 |
+
self._strict_map_key = bool(strict_map_key)
|
| 295 |
+
self._unicode_errors = unicode_errors
|
| 296 |
+
self._use_list = use_list
|
| 297 |
+
if not (0 <= timestamp <= 3):
|
| 298 |
+
raise ValueError("timestamp must be 0..3")
|
| 299 |
+
self._timestamp = timestamp
|
| 300 |
+
self._list_hook = list_hook
|
| 301 |
+
self._object_hook = object_hook
|
| 302 |
+
self._object_pairs_hook = object_pairs_hook
|
| 303 |
+
self._ext_hook = ext_hook
|
| 304 |
+
self._max_str_len = max_str_len
|
| 305 |
+
self._max_bin_len = max_bin_len
|
| 306 |
+
self._max_array_len = max_array_len
|
| 307 |
+
self._max_map_len = max_map_len
|
| 308 |
+
self._max_ext_len = max_ext_len
|
| 309 |
+
self._stream_offset = 0
|
| 310 |
+
|
| 311 |
+
if list_hook is not None and not callable(list_hook):
|
| 312 |
+
raise TypeError("`list_hook` is not callable")
|
| 313 |
+
if object_hook is not None and not callable(object_hook):
|
| 314 |
+
raise TypeError("`object_hook` is not callable")
|
| 315 |
+
if object_pairs_hook is not None and not callable(object_pairs_hook):
|
| 316 |
+
raise TypeError("`object_pairs_hook` is not callable")
|
| 317 |
+
if object_hook is not None and object_pairs_hook is not None:
|
| 318 |
+
raise TypeError("object_pairs_hook and object_hook are mutually exclusive")
|
| 319 |
+
if not callable(ext_hook):
|
| 320 |
+
raise TypeError("`ext_hook` is not callable")
|
| 321 |
+
|
| 322 |
+
def feed(self, next_bytes):
|
| 323 |
+
assert self._feeding
|
| 324 |
+
view = _get_data_from_buffer(next_bytes)
|
| 325 |
+
if len(self._buffer) - self._buff_i + len(view) > self._max_buffer_size:
|
| 326 |
+
raise BufferFull
|
| 327 |
+
|
| 328 |
+
# Strip buffer before checkpoint before reading file.
|
| 329 |
+
if self._buf_checkpoint > 0:
|
| 330 |
+
del self._buffer[: self._buf_checkpoint]
|
| 331 |
+
self._buff_i -= self._buf_checkpoint
|
| 332 |
+
self._buf_checkpoint = 0
|
| 333 |
+
|
| 334 |
+
# Use extend here: INPLACE_ADD += doesn't reliably typecast memoryview in jython
|
| 335 |
+
self._buffer.extend(view)
|
| 336 |
+
|
| 337 |
+
def _consume(self):
|
| 338 |
+
"""Gets rid of the used parts of the buffer."""
|
| 339 |
+
self._stream_offset += self._buff_i - self._buf_checkpoint
|
| 340 |
+
self._buf_checkpoint = self._buff_i
|
| 341 |
+
|
| 342 |
+
def _got_extradata(self):
|
| 343 |
+
return self._buff_i < len(self._buffer)
|
| 344 |
+
|
| 345 |
+
def _get_extradata(self):
|
| 346 |
+
return self._buffer[self._buff_i :]
|
| 347 |
+
|
| 348 |
+
def read_bytes(self, n):
|
| 349 |
+
ret = self._read(n, raise_outofdata=False)
|
| 350 |
+
self._consume()
|
| 351 |
+
return ret
|
| 352 |
+
|
| 353 |
+
def _read(self, n, raise_outofdata=True):
|
| 354 |
+
# (int) -> bytearray
|
| 355 |
+
self._reserve(n, raise_outofdata=raise_outofdata)
|
| 356 |
+
i = self._buff_i
|
| 357 |
+
ret = self._buffer[i : i + n]
|
| 358 |
+
self._buff_i = i + len(ret)
|
| 359 |
+
return ret
|
| 360 |
+
|
| 361 |
+
def _reserve(self, n, raise_outofdata=True):
|
| 362 |
+
remain_bytes = len(self._buffer) - self._buff_i - n
|
| 363 |
+
|
| 364 |
+
# Fast path: buffer has n bytes already
|
| 365 |
+
if remain_bytes >= 0:
|
| 366 |
+
return
|
| 367 |
+
|
| 368 |
+
if self._feeding:
|
| 369 |
+
self._buff_i = self._buf_checkpoint
|
| 370 |
+
raise OutOfData
|
| 371 |
+
|
| 372 |
+
# Strip buffer before checkpoint before reading file.
|
| 373 |
+
if self._buf_checkpoint > 0:
|
| 374 |
+
del self._buffer[: self._buf_checkpoint]
|
| 375 |
+
self._buff_i -= self._buf_checkpoint
|
| 376 |
+
self._buf_checkpoint = 0
|
| 377 |
+
|
| 378 |
+
# Read from file
|
| 379 |
+
remain_bytes = -remain_bytes
|
| 380 |
+
if remain_bytes + len(self._buffer) > self._max_buffer_size:
|
| 381 |
+
raise BufferFull
|
| 382 |
+
while remain_bytes > 0:
|
| 383 |
+
to_read_bytes = max(self._read_size, remain_bytes)
|
| 384 |
+
read_data = self.file_like.read(to_read_bytes)
|
| 385 |
+
if not read_data:
|
| 386 |
+
break
|
| 387 |
+
assert isinstance(read_data, bytes)
|
| 388 |
+
self._buffer += read_data
|
| 389 |
+
remain_bytes -= len(read_data)
|
| 390 |
+
|
| 391 |
+
if len(self._buffer) < n + self._buff_i and raise_outofdata:
|
| 392 |
+
self._buff_i = 0 # rollback
|
| 393 |
+
raise OutOfData
|
| 394 |
+
|
| 395 |
+
def _read_header(self):
|
| 396 |
+
typ = TYPE_IMMEDIATE
|
| 397 |
+
n = 0
|
| 398 |
+
obj = None
|
| 399 |
+
self._reserve(1)
|
| 400 |
+
b = self._buffer[self._buff_i]
|
| 401 |
+
self._buff_i += 1
|
| 402 |
+
if b & 0b10000000 == 0:
|
| 403 |
+
obj = b
|
| 404 |
+
elif b & 0b11100000 == 0b11100000:
|
| 405 |
+
obj = -1 - (b ^ 0xFF)
|
| 406 |
+
elif b & 0b11100000 == 0b10100000:
|
| 407 |
+
n = b & 0b00011111
|
| 408 |
+
typ = TYPE_RAW
|
| 409 |
+
if n > self._max_str_len:
|
| 410 |
+
raise ValueError(f"{n} exceeds max_str_len({self._max_str_len})")
|
| 411 |
+
obj = self._read(n)
|
| 412 |
+
elif b & 0b11110000 == 0b10010000:
|
| 413 |
+
n = b & 0b00001111
|
| 414 |
+
typ = TYPE_ARRAY
|
| 415 |
+
if n > self._max_array_len:
|
| 416 |
+
raise ValueError(f"{n} exceeds max_array_len({self._max_array_len})")
|
| 417 |
+
elif b & 0b11110000 == 0b10000000:
|
| 418 |
+
n = b & 0b00001111
|
| 419 |
+
typ = TYPE_MAP
|
| 420 |
+
if n > self._max_map_len:
|
| 421 |
+
raise ValueError(f"{n} exceeds max_map_len({self._max_map_len})")
|
| 422 |
+
elif b == 0xC0:
|
| 423 |
+
obj = None
|
| 424 |
+
elif b == 0xC2:
|
| 425 |
+
obj = False
|
| 426 |
+
elif b == 0xC3:
|
| 427 |
+
obj = True
|
| 428 |
+
elif 0xC4 <= b <= 0xC6:
|
| 429 |
+
size, fmt, typ = _MSGPACK_HEADERS[b]
|
| 430 |
+
self._reserve(size)
|
| 431 |
+
if len(fmt) > 0:
|
| 432 |
+
n = struct.unpack_from(fmt, self._buffer, self._buff_i)[0]
|
| 433 |
+
else:
|
| 434 |
+
n = self._buffer[self._buff_i]
|
| 435 |
+
self._buff_i += size
|
| 436 |
+
if n > self._max_bin_len:
|
| 437 |
+
raise ValueError(f"{n} exceeds max_bin_len({self._max_bin_len})")
|
| 438 |
+
obj = self._read(n)
|
| 439 |
+
elif 0xC7 <= b <= 0xC9:
|
| 440 |
+
size, fmt, typ = _MSGPACK_HEADERS[b]
|
| 441 |
+
self._reserve(size)
|
| 442 |
+
L, n = struct.unpack_from(fmt, self._buffer, self._buff_i)
|
| 443 |
+
self._buff_i += size
|
| 444 |
+
if L > self._max_ext_len:
|
| 445 |
+
raise ValueError(f"{L} exceeds max_ext_len({self._max_ext_len})")
|
| 446 |
+
obj = self._read(L)
|
| 447 |
+
elif 0xCA <= b <= 0xD3:
|
| 448 |
+
size, fmt = _MSGPACK_HEADERS[b]
|
| 449 |
+
self._reserve(size)
|
| 450 |
+
if len(fmt) > 0:
|
| 451 |
+
obj = struct.unpack_from(fmt, self._buffer, self._buff_i)[0]
|
| 452 |
+
else:
|
| 453 |
+
obj = self._buffer[self._buff_i]
|
| 454 |
+
self._buff_i += size
|
| 455 |
+
elif 0xD4 <= b <= 0xD8:
|
| 456 |
+
size, fmt, typ = _MSGPACK_HEADERS[b]
|
| 457 |
+
if self._max_ext_len < size:
|
| 458 |
+
raise ValueError(f"{size} exceeds max_ext_len({self._max_ext_len})")
|
| 459 |
+
self._reserve(size + 1)
|
| 460 |
+
n, obj = struct.unpack_from(fmt, self._buffer, self._buff_i)
|
| 461 |
+
self._buff_i += size + 1
|
| 462 |
+
elif 0xD9 <= b <= 0xDB:
|
| 463 |
+
size, fmt, typ = _MSGPACK_HEADERS[b]
|
| 464 |
+
self._reserve(size)
|
| 465 |
+
if len(fmt) > 0:
|
| 466 |
+
(n,) = struct.unpack_from(fmt, self._buffer, self._buff_i)
|
| 467 |
+
else:
|
| 468 |
+
n = self._buffer[self._buff_i]
|
| 469 |
+
self._buff_i += size
|
| 470 |
+
if n > self._max_str_len:
|
| 471 |
+
raise ValueError(f"{n} exceeds max_str_len({self._max_str_len})")
|
| 472 |
+
obj = self._read(n)
|
| 473 |
+
elif 0xDC <= b <= 0xDD:
|
| 474 |
+
size, fmt, typ = _MSGPACK_HEADERS[b]
|
| 475 |
+
self._reserve(size)
|
| 476 |
+
(n,) = struct.unpack_from(fmt, self._buffer, self._buff_i)
|
| 477 |
+
self._buff_i += size
|
| 478 |
+
if n > self._max_array_len:
|
| 479 |
+
raise ValueError(f"{n} exceeds max_array_len({self._max_array_len})")
|
| 480 |
+
elif 0xDE <= b <= 0xDF:
|
| 481 |
+
size, fmt, typ = _MSGPACK_HEADERS[b]
|
| 482 |
+
self._reserve(size)
|
| 483 |
+
(n,) = struct.unpack_from(fmt, self._buffer, self._buff_i)
|
| 484 |
+
self._buff_i += size
|
| 485 |
+
if n > self._max_map_len:
|
| 486 |
+
raise ValueError(f"{n} exceeds max_map_len({self._max_map_len})")
|
| 487 |
+
else:
|
| 488 |
+
raise FormatError("Unknown header: 0x%x" % b)
|
| 489 |
+
return typ, n, obj
|
| 490 |
+
|
| 491 |
+
def _unpack(self, execute=EX_CONSTRUCT):
|
| 492 |
+
typ, n, obj = self._read_header()
|
| 493 |
+
|
| 494 |
+
if execute == EX_READ_ARRAY_HEADER:
|
| 495 |
+
if typ != TYPE_ARRAY:
|
| 496 |
+
raise ValueError("Expected array")
|
| 497 |
+
return n
|
| 498 |
+
if execute == EX_READ_MAP_HEADER:
|
| 499 |
+
if typ != TYPE_MAP:
|
| 500 |
+
raise ValueError("Expected map")
|
| 501 |
+
return n
|
| 502 |
+
# TODO should we eliminate the recursion?
|
| 503 |
+
if typ == TYPE_ARRAY:
|
| 504 |
+
if execute == EX_SKIP:
|
| 505 |
+
for i in range(n):
|
| 506 |
+
# TODO check whether we need to call `list_hook`
|
| 507 |
+
self._unpack(EX_SKIP)
|
| 508 |
+
return
|
| 509 |
+
ret = newlist_hint(n)
|
| 510 |
+
for i in range(n):
|
| 511 |
+
ret.append(self._unpack(EX_CONSTRUCT))
|
| 512 |
+
if self._list_hook is not None:
|
| 513 |
+
ret = self._list_hook(ret)
|
| 514 |
+
# TODO is the interaction between `list_hook` and `use_list` ok?
|
| 515 |
+
return ret if self._use_list else tuple(ret)
|
| 516 |
+
if typ == TYPE_MAP:
|
| 517 |
+
if execute == EX_SKIP:
|
| 518 |
+
for i in range(n):
|
| 519 |
+
# TODO check whether we need to call hooks
|
| 520 |
+
self._unpack(EX_SKIP)
|
| 521 |
+
self._unpack(EX_SKIP)
|
| 522 |
+
return
|
| 523 |
+
if self._object_pairs_hook is not None:
|
| 524 |
+
ret = self._object_pairs_hook(
|
| 525 |
+
(self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT)) for _ in range(n)
|
| 526 |
+
)
|
| 527 |
+
else:
|
| 528 |
+
ret = {}
|
| 529 |
+
for _ in range(n):
|
| 530 |
+
key = self._unpack(EX_CONSTRUCT)
|
| 531 |
+
if self._strict_map_key and type(key) not in (str, bytes):
|
| 532 |
+
raise ValueError("%s is not allowed for map key" % str(type(key)))
|
| 533 |
+
if isinstance(key, str):
|
| 534 |
+
key = sys.intern(key)
|
| 535 |
+
ret[key] = self._unpack(EX_CONSTRUCT)
|
| 536 |
+
if self._object_hook is not None:
|
| 537 |
+
ret = self._object_hook(ret)
|
| 538 |
+
return ret
|
| 539 |
+
if execute == EX_SKIP:
|
| 540 |
+
return
|
| 541 |
+
if typ == TYPE_RAW:
|
| 542 |
+
if self._raw:
|
| 543 |
+
obj = bytes(obj)
|
| 544 |
+
else:
|
| 545 |
+
obj = obj.decode("utf_8", self._unicode_errors)
|
| 546 |
+
return obj
|
| 547 |
+
if typ == TYPE_BIN:
|
| 548 |
+
return bytes(obj)
|
| 549 |
+
if typ == TYPE_EXT:
|
| 550 |
+
if n == -1: # timestamp
|
| 551 |
+
ts = Timestamp.from_bytes(bytes(obj))
|
| 552 |
+
if self._timestamp == 1:
|
| 553 |
+
return ts.to_unix()
|
| 554 |
+
elif self._timestamp == 2:
|
| 555 |
+
return ts.to_unix_nano()
|
| 556 |
+
elif self._timestamp == 3:
|
| 557 |
+
return ts.to_datetime()
|
| 558 |
+
else:
|
| 559 |
+
return ts
|
| 560 |
+
else:
|
| 561 |
+
return self._ext_hook(n, bytes(obj))
|
| 562 |
+
assert typ == TYPE_IMMEDIATE
|
| 563 |
+
return obj
|
| 564 |
+
|
| 565 |
+
def __iter__(self):
|
| 566 |
+
return self
|
| 567 |
+
|
| 568 |
+
def __next__(self):
|
| 569 |
+
try:
|
| 570 |
+
ret = self._unpack(EX_CONSTRUCT)
|
| 571 |
+
self._consume()
|
| 572 |
+
return ret
|
| 573 |
+
except OutOfData:
|
| 574 |
+
self._consume()
|
| 575 |
+
raise StopIteration
|
| 576 |
+
except RecursionError:
|
| 577 |
+
raise StackError
|
| 578 |
+
|
| 579 |
+
next = __next__
|
| 580 |
+
|
| 581 |
+
def skip(self):
|
| 582 |
+
self._unpack(EX_SKIP)
|
| 583 |
+
self._consume()
|
| 584 |
+
|
| 585 |
+
def unpack(self):
|
| 586 |
+
try:
|
| 587 |
+
ret = self._unpack(EX_CONSTRUCT)
|
| 588 |
+
except RecursionError:
|
| 589 |
+
raise StackError
|
| 590 |
+
self._consume()
|
| 591 |
+
return ret
|
| 592 |
+
|
| 593 |
+
def read_array_header(self):
|
| 594 |
+
ret = self._unpack(EX_READ_ARRAY_HEADER)
|
| 595 |
+
self._consume()
|
| 596 |
+
return ret
|
| 597 |
+
|
| 598 |
+
def read_map_header(self):
|
| 599 |
+
ret = self._unpack(EX_READ_MAP_HEADER)
|
| 600 |
+
self._consume()
|
| 601 |
+
return ret
|
| 602 |
+
|
| 603 |
+
def tell(self):
|
| 604 |
+
return self._stream_offset
|
| 605 |
+
|
| 606 |
+
|
| 607 |
+
class Packer:
|
| 608 |
+
"""
|
| 609 |
+
MessagePack Packer
|
| 610 |
+
|
| 611 |
+
Usage::
|
| 612 |
+
|
| 613 |
+
packer = Packer()
|
| 614 |
+
astream.write(packer.pack(a))
|
| 615 |
+
astream.write(packer.pack(b))
|
| 616 |
+
|
| 617 |
+
Packer's constructor has some keyword arguments:
|
| 618 |
+
|
| 619 |
+
:param default:
|
| 620 |
+
When specified, it should be callable.
|
| 621 |
+
Convert user type to builtin type that Packer supports.
|
| 622 |
+
See also simplejson's document.
|
| 623 |
+
|
| 624 |
+
:param bool use_single_float:
|
| 625 |
+
Use single precision float type for float. (default: False)
|
| 626 |
+
|
| 627 |
+
:param bool autoreset:
|
| 628 |
+
Reset buffer after each pack and return its content as `bytes`. (default: True).
|
| 629 |
+
If set this to false, use `bytes()` to get content and `.reset()` to clear buffer.
|
| 630 |
+
|
| 631 |
+
:param bool use_bin_type:
|
| 632 |
+
Use bin type introduced in msgpack spec 2.0 for bytes.
|
| 633 |
+
It also enables str8 type for unicode. (default: True)
|
| 634 |
+
|
| 635 |
+
:param bool strict_types:
|
| 636 |
+
If set to true, types will be checked to be exact. Derived classes
|
| 637 |
+
from serializable types will not be serialized and will be
|
| 638 |
+
treated as unsupported type and forwarded to default.
|
| 639 |
+
Additionally tuples will not be serialized as lists.
|
| 640 |
+
This is useful when trying to implement accurate serialization
|
| 641 |
+
for python types.
|
| 642 |
+
|
| 643 |
+
:param bool datetime:
|
| 644 |
+
If set to true, datetime with tzinfo is packed into Timestamp type.
|
| 645 |
+
Note that the tzinfo is stripped in the timestamp.
|
| 646 |
+
You can get UTC datetime with `timestamp=3` option of the Unpacker.
|
| 647 |
+
|
| 648 |
+
:param str unicode_errors:
|
| 649 |
+
The error handler for encoding unicode. (default: 'strict')
|
| 650 |
+
DO NOT USE THIS!! This option is kept for very specific usage.
|
| 651 |
+
|
| 652 |
+
Example of streaming deserialize from file-like object::
|
| 653 |
+
|
| 654 |
+
unpacker = Unpacker(file_like)
|
| 655 |
+
for o in unpacker:
|
| 656 |
+
process(o)
|
| 657 |
+
|
| 658 |
+
Example of streaming deserialize from socket::
|
| 659 |
+
|
| 660 |
+
unpacker = Unpacker()
|
| 661 |
+
while True:
|
| 662 |
+
buf = sock.recv(1024**2)
|
| 663 |
+
if not buf:
|
| 664 |
+
break
|
| 665 |
+
unpacker.feed(buf)
|
| 666 |
+
for o in unpacker:
|
| 667 |
+
process(o)
|
| 668 |
+
|
| 669 |
+
Raises ``ExtraData`` when *packed* contains extra bytes.
|
| 670 |
+
Raises ``OutOfData`` when *packed* is incomplete.
|
| 671 |
+
Raises ``FormatError`` when *packed* is not valid msgpack.
|
| 672 |
+
Raises ``StackError`` when *packed* contains too nested.
|
| 673 |
+
Other exceptions can be raised during unpacking.
|
| 674 |
+
"""
|
| 675 |
+
|
| 676 |
+
def __init__(
|
| 677 |
+
self,
|
| 678 |
+
default=None,
|
| 679 |
+
use_single_float=False,
|
| 680 |
+
autoreset=True,
|
| 681 |
+
use_bin_type=True,
|
| 682 |
+
strict_types=False,
|
| 683 |
+
datetime=False,
|
| 684 |
+
unicode_errors=None,
|
| 685 |
+
):
|
| 686 |
+
self._strict_types = strict_types
|
| 687 |
+
self._use_float = use_single_float
|
| 688 |
+
self._autoreset = autoreset
|
| 689 |
+
self._use_bin_type = use_bin_type
|
| 690 |
+
self._buffer = StringIO()
|
| 691 |
+
self._datetime = bool(datetime)
|
| 692 |
+
self._unicode_errors = unicode_errors or "strict"
|
| 693 |
+
if default is not None:
|
| 694 |
+
if not callable(default):
|
| 695 |
+
raise TypeError("default must be callable")
|
| 696 |
+
self._default = default
|
| 697 |
+
|
| 698 |
+
def _pack(
|
| 699 |
+
self,
|
| 700 |
+
obj,
|
| 701 |
+
nest_limit=DEFAULT_RECURSE_LIMIT,
|
| 702 |
+
check=isinstance,
|
| 703 |
+
check_type_strict=_check_type_strict,
|
| 704 |
+
):
|
| 705 |
+
default_used = False
|
| 706 |
+
if self._strict_types:
|
| 707 |
+
check = check_type_strict
|
| 708 |
+
list_types = list
|
| 709 |
+
else:
|
| 710 |
+
list_types = (list, tuple)
|
| 711 |
+
while True:
|
| 712 |
+
if nest_limit < 0:
|
| 713 |
+
raise ValueError("recursion limit exceeded")
|
| 714 |
+
if obj is None:
|
| 715 |
+
return self._buffer.write(b"\xc0")
|
| 716 |
+
if check(obj, bool):
|
| 717 |
+
if obj:
|
| 718 |
+
return self._buffer.write(b"\xc3")
|
| 719 |
+
return self._buffer.write(b"\xc2")
|
| 720 |
+
if check(obj, int):
|
| 721 |
+
if 0 <= obj < 0x80:
|
| 722 |
+
return self._buffer.write(struct.pack("B", obj))
|
| 723 |
+
if -0x20 <= obj < 0:
|
| 724 |
+
return self._buffer.write(struct.pack("b", obj))
|
| 725 |
+
if 0x80 <= obj <= 0xFF:
|
| 726 |
+
return self._buffer.write(struct.pack("BB", 0xCC, obj))
|
| 727 |
+
if -0x80 <= obj < 0:
|
| 728 |
+
return self._buffer.write(struct.pack(">Bb", 0xD0, obj))
|
| 729 |
+
if 0xFF < obj <= 0xFFFF:
|
| 730 |
+
return self._buffer.write(struct.pack(">BH", 0xCD, obj))
|
| 731 |
+
if -0x8000 <= obj < -0x80:
|
| 732 |
+
return self._buffer.write(struct.pack(">Bh", 0xD1, obj))
|
| 733 |
+
if 0xFFFF < obj <= 0xFFFFFFFF:
|
| 734 |
+
return self._buffer.write(struct.pack(">BI", 0xCE, obj))
|
| 735 |
+
if -0x80000000 <= obj < -0x8000:
|
| 736 |
+
return self._buffer.write(struct.pack(">Bi", 0xD2, obj))
|
| 737 |
+
if 0xFFFFFFFF < obj <= 0xFFFFFFFFFFFFFFFF:
|
| 738 |
+
return self._buffer.write(struct.pack(">BQ", 0xCF, obj))
|
| 739 |
+
if -0x8000000000000000 <= obj < -0x80000000:
|
| 740 |
+
return self._buffer.write(struct.pack(">Bq", 0xD3, obj))
|
| 741 |
+
if not default_used and self._default is not None:
|
| 742 |
+
obj = self._default(obj)
|
| 743 |
+
default_used = True
|
| 744 |
+
continue
|
| 745 |
+
raise OverflowError("Integer value out of range")
|
| 746 |
+
if check(obj, (bytes, bytearray)):
|
| 747 |
+
n = len(obj)
|
| 748 |
+
if n >= 2**32:
|
| 749 |
+
raise ValueError("%s is too large" % type(obj).__name__)
|
| 750 |
+
self._pack_bin_header(n)
|
| 751 |
+
return self._buffer.write(obj)
|
| 752 |
+
if check(obj, str):
|
| 753 |
+
obj = obj.encode("utf-8", self._unicode_errors)
|
| 754 |
+
n = len(obj)
|
| 755 |
+
if n >= 2**32:
|
| 756 |
+
raise ValueError("String is too large")
|
| 757 |
+
self._pack_raw_header(n)
|
| 758 |
+
return self._buffer.write(obj)
|
| 759 |
+
if check(obj, memoryview):
|
| 760 |
+
n = obj.nbytes
|
| 761 |
+
if n >= 2**32:
|
| 762 |
+
raise ValueError("Memoryview is too large")
|
| 763 |
+
self._pack_bin_header(n)
|
| 764 |
+
return self._buffer.write(obj)
|
| 765 |
+
if check(obj, float):
|
| 766 |
+
if self._use_float:
|
| 767 |
+
return self._buffer.write(struct.pack(">Bf", 0xCA, obj))
|
| 768 |
+
return self._buffer.write(struct.pack(">Bd", 0xCB, obj))
|
| 769 |
+
if check(obj, (ExtType, Timestamp)):
|
| 770 |
+
if check(obj, Timestamp):
|
| 771 |
+
code = -1
|
| 772 |
+
data = obj.to_bytes()
|
| 773 |
+
else:
|
| 774 |
+
code = obj.code
|
| 775 |
+
data = obj.data
|
| 776 |
+
assert isinstance(code, int)
|
| 777 |
+
assert isinstance(data, bytes)
|
| 778 |
+
L = len(data)
|
| 779 |
+
if L == 1:
|
| 780 |
+
self._buffer.write(b"\xd4")
|
| 781 |
+
elif L == 2:
|
| 782 |
+
self._buffer.write(b"\xd5")
|
| 783 |
+
elif L == 4:
|
| 784 |
+
self._buffer.write(b"\xd6")
|
| 785 |
+
elif L == 8:
|
| 786 |
+
self._buffer.write(b"\xd7")
|
| 787 |
+
elif L == 16:
|
| 788 |
+
self._buffer.write(b"\xd8")
|
| 789 |
+
elif L <= 0xFF:
|
| 790 |
+
self._buffer.write(struct.pack(">BB", 0xC7, L))
|
| 791 |
+
elif L <= 0xFFFF:
|
| 792 |
+
self._buffer.write(struct.pack(">BH", 0xC8, L))
|
| 793 |
+
else:
|
| 794 |
+
self._buffer.write(struct.pack(">BI", 0xC9, L))
|
| 795 |
+
self._buffer.write(struct.pack("b", code))
|
| 796 |
+
self._buffer.write(data)
|
| 797 |
+
return
|
| 798 |
+
if check(obj, list_types):
|
| 799 |
+
n = len(obj)
|
| 800 |
+
self._pack_array_header(n)
|
| 801 |
+
for i in range(n):
|
| 802 |
+
self._pack(obj[i], nest_limit - 1)
|
| 803 |
+
return
|
| 804 |
+
if check(obj, dict):
|
| 805 |
+
return self._pack_map_pairs(len(obj), obj.items(), nest_limit - 1)
|
| 806 |
+
|
| 807 |
+
if self._datetime and check(obj, _DateTime) and obj.tzinfo is not None:
|
| 808 |
+
obj = Timestamp.from_datetime(obj)
|
| 809 |
+
default_used = 1
|
| 810 |
+
continue
|
| 811 |
+
|
| 812 |
+
if not default_used and self._default is not None:
|
| 813 |
+
obj = self._default(obj)
|
| 814 |
+
default_used = 1
|
| 815 |
+
continue
|
| 816 |
+
|
| 817 |
+
if self._datetime and check(obj, _DateTime):
|
| 818 |
+
raise ValueError(f"Cannot serialize {obj!r} where tzinfo=None")
|
| 819 |
+
|
| 820 |
+
raise TypeError(f"Cannot serialize {obj!r}")
|
| 821 |
+
|
| 822 |
+
def pack(self, obj):
|
| 823 |
+
try:
|
| 824 |
+
self._pack(obj)
|
| 825 |
+
except:
|
| 826 |
+
self._buffer = StringIO() # force reset
|
| 827 |
+
raise
|
| 828 |
+
if self._autoreset:
|
| 829 |
+
ret = self._buffer.getvalue()
|
| 830 |
+
self._buffer = StringIO()
|
| 831 |
+
return ret
|
| 832 |
+
|
| 833 |
+
def pack_map_pairs(self, pairs):
|
| 834 |
+
self._pack_map_pairs(len(pairs), pairs)
|
| 835 |
+
if self._autoreset:
|
| 836 |
+
ret = self._buffer.getvalue()
|
| 837 |
+
self._buffer = StringIO()
|
| 838 |
+
return ret
|
| 839 |
+
|
| 840 |
+
def pack_array_header(self, n):
|
| 841 |
+
if n >= 2**32:
|
| 842 |
+
raise ValueError
|
| 843 |
+
self._pack_array_header(n)
|
| 844 |
+
if self._autoreset:
|
| 845 |
+
ret = self._buffer.getvalue()
|
| 846 |
+
self._buffer = StringIO()
|
| 847 |
+
return ret
|
| 848 |
+
|
| 849 |
+
def pack_map_header(self, n):
|
| 850 |
+
if n >= 2**32:
|
| 851 |
+
raise ValueError
|
| 852 |
+
self._pack_map_header(n)
|
| 853 |
+
if self._autoreset:
|
| 854 |
+
ret = self._buffer.getvalue()
|
| 855 |
+
self._buffer = StringIO()
|
| 856 |
+
return ret
|
| 857 |
+
|
| 858 |
+
def pack_ext_type(self, typecode, data):
|
| 859 |
+
if not isinstance(typecode, int):
|
| 860 |
+
raise TypeError("typecode must have int type.")
|
| 861 |
+
if not 0 <= typecode <= 127:
|
| 862 |
+
raise ValueError("typecode should be 0-127")
|
| 863 |
+
if not isinstance(data, bytes):
|
| 864 |
+
raise TypeError("data must have bytes type")
|
| 865 |
+
L = len(data)
|
| 866 |
+
if L > 0xFFFFFFFF:
|
| 867 |
+
raise ValueError("Too large data")
|
| 868 |
+
if L == 1:
|
| 869 |
+
self._buffer.write(b"\xd4")
|
| 870 |
+
elif L == 2:
|
| 871 |
+
self._buffer.write(b"\xd5")
|
| 872 |
+
elif L == 4:
|
| 873 |
+
self._buffer.write(b"\xd6")
|
| 874 |
+
elif L == 8:
|
| 875 |
+
self._buffer.write(b"\xd7")
|
| 876 |
+
elif L == 16:
|
| 877 |
+
self._buffer.write(b"\xd8")
|
| 878 |
+
elif L <= 0xFF:
|
| 879 |
+
self._buffer.write(b"\xc7" + struct.pack("B", L))
|
| 880 |
+
elif L <= 0xFFFF:
|
| 881 |
+
self._buffer.write(b"\xc8" + struct.pack(">H", L))
|
| 882 |
+
else:
|
| 883 |
+
self._buffer.write(b"\xc9" + struct.pack(">I", L))
|
| 884 |
+
self._buffer.write(struct.pack("B", typecode))
|
| 885 |
+
self._buffer.write(data)
|
| 886 |
+
|
| 887 |
+
def _pack_array_header(self, n):
|
| 888 |
+
if n <= 0x0F:
|
| 889 |
+
return self._buffer.write(struct.pack("B", 0x90 + n))
|
| 890 |
+
if n <= 0xFFFF:
|
| 891 |
+
return self._buffer.write(struct.pack(">BH", 0xDC, n))
|
| 892 |
+
if n <= 0xFFFFFFFF:
|
| 893 |
+
return self._buffer.write(struct.pack(">BI", 0xDD, n))
|
| 894 |
+
raise ValueError("Array is too large")
|
| 895 |
+
|
| 896 |
+
def _pack_map_header(self, n):
|
| 897 |
+
if n <= 0x0F:
|
| 898 |
+
return self._buffer.write(struct.pack("B", 0x80 + n))
|
| 899 |
+
if n <= 0xFFFF:
|
| 900 |
+
return self._buffer.write(struct.pack(">BH", 0xDE, n))
|
| 901 |
+
if n <= 0xFFFFFFFF:
|
| 902 |
+
return self._buffer.write(struct.pack(">BI", 0xDF, n))
|
| 903 |
+
raise ValueError("Dict is too large")
|
| 904 |
+
|
| 905 |
+
def _pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT):
|
| 906 |
+
self._pack_map_header(n)
|
| 907 |
+
for k, v in pairs:
|
| 908 |
+
self._pack(k, nest_limit - 1)
|
| 909 |
+
self._pack(v, nest_limit - 1)
|
| 910 |
+
|
| 911 |
+
def _pack_raw_header(self, n):
|
| 912 |
+
if n <= 0x1F:
|
| 913 |
+
self._buffer.write(struct.pack("B", 0xA0 + n))
|
| 914 |
+
elif self._use_bin_type and n <= 0xFF:
|
| 915 |
+
self._buffer.write(struct.pack(">BB", 0xD9, n))
|
| 916 |
+
elif n <= 0xFFFF:
|
| 917 |
+
self._buffer.write(struct.pack(">BH", 0xDA, n))
|
| 918 |
+
elif n <= 0xFFFFFFFF:
|
| 919 |
+
self._buffer.write(struct.pack(">BI", 0xDB, n))
|
| 920 |
+
else:
|
| 921 |
+
raise ValueError("Raw is too large")
|
| 922 |
+
|
| 923 |
+
def _pack_bin_header(self, n):
|
| 924 |
+
if not self._use_bin_type:
|
| 925 |
+
return self._pack_raw_header(n)
|
| 926 |
+
elif n <= 0xFF:
|
| 927 |
+
return self._buffer.write(struct.pack(">BB", 0xC4, n))
|
| 928 |
+
elif n <= 0xFFFF:
|
| 929 |
+
return self._buffer.write(struct.pack(">BH", 0xC5, n))
|
| 930 |
+
elif n <= 0xFFFFFFFF:
|
| 931 |
+
return self._buffer.write(struct.pack(">BI", 0xC6, n))
|
| 932 |
+
else:
|
| 933 |
+
raise ValueError("Bin is too large")
|
| 934 |
+
|
| 935 |
+
def bytes(self):
|
| 936 |
+
"""Return internal buffer contents as bytes object"""
|
| 937 |
+
return self._buffer.getvalue()
|
| 938 |
+
|
| 939 |
+
def reset(self):
|
| 940 |
+
"""Reset internal buffer.
|
| 941 |
+
|
| 942 |
+
This method is useful only when autoreset=False.
|
| 943 |
+
"""
|
| 944 |
+
self._buffer = StringIO()
|
| 945 |
+
|
| 946 |
+
def getbuffer(self):
|
| 947 |
+
"""Return view of internal buffer."""
|
| 948 |
+
if USING_STRINGBUILDER:
|
| 949 |
+
return memoryview(self.bytes())
|
| 950 |
+
else:
|
| 951 |
+
return self._buffer.getbuffer()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__init__.py
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Rich text and beautiful formatting in the terminal."""
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
from typing import IO, TYPE_CHECKING, Any, Callable, Optional, Union
|
| 5 |
+
|
| 6 |
+
from ._extension import load_ipython_extension # noqa: F401
|
| 7 |
+
|
| 8 |
+
__all__ = ["get_console", "reconfigure", "print", "inspect", "print_json"]
|
| 9 |
+
|
| 10 |
+
if TYPE_CHECKING:
|
| 11 |
+
from .console import Console
|
| 12 |
+
|
| 13 |
+
# Global console used by alternative print
|
| 14 |
+
_console: Optional["Console"] = None
|
| 15 |
+
|
| 16 |
+
try:
|
| 17 |
+
_IMPORT_CWD = os.path.abspath(os.getcwd())
|
| 18 |
+
except FileNotFoundError:
|
| 19 |
+
# Can happen if the cwd has been deleted
|
| 20 |
+
_IMPORT_CWD = ""
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def get_console() -> "Console":
|
| 24 |
+
"""Get a global :class:`~rich.console.Console` instance. This function is used when Rich requires a Console,
|
| 25 |
+
and hasn't been explicitly given one.
|
| 26 |
+
|
| 27 |
+
Returns:
|
| 28 |
+
Console: A console instance.
|
| 29 |
+
"""
|
| 30 |
+
global _console
|
| 31 |
+
if _console is None:
|
| 32 |
+
from .console import Console
|
| 33 |
+
|
| 34 |
+
_console = Console()
|
| 35 |
+
|
| 36 |
+
return _console
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def reconfigure(*args: Any, **kwargs: Any) -> None:
|
| 40 |
+
"""Reconfigures the global console by replacing it with another.
|
| 41 |
+
|
| 42 |
+
Args:
|
| 43 |
+
*args (Any): Positional arguments for the replacement :class:`~rich.console.Console`.
|
| 44 |
+
**kwargs (Any): Keyword arguments for the replacement :class:`~rich.console.Console`.
|
| 45 |
+
"""
|
| 46 |
+
from pip._vendor.rich.console import Console
|
| 47 |
+
|
| 48 |
+
new_console = Console(*args, **kwargs)
|
| 49 |
+
_console = get_console()
|
| 50 |
+
_console.__dict__ = new_console.__dict__
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def print(
|
| 54 |
+
*objects: Any,
|
| 55 |
+
sep: str = " ",
|
| 56 |
+
end: str = "\n",
|
| 57 |
+
file: Optional[IO[str]] = None,
|
| 58 |
+
flush: bool = False,
|
| 59 |
+
) -> None:
|
| 60 |
+
r"""Print object(s) supplied via positional arguments.
|
| 61 |
+
This function has an identical signature to the built-in print.
|
| 62 |
+
For more advanced features, see the :class:`~rich.console.Console` class.
|
| 63 |
+
|
| 64 |
+
Args:
|
| 65 |
+
sep (str, optional): Separator between printed objects. Defaults to " ".
|
| 66 |
+
end (str, optional): Character to write at end of output. Defaults to "\\n".
|
| 67 |
+
file (IO[str], optional): File to write to, or None for stdout. Defaults to None.
|
| 68 |
+
flush (bool, optional): Has no effect as Rich always flushes output. Defaults to False.
|
| 69 |
+
|
| 70 |
+
"""
|
| 71 |
+
from .console import Console
|
| 72 |
+
|
| 73 |
+
write_console = get_console() if file is None else Console(file=file)
|
| 74 |
+
return write_console.print(*objects, sep=sep, end=end)
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def print_json(
|
| 78 |
+
json: Optional[str] = None,
|
| 79 |
+
*,
|
| 80 |
+
data: Any = None,
|
| 81 |
+
indent: Union[None, int, str] = 2,
|
| 82 |
+
highlight: bool = True,
|
| 83 |
+
skip_keys: bool = False,
|
| 84 |
+
ensure_ascii: bool = False,
|
| 85 |
+
check_circular: bool = True,
|
| 86 |
+
allow_nan: bool = True,
|
| 87 |
+
default: Optional[Callable[[Any], Any]] = None,
|
| 88 |
+
sort_keys: bool = False,
|
| 89 |
+
) -> None:
|
| 90 |
+
"""Pretty prints JSON. Output will be valid JSON.
|
| 91 |
+
|
| 92 |
+
Args:
|
| 93 |
+
json (str): A string containing JSON.
|
| 94 |
+
data (Any): If json is not supplied, then encode this data.
|
| 95 |
+
indent (int, optional): Number of spaces to indent. Defaults to 2.
|
| 96 |
+
highlight (bool, optional): Enable highlighting of output: Defaults to True.
|
| 97 |
+
skip_keys (bool, optional): Skip keys not of a basic type. Defaults to False.
|
| 98 |
+
ensure_ascii (bool, optional): Escape all non-ascii characters. Defaults to False.
|
| 99 |
+
check_circular (bool, optional): Check for circular references. Defaults to True.
|
| 100 |
+
allow_nan (bool, optional): Allow NaN and Infinity values. Defaults to True.
|
| 101 |
+
default (Callable, optional): A callable that converts values that can not be encoded
|
| 102 |
+
in to something that can be JSON encoded. Defaults to None.
|
| 103 |
+
sort_keys (bool, optional): Sort dictionary keys. Defaults to False.
|
| 104 |
+
"""
|
| 105 |
+
|
| 106 |
+
get_console().print_json(
|
| 107 |
+
json,
|
| 108 |
+
data=data,
|
| 109 |
+
indent=indent,
|
| 110 |
+
highlight=highlight,
|
| 111 |
+
skip_keys=skip_keys,
|
| 112 |
+
ensure_ascii=ensure_ascii,
|
| 113 |
+
check_circular=check_circular,
|
| 114 |
+
allow_nan=allow_nan,
|
| 115 |
+
default=default,
|
| 116 |
+
sort_keys=sort_keys,
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
def inspect(
|
| 121 |
+
obj: Any,
|
| 122 |
+
*,
|
| 123 |
+
console: Optional["Console"] = None,
|
| 124 |
+
title: Optional[str] = None,
|
| 125 |
+
help: bool = False,
|
| 126 |
+
methods: bool = False,
|
| 127 |
+
docs: bool = True,
|
| 128 |
+
private: bool = False,
|
| 129 |
+
dunder: bool = False,
|
| 130 |
+
sort: bool = True,
|
| 131 |
+
all: bool = False,
|
| 132 |
+
value: bool = True,
|
| 133 |
+
) -> None:
|
| 134 |
+
"""Inspect any Python object.
|
| 135 |
+
|
| 136 |
+
* inspect(<OBJECT>) to see summarized info.
|
| 137 |
+
* inspect(<OBJECT>, methods=True) to see methods.
|
| 138 |
+
* inspect(<OBJECT>, help=True) to see full (non-abbreviated) help.
|
| 139 |
+
* inspect(<OBJECT>, private=True) to see private attributes (single underscore).
|
| 140 |
+
* inspect(<OBJECT>, dunder=True) to see attributes beginning with double underscore.
|
| 141 |
+
* inspect(<OBJECT>, all=True) to see all attributes.
|
| 142 |
+
|
| 143 |
+
Args:
|
| 144 |
+
obj (Any): An object to inspect.
|
| 145 |
+
title (str, optional): Title to display over inspect result, or None use type. Defaults to None.
|
| 146 |
+
help (bool, optional): Show full help text rather than just first paragraph. Defaults to False.
|
| 147 |
+
methods (bool, optional): Enable inspection of callables. Defaults to False.
|
| 148 |
+
docs (bool, optional): Also render doc strings. Defaults to True.
|
| 149 |
+
private (bool, optional): Show private attributes (beginning with underscore). Defaults to False.
|
| 150 |
+
dunder (bool, optional): Show attributes starting with double underscore. Defaults to False.
|
| 151 |
+
sort (bool, optional): Sort attributes alphabetically. Defaults to True.
|
| 152 |
+
all (bool, optional): Show all attributes. Defaults to False.
|
| 153 |
+
value (bool, optional): Pretty print value. Defaults to True.
|
| 154 |
+
"""
|
| 155 |
+
_console = console or get_console()
|
| 156 |
+
from pip._vendor.rich._inspect import Inspect
|
| 157 |
+
|
| 158 |
+
# Special case for inspect(inspect)
|
| 159 |
+
is_inspect = obj is inspect
|
| 160 |
+
|
| 161 |
+
_inspect = Inspect(
|
| 162 |
+
obj,
|
| 163 |
+
title=title,
|
| 164 |
+
help=is_inspect or help,
|
| 165 |
+
methods=is_inspect or methods,
|
| 166 |
+
docs=is_inspect or docs,
|
| 167 |
+
private=private,
|
| 168 |
+
dunder=dunder,
|
| 169 |
+
sort=sort,
|
| 170 |
+
all=all,
|
| 171 |
+
value=value,
|
| 172 |
+
)
|
| 173 |
+
_console.print(_inspect)
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
if __name__ == "__main__": # pragma: no cover
|
| 177 |
+
print("Hello, **World**")
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__pycache__/control.cpython-311.pyc
ADDED
|
Binary file (11.9 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-311.pyc
ADDED
|
Binary file (2.8 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/_fileno.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from typing import IO, Callable
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def get_fileno(file_like: IO[str]) -> int | None:
|
| 7 |
+
"""Get fileno() from a file, accounting for poorly implemented file-like objects.
|
| 8 |
+
|
| 9 |
+
Args:
|
| 10 |
+
file_like (IO): A file-like object.
|
| 11 |
+
|
| 12 |
+
Returns:
|
| 13 |
+
int | None: The result of fileno if available, or None if operation failed.
|
| 14 |
+
"""
|
| 15 |
+
fileno: Callable[[], int] | None = getattr(file_like, "fileno", None)
|
| 16 |
+
if fileno is not None:
|
| 17 |
+
try:
|
| 18 |
+
return fileno()
|
| 19 |
+
except Exception:
|
| 20 |
+
# `fileno` is documented as potentially raising a OSError
|
| 21 |
+
# Alas, from the issues, there are so many poorly implemented file-like objects,
|
| 22 |
+
# that `fileno()` can raise just about anything.
|
| 23 |
+
return None
|
| 24 |
+
return None
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/_null_file.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from types import TracebackType
|
| 2 |
+
from typing import IO, Iterable, Iterator, List, Optional, Type
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class NullFile(IO[str]):
|
| 6 |
+
def close(self) -> None:
|
| 7 |
+
pass
|
| 8 |
+
|
| 9 |
+
def isatty(self) -> bool:
|
| 10 |
+
return False
|
| 11 |
+
|
| 12 |
+
def read(self, __n: int = 1) -> str:
|
| 13 |
+
return ""
|
| 14 |
+
|
| 15 |
+
def readable(self) -> bool:
|
| 16 |
+
return False
|
| 17 |
+
|
| 18 |
+
def readline(self, __limit: int = 1) -> str:
|
| 19 |
+
return ""
|
| 20 |
+
|
| 21 |
+
def readlines(self, __hint: int = 1) -> List[str]:
|
| 22 |
+
return []
|
| 23 |
+
|
| 24 |
+
def seek(self, __offset: int, __whence: int = 1) -> int:
|
| 25 |
+
return 0
|
| 26 |
+
|
| 27 |
+
def seekable(self) -> bool:
|
| 28 |
+
return False
|
| 29 |
+
|
| 30 |
+
def tell(self) -> int:
|
| 31 |
+
return 0
|
| 32 |
+
|
| 33 |
+
def truncate(self, __size: Optional[int] = 1) -> int:
|
| 34 |
+
return 0
|
| 35 |
+
|
| 36 |
+
def writable(self) -> bool:
|
| 37 |
+
return False
|
| 38 |
+
|
| 39 |
+
def writelines(self, __lines: Iterable[str]) -> None:
|
| 40 |
+
pass
|
| 41 |
+
|
| 42 |
+
def __next__(self) -> str:
|
| 43 |
+
return ""
|
| 44 |
+
|
| 45 |
+
def __iter__(self) -> Iterator[str]:
|
| 46 |
+
return iter([""])
|
| 47 |
+
|
| 48 |
+
def __enter__(self) -> IO[str]:
|
| 49 |
+
pass
|
| 50 |
+
|
| 51 |
+
def __exit__(
|
| 52 |
+
self,
|
| 53 |
+
__t: Optional[Type[BaseException]],
|
| 54 |
+
__value: Optional[BaseException],
|
| 55 |
+
__traceback: Optional[TracebackType],
|
| 56 |
+
) -> None:
|
| 57 |
+
pass
|
| 58 |
+
|
| 59 |
+
def write(self, text: str) -> int:
|
| 60 |
+
return 0
|
| 61 |
+
|
| 62 |
+
def flush(self) -> None:
|
| 63 |
+
pass
|
| 64 |
+
|
| 65 |
+
def fileno(self) -> int:
|
| 66 |
+
return -1
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
NULL_FILE = NullFile()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/_pick.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def pick_bool(*values: Optional[bool]) -> bool:
|
| 5 |
+
"""Pick the first non-none bool or return the last value.
|
| 6 |
+
|
| 7 |
+
Args:
|
| 8 |
+
*values (bool): Any number of boolean or None values.
|
| 9 |
+
|
| 10 |
+
Returns:
|
| 11 |
+
bool: First non-none boolean.
|
| 12 |
+
"""
|
| 13 |
+
assert values, "1 or more values required"
|
| 14 |
+
for value in values:
|
| 15 |
+
if value is not None:
|
| 16 |
+
return value
|
| 17 |
+
return bool(value)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/_windows_renderer.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Iterable, Sequence, Tuple, cast
|
| 2 |
+
|
| 3 |
+
from pip._vendor.rich._win32_console import LegacyWindowsTerm, WindowsCoordinates
|
| 4 |
+
from pip._vendor.rich.segment import ControlCode, ControlType, Segment
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def legacy_windows_render(buffer: Iterable[Segment], term: LegacyWindowsTerm) -> None:
|
| 8 |
+
"""Makes appropriate Windows Console API calls based on the segments in the buffer.
|
| 9 |
+
|
| 10 |
+
Args:
|
| 11 |
+
buffer (Iterable[Segment]): Iterable of Segments to convert to Win32 API calls.
|
| 12 |
+
term (LegacyWindowsTerm): Used to call the Windows Console API.
|
| 13 |
+
"""
|
| 14 |
+
for text, style, control in buffer:
|
| 15 |
+
if not control:
|
| 16 |
+
if style:
|
| 17 |
+
term.write_styled(text, style)
|
| 18 |
+
else:
|
| 19 |
+
term.write_text(text)
|
| 20 |
+
else:
|
| 21 |
+
control_codes: Sequence[ControlCode] = control
|
| 22 |
+
for control_code in control_codes:
|
| 23 |
+
control_type = control_code[0]
|
| 24 |
+
if control_type == ControlType.CURSOR_MOVE_TO:
|
| 25 |
+
_, x, y = cast(Tuple[ControlType, int, int], control_code)
|
| 26 |
+
term.move_cursor_to(WindowsCoordinates(row=y - 1, col=x - 1))
|
| 27 |
+
elif control_type == ControlType.CARRIAGE_RETURN:
|
| 28 |
+
term.write_text("\r")
|
| 29 |
+
elif control_type == ControlType.HOME:
|
| 30 |
+
term.move_cursor_to(WindowsCoordinates(0, 0))
|
| 31 |
+
elif control_type == ControlType.CURSOR_UP:
|
| 32 |
+
term.move_cursor_up()
|
| 33 |
+
elif control_type == ControlType.CURSOR_DOWN:
|
| 34 |
+
term.move_cursor_down()
|
| 35 |
+
elif control_type == ControlType.CURSOR_FORWARD:
|
| 36 |
+
term.move_cursor_forward()
|
| 37 |
+
elif control_type == ControlType.CURSOR_BACKWARD:
|
| 38 |
+
term.move_cursor_backward()
|
| 39 |
+
elif control_type == ControlType.CURSOR_MOVE_TO_COLUMN:
|
| 40 |
+
_, column = cast(Tuple[ControlType, int], control_code)
|
| 41 |
+
term.move_cursor_to_column(column - 1)
|
| 42 |
+
elif control_type == ControlType.HIDE_CURSOR:
|
| 43 |
+
term.hide_cursor()
|
| 44 |
+
elif control_type == ControlType.SHOW_CURSOR:
|
| 45 |
+
term.show_cursor()
|
| 46 |
+
elif control_type == ControlType.ERASE_IN_LINE:
|
| 47 |
+
_, mode = cast(Tuple[ControlType, int], control_code)
|
| 48 |
+
if mode == 0:
|
| 49 |
+
term.erase_end_of_line()
|
| 50 |
+
elif mode == 1:
|
| 51 |
+
term.erase_start_of_line()
|
| 52 |
+
elif mode == 2:
|
| 53 |
+
term.erase_line()
|
| 54 |
+
elif control_type == ControlType.SET_WINDOW_TITLE:
|
| 55 |
+
_, title = cast(Tuple[ControlType, str], control_code)
|
| 56 |
+
term.set_title(title)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/ansi.py
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
import sys
|
| 3 |
+
from contextlib import suppress
|
| 4 |
+
from typing import Iterable, NamedTuple, Optional
|
| 5 |
+
|
| 6 |
+
from .color import Color
|
| 7 |
+
from .style import Style
|
| 8 |
+
from .text import Text
|
| 9 |
+
|
| 10 |
+
re_ansi = re.compile(
|
| 11 |
+
r"""
|
| 12 |
+
(?:\x1b\](.*?)\x1b\\)|
|
| 13 |
+
(?:\x1b([(@-Z\\-_]|\[[0-?]*[ -/]*[@-~]))
|
| 14 |
+
""",
|
| 15 |
+
re.VERBOSE,
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class _AnsiToken(NamedTuple):
|
| 20 |
+
"""Result of ansi tokenized string."""
|
| 21 |
+
|
| 22 |
+
plain: str = ""
|
| 23 |
+
sgr: Optional[str] = ""
|
| 24 |
+
osc: Optional[str] = ""
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def _ansi_tokenize(ansi_text: str) -> Iterable[_AnsiToken]:
|
| 28 |
+
"""Tokenize a string in to plain text and ANSI codes.
|
| 29 |
+
|
| 30 |
+
Args:
|
| 31 |
+
ansi_text (str): A String containing ANSI codes.
|
| 32 |
+
|
| 33 |
+
Yields:
|
| 34 |
+
AnsiToken: A named tuple of (plain, sgr, osc)
|
| 35 |
+
"""
|
| 36 |
+
|
| 37 |
+
position = 0
|
| 38 |
+
sgr: Optional[str]
|
| 39 |
+
osc: Optional[str]
|
| 40 |
+
for match in re_ansi.finditer(ansi_text):
|
| 41 |
+
start, end = match.span(0)
|
| 42 |
+
osc, sgr = match.groups()
|
| 43 |
+
if start > position:
|
| 44 |
+
yield _AnsiToken(ansi_text[position:start])
|
| 45 |
+
if sgr:
|
| 46 |
+
if sgr == "(":
|
| 47 |
+
position = end + 1
|
| 48 |
+
continue
|
| 49 |
+
if sgr.endswith("m"):
|
| 50 |
+
yield _AnsiToken("", sgr[1:-1], osc)
|
| 51 |
+
else:
|
| 52 |
+
yield _AnsiToken("", sgr, osc)
|
| 53 |
+
position = end
|
| 54 |
+
if position < len(ansi_text):
|
| 55 |
+
yield _AnsiToken(ansi_text[position:])
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
SGR_STYLE_MAP = {
|
| 59 |
+
1: "bold",
|
| 60 |
+
2: "dim",
|
| 61 |
+
3: "italic",
|
| 62 |
+
4: "underline",
|
| 63 |
+
5: "blink",
|
| 64 |
+
6: "blink2",
|
| 65 |
+
7: "reverse",
|
| 66 |
+
8: "conceal",
|
| 67 |
+
9: "strike",
|
| 68 |
+
21: "underline2",
|
| 69 |
+
22: "not dim not bold",
|
| 70 |
+
23: "not italic",
|
| 71 |
+
24: "not underline",
|
| 72 |
+
25: "not blink",
|
| 73 |
+
26: "not blink2",
|
| 74 |
+
27: "not reverse",
|
| 75 |
+
28: "not conceal",
|
| 76 |
+
29: "not strike",
|
| 77 |
+
30: "color(0)",
|
| 78 |
+
31: "color(1)",
|
| 79 |
+
32: "color(2)",
|
| 80 |
+
33: "color(3)",
|
| 81 |
+
34: "color(4)",
|
| 82 |
+
35: "color(5)",
|
| 83 |
+
36: "color(6)",
|
| 84 |
+
37: "color(7)",
|
| 85 |
+
39: "default",
|
| 86 |
+
40: "on color(0)",
|
| 87 |
+
41: "on color(1)",
|
| 88 |
+
42: "on color(2)",
|
| 89 |
+
43: "on color(3)",
|
| 90 |
+
44: "on color(4)",
|
| 91 |
+
45: "on color(5)",
|
| 92 |
+
46: "on color(6)",
|
| 93 |
+
47: "on color(7)",
|
| 94 |
+
49: "on default",
|
| 95 |
+
51: "frame",
|
| 96 |
+
52: "encircle",
|
| 97 |
+
53: "overline",
|
| 98 |
+
54: "not frame not encircle",
|
| 99 |
+
55: "not overline",
|
| 100 |
+
90: "color(8)",
|
| 101 |
+
91: "color(9)",
|
| 102 |
+
92: "color(10)",
|
| 103 |
+
93: "color(11)",
|
| 104 |
+
94: "color(12)",
|
| 105 |
+
95: "color(13)",
|
| 106 |
+
96: "color(14)",
|
| 107 |
+
97: "color(15)",
|
| 108 |
+
100: "on color(8)",
|
| 109 |
+
101: "on color(9)",
|
| 110 |
+
102: "on color(10)",
|
| 111 |
+
103: "on color(11)",
|
| 112 |
+
104: "on color(12)",
|
| 113 |
+
105: "on color(13)",
|
| 114 |
+
106: "on color(14)",
|
| 115 |
+
107: "on color(15)",
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
class AnsiDecoder:
|
| 120 |
+
"""Translate ANSI code in to styled Text."""
|
| 121 |
+
|
| 122 |
+
def __init__(self) -> None:
|
| 123 |
+
self.style = Style.null()
|
| 124 |
+
|
| 125 |
+
def decode(self, terminal_text: str) -> Iterable[Text]:
|
| 126 |
+
"""Decode ANSI codes in an iterable of lines.
|
| 127 |
+
|
| 128 |
+
Args:
|
| 129 |
+
lines (Iterable[str]): An iterable of lines of terminal output.
|
| 130 |
+
|
| 131 |
+
Yields:
|
| 132 |
+
Text: Marked up Text.
|
| 133 |
+
"""
|
| 134 |
+
for line in terminal_text.splitlines():
|
| 135 |
+
yield self.decode_line(line)
|
| 136 |
+
|
| 137 |
+
def decode_line(self, line: str) -> Text:
|
| 138 |
+
"""Decode a line containing ansi codes.
|
| 139 |
+
|
| 140 |
+
Args:
|
| 141 |
+
line (str): A line of terminal output.
|
| 142 |
+
|
| 143 |
+
Returns:
|
| 144 |
+
Text: A Text instance marked up according to ansi codes.
|
| 145 |
+
"""
|
| 146 |
+
from_ansi = Color.from_ansi
|
| 147 |
+
from_rgb = Color.from_rgb
|
| 148 |
+
_Style = Style
|
| 149 |
+
text = Text()
|
| 150 |
+
append = text.append
|
| 151 |
+
line = line.rsplit("\r", 1)[-1]
|
| 152 |
+
for plain_text, sgr, osc in _ansi_tokenize(line):
|
| 153 |
+
if plain_text:
|
| 154 |
+
append(plain_text, self.style or None)
|
| 155 |
+
elif osc is not None:
|
| 156 |
+
if osc.startswith("8;"):
|
| 157 |
+
_params, semicolon, link = osc[2:].partition(";")
|
| 158 |
+
if semicolon:
|
| 159 |
+
self.style = self.style.update_link(link or None)
|
| 160 |
+
elif sgr is not None:
|
| 161 |
+
# Translate in to semi-colon separated codes
|
| 162 |
+
# Ignore invalid codes, because we want to be lenient
|
| 163 |
+
codes = [
|
| 164 |
+
min(255, int(_code) if _code else 0)
|
| 165 |
+
for _code in sgr.split(";")
|
| 166 |
+
if _code.isdigit() or _code == ""
|
| 167 |
+
]
|
| 168 |
+
iter_codes = iter(codes)
|
| 169 |
+
for code in iter_codes:
|
| 170 |
+
if code == 0:
|
| 171 |
+
# reset
|
| 172 |
+
self.style = _Style.null()
|
| 173 |
+
elif code in SGR_STYLE_MAP:
|
| 174 |
+
# styles
|
| 175 |
+
self.style += _Style.parse(SGR_STYLE_MAP[code])
|
| 176 |
+
elif code == 38:
|
| 177 |
+
# Foreground
|
| 178 |
+
with suppress(StopIteration):
|
| 179 |
+
color_type = next(iter_codes)
|
| 180 |
+
if color_type == 5:
|
| 181 |
+
self.style += _Style.from_color(
|
| 182 |
+
from_ansi(next(iter_codes))
|
| 183 |
+
)
|
| 184 |
+
elif color_type == 2:
|
| 185 |
+
self.style += _Style.from_color(
|
| 186 |
+
from_rgb(
|
| 187 |
+
next(iter_codes),
|
| 188 |
+
next(iter_codes),
|
| 189 |
+
next(iter_codes),
|
| 190 |
+
)
|
| 191 |
+
)
|
| 192 |
+
elif code == 48:
|
| 193 |
+
# Background
|
| 194 |
+
with suppress(StopIteration):
|
| 195 |
+
color_type = next(iter_codes)
|
| 196 |
+
if color_type == 5:
|
| 197 |
+
self.style += _Style.from_color(
|
| 198 |
+
None, from_ansi(next(iter_codes))
|
| 199 |
+
)
|
| 200 |
+
elif color_type == 2:
|
| 201 |
+
self.style += _Style.from_color(
|
| 202 |
+
None,
|
| 203 |
+
from_rgb(
|
| 204 |
+
next(iter_codes),
|
| 205 |
+
next(iter_codes),
|
| 206 |
+
next(iter_codes),
|
| 207 |
+
),
|
| 208 |
+
)
|
| 209 |
+
|
| 210 |
+
return text
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
if sys.platform != "win32" and __name__ == "__main__": # pragma: no cover
|
| 214 |
+
import io
|
| 215 |
+
import os
|
| 216 |
+
import pty
|
| 217 |
+
import sys
|
| 218 |
+
|
| 219 |
+
decoder = AnsiDecoder()
|
| 220 |
+
|
| 221 |
+
stdout = io.BytesIO()
|
| 222 |
+
|
| 223 |
+
def read(fd: int) -> bytes:
|
| 224 |
+
data = os.read(fd, 1024)
|
| 225 |
+
stdout.write(data)
|
| 226 |
+
return data
|
| 227 |
+
|
| 228 |
+
pty.spawn(sys.argv[1:], read)
|
| 229 |
+
|
| 230 |
+
from .console import Console
|
| 231 |
+
|
| 232 |
+
console = Console(record=True)
|
| 233 |
+
|
| 234 |
+
stdout_result = stdout.getvalue().decode("utf-8")
|
| 235 |
+
print(stdout_result)
|
| 236 |
+
|
| 237 |
+
for line in decoder.decode(stdout_result):
|
| 238 |
+
console.print(line)
|
| 239 |
+
|
| 240 |
+
console.save_html("stdout.html")
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/columns.py
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections import defaultdict
|
| 2 |
+
from itertools import chain
|
| 3 |
+
from operator import itemgetter
|
| 4 |
+
from typing import Dict, Iterable, List, Optional, Tuple
|
| 5 |
+
|
| 6 |
+
from .align import Align, AlignMethod
|
| 7 |
+
from .console import Console, ConsoleOptions, RenderableType, RenderResult
|
| 8 |
+
from .constrain import Constrain
|
| 9 |
+
from .measure import Measurement
|
| 10 |
+
from .padding import Padding, PaddingDimensions
|
| 11 |
+
from .table import Table
|
| 12 |
+
from .text import TextType
|
| 13 |
+
from .jupyter import JupyterMixin
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class Columns(JupyterMixin):
|
| 17 |
+
"""Display renderables in neat columns.
|
| 18 |
+
|
| 19 |
+
Args:
|
| 20 |
+
renderables (Iterable[RenderableType]): Any number of Rich renderables (including str).
|
| 21 |
+
width (int, optional): The desired width of the columns, or None to auto detect. Defaults to None.
|
| 22 |
+
padding (PaddingDimensions, optional): Optional padding around cells. Defaults to (0, 1).
|
| 23 |
+
expand (bool, optional): Expand columns to full width. Defaults to False.
|
| 24 |
+
equal (bool, optional): Arrange in to equal sized columns. Defaults to False.
|
| 25 |
+
column_first (bool, optional): Align items from top to bottom (rather than left to right). Defaults to False.
|
| 26 |
+
right_to_left (bool, optional): Start column from right hand side. Defaults to False.
|
| 27 |
+
align (str, optional): Align value ("left", "right", or "center") or None for default. Defaults to None.
|
| 28 |
+
title (TextType, optional): Optional title for Columns.
|
| 29 |
+
"""
|
| 30 |
+
|
| 31 |
+
def __init__(
|
| 32 |
+
self,
|
| 33 |
+
renderables: Optional[Iterable[RenderableType]] = None,
|
| 34 |
+
padding: PaddingDimensions = (0, 1),
|
| 35 |
+
*,
|
| 36 |
+
width: Optional[int] = None,
|
| 37 |
+
expand: bool = False,
|
| 38 |
+
equal: bool = False,
|
| 39 |
+
column_first: bool = False,
|
| 40 |
+
right_to_left: bool = False,
|
| 41 |
+
align: Optional[AlignMethod] = None,
|
| 42 |
+
title: Optional[TextType] = None,
|
| 43 |
+
) -> None:
|
| 44 |
+
self.renderables = list(renderables or [])
|
| 45 |
+
self.width = width
|
| 46 |
+
self.padding = padding
|
| 47 |
+
self.expand = expand
|
| 48 |
+
self.equal = equal
|
| 49 |
+
self.column_first = column_first
|
| 50 |
+
self.right_to_left = right_to_left
|
| 51 |
+
self.align: Optional[AlignMethod] = align
|
| 52 |
+
self.title = title
|
| 53 |
+
|
| 54 |
+
def add_renderable(self, renderable: RenderableType) -> None:
|
| 55 |
+
"""Add a renderable to the columns.
|
| 56 |
+
|
| 57 |
+
Args:
|
| 58 |
+
renderable (RenderableType): Any renderable object.
|
| 59 |
+
"""
|
| 60 |
+
self.renderables.append(renderable)
|
| 61 |
+
|
| 62 |
+
def __rich_console__(
|
| 63 |
+
self, console: Console, options: ConsoleOptions
|
| 64 |
+
) -> RenderResult:
|
| 65 |
+
render_str = console.render_str
|
| 66 |
+
renderables = [
|
| 67 |
+
render_str(renderable) if isinstance(renderable, str) else renderable
|
| 68 |
+
for renderable in self.renderables
|
| 69 |
+
]
|
| 70 |
+
if not renderables:
|
| 71 |
+
return
|
| 72 |
+
_top, right, _bottom, left = Padding.unpack(self.padding)
|
| 73 |
+
width_padding = max(left, right)
|
| 74 |
+
max_width = options.max_width
|
| 75 |
+
widths: Dict[int, int] = defaultdict(int)
|
| 76 |
+
column_count = len(renderables)
|
| 77 |
+
|
| 78 |
+
get_measurement = Measurement.get
|
| 79 |
+
renderable_widths = [
|
| 80 |
+
get_measurement(console, options, renderable).maximum
|
| 81 |
+
for renderable in renderables
|
| 82 |
+
]
|
| 83 |
+
if self.equal:
|
| 84 |
+
renderable_widths = [max(renderable_widths)] * len(renderable_widths)
|
| 85 |
+
|
| 86 |
+
def iter_renderables(
|
| 87 |
+
column_count: int,
|
| 88 |
+
) -> Iterable[Tuple[int, Optional[RenderableType]]]:
|
| 89 |
+
item_count = len(renderables)
|
| 90 |
+
if self.column_first:
|
| 91 |
+
width_renderables = list(zip(renderable_widths, renderables))
|
| 92 |
+
|
| 93 |
+
column_lengths: List[int] = [item_count // column_count] * column_count
|
| 94 |
+
for col_no in range(item_count % column_count):
|
| 95 |
+
column_lengths[col_no] += 1
|
| 96 |
+
|
| 97 |
+
row_count = (item_count + column_count - 1) // column_count
|
| 98 |
+
cells = [[-1] * column_count for _ in range(row_count)]
|
| 99 |
+
row = col = 0
|
| 100 |
+
for index in range(item_count):
|
| 101 |
+
cells[row][col] = index
|
| 102 |
+
column_lengths[col] -= 1
|
| 103 |
+
if column_lengths[col]:
|
| 104 |
+
row += 1
|
| 105 |
+
else:
|
| 106 |
+
col += 1
|
| 107 |
+
row = 0
|
| 108 |
+
for index in chain.from_iterable(cells):
|
| 109 |
+
if index == -1:
|
| 110 |
+
break
|
| 111 |
+
yield width_renderables[index]
|
| 112 |
+
else:
|
| 113 |
+
yield from zip(renderable_widths, renderables)
|
| 114 |
+
# Pad odd elements with spaces
|
| 115 |
+
if item_count % column_count:
|
| 116 |
+
for _ in range(column_count - (item_count % column_count)):
|
| 117 |
+
yield 0, None
|
| 118 |
+
|
| 119 |
+
table = Table.grid(padding=self.padding, collapse_padding=True, pad_edge=False)
|
| 120 |
+
table.expand = self.expand
|
| 121 |
+
table.title = self.title
|
| 122 |
+
|
| 123 |
+
if self.width is not None:
|
| 124 |
+
column_count = (max_width) // (self.width + width_padding)
|
| 125 |
+
for _ in range(column_count):
|
| 126 |
+
table.add_column(width=self.width)
|
| 127 |
+
else:
|
| 128 |
+
while column_count > 1:
|
| 129 |
+
widths.clear()
|
| 130 |
+
column_no = 0
|
| 131 |
+
for renderable_width, _ in iter_renderables(column_count):
|
| 132 |
+
widths[column_no] = max(widths[column_no], renderable_width)
|
| 133 |
+
total_width = sum(widths.values()) + width_padding * (
|
| 134 |
+
len(widths) - 1
|
| 135 |
+
)
|
| 136 |
+
if total_width > max_width:
|
| 137 |
+
column_count = len(widths) - 1
|
| 138 |
+
break
|
| 139 |
+
else:
|
| 140 |
+
column_no = (column_no + 1) % column_count
|
| 141 |
+
else:
|
| 142 |
+
break
|
| 143 |
+
|
| 144 |
+
get_renderable = itemgetter(1)
|
| 145 |
+
_renderables = [
|
| 146 |
+
get_renderable(_renderable)
|
| 147 |
+
for _renderable in iter_renderables(column_count)
|
| 148 |
+
]
|
| 149 |
+
if self.equal:
|
| 150 |
+
_renderables = [
|
| 151 |
+
None
|
| 152 |
+
if renderable is None
|
| 153 |
+
else Constrain(renderable, renderable_widths[0])
|
| 154 |
+
for renderable in _renderables
|
| 155 |
+
]
|
| 156 |
+
if self.align:
|
| 157 |
+
align = self.align
|
| 158 |
+
_Align = Align
|
| 159 |
+
_renderables = [
|
| 160 |
+
None if renderable is None else _Align(renderable, align)
|
| 161 |
+
for renderable in _renderables
|
| 162 |
+
]
|
| 163 |
+
|
| 164 |
+
right_to_left = self.right_to_left
|
| 165 |
+
add_row = table.add_row
|
| 166 |
+
for start in range(0, len(_renderables), column_count):
|
| 167 |
+
row = _renderables[start : start + column_count]
|
| 168 |
+
if right_to_left:
|
| 169 |
+
row = row[::-1]
|
| 170 |
+
add_row(*row)
|
| 171 |
+
yield table
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
if __name__ == "__main__": # pragma: no cover
|
| 175 |
+
import os
|
| 176 |
+
|
| 177 |
+
console = Console()
|
| 178 |
+
|
| 179 |
+
files = [f"{i} {s}" for i, s in enumerate(sorted(os.listdir()))]
|
| 180 |
+
columns = Columns(files, padding=(0, 1), expand=False, equal=False)
|
| 181 |
+
console.print(columns)
|
| 182 |
+
console.rule()
|
| 183 |
+
columns.column_first = True
|
| 184 |
+
console.print(columns)
|
| 185 |
+
columns.right_to_left = True
|
| 186 |
+
console.rule()
|
| 187 |
+
console.print(columns)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/containers.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from itertools import zip_longest
|
| 2 |
+
from typing import (
|
| 3 |
+
TYPE_CHECKING,
|
| 4 |
+
Iterable,
|
| 5 |
+
Iterator,
|
| 6 |
+
List,
|
| 7 |
+
Optional,
|
| 8 |
+
TypeVar,
|
| 9 |
+
Union,
|
| 10 |
+
overload,
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
if TYPE_CHECKING:
|
| 14 |
+
from .console import (
|
| 15 |
+
Console,
|
| 16 |
+
ConsoleOptions,
|
| 17 |
+
JustifyMethod,
|
| 18 |
+
OverflowMethod,
|
| 19 |
+
RenderResult,
|
| 20 |
+
RenderableType,
|
| 21 |
+
)
|
| 22 |
+
from .text import Text
|
| 23 |
+
|
| 24 |
+
from .cells import cell_len
|
| 25 |
+
from .measure import Measurement
|
| 26 |
+
|
| 27 |
+
T = TypeVar("T")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class Renderables:
|
| 31 |
+
"""A list subclass which renders its contents to the console."""
|
| 32 |
+
|
| 33 |
+
def __init__(
|
| 34 |
+
self, renderables: Optional[Iterable["RenderableType"]] = None
|
| 35 |
+
) -> None:
|
| 36 |
+
self._renderables: List["RenderableType"] = (
|
| 37 |
+
list(renderables) if renderables is not None else []
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
def __rich_console__(
|
| 41 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 42 |
+
) -> "RenderResult":
|
| 43 |
+
"""Console render method to insert line-breaks."""
|
| 44 |
+
yield from self._renderables
|
| 45 |
+
|
| 46 |
+
def __rich_measure__(
|
| 47 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 48 |
+
) -> "Measurement":
|
| 49 |
+
dimensions = [
|
| 50 |
+
Measurement.get(console, options, renderable)
|
| 51 |
+
for renderable in self._renderables
|
| 52 |
+
]
|
| 53 |
+
if not dimensions:
|
| 54 |
+
return Measurement(1, 1)
|
| 55 |
+
_min = max(dimension.minimum for dimension in dimensions)
|
| 56 |
+
_max = max(dimension.maximum for dimension in dimensions)
|
| 57 |
+
return Measurement(_min, _max)
|
| 58 |
+
|
| 59 |
+
def append(self, renderable: "RenderableType") -> None:
|
| 60 |
+
self._renderables.append(renderable)
|
| 61 |
+
|
| 62 |
+
def __iter__(self) -> Iterable["RenderableType"]:
|
| 63 |
+
return iter(self._renderables)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class Lines:
|
| 67 |
+
"""A list subclass which can render to the console."""
|
| 68 |
+
|
| 69 |
+
def __init__(self, lines: Iterable["Text"] = ()) -> None:
|
| 70 |
+
self._lines: List["Text"] = list(lines)
|
| 71 |
+
|
| 72 |
+
def __repr__(self) -> str:
|
| 73 |
+
return f"Lines({self._lines!r})"
|
| 74 |
+
|
| 75 |
+
def __iter__(self) -> Iterator["Text"]:
|
| 76 |
+
return iter(self._lines)
|
| 77 |
+
|
| 78 |
+
@overload
|
| 79 |
+
def __getitem__(self, index: int) -> "Text":
|
| 80 |
+
...
|
| 81 |
+
|
| 82 |
+
@overload
|
| 83 |
+
def __getitem__(self, index: slice) -> List["Text"]:
|
| 84 |
+
...
|
| 85 |
+
|
| 86 |
+
def __getitem__(self, index: Union[slice, int]) -> Union["Text", List["Text"]]:
|
| 87 |
+
return self._lines[index]
|
| 88 |
+
|
| 89 |
+
def __setitem__(self, index: int, value: "Text") -> "Lines":
|
| 90 |
+
self._lines[index] = value
|
| 91 |
+
return self
|
| 92 |
+
|
| 93 |
+
def __len__(self) -> int:
|
| 94 |
+
return self._lines.__len__()
|
| 95 |
+
|
| 96 |
+
def __rich_console__(
|
| 97 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 98 |
+
) -> "RenderResult":
|
| 99 |
+
"""Console render method to insert line-breaks."""
|
| 100 |
+
yield from self._lines
|
| 101 |
+
|
| 102 |
+
def append(self, line: "Text") -> None:
|
| 103 |
+
self._lines.append(line)
|
| 104 |
+
|
| 105 |
+
def extend(self, lines: Iterable["Text"]) -> None:
|
| 106 |
+
self._lines.extend(lines)
|
| 107 |
+
|
| 108 |
+
def pop(self, index: int = -1) -> "Text":
|
| 109 |
+
return self._lines.pop(index)
|
| 110 |
+
|
| 111 |
+
def justify(
|
| 112 |
+
self,
|
| 113 |
+
console: "Console",
|
| 114 |
+
width: int,
|
| 115 |
+
justify: "JustifyMethod" = "left",
|
| 116 |
+
overflow: "OverflowMethod" = "fold",
|
| 117 |
+
) -> None:
|
| 118 |
+
"""Justify and overflow text to a given width.
|
| 119 |
+
|
| 120 |
+
Args:
|
| 121 |
+
console (Console): Console instance.
|
| 122 |
+
width (int): Number of cells available per line.
|
| 123 |
+
justify (str, optional): Default justify method for text: "left", "center", "full" or "right". Defaults to "left".
|
| 124 |
+
overflow (str, optional): Default overflow for text: "crop", "fold", or "ellipsis". Defaults to "fold".
|
| 125 |
+
|
| 126 |
+
"""
|
| 127 |
+
from .text import Text
|
| 128 |
+
|
| 129 |
+
if justify == "left":
|
| 130 |
+
for line in self._lines:
|
| 131 |
+
line.truncate(width, overflow=overflow, pad=True)
|
| 132 |
+
elif justify == "center":
|
| 133 |
+
for line in self._lines:
|
| 134 |
+
line.rstrip()
|
| 135 |
+
line.truncate(width, overflow=overflow)
|
| 136 |
+
line.pad_left((width - cell_len(line.plain)) // 2)
|
| 137 |
+
line.pad_right(width - cell_len(line.plain))
|
| 138 |
+
elif justify == "right":
|
| 139 |
+
for line in self._lines:
|
| 140 |
+
line.rstrip()
|
| 141 |
+
line.truncate(width, overflow=overflow)
|
| 142 |
+
line.pad_left(width - cell_len(line.plain))
|
| 143 |
+
elif justify == "full":
|
| 144 |
+
for line_index, line in enumerate(self._lines):
|
| 145 |
+
if line_index == len(self._lines) - 1:
|
| 146 |
+
break
|
| 147 |
+
words = line.split(" ")
|
| 148 |
+
words_size = sum(cell_len(word.plain) for word in words)
|
| 149 |
+
num_spaces = len(words) - 1
|
| 150 |
+
spaces = [1 for _ in range(num_spaces)]
|
| 151 |
+
index = 0
|
| 152 |
+
if spaces:
|
| 153 |
+
while words_size + num_spaces < width:
|
| 154 |
+
spaces[len(spaces) - index - 1] += 1
|
| 155 |
+
num_spaces += 1
|
| 156 |
+
index = (index + 1) % len(spaces)
|
| 157 |
+
tokens: List[Text] = []
|
| 158 |
+
for index, (word, next_word) in enumerate(
|
| 159 |
+
zip_longest(words, words[1:])
|
| 160 |
+
):
|
| 161 |
+
tokens.append(word)
|
| 162 |
+
if index < len(spaces):
|
| 163 |
+
style = word.get_style_at_offset(console, -1)
|
| 164 |
+
next_style = next_word.get_style_at_offset(console, 0)
|
| 165 |
+
space_style = style if style == next_style else line.style
|
| 166 |
+
tokens.append(Text(" " * spaces[index], style=space_style))
|
| 167 |
+
self[line_index] = Text("").join(tokens)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/default_styles.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Dict
|
| 2 |
+
|
| 3 |
+
from .style import Style
|
| 4 |
+
|
| 5 |
+
DEFAULT_STYLES: Dict[str, Style] = {
|
| 6 |
+
"none": Style.null(),
|
| 7 |
+
"reset": Style(
|
| 8 |
+
color="default",
|
| 9 |
+
bgcolor="default",
|
| 10 |
+
dim=False,
|
| 11 |
+
bold=False,
|
| 12 |
+
italic=False,
|
| 13 |
+
underline=False,
|
| 14 |
+
blink=False,
|
| 15 |
+
blink2=False,
|
| 16 |
+
reverse=False,
|
| 17 |
+
conceal=False,
|
| 18 |
+
strike=False,
|
| 19 |
+
),
|
| 20 |
+
"dim": Style(dim=True),
|
| 21 |
+
"bright": Style(dim=False),
|
| 22 |
+
"bold": Style(bold=True),
|
| 23 |
+
"strong": Style(bold=True),
|
| 24 |
+
"code": Style(reverse=True, bold=True),
|
| 25 |
+
"italic": Style(italic=True),
|
| 26 |
+
"emphasize": Style(italic=True),
|
| 27 |
+
"underline": Style(underline=True),
|
| 28 |
+
"blink": Style(blink=True),
|
| 29 |
+
"blink2": Style(blink2=True),
|
| 30 |
+
"reverse": Style(reverse=True),
|
| 31 |
+
"strike": Style(strike=True),
|
| 32 |
+
"black": Style(color="black"),
|
| 33 |
+
"red": Style(color="red"),
|
| 34 |
+
"green": Style(color="green"),
|
| 35 |
+
"yellow": Style(color="yellow"),
|
| 36 |
+
"magenta": Style(color="magenta"),
|
| 37 |
+
"cyan": Style(color="cyan"),
|
| 38 |
+
"white": Style(color="white"),
|
| 39 |
+
"inspect.attr": Style(color="yellow", italic=True),
|
| 40 |
+
"inspect.attr.dunder": Style(color="yellow", italic=True, dim=True),
|
| 41 |
+
"inspect.callable": Style(bold=True, color="red"),
|
| 42 |
+
"inspect.async_def": Style(italic=True, color="bright_cyan"),
|
| 43 |
+
"inspect.def": Style(italic=True, color="bright_cyan"),
|
| 44 |
+
"inspect.class": Style(italic=True, color="bright_cyan"),
|
| 45 |
+
"inspect.error": Style(bold=True, color="red"),
|
| 46 |
+
"inspect.equals": Style(),
|
| 47 |
+
"inspect.help": Style(color="cyan"),
|
| 48 |
+
"inspect.doc": Style(dim=True),
|
| 49 |
+
"inspect.value.border": Style(color="green"),
|
| 50 |
+
"live.ellipsis": Style(bold=True, color="red"),
|
| 51 |
+
"layout.tree.row": Style(dim=False, color="red"),
|
| 52 |
+
"layout.tree.column": Style(dim=False, color="blue"),
|
| 53 |
+
"logging.keyword": Style(bold=True, color="yellow"),
|
| 54 |
+
"logging.level.notset": Style(dim=True),
|
| 55 |
+
"logging.level.debug": Style(color="green"),
|
| 56 |
+
"logging.level.info": Style(color="blue"),
|
| 57 |
+
"logging.level.warning": Style(color="red"),
|
| 58 |
+
"logging.level.error": Style(color="red", bold=True),
|
| 59 |
+
"logging.level.critical": Style(color="red", bold=True, reverse=True),
|
| 60 |
+
"log.level": Style.null(),
|
| 61 |
+
"log.time": Style(color="cyan", dim=True),
|
| 62 |
+
"log.message": Style.null(),
|
| 63 |
+
"log.path": Style(dim=True),
|
| 64 |
+
"repr.ellipsis": Style(color="yellow"),
|
| 65 |
+
"repr.indent": Style(color="green", dim=True),
|
| 66 |
+
"repr.error": Style(color="red", bold=True),
|
| 67 |
+
"repr.str": Style(color="green", italic=False, bold=False),
|
| 68 |
+
"repr.brace": Style(bold=True),
|
| 69 |
+
"repr.comma": Style(bold=True),
|
| 70 |
+
"repr.ipv4": Style(bold=True, color="bright_green"),
|
| 71 |
+
"repr.ipv6": Style(bold=True, color="bright_green"),
|
| 72 |
+
"repr.eui48": Style(bold=True, color="bright_green"),
|
| 73 |
+
"repr.eui64": Style(bold=True, color="bright_green"),
|
| 74 |
+
"repr.tag_start": Style(bold=True),
|
| 75 |
+
"repr.tag_name": Style(color="bright_magenta", bold=True),
|
| 76 |
+
"repr.tag_contents": Style(color="default"),
|
| 77 |
+
"repr.tag_end": Style(bold=True),
|
| 78 |
+
"repr.attrib_name": Style(color="yellow", italic=False),
|
| 79 |
+
"repr.attrib_equal": Style(bold=True),
|
| 80 |
+
"repr.attrib_value": Style(color="magenta", italic=False),
|
| 81 |
+
"repr.number": Style(color="cyan", bold=True, italic=False),
|
| 82 |
+
"repr.number_complex": Style(color="cyan", bold=True, italic=False), # same
|
| 83 |
+
"repr.bool_true": Style(color="bright_green", italic=True),
|
| 84 |
+
"repr.bool_false": Style(color="bright_red", italic=True),
|
| 85 |
+
"repr.none": Style(color="magenta", italic=True),
|
| 86 |
+
"repr.url": Style(underline=True, color="bright_blue", italic=False, bold=False),
|
| 87 |
+
"repr.uuid": Style(color="bright_yellow", bold=False),
|
| 88 |
+
"repr.call": Style(color="magenta", bold=True),
|
| 89 |
+
"repr.path": Style(color="magenta"),
|
| 90 |
+
"repr.filename": Style(color="bright_magenta"),
|
| 91 |
+
"rule.line": Style(color="bright_green"),
|
| 92 |
+
"rule.text": Style.null(),
|
| 93 |
+
"json.brace": Style(bold=True),
|
| 94 |
+
"json.bool_true": Style(color="bright_green", italic=True),
|
| 95 |
+
"json.bool_false": Style(color="bright_red", italic=True),
|
| 96 |
+
"json.null": Style(color="magenta", italic=True),
|
| 97 |
+
"json.number": Style(color="cyan", bold=True, italic=False),
|
| 98 |
+
"json.str": Style(color="green", italic=False, bold=False),
|
| 99 |
+
"json.key": Style(color="blue", bold=True),
|
| 100 |
+
"prompt": Style.null(),
|
| 101 |
+
"prompt.choices": Style(color="magenta", bold=True),
|
| 102 |
+
"prompt.default": Style(color="cyan", bold=True),
|
| 103 |
+
"prompt.invalid": Style(color="red"),
|
| 104 |
+
"prompt.invalid.choice": Style(color="red"),
|
| 105 |
+
"pretty": Style.null(),
|
| 106 |
+
"scope.border": Style(color="blue"),
|
| 107 |
+
"scope.key": Style(color="yellow", italic=True),
|
| 108 |
+
"scope.key.special": Style(color="yellow", italic=True, dim=True),
|
| 109 |
+
"scope.equals": Style(color="red"),
|
| 110 |
+
"table.header": Style(bold=True),
|
| 111 |
+
"table.footer": Style(bold=True),
|
| 112 |
+
"table.cell": Style.null(),
|
| 113 |
+
"table.title": Style(italic=True),
|
| 114 |
+
"table.caption": Style(italic=True, dim=True),
|
| 115 |
+
"traceback.error": Style(color="red", italic=True),
|
| 116 |
+
"traceback.border.syntax_error": Style(color="bright_red"),
|
| 117 |
+
"traceback.border": Style(color="red"),
|
| 118 |
+
"traceback.text": Style.null(),
|
| 119 |
+
"traceback.title": Style(color="red", bold=True),
|
| 120 |
+
"traceback.exc_type": Style(color="bright_red", bold=True),
|
| 121 |
+
"traceback.exc_value": Style.null(),
|
| 122 |
+
"traceback.offset": Style(color="bright_red", bold=True),
|
| 123 |
+
"bar.back": Style(color="grey23"),
|
| 124 |
+
"bar.complete": Style(color="rgb(249,38,114)"),
|
| 125 |
+
"bar.finished": Style(color="rgb(114,156,31)"),
|
| 126 |
+
"bar.pulse": Style(color="rgb(249,38,114)"),
|
| 127 |
+
"progress.description": Style.null(),
|
| 128 |
+
"progress.filesize": Style(color="green"),
|
| 129 |
+
"progress.filesize.total": Style(color="green"),
|
| 130 |
+
"progress.download": Style(color="green"),
|
| 131 |
+
"progress.elapsed": Style(color="yellow"),
|
| 132 |
+
"progress.percentage": Style(color="magenta"),
|
| 133 |
+
"progress.remaining": Style(color="cyan"),
|
| 134 |
+
"progress.data.speed": Style(color="red"),
|
| 135 |
+
"progress.spinner": Style(color="green"),
|
| 136 |
+
"status.spinner": Style(color="green"),
|
| 137 |
+
"tree": Style(),
|
| 138 |
+
"tree.line": Style(),
|
| 139 |
+
"markdown.paragraph": Style(),
|
| 140 |
+
"markdown.text": Style(),
|
| 141 |
+
"markdown.em": Style(italic=True),
|
| 142 |
+
"markdown.emph": Style(italic=True), # For commonmark backwards compatibility
|
| 143 |
+
"markdown.strong": Style(bold=True),
|
| 144 |
+
"markdown.code": Style(bold=True, color="cyan", bgcolor="black"),
|
| 145 |
+
"markdown.code_block": Style(color="cyan", bgcolor="black"),
|
| 146 |
+
"markdown.block_quote": Style(color="magenta"),
|
| 147 |
+
"markdown.list": Style(color="cyan"),
|
| 148 |
+
"markdown.item": Style(),
|
| 149 |
+
"markdown.item.bullet": Style(color="yellow", bold=True),
|
| 150 |
+
"markdown.item.number": Style(color="yellow", bold=True),
|
| 151 |
+
"markdown.hr": Style(color="yellow"),
|
| 152 |
+
"markdown.h1.border": Style(),
|
| 153 |
+
"markdown.h1": Style(bold=True),
|
| 154 |
+
"markdown.h2": Style(bold=True, underline=True),
|
| 155 |
+
"markdown.h3": Style(bold=True),
|
| 156 |
+
"markdown.h4": Style(bold=True, dim=True),
|
| 157 |
+
"markdown.h5": Style(underline=True),
|
| 158 |
+
"markdown.h6": Style(italic=True),
|
| 159 |
+
"markdown.h7": Style(italic=True, dim=True),
|
| 160 |
+
"markdown.link": Style(color="bright_blue"),
|
| 161 |
+
"markdown.link_url": Style(color="blue", underline=True),
|
| 162 |
+
"markdown.s": Style(strike=True),
|
| 163 |
+
"iso8601.date": Style(color="blue"),
|
| 164 |
+
"iso8601.time": Style(color="magenta"),
|
| 165 |
+
"iso8601.timezone": Style(color="yellow"),
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
if __name__ == "__main__": # pragma: no cover
|
| 170 |
+
import argparse
|
| 171 |
+
import io
|
| 172 |
+
|
| 173 |
+
from pip._vendor.rich.console import Console
|
| 174 |
+
from pip._vendor.rich.table import Table
|
| 175 |
+
from pip._vendor.rich.text import Text
|
| 176 |
+
|
| 177 |
+
parser = argparse.ArgumentParser()
|
| 178 |
+
parser.add_argument("--html", action="store_true", help="Export as HTML table")
|
| 179 |
+
args = parser.parse_args()
|
| 180 |
+
html: bool = args.html
|
| 181 |
+
console = Console(record=True, width=70, file=io.StringIO()) if html else Console()
|
| 182 |
+
|
| 183 |
+
table = Table("Name", "Styling")
|
| 184 |
+
|
| 185 |
+
for style_name, style in DEFAULT_STYLES.items():
|
| 186 |
+
table.add_row(Text(style_name, style=style), str(style))
|
| 187 |
+
|
| 188 |
+
console.print(table)
|
| 189 |
+
if html:
|
| 190 |
+
print(console.export_html(inline_styles=True))
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/diagnose.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import platform
|
| 3 |
+
|
| 4 |
+
from pip._vendor.rich import inspect
|
| 5 |
+
from pip._vendor.rich.console import Console, get_windows_console_features
|
| 6 |
+
from pip._vendor.rich.panel import Panel
|
| 7 |
+
from pip._vendor.rich.pretty import Pretty
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def report() -> None: # pragma: no cover
|
| 11 |
+
"""Print a report to the terminal with debugging information"""
|
| 12 |
+
console = Console()
|
| 13 |
+
inspect(console)
|
| 14 |
+
features = get_windows_console_features()
|
| 15 |
+
inspect(features)
|
| 16 |
+
|
| 17 |
+
env_names = (
|
| 18 |
+
"TERM",
|
| 19 |
+
"COLORTERM",
|
| 20 |
+
"CLICOLOR",
|
| 21 |
+
"NO_COLOR",
|
| 22 |
+
"TERM_PROGRAM",
|
| 23 |
+
"COLUMNS",
|
| 24 |
+
"LINES",
|
| 25 |
+
"JUPYTER_COLUMNS",
|
| 26 |
+
"JUPYTER_LINES",
|
| 27 |
+
"JPY_PARENT_PID",
|
| 28 |
+
"VSCODE_VERBOSE_LOGGING",
|
| 29 |
+
)
|
| 30 |
+
env = {name: os.getenv(name) for name in env_names}
|
| 31 |
+
console.print(Panel.fit((Pretty(env)), title="[b]Environment Variables"))
|
| 32 |
+
|
| 33 |
+
console.print(f'platform="{platform.system()}"')
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
if __name__ == "__main__": # pragma: no cover
|
| 37 |
+
report()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/emoji.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
from typing import TYPE_CHECKING, Optional, Union
|
| 3 |
+
|
| 4 |
+
from .jupyter import JupyterMixin
|
| 5 |
+
from .segment import Segment
|
| 6 |
+
from .style import Style
|
| 7 |
+
from ._emoji_codes import EMOJI
|
| 8 |
+
from ._emoji_replace import _emoji_replace
|
| 9 |
+
|
| 10 |
+
if sys.version_info >= (3, 8):
|
| 11 |
+
from typing import Literal
|
| 12 |
+
else:
|
| 13 |
+
from pip._vendor.typing_extensions import Literal # pragma: no cover
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
if TYPE_CHECKING:
|
| 17 |
+
from .console import Console, ConsoleOptions, RenderResult
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
EmojiVariant = Literal["emoji", "text"]
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class NoEmoji(Exception):
|
| 24 |
+
"""No emoji by that name."""
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class Emoji(JupyterMixin):
|
| 28 |
+
__slots__ = ["name", "style", "_char", "variant"]
|
| 29 |
+
|
| 30 |
+
VARIANTS = {"text": "\uFE0E", "emoji": "\uFE0F"}
|
| 31 |
+
|
| 32 |
+
def __init__(
|
| 33 |
+
self,
|
| 34 |
+
name: str,
|
| 35 |
+
style: Union[str, Style] = "none",
|
| 36 |
+
variant: Optional[EmojiVariant] = None,
|
| 37 |
+
) -> None:
|
| 38 |
+
"""A single emoji character.
|
| 39 |
+
|
| 40 |
+
Args:
|
| 41 |
+
name (str): Name of emoji.
|
| 42 |
+
style (Union[str, Style], optional): Optional style. Defaults to None.
|
| 43 |
+
|
| 44 |
+
Raises:
|
| 45 |
+
NoEmoji: If the emoji doesn't exist.
|
| 46 |
+
"""
|
| 47 |
+
self.name = name
|
| 48 |
+
self.style = style
|
| 49 |
+
self.variant = variant
|
| 50 |
+
try:
|
| 51 |
+
self._char = EMOJI[name]
|
| 52 |
+
except KeyError:
|
| 53 |
+
raise NoEmoji(f"No emoji called {name!r}")
|
| 54 |
+
if variant is not None:
|
| 55 |
+
self._char += self.VARIANTS.get(variant, "")
|
| 56 |
+
|
| 57 |
+
@classmethod
|
| 58 |
+
def replace(cls, text: str) -> str:
|
| 59 |
+
"""Replace emoji markup with corresponding unicode characters.
|
| 60 |
+
|
| 61 |
+
Args:
|
| 62 |
+
text (str): A string with emojis codes, e.g. "Hello :smiley:!"
|
| 63 |
+
|
| 64 |
+
Returns:
|
| 65 |
+
str: A string with emoji codes replaces with actual emoji.
|
| 66 |
+
"""
|
| 67 |
+
return _emoji_replace(text)
|
| 68 |
+
|
| 69 |
+
def __repr__(self) -> str:
|
| 70 |
+
return f"<emoji {self.name!r}>"
|
| 71 |
+
|
| 72 |
+
def __str__(self) -> str:
|
| 73 |
+
return self._char
|
| 74 |
+
|
| 75 |
+
def __rich_console__(
|
| 76 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 77 |
+
) -> "RenderResult":
|
| 78 |
+
yield Segment(self._char, console.get_style(self.style))
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
if __name__ == "__main__": # pragma: no cover
|
| 82 |
+
import sys
|
| 83 |
+
|
| 84 |
+
from pip._vendor.rich.columns import Columns
|
| 85 |
+
from pip._vendor.rich.console import Console
|
| 86 |
+
|
| 87 |
+
console = Console(record=True)
|
| 88 |
+
|
| 89 |
+
columns = Columns(
|
| 90 |
+
(f":{name}: {name}" for name in sorted(EMOJI.keys()) if "\u200D" not in name),
|
| 91 |
+
column_first=True,
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
console.print(columns)
|
| 95 |
+
if len(sys.argv) > 1:
|
| 96 |
+
console.save_html(sys.argv[1])
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/live_render.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
from typing import Optional, Tuple
|
| 3 |
+
|
| 4 |
+
if sys.version_info >= (3, 8):
|
| 5 |
+
from typing import Literal
|
| 6 |
+
else:
|
| 7 |
+
from pip._vendor.typing_extensions import Literal # pragma: no cover
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
from ._loop import loop_last
|
| 11 |
+
from .console import Console, ConsoleOptions, RenderableType, RenderResult
|
| 12 |
+
from .control import Control
|
| 13 |
+
from .segment import ControlType, Segment
|
| 14 |
+
from .style import StyleType
|
| 15 |
+
from .text import Text
|
| 16 |
+
|
| 17 |
+
VerticalOverflowMethod = Literal["crop", "ellipsis", "visible"]
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class LiveRender:
|
| 21 |
+
"""Creates a renderable that may be updated.
|
| 22 |
+
|
| 23 |
+
Args:
|
| 24 |
+
renderable (RenderableType): Any renderable object.
|
| 25 |
+
style (StyleType, optional): An optional style to apply to the renderable. Defaults to "".
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
def __init__(
|
| 29 |
+
self,
|
| 30 |
+
renderable: RenderableType,
|
| 31 |
+
style: StyleType = "",
|
| 32 |
+
vertical_overflow: VerticalOverflowMethod = "ellipsis",
|
| 33 |
+
) -> None:
|
| 34 |
+
self.renderable = renderable
|
| 35 |
+
self.style = style
|
| 36 |
+
self.vertical_overflow = vertical_overflow
|
| 37 |
+
self._shape: Optional[Tuple[int, int]] = None
|
| 38 |
+
|
| 39 |
+
def set_renderable(self, renderable: RenderableType) -> None:
|
| 40 |
+
"""Set a new renderable.
|
| 41 |
+
|
| 42 |
+
Args:
|
| 43 |
+
renderable (RenderableType): Any renderable object, including str.
|
| 44 |
+
"""
|
| 45 |
+
self.renderable = renderable
|
| 46 |
+
|
| 47 |
+
def position_cursor(self) -> Control:
|
| 48 |
+
"""Get control codes to move cursor to beginning of live render.
|
| 49 |
+
|
| 50 |
+
Returns:
|
| 51 |
+
Control: A control instance that may be printed.
|
| 52 |
+
"""
|
| 53 |
+
if self._shape is not None:
|
| 54 |
+
_, height = self._shape
|
| 55 |
+
return Control(
|
| 56 |
+
ControlType.CARRIAGE_RETURN,
|
| 57 |
+
(ControlType.ERASE_IN_LINE, 2),
|
| 58 |
+
*(
|
| 59 |
+
(
|
| 60 |
+
(ControlType.CURSOR_UP, 1),
|
| 61 |
+
(ControlType.ERASE_IN_LINE, 2),
|
| 62 |
+
)
|
| 63 |
+
* (height - 1)
|
| 64 |
+
)
|
| 65 |
+
)
|
| 66 |
+
return Control()
|
| 67 |
+
|
| 68 |
+
def restore_cursor(self) -> Control:
|
| 69 |
+
"""Get control codes to clear the render and restore the cursor to its previous position.
|
| 70 |
+
|
| 71 |
+
Returns:
|
| 72 |
+
Control: A Control instance that may be printed.
|
| 73 |
+
"""
|
| 74 |
+
if self._shape is not None:
|
| 75 |
+
_, height = self._shape
|
| 76 |
+
return Control(
|
| 77 |
+
ControlType.CARRIAGE_RETURN,
|
| 78 |
+
*((ControlType.CURSOR_UP, 1), (ControlType.ERASE_IN_LINE, 2)) * height
|
| 79 |
+
)
|
| 80 |
+
return Control()
|
| 81 |
+
|
| 82 |
+
def __rich_console__(
|
| 83 |
+
self, console: Console, options: ConsoleOptions
|
| 84 |
+
) -> RenderResult:
|
| 85 |
+
renderable = self.renderable
|
| 86 |
+
style = console.get_style(self.style)
|
| 87 |
+
lines = console.render_lines(renderable, options, style=style, pad=False)
|
| 88 |
+
shape = Segment.get_shape(lines)
|
| 89 |
+
|
| 90 |
+
_, height = shape
|
| 91 |
+
if height > options.size.height:
|
| 92 |
+
if self.vertical_overflow == "crop":
|
| 93 |
+
lines = lines[: options.size.height]
|
| 94 |
+
shape = Segment.get_shape(lines)
|
| 95 |
+
elif self.vertical_overflow == "ellipsis":
|
| 96 |
+
lines = lines[: (options.size.height - 1)]
|
| 97 |
+
overflow_text = Text(
|
| 98 |
+
"...",
|
| 99 |
+
overflow="crop",
|
| 100 |
+
justify="center",
|
| 101 |
+
end="",
|
| 102 |
+
style="live.ellipsis",
|
| 103 |
+
)
|
| 104 |
+
lines.append(list(console.render(overflow_text)))
|
| 105 |
+
shape = Segment.get_shape(lines)
|
| 106 |
+
self._shape = shape
|
| 107 |
+
|
| 108 |
+
new_line = Segment.line()
|
| 109 |
+
for last, line in loop_last(lines):
|
| 110 |
+
yield from line
|
| 111 |
+
if not last:
|
| 112 |
+
yield new_line
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/measure.py
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from operator import itemgetter
|
| 2 |
+
from typing import TYPE_CHECKING, Callable, NamedTuple, Optional, Sequence
|
| 3 |
+
|
| 4 |
+
from . import errors
|
| 5 |
+
from .protocol import is_renderable, rich_cast
|
| 6 |
+
|
| 7 |
+
if TYPE_CHECKING:
|
| 8 |
+
from .console import Console, ConsoleOptions, RenderableType
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class Measurement(NamedTuple):
|
| 12 |
+
"""Stores the minimum and maximum widths (in characters) required to render an object."""
|
| 13 |
+
|
| 14 |
+
minimum: int
|
| 15 |
+
"""Minimum number of cells required to render."""
|
| 16 |
+
maximum: int
|
| 17 |
+
"""Maximum number of cells required to render."""
|
| 18 |
+
|
| 19 |
+
@property
|
| 20 |
+
def span(self) -> int:
|
| 21 |
+
"""Get difference between maximum and minimum."""
|
| 22 |
+
return self.maximum - self.minimum
|
| 23 |
+
|
| 24 |
+
def normalize(self) -> "Measurement":
|
| 25 |
+
"""Get measurement that ensures that minimum <= maximum and minimum >= 0
|
| 26 |
+
|
| 27 |
+
Returns:
|
| 28 |
+
Measurement: A normalized measurement.
|
| 29 |
+
"""
|
| 30 |
+
minimum, maximum = self
|
| 31 |
+
minimum = min(max(0, minimum), maximum)
|
| 32 |
+
return Measurement(max(0, minimum), max(0, max(minimum, maximum)))
|
| 33 |
+
|
| 34 |
+
def with_maximum(self, width: int) -> "Measurement":
|
| 35 |
+
"""Get a RenderableWith where the widths are <= width.
|
| 36 |
+
|
| 37 |
+
Args:
|
| 38 |
+
width (int): Maximum desired width.
|
| 39 |
+
|
| 40 |
+
Returns:
|
| 41 |
+
Measurement: New Measurement object.
|
| 42 |
+
"""
|
| 43 |
+
minimum, maximum = self
|
| 44 |
+
return Measurement(min(minimum, width), min(maximum, width))
|
| 45 |
+
|
| 46 |
+
def with_minimum(self, width: int) -> "Measurement":
|
| 47 |
+
"""Get a RenderableWith where the widths are >= width.
|
| 48 |
+
|
| 49 |
+
Args:
|
| 50 |
+
width (int): Minimum desired width.
|
| 51 |
+
|
| 52 |
+
Returns:
|
| 53 |
+
Measurement: New Measurement object.
|
| 54 |
+
"""
|
| 55 |
+
minimum, maximum = self
|
| 56 |
+
width = max(0, width)
|
| 57 |
+
return Measurement(max(minimum, width), max(maximum, width))
|
| 58 |
+
|
| 59 |
+
def clamp(
|
| 60 |
+
self, min_width: Optional[int] = None, max_width: Optional[int] = None
|
| 61 |
+
) -> "Measurement":
|
| 62 |
+
"""Clamp a measurement within the specified range.
|
| 63 |
+
|
| 64 |
+
Args:
|
| 65 |
+
min_width (int): Minimum desired width, or ``None`` for no minimum. Defaults to None.
|
| 66 |
+
max_width (int): Maximum desired width, or ``None`` for no maximum. Defaults to None.
|
| 67 |
+
|
| 68 |
+
Returns:
|
| 69 |
+
Measurement: New Measurement object.
|
| 70 |
+
"""
|
| 71 |
+
measurement = self
|
| 72 |
+
if min_width is not None:
|
| 73 |
+
measurement = measurement.with_minimum(min_width)
|
| 74 |
+
if max_width is not None:
|
| 75 |
+
measurement = measurement.with_maximum(max_width)
|
| 76 |
+
return measurement
|
| 77 |
+
|
| 78 |
+
@classmethod
|
| 79 |
+
def get(
|
| 80 |
+
cls, console: "Console", options: "ConsoleOptions", renderable: "RenderableType"
|
| 81 |
+
) -> "Measurement":
|
| 82 |
+
"""Get a measurement for a renderable.
|
| 83 |
+
|
| 84 |
+
Args:
|
| 85 |
+
console (~rich.console.Console): Console instance.
|
| 86 |
+
options (~rich.console.ConsoleOptions): Console options.
|
| 87 |
+
renderable (RenderableType): An object that may be rendered with Rich.
|
| 88 |
+
|
| 89 |
+
Raises:
|
| 90 |
+
errors.NotRenderableError: If the object is not renderable.
|
| 91 |
+
|
| 92 |
+
Returns:
|
| 93 |
+
Measurement: Measurement object containing range of character widths required to render the object.
|
| 94 |
+
"""
|
| 95 |
+
_max_width = options.max_width
|
| 96 |
+
if _max_width < 1:
|
| 97 |
+
return Measurement(0, 0)
|
| 98 |
+
if isinstance(renderable, str):
|
| 99 |
+
renderable = console.render_str(
|
| 100 |
+
renderable, markup=options.markup, highlight=False
|
| 101 |
+
)
|
| 102 |
+
renderable = rich_cast(renderable)
|
| 103 |
+
if is_renderable(renderable):
|
| 104 |
+
get_console_width: Optional[
|
| 105 |
+
Callable[["Console", "ConsoleOptions"], "Measurement"]
|
| 106 |
+
] = getattr(renderable, "__rich_measure__", None)
|
| 107 |
+
if get_console_width is not None:
|
| 108 |
+
render_width = (
|
| 109 |
+
get_console_width(console, options)
|
| 110 |
+
.normalize()
|
| 111 |
+
.with_maximum(_max_width)
|
| 112 |
+
)
|
| 113 |
+
if render_width.maximum < 1:
|
| 114 |
+
return Measurement(0, 0)
|
| 115 |
+
return render_width.normalize()
|
| 116 |
+
else:
|
| 117 |
+
return Measurement(0, _max_width)
|
| 118 |
+
else:
|
| 119 |
+
raise errors.NotRenderableError(
|
| 120 |
+
f"Unable to get render width for {renderable!r}; "
|
| 121 |
+
"a str, Segment, or object with __rich_console__ method is required"
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def measure_renderables(
|
| 126 |
+
console: "Console",
|
| 127 |
+
options: "ConsoleOptions",
|
| 128 |
+
renderables: Sequence["RenderableType"],
|
| 129 |
+
) -> "Measurement":
|
| 130 |
+
"""Get a measurement that would fit a number of renderables.
|
| 131 |
+
|
| 132 |
+
Args:
|
| 133 |
+
console (~rich.console.Console): Console instance.
|
| 134 |
+
options (~rich.console.ConsoleOptions): Console options.
|
| 135 |
+
renderables (Iterable[RenderableType]): One or more renderable objects.
|
| 136 |
+
|
| 137 |
+
Returns:
|
| 138 |
+
Measurement: Measurement object containing range of character widths required to
|
| 139 |
+
contain all given renderables.
|
| 140 |
+
"""
|
| 141 |
+
if not renderables:
|
| 142 |
+
return Measurement(0, 0)
|
| 143 |
+
get_measurement = Measurement.get
|
| 144 |
+
measurements = [
|
| 145 |
+
get_measurement(console, options, renderable) for renderable in renderables
|
| 146 |
+
]
|
| 147 |
+
measured_width = Measurement(
|
| 148 |
+
max(measurements, key=itemgetter(0)).minimum,
|
| 149 |
+
max(measurements, key=itemgetter(1)).maximum,
|
| 150 |
+
)
|
| 151 |
+
return measured_width
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/padding.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import cast, List, Optional, Tuple, TYPE_CHECKING, Union
|
| 2 |
+
|
| 3 |
+
if TYPE_CHECKING:
|
| 4 |
+
from .console import (
|
| 5 |
+
Console,
|
| 6 |
+
ConsoleOptions,
|
| 7 |
+
RenderableType,
|
| 8 |
+
RenderResult,
|
| 9 |
+
)
|
| 10 |
+
from .jupyter import JupyterMixin
|
| 11 |
+
from .measure import Measurement
|
| 12 |
+
from .style import Style
|
| 13 |
+
from .segment import Segment
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
PaddingDimensions = Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int, int]]
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class Padding(JupyterMixin):
|
| 20 |
+
"""Draw space around content.
|
| 21 |
+
|
| 22 |
+
Example:
|
| 23 |
+
>>> print(Padding("Hello", (2, 4), style="on blue"))
|
| 24 |
+
|
| 25 |
+
Args:
|
| 26 |
+
renderable (RenderableType): String or other renderable.
|
| 27 |
+
pad (Union[int, Tuple[int]]): Padding for top, right, bottom, and left borders.
|
| 28 |
+
May be specified with 1, 2, or 4 integers (CSS style).
|
| 29 |
+
style (Union[str, Style], optional): Style for padding characters. Defaults to "none".
|
| 30 |
+
expand (bool, optional): Expand padding to fit available width. Defaults to True.
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
def __init__(
|
| 34 |
+
self,
|
| 35 |
+
renderable: "RenderableType",
|
| 36 |
+
pad: "PaddingDimensions" = (0, 0, 0, 0),
|
| 37 |
+
*,
|
| 38 |
+
style: Union[str, Style] = "none",
|
| 39 |
+
expand: bool = True,
|
| 40 |
+
):
|
| 41 |
+
self.renderable = renderable
|
| 42 |
+
self.top, self.right, self.bottom, self.left = self.unpack(pad)
|
| 43 |
+
self.style = style
|
| 44 |
+
self.expand = expand
|
| 45 |
+
|
| 46 |
+
@classmethod
|
| 47 |
+
def indent(cls, renderable: "RenderableType", level: int) -> "Padding":
|
| 48 |
+
"""Make padding instance to render an indent.
|
| 49 |
+
|
| 50 |
+
Args:
|
| 51 |
+
renderable (RenderableType): String or other renderable.
|
| 52 |
+
level (int): Number of characters to indent.
|
| 53 |
+
|
| 54 |
+
Returns:
|
| 55 |
+
Padding: A Padding instance.
|
| 56 |
+
"""
|
| 57 |
+
|
| 58 |
+
return Padding(renderable, pad=(0, 0, 0, level), expand=False)
|
| 59 |
+
|
| 60 |
+
@staticmethod
|
| 61 |
+
def unpack(pad: "PaddingDimensions") -> Tuple[int, int, int, int]:
|
| 62 |
+
"""Unpack padding specified in CSS style."""
|
| 63 |
+
if isinstance(pad, int):
|
| 64 |
+
return (pad, pad, pad, pad)
|
| 65 |
+
if len(pad) == 1:
|
| 66 |
+
_pad = pad[0]
|
| 67 |
+
return (_pad, _pad, _pad, _pad)
|
| 68 |
+
if len(pad) == 2:
|
| 69 |
+
pad_top, pad_right = cast(Tuple[int, int], pad)
|
| 70 |
+
return (pad_top, pad_right, pad_top, pad_right)
|
| 71 |
+
if len(pad) == 4:
|
| 72 |
+
top, right, bottom, left = cast(Tuple[int, int, int, int], pad)
|
| 73 |
+
return (top, right, bottom, left)
|
| 74 |
+
raise ValueError(f"1, 2 or 4 integers required for padding; {len(pad)} given")
|
| 75 |
+
|
| 76 |
+
def __repr__(self) -> str:
|
| 77 |
+
return f"Padding({self.renderable!r}, ({self.top},{self.right},{self.bottom},{self.left}))"
|
| 78 |
+
|
| 79 |
+
def __rich_console__(
|
| 80 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 81 |
+
) -> "RenderResult":
|
| 82 |
+
style = console.get_style(self.style)
|
| 83 |
+
if self.expand:
|
| 84 |
+
width = options.max_width
|
| 85 |
+
else:
|
| 86 |
+
width = min(
|
| 87 |
+
Measurement.get(console, options, self.renderable).maximum
|
| 88 |
+
+ self.left
|
| 89 |
+
+ self.right,
|
| 90 |
+
options.max_width,
|
| 91 |
+
)
|
| 92 |
+
render_options = options.update_width(width - self.left - self.right)
|
| 93 |
+
if render_options.height is not None:
|
| 94 |
+
render_options = render_options.update_height(
|
| 95 |
+
height=render_options.height - self.top - self.bottom
|
| 96 |
+
)
|
| 97 |
+
lines = console.render_lines(
|
| 98 |
+
self.renderable, render_options, style=style, pad=True
|
| 99 |
+
)
|
| 100 |
+
_Segment = Segment
|
| 101 |
+
|
| 102 |
+
left = _Segment(" " * self.left, style) if self.left else None
|
| 103 |
+
right = (
|
| 104 |
+
[_Segment(f'{" " * self.right}', style), _Segment.line()]
|
| 105 |
+
if self.right
|
| 106 |
+
else [_Segment.line()]
|
| 107 |
+
)
|
| 108 |
+
blank_line: Optional[List[Segment]] = None
|
| 109 |
+
if self.top:
|
| 110 |
+
blank_line = [_Segment(f'{" " * width}\n', style)]
|
| 111 |
+
yield from blank_line * self.top
|
| 112 |
+
if left:
|
| 113 |
+
for line in lines:
|
| 114 |
+
yield left
|
| 115 |
+
yield from line
|
| 116 |
+
yield from right
|
| 117 |
+
else:
|
| 118 |
+
for line in lines:
|
| 119 |
+
yield from line
|
| 120 |
+
yield from right
|
| 121 |
+
if self.bottom:
|
| 122 |
+
blank_line = blank_line or [_Segment(f'{" " * width}\n', style)]
|
| 123 |
+
yield from blank_line * self.bottom
|
| 124 |
+
|
| 125 |
+
def __rich_measure__(
|
| 126 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 127 |
+
) -> "Measurement":
|
| 128 |
+
max_width = options.max_width
|
| 129 |
+
extra_width = self.left + self.right
|
| 130 |
+
if max_width - extra_width < 1:
|
| 131 |
+
return Measurement(max_width, max_width)
|
| 132 |
+
measure_min, measure_max = Measurement.get(console, options, self.renderable)
|
| 133 |
+
measurement = Measurement(measure_min + extra_width, measure_max + extra_width)
|
| 134 |
+
measurement = measurement.with_maximum(max_width)
|
| 135 |
+
return measurement
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
if __name__ == "__main__": # pragma: no cover
|
| 139 |
+
from pip._vendor.rich import print
|
| 140 |
+
|
| 141 |
+
print(Padding("Hello, World", (2, 4), style="on blue"))
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/pager.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from abc import ABC, abstractmethod
|
| 2 |
+
from typing import Any
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class Pager(ABC):
|
| 6 |
+
"""Base class for a pager."""
|
| 7 |
+
|
| 8 |
+
@abstractmethod
|
| 9 |
+
def show(self, content: str) -> None:
|
| 10 |
+
"""Show content in pager.
|
| 11 |
+
|
| 12 |
+
Args:
|
| 13 |
+
content (str): Content to be displayed.
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class SystemPager(Pager):
|
| 18 |
+
"""Uses the pager installed on the system."""
|
| 19 |
+
|
| 20 |
+
def _pager(self, content: str) -> Any: # pragma: no cover
|
| 21 |
+
return __import__("pydoc").pager(content)
|
| 22 |
+
|
| 23 |
+
def show(self, content: str) -> None:
|
| 24 |
+
"""Use the same pager used by pydoc."""
|
| 25 |
+
self._pager(content)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
if __name__ == "__main__": # pragma: no cover
|
| 29 |
+
from .__main__ import make_test_card
|
| 30 |
+
from .console import Console
|
| 31 |
+
|
| 32 |
+
console = Console()
|
| 33 |
+
with console.pager(styles=True):
|
| 34 |
+
console.print(make_test_card())
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/pretty.py
ADDED
|
@@ -0,0 +1,995 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import builtins
|
| 2 |
+
import collections
|
| 3 |
+
import dataclasses
|
| 4 |
+
import inspect
|
| 5 |
+
import os
|
| 6 |
+
import sys
|
| 7 |
+
from array import array
|
| 8 |
+
from collections import Counter, UserDict, UserList, defaultdict, deque
|
| 9 |
+
from dataclasses import dataclass, fields, is_dataclass
|
| 10 |
+
from inspect import isclass
|
| 11 |
+
from itertools import islice
|
| 12 |
+
from types import MappingProxyType
|
| 13 |
+
from typing import (
|
| 14 |
+
TYPE_CHECKING,
|
| 15 |
+
Any,
|
| 16 |
+
Callable,
|
| 17 |
+
DefaultDict,
|
| 18 |
+
Dict,
|
| 19 |
+
Iterable,
|
| 20 |
+
List,
|
| 21 |
+
Optional,
|
| 22 |
+
Sequence,
|
| 23 |
+
Set,
|
| 24 |
+
Tuple,
|
| 25 |
+
Union,
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
from pip._vendor.rich.repr import RichReprResult
|
| 29 |
+
|
| 30 |
+
try:
|
| 31 |
+
import attr as _attr_module
|
| 32 |
+
|
| 33 |
+
_has_attrs = hasattr(_attr_module, "ib")
|
| 34 |
+
except ImportError: # pragma: no cover
|
| 35 |
+
_has_attrs = False
|
| 36 |
+
|
| 37 |
+
from . import get_console
|
| 38 |
+
from ._loop import loop_last
|
| 39 |
+
from ._pick import pick_bool
|
| 40 |
+
from .abc import RichRenderable
|
| 41 |
+
from .cells import cell_len
|
| 42 |
+
from .highlighter import ReprHighlighter
|
| 43 |
+
from .jupyter import JupyterMixin, JupyterRenderable
|
| 44 |
+
from .measure import Measurement
|
| 45 |
+
from .text import Text
|
| 46 |
+
|
| 47 |
+
if TYPE_CHECKING:
|
| 48 |
+
from .console import (
|
| 49 |
+
Console,
|
| 50 |
+
ConsoleOptions,
|
| 51 |
+
HighlighterType,
|
| 52 |
+
JustifyMethod,
|
| 53 |
+
OverflowMethod,
|
| 54 |
+
RenderResult,
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def _is_attr_object(obj: Any) -> bool:
|
| 59 |
+
"""Check if an object was created with attrs module."""
|
| 60 |
+
return _has_attrs and _attr_module.has(type(obj))
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def _get_attr_fields(obj: Any) -> Sequence["_attr_module.Attribute[Any]"]:
|
| 64 |
+
"""Get fields for an attrs object."""
|
| 65 |
+
return _attr_module.fields(type(obj)) if _has_attrs else []
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def _is_dataclass_repr(obj: object) -> bool:
|
| 69 |
+
"""Check if an instance of a dataclass contains the default repr.
|
| 70 |
+
|
| 71 |
+
Args:
|
| 72 |
+
obj (object): A dataclass instance.
|
| 73 |
+
|
| 74 |
+
Returns:
|
| 75 |
+
bool: True if the default repr is used, False if there is a custom repr.
|
| 76 |
+
"""
|
| 77 |
+
# Digging in to a lot of internals here
|
| 78 |
+
# Catching all exceptions in case something is missing on a non CPython implementation
|
| 79 |
+
try:
|
| 80 |
+
return obj.__repr__.__code__.co_filename == dataclasses.__file__
|
| 81 |
+
except Exception: # pragma: no coverage
|
| 82 |
+
return False
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
_dummy_namedtuple = collections.namedtuple("_dummy_namedtuple", [])
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def _has_default_namedtuple_repr(obj: object) -> bool:
|
| 89 |
+
"""Check if an instance of namedtuple contains the default repr
|
| 90 |
+
|
| 91 |
+
Args:
|
| 92 |
+
obj (object): A namedtuple
|
| 93 |
+
|
| 94 |
+
Returns:
|
| 95 |
+
bool: True if the default repr is used, False if there's a custom repr.
|
| 96 |
+
"""
|
| 97 |
+
obj_file = None
|
| 98 |
+
try:
|
| 99 |
+
obj_file = inspect.getfile(obj.__repr__)
|
| 100 |
+
except (OSError, TypeError):
|
| 101 |
+
# OSError handles case where object is defined in __main__ scope, e.g. REPL - no filename available.
|
| 102 |
+
# TypeError trapped defensively, in case of object without filename slips through.
|
| 103 |
+
pass
|
| 104 |
+
default_repr_file = inspect.getfile(_dummy_namedtuple.__repr__)
|
| 105 |
+
return obj_file == default_repr_file
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def _ipy_display_hook(
|
| 109 |
+
value: Any,
|
| 110 |
+
console: Optional["Console"] = None,
|
| 111 |
+
overflow: "OverflowMethod" = "ignore",
|
| 112 |
+
crop: bool = False,
|
| 113 |
+
indent_guides: bool = False,
|
| 114 |
+
max_length: Optional[int] = None,
|
| 115 |
+
max_string: Optional[int] = None,
|
| 116 |
+
max_depth: Optional[int] = None,
|
| 117 |
+
expand_all: bool = False,
|
| 118 |
+
) -> Union[str, None]:
|
| 119 |
+
# needed here to prevent circular import:
|
| 120 |
+
from .console import ConsoleRenderable
|
| 121 |
+
|
| 122 |
+
# always skip rich generated jupyter renderables or None values
|
| 123 |
+
if _safe_isinstance(value, JupyterRenderable) or value is None:
|
| 124 |
+
return None
|
| 125 |
+
|
| 126 |
+
console = console or get_console()
|
| 127 |
+
|
| 128 |
+
with console.capture() as capture:
|
| 129 |
+
# certain renderables should start on a new line
|
| 130 |
+
if _safe_isinstance(value, ConsoleRenderable):
|
| 131 |
+
console.line()
|
| 132 |
+
console.print(
|
| 133 |
+
value
|
| 134 |
+
if _safe_isinstance(value, RichRenderable)
|
| 135 |
+
else Pretty(
|
| 136 |
+
value,
|
| 137 |
+
overflow=overflow,
|
| 138 |
+
indent_guides=indent_guides,
|
| 139 |
+
max_length=max_length,
|
| 140 |
+
max_string=max_string,
|
| 141 |
+
max_depth=max_depth,
|
| 142 |
+
expand_all=expand_all,
|
| 143 |
+
margin=12,
|
| 144 |
+
),
|
| 145 |
+
crop=crop,
|
| 146 |
+
new_line_start=True,
|
| 147 |
+
end="",
|
| 148 |
+
)
|
| 149 |
+
# strip trailing newline, not usually part of a text repr
|
| 150 |
+
# I'm not sure if this should be prevented at a lower level
|
| 151 |
+
return capture.get().rstrip("\n")
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def _safe_isinstance(
|
| 155 |
+
obj: object, class_or_tuple: Union[type, Tuple[type, ...]]
|
| 156 |
+
) -> bool:
|
| 157 |
+
"""isinstance can fail in rare cases, for example types with no __class__"""
|
| 158 |
+
try:
|
| 159 |
+
return isinstance(obj, class_or_tuple)
|
| 160 |
+
except Exception:
|
| 161 |
+
return False
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
def install(
|
| 165 |
+
console: Optional["Console"] = None,
|
| 166 |
+
overflow: "OverflowMethod" = "ignore",
|
| 167 |
+
crop: bool = False,
|
| 168 |
+
indent_guides: bool = False,
|
| 169 |
+
max_length: Optional[int] = None,
|
| 170 |
+
max_string: Optional[int] = None,
|
| 171 |
+
max_depth: Optional[int] = None,
|
| 172 |
+
expand_all: bool = False,
|
| 173 |
+
) -> None:
|
| 174 |
+
"""Install automatic pretty printing in the Python REPL.
|
| 175 |
+
|
| 176 |
+
Args:
|
| 177 |
+
console (Console, optional): Console instance or ``None`` to use global console. Defaults to None.
|
| 178 |
+
overflow (Optional[OverflowMethod], optional): Overflow method. Defaults to "ignore".
|
| 179 |
+
crop (Optional[bool], optional): Enable cropping of long lines. Defaults to False.
|
| 180 |
+
indent_guides (bool, optional): Enable indentation guides. Defaults to False.
|
| 181 |
+
max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
|
| 182 |
+
Defaults to None.
|
| 183 |
+
max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to None.
|
| 184 |
+
max_depth (int, optional): Maximum depth of nested data structures, or None for no maximum. Defaults to None.
|
| 185 |
+
expand_all (bool, optional): Expand all containers. Defaults to False.
|
| 186 |
+
max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100.
|
| 187 |
+
"""
|
| 188 |
+
from pip._vendor.rich import get_console
|
| 189 |
+
|
| 190 |
+
console = console or get_console()
|
| 191 |
+
assert console is not None
|
| 192 |
+
|
| 193 |
+
def display_hook(value: Any) -> None:
|
| 194 |
+
"""Replacement sys.displayhook which prettifies objects with Rich."""
|
| 195 |
+
if value is not None:
|
| 196 |
+
assert console is not None
|
| 197 |
+
builtins._ = None # type: ignore[attr-defined]
|
| 198 |
+
console.print(
|
| 199 |
+
value
|
| 200 |
+
if _safe_isinstance(value, RichRenderable)
|
| 201 |
+
else Pretty(
|
| 202 |
+
value,
|
| 203 |
+
overflow=overflow,
|
| 204 |
+
indent_guides=indent_guides,
|
| 205 |
+
max_length=max_length,
|
| 206 |
+
max_string=max_string,
|
| 207 |
+
max_depth=max_depth,
|
| 208 |
+
expand_all=expand_all,
|
| 209 |
+
),
|
| 210 |
+
crop=crop,
|
| 211 |
+
)
|
| 212 |
+
builtins._ = value # type: ignore[attr-defined]
|
| 213 |
+
|
| 214 |
+
try:
|
| 215 |
+
ip = get_ipython() # type: ignore[name-defined]
|
| 216 |
+
except NameError:
|
| 217 |
+
sys.displayhook = display_hook
|
| 218 |
+
else:
|
| 219 |
+
from IPython.core.formatters import BaseFormatter
|
| 220 |
+
|
| 221 |
+
class RichFormatter(BaseFormatter): # type: ignore[misc]
|
| 222 |
+
pprint: bool = True
|
| 223 |
+
|
| 224 |
+
def __call__(self, value: Any) -> Any:
|
| 225 |
+
if self.pprint:
|
| 226 |
+
return _ipy_display_hook(
|
| 227 |
+
value,
|
| 228 |
+
console=get_console(),
|
| 229 |
+
overflow=overflow,
|
| 230 |
+
indent_guides=indent_guides,
|
| 231 |
+
max_length=max_length,
|
| 232 |
+
max_string=max_string,
|
| 233 |
+
max_depth=max_depth,
|
| 234 |
+
expand_all=expand_all,
|
| 235 |
+
)
|
| 236 |
+
else:
|
| 237 |
+
return repr(value)
|
| 238 |
+
|
| 239 |
+
# replace plain text formatter with rich formatter
|
| 240 |
+
rich_formatter = RichFormatter()
|
| 241 |
+
ip.display_formatter.formatters["text/plain"] = rich_formatter
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
class Pretty(JupyterMixin):
|
| 245 |
+
"""A rich renderable that pretty prints an object.
|
| 246 |
+
|
| 247 |
+
Args:
|
| 248 |
+
_object (Any): An object to pretty print.
|
| 249 |
+
highlighter (HighlighterType, optional): Highlighter object to apply to result, or None for ReprHighlighter. Defaults to None.
|
| 250 |
+
indent_size (int, optional): Number of spaces in indent. Defaults to 4.
|
| 251 |
+
justify (JustifyMethod, optional): Justify method, or None for default. Defaults to None.
|
| 252 |
+
overflow (OverflowMethod, optional): Overflow method, or None for default. Defaults to None.
|
| 253 |
+
no_wrap (Optional[bool], optional): Disable word wrapping. Defaults to False.
|
| 254 |
+
indent_guides (bool, optional): Enable indentation guides. Defaults to False.
|
| 255 |
+
max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
|
| 256 |
+
Defaults to None.
|
| 257 |
+
max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to None.
|
| 258 |
+
max_depth (int, optional): Maximum depth of nested data structures, or None for no maximum. Defaults to None.
|
| 259 |
+
expand_all (bool, optional): Expand all containers. Defaults to False.
|
| 260 |
+
margin (int, optional): Subtrace a margin from width to force containers to expand earlier. Defaults to 0.
|
| 261 |
+
insert_line (bool, optional): Insert a new line if the output has multiple new lines. Defaults to False.
|
| 262 |
+
"""
|
| 263 |
+
|
| 264 |
+
def __init__(
|
| 265 |
+
self,
|
| 266 |
+
_object: Any,
|
| 267 |
+
highlighter: Optional["HighlighterType"] = None,
|
| 268 |
+
*,
|
| 269 |
+
indent_size: int = 4,
|
| 270 |
+
justify: Optional["JustifyMethod"] = None,
|
| 271 |
+
overflow: Optional["OverflowMethod"] = None,
|
| 272 |
+
no_wrap: Optional[bool] = False,
|
| 273 |
+
indent_guides: bool = False,
|
| 274 |
+
max_length: Optional[int] = None,
|
| 275 |
+
max_string: Optional[int] = None,
|
| 276 |
+
max_depth: Optional[int] = None,
|
| 277 |
+
expand_all: bool = False,
|
| 278 |
+
margin: int = 0,
|
| 279 |
+
insert_line: bool = False,
|
| 280 |
+
) -> None:
|
| 281 |
+
self._object = _object
|
| 282 |
+
self.highlighter = highlighter or ReprHighlighter()
|
| 283 |
+
self.indent_size = indent_size
|
| 284 |
+
self.justify: Optional["JustifyMethod"] = justify
|
| 285 |
+
self.overflow: Optional["OverflowMethod"] = overflow
|
| 286 |
+
self.no_wrap = no_wrap
|
| 287 |
+
self.indent_guides = indent_guides
|
| 288 |
+
self.max_length = max_length
|
| 289 |
+
self.max_string = max_string
|
| 290 |
+
self.max_depth = max_depth
|
| 291 |
+
self.expand_all = expand_all
|
| 292 |
+
self.margin = margin
|
| 293 |
+
self.insert_line = insert_line
|
| 294 |
+
|
| 295 |
+
def __rich_console__(
|
| 296 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 297 |
+
) -> "RenderResult":
|
| 298 |
+
pretty_str = pretty_repr(
|
| 299 |
+
self._object,
|
| 300 |
+
max_width=options.max_width - self.margin,
|
| 301 |
+
indent_size=self.indent_size,
|
| 302 |
+
max_length=self.max_length,
|
| 303 |
+
max_string=self.max_string,
|
| 304 |
+
max_depth=self.max_depth,
|
| 305 |
+
expand_all=self.expand_all,
|
| 306 |
+
)
|
| 307 |
+
pretty_text = Text.from_ansi(
|
| 308 |
+
pretty_str,
|
| 309 |
+
justify=self.justify or options.justify,
|
| 310 |
+
overflow=self.overflow or options.overflow,
|
| 311 |
+
no_wrap=pick_bool(self.no_wrap, options.no_wrap),
|
| 312 |
+
style="pretty",
|
| 313 |
+
)
|
| 314 |
+
pretty_text = (
|
| 315 |
+
self.highlighter(pretty_text)
|
| 316 |
+
if pretty_text
|
| 317 |
+
else Text(
|
| 318 |
+
f"{type(self._object)}.__repr__ returned empty string",
|
| 319 |
+
style="dim italic",
|
| 320 |
+
)
|
| 321 |
+
)
|
| 322 |
+
if self.indent_guides and not options.ascii_only:
|
| 323 |
+
pretty_text = pretty_text.with_indent_guides(
|
| 324 |
+
self.indent_size, style="repr.indent"
|
| 325 |
+
)
|
| 326 |
+
if self.insert_line and "\n" in pretty_text:
|
| 327 |
+
yield ""
|
| 328 |
+
yield pretty_text
|
| 329 |
+
|
| 330 |
+
def __rich_measure__(
|
| 331 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 332 |
+
) -> "Measurement":
|
| 333 |
+
pretty_str = pretty_repr(
|
| 334 |
+
self._object,
|
| 335 |
+
max_width=options.max_width,
|
| 336 |
+
indent_size=self.indent_size,
|
| 337 |
+
max_length=self.max_length,
|
| 338 |
+
max_string=self.max_string,
|
| 339 |
+
max_depth=self.max_depth,
|
| 340 |
+
expand_all=self.expand_all,
|
| 341 |
+
)
|
| 342 |
+
text_width = (
|
| 343 |
+
max(cell_len(line) for line in pretty_str.splitlines()) if pretty_str else 0
|
| 344 |
+
)
|
| 345 |
+
return Measurement(text_width, text_width)
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
def _get_braces_for_defaultdict(_object: DefaultDict[Any, Any]) -> Tuple[str, str, str]:
|
| 349 |
+
return (
|
| 350 |
+
f"defaultdict({_object.default_factory!r}, {{",
|
| 351 |
+
"})",
|
| 352 |
+
f"defaultdict({_object.default_factory!r}, {{}})",
|
| 353 |
+
)
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
def _get_braces_for_array(_object: "array[Any]") -> Tuple[str, str, str]:
|
| 357 |
+
return (f"array({_object.typecode!r}, [", "])", f"array({_object.typecode!r})")
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
_BRACES: Dict[type, Callable[[Any], Tuple[str, str, str]]] = {
|
| 361 |
+
os._Environ: lambda _object: ("environ({", "})", "environ({})"),
|
| 362 |
+
array: _get_braces_for_array,
|
| 363 |
+
defaultdict: _get_braces_for_defaultdict,
|
| 364 |
+
Counter: lambda _object: ("Counter({", "})", "Counter()"),
|
| 365 |
+
deque: lambda _object: ("deque([", "])", "deque()"),
|
| 366 |
+
dict: lambda _object: ("{", "}", "{}"),
|
| 367 |
+
UserDict: lambda _object: ("{", "}", "{}"),
|
| 368 |
+
frozenset: lambda _object: ("frozenset({", "})", "frozenset()"),
|
| 369 |
+
list: lambda _object: ("[", "]", "[]"),
|
| 370 |
+
UserList: lambda _object: ("[", "]", "[]"),
|
| 371 |
+
set: lambda _object: ("{", "}", "set()"),
|
| 372 |
+
tuple: lambda _object: ("(", ")", "()"),
|
| 373 |
+
MappingProxyType: lambda _object: ("mappingproxy({", "})", "mappingproxy({})"),
|
| 374 |
+
}
|
| 375 |
+
_CONTAINERS = tuple(_BRACES.keys())
|
| 376 |
+
_MAPPING_CONTAINERS = (dict, os._Environ, MappingProxyType, UserDict)
|
| 377 |
+
|
| 378 |
+
|
| 379 |
+
def is_expandable(obj: Any) -> bool:
|
| 380 |
+
"""Check if an object may be expanded by pretty print."""
|
| 381 |
+
return (
|
| 382 |
+
_safe_isinstance(obj, _CONTAINERS)
|
| 383 |
+
or (is_dataclass(obj))
|
| 384 |
+
or (hasattr(obj, "__rich_repr__"))
|
| 385 |
+
or _is_attr_object(obj)
|
| 386 |
+
) and not isclass(obj)
|
| 387 |
+
|
| 388 |
+
|
| 389 |
+
@dataclass
|
| 390 |
+
class Node:
|
| 391 |
+
"""A node in a repr tree. May be atomic or a container."""
|
| 392 |
+
|
| 393 |
+
key_repr: str = ""
|
| 394 |
+
value_repr: str = ""
|
| 395 |
+
open_brace: str = ""
|
| 396 |
+
close_brace: str = ""
|
| 397 |
+
empty: str = ""
|
| 398 |
+
last: bool = False
|
| 399 |
+
is_tuple: bool = False
|
| 400 |
+
is_namedtuple: bool = False
|
| 401 |
+
children: Optional[List["Node"]] = None
|
| 402 |
+
key_separator: str = ": "
|
| 403 |
+
separator: str = ", "
|
| 404 |
+
|
| 405 |
+
def iter_tokens(self) -> Iterable[str]:
|
| 406 |
+
"""Generate tokens for this node."""
|
| 407 |
+
if self.key_repr:
|
| 408 |
+
yield self.key_repr
|
| 409 |
+
yield self.key_separator
|
| 410 |
+
if self.value_repr:
|
| 411 |
+
yield self.value_repr
|
| 412 |
+
elif self.children is not None:
|
| 413 |
+
if self.children:
|
| 414 |
+
yield self.open_brace
|
| 415 |
+
if self.is_tuple and not self.is_namedtuple and len(self.children) == 1:
|
| 416 |
+
yield from self.children[0].iter_tokens()
|
| 417 |
+
yield ","
|
| 418 |
+
else:
|
| 419 |
+
for child in self.children:
|
| 420 |
+
yield from child.iter_tokens()
|
| 421 |
+
if not child.last:
|
| 422 |
+
yield self.separator
|
| 423 |
+
yield self.close_brace
|
| 424 |
+
else:
|
| 425 |
+
yield self.empty
|
| 426 |
+
|
| 427 |
+
def check_length(self, start_length: int, max_length: int) -> bool:
|
| 428 |
+
"""Check the length fits within a limit.
|
| 429 |
+
|
| 430 |
+
Args:
|
| 431 |
+
start_length (int): Starting length of the line (indent, prefix, suffix).
|
| 432 |
+
max_length (int): Maximum length.
|
| 433 |
+
|
| 434 |
+
Returns:
|
| 435 |
+
bool: True if the node can be rendered within max length, otherwise False.
|
| 436 |
+
"""
|
| 437 |
+
total_length = start_length
|
| 438 |
+
for token in self.iter_tokens():
|
| 439 |
+
total_length += cell_len(token)
|
| 440 |
+
if total_length > max_length:
|
| 441 |
+
return False
|
| 442 |
+
return True
|
| 443 |
+
|
| 444 |
+
def __str__(self) -> str:
|
| 445 |
+
repr_text = "".join(self.iter_tokens())
|
| 446 |
+
return repr_text
|
| 447 |
+
|
| 448 |
+
def render(
|
| 449 |
+
self, max_width: int = 80, indent_size: int = 4, expand_all: bool = False
|
| 450 |
+
) -> str:
|
| 451 |
+
"""Render the node to a pretty repr.
|
| 452 |
+
|
| 453 |
+
Args:
|
| 454 |
+
max_width (int, optional): Maximum width of the repr. Defaults to 80.
|
| 455 |
+
indent_size (int, optional): Size of indents. Defaults to 4.
|
| 456 |
+
expand_all (bool, optional): Expand all levels. Defaults to False.
|
| 457 |
+
|
| 458 |
+
Returns:
|
| 459 |
+
str: A repr string of the original object.
|
| 460 |
+
"""
|
| 461 |
+
lines = [_Line(node=self, is_root=True)]
|
| 462 |
+
line_no = 0
|
| 463 |
+
while line_no < len(lines):
|
| 464 |
+
line = lines[line_no]
|
| 465 |
+
if line.expandable and not line.expanded:
|
| 466 |
+
if expand_all or not line.check_length(max_width):
|
| 467 |
+
lines[line_no : line_no + 1] = line.expand(indent_size)
|
| 468 |
+
line_no += 1
|
| 469 |
+
|
| 470 |
+
repr_str = "\n".join(str(line) for line in lines)
|
| 471 |
+
return repr_str
|
| 472 |
+
|
| 473 |
+
|
| 474 |
+
@dataclass
|
| 475 |
+
class _Line:
|
| 476 |
+
"""A line in repr output."""
|
| 477 |
+
|
| 478 |
+
parent: Optional["_Line"] = None
|
| 479 |
+
is_root: bool = False
|
| 480 |
+
node: Optional[Node] = None
|
| 481 |
+
text: str = ""
|
| 482 |
+
suffix: str = ""
|
| 483 |
+
whitespace: str = ""
|
| 484 |
+
expanded: bool = False
|
| 485 |
+
last: bool = False
|
| 486 |
+
|
| 487 |
+
@property
|
| 488 |
+
def expandable(self) -> bool:
|
| 489 |
+
"""Check if the line may be expanded."""
|
| 490 |
+
return bool(self.node is not None and self.node.children)
|
| 491 |
+
|
| 492 |
+
def check_length(self, max_length: int) -> bool:
|
| 493 |
+
"""Check this line fits within a given number of cells."""
|
| 494 |
+
start_length = (
|
| 495 |
+
len(self.whitespace) + cell_len(self.text) + cell_len(self.suffix)
|
| 496 |
+
)
|
| 497 |
+
assert self.node is not None
|
| 498 |
+
return self.node.check_length(start_length, max_length)
|
| 499 |
+
|
| 500 |
+
def expand(self, indent_size: int) -> Iterable["_Line"]:
|
| 501 |
+
"""Expand this line by adding children on their own line."""
|
| 502 |
+
node = self.node
|
| 503 |
+
assert node is not None
|
| 504 |
+
whitespace = self.whitespace
|
| 505 |
+
assert node.children
|
| 506 |
+
if node.key_repr:
|
| 507 |
+
new_line = yield _Line(
|
| 508 |
+
text=f"{node.key_repr}{node.key_separator}{node.open_brace}",
|
| 509 |
+
whitespace=whitespace,
|
| 510 |
+
)
|
| 511 |
+
else:
|
| 512 |
+
new_line = yield _Line(text=node.open_brace, whitespace=whitespace)
|
| 513 |
+
child_whitespace = self.whitespace + " " * indent_size
|
| 514 |
+
tuple_of_one = node.is_tuple and len(node.children) == 1
|
| 515 |
+
for last, child in loop_last(node.children):
|
| 516 |
+
separator = "," if tuple_of_one else node.separator
|
| 517 |
+
line = _Line(
|
| 518 |
+
parent=new_line,
|
| 519 |
+
node=child,
|
| 520 |
+
whitespace=child_whitespace,
|
| 521 |
+
suffix=separator,
|
| 522 |
+
last=last and not tuple_of_one,
|
| 523 |
+
)
|
| 524 |
+
yield line
|
| 525 |
+
|
| 526 |
+
yield _Line(
|
| 527 |
+
text=node.close_brace,
|
| 528 |
+
whitespace=whitespace,
|
| 529 |
+
suffix=self.suffix,
|
| 530 |
+
last=self.last,
|
| 531 |
+
)
|
| 532 |
+
|
| 533 |
+
def __str__(self) -> str:
|
| 534 |
+
if self.last:
|
| 535 |
+
return f"{self.whitespace}{self.text}{self.node or ''}"
|
| 536 |
+
else:
|
| 537 |
+
return (
|
| 538 |
+
f"{self.whitespace}{self.text}{self.node or ''}{self.suffix.rstrip()}"
|
| 539 |
+
)
|
| 540 |
+
|
| 541 |
+
|
| 542 |
+
def _is_namedtuple(obj: Any) -> bool:
|
| 543 |
+
"""Checks if an object is most likely a namedtuple. It is possible
|
| 544 |
+
to craft an object that passes this check and isn't a namedtuple, but
|
| 545 |
+
there is only a minuscule chance of this happening unintentionally.
|
| 546 |
+
|
| 547 |
+
Args:
|
| 548 |
+
obj (Any): The object to test
|
| 549 |
+
|
| 550 |
+
Returns:
|
| 551 |
+
bool: True if the object is a namedtuple. False otherwise.
|
| 552 |
+
"""
|
| 553 |
+
try:
|
| 554 |
+
fields = getattr(obj, "_fields", None)
|
| 555 |
+
except Exception:
|
| 556 |
+
# Being very defensive - if we cannot get the attr then its not a namedtuple
|
| 557 |
+
return False
|
| 558 |
+
return isinstance(obj, tuple) and isinstance(fields, tuple)
|
| 559 |
+
|
| 560 |
+
|
| 561 |
+
def traverse(
|
| 562 |
+
_object: Any,
|
| 563 |
+
max_length: Optional[int] = None,
|
| 564 |
+
max_string: Optional[int] = None,
|
| 565 |
+
max_depth: Optional[int] = None,
|
| 566 |
+
) -> Node:
|
| 567 |
+
"""Traverse object and generate a tree.
|
| 568 |
+
|
| 569 |
+
Args:
|
| 570 |
+
_object (Any): Object to be traversed.
|
| 571 |
+
max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
|
| 572 |
+
Defaults to None.
|
| 573 |
+
max_string (int, optional): Maximum length of string before truncating, or None to disable truncating.
|
| 574 |
+
Defaults to None.
|
| 575 |
+
max_depth (int, optional): Maximum depth of data structures, or None for no maximum.
|
| 576 |
+
Defaults to None.
|
| 577 |
+
|
| 578 |
+
Returns:
|
| 579 |
+
Node: The root of a tree structure which can be used to render a pretty repr.
|
| 580 |
+
"""
|
| 581 |
+
|
| 582 |
+
def to_repr(obj: Any) -> str:
|
| 583 |
+
"""Get repr string for an object, but catch errors."""
|
| 584 |
+
if (
|
| 585 |
+
max_string is not None
|
| 586 |
+
and _safe_isinstance(obj, (bytes, str))
|
| 587 |
+
and len(obj) > max_string
|
| 588 |
+
):
|
| 589 |
+
truncated = len(obj) - max_string
|
| 590 |
+
obj_repr = f"{obj[:max_string]!r}+{truncated}"
|
| 591 |
+
else:
|
| 592 |
+
try:
|
| 593 |
+
obj_repr = repr(obj)
|
| 594 |
+
except Exception as error:
|
| 595 |
+
obj_repr = f"<repr-error {str(error)!r}>"
|
| 596 |
+
return obj_repr
|
| 597 |
+
|
| 598 |
+
visited_ids: Set[int] = set()
|
| 599 |
+
push_visited = visited_ids.add
|
| 600 |
+
pop_visited = visited_ids.remove
|
| 601 |
+
|
| 602 |
+
def _traverse(obj: Any, root: bool = False, depth: int = 0) -> Node:
|
| 603 |
+
"""Walk the object depth first."""
|
| 604 |
+
|
| 605 |
+
obj_id = id(obj)
|
| 606 |
+
if obj_id in visited_ids:
|
| 607 |
+
# Recursion detected
|
| 608 |
+
return Node(value_repr="...")
|
| 609 |
+
|
| 610 |
+
obj_type = type(obj)
|
| 611 |
+
children: List[Node]
|
| 612 |
+
reached_max_depth = max_depth is not None and depth >= max_depth
|
| 613 |
+
|
| 614 |
+
def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]:
|
| 615 |
+
for arg in rich_args:
|
| 616 |
+
if _safe_isinstance(arg, tuple):
|
| 617 |
+
if len(arg) == 3:
|
| 618 |
+
key, child, default = arg
|
| 619 |
+
if default == child:
|
| 620 |
+
continue
|
| 621 |
+
yield key, child
|
| 622 |
+
elif len(arg) == 2:
|
| 623 |
+
key, child = arg
|
| 624 |
+
yield key, child
|
| 625 |
+
elif len(arg) == 1:
|
| 626 |
+
yield arg[0]
|
| 627 |
+
else:
|
| 628 |
+
yield arg
|
| 629 |
+
|
| 630 |
+
try:
|
| 631 |
+
fake_attributes = hasattr(
|
| 632 |
+
obj, "awehoi234_wdfjwljet234_234wdfoijsdfmmnxpi492"
|
| 633 |
+
)
|
| 634 |
+
except Exception:
|
| 635 |
+
fake_attributes = False
|
| 636 |
+
|
| 637 |
+
rich_repr_result: Optional[RichReprResult] = None
|
| 638 |
+
if not fake_attributes:
|
| 639 |
+
try:
|
| 640 |
+
if hasattr(obj, "__rich_repr__") and not isclass(obj):
|
| 641 |
+
rich_repr_result = obj.__rich_repr__()
|
| 642 |
+
except Exception:
|
| 643 |
+
pass
|
| 644 |
+
|
| 645 |
+
if rich_repr_result is not None:
|
| 646 |
+
push_visited(obj_id)
|
| 647 |
+
angular = getattr(obj.__rich_repr__, "angular", False)
|
| 648 |
+
args = list(iter_rich_args(rich_repr_result))
|
| 649 |
+
class_name = obj.__class__.__name__
|
| 650 |
+
|
| 651 |
+
if args:
|
| 652 |
+
children = []
|
| 653 |
+
append = children.append
|
| 654 |
+
|
| 655 |
+
if reached_max_depth:
|
| 656 |
+
if angular:
|
| 657 |
+
node = Node(value_repr=f"<{class_name}...>")
|
| 658 |
+
else:
|
| 659 |
+
node = Node(value_repr=f"{class_name}(...)")
|
| 660 |
+
else:
|
| 661 |
+
if angular:
|
| 662 |
+
node = Node(
|
| 663 |
+
open_brace=f"<{class_name} ",
|
| 664 |
+
close_brace=">",
|
| 665 |
+
children=children,
|
| 666 |
+
last=root,
|
| 667 |
+
separator=" ",
|
| 668 |
+
)
|
| 669 |
+
else:
|
| 670 |
+
node = Node(
|
| 671 |
+
open_brace=f"{class_name}(",
|
| 672 |
+
close_brace=")",
|
| 673 |
+
children=children,
|
| 674 |
+
last=root,
|
| 675 |
+
)
|
| 676 |
+
for last, arg in loop_last(args):
|
| 677 |
+
if _safe_isinstance(arg, tuple):
|
| 678 |
+
key, child = arg
|
| 679 |
+
child_node = _traverse(child, depth=depth + 1)
|
| 680 |
+
child_node.last = last
|
| 681 |
+
child_node.key_repr = key
|
| 682 |
+
child_node.key_separator = "="
|
| 683 |
+
append(child_node)
|
| 684 |
+
else:
|
| 685 |
+
child_node = _traverse(arg, depth=depth + 1)
|
| 686 |
+
child_node.last = last
|
| 687 |
+
append(child_node)
|
| 688 |
+
else:
|
| 689 |
+
node = Node(
|
| 690 |
+
value_repr=f"<{class_name}>" if angular else f"{class_name}()",
|
| 691 |
+
children=[],
|
| 692 |
+
last=root,
|
| 693 |
+
)
|
| 694 |
+
pop_visited(obj_id)
|
| 695 |
+
elif _is_attr_object(obj) and not fake_attributes:
|
| 696 |
+
push_visited(obj_id)
|
| 697 |
+
children = []
|
| 698 |
+
append = children.append
|
| 699 |
+
|
| 700 |
+
attr_fields = _get_attr_fields(obj)
|
| 701 |
+
if attr_fields:
|
| 702 |
+
if reached_max_depth:
|
| 703 |
+
node = Node(value_repr=f"{obj.__class__.__name__}(...)")
|
| 704 |
+
else:
|
| 705 |
+
node = Node(
|
| 706 |
+
open_brace=f"{obj.__class__.__name__}(",
|
| 707 |
+
close_brace=")",
|
| 708 |
+
children=children,
|
| 709 |
+
last=root,
|
| 710 |
+
)
|
| 711 |
+
|
| 712 |
+
def iter_attrs() -> (
|
| 713 |
+
Iterable[Tuple[str, Any, Optional[Callable[[Any], str]]]]
|
| 714 |
+
):
|
| 715 |
+
"""Iterate over attr fields and values."""
|
| 716 |
+
for attr in attr_fields:
|
| 717 |
+
if attr.repr:
|
| 718 |
+
try:
|
| 719 |
+
value = getattr(obj, attr.name)
|
| 720 |
+
except Exception as error:
|
| 721 |
+
# Can happen, albeit rarely
|
| 722 |
+
yield (attr.name, error, None)
|
| 723 |
+
else:
|
| 724 |
+
yield (
|
| 725 |
+
attr.name,
|
| 726 |
+
value,
|
| 727 |
+
attr.repr if callable(attr.repr) else None,
|
| 728 |
+
)
|
| 729 |
+
|
| 730 |
+
for last, (name, value, repr_callable) in loop_last(iter_attrs()):
|
| 731 |
+
if repr_callable:
|
| 732 |
+
child_node = Node(value_repr=str(repr_callable(value)))
|
| 733 |
+
else:
|
| 734 |
+
child_node = _traverse(value, depth=depth + 1)
|
| 735 |
+
child_node.last = last
|
| 736 |
+
child_node.key_repr = name
|
| 737 |
+
child_node.key_separator = "="
|
| 738 |
+
append(child_node)
|
| 739 |
+
else:
|
| 740 |
+
node = Node(
|
| 741 |
+
value_repr=f"{obj.__class__.__name__}()", children=[], last=root
|
| 742 |
+
)
|
| 743 |
+
pop_visited(obj_id)
|
| 744 |
+
elif (
|
| 745 |
+
is_dataclass(obj)
|
| 746 |
+
and not _safe_isinstance(obj, type)
|
| 747 |
+
and not fake_attributes
|
| 748 |
+
and _is_dataclass_repr(obj)
|
| 749 |
+
):
|
| 750 |
+
push_visited(obj_id)
|
| 751 |
+
children = []
|
| 752 |
+
append = children.append
|
| 753 |
+
if reached_max_depth:
|
| 754 |
+
node = Node(value_repr=f"{obj.__class__.__name__}(...)")
|
| 755 |
+
else:
|
| 756 |
+
node = Node(
|
| 757 |
+
open_brace=f"{obj.__class__.__name__}(",
|
| 758 |
+
close_brace=")",
|
| 759 |
+
children=children,
|
| 760 |
+
last=root,
|
| 761 |
+
empty=f"{obj.__class__.__name__}()",
|
| 762 |
+
)
|
| 763 |
+
|
| 764 |
+
for last, field in loop_last(
|
| 765 |
+
field for field in fields(obj) if field.repr
|
| 766 |
+
):
|
| 767 |
+
child_node = _traverse(getattr(obj, field.name), depth=depth + 1)
|
| 768 |
+
child_node.key_repr = field.name
|
| 769 |
+
child_node.last = last
|
| 770 |
+
child_node.key_separator = "="
|
| 771 |
+
append(child_node)
|
| 772 |
+
|
| 773 |
+
pop_visited(obj_id)
|
| 774 |
+
elif _is_namedtuple(obj) and _has_default_namedtuple_repr(obj):
|
| 775 |
+
push_visited(obj_id)
|
| 776 |
+
class_name = obj.__class__.__name__
|
| 777 |
+
if reached_max_depth:
|
| 778 |
+
# If we've reached the max depth, we still show the class name, but not its contents
|
| 779 |
+
node = Node(
|
| 780 |
+
value_repr=f"{class_name}(...)",
|
| 781 |
+
)
|
| 782 |
+
else:
|
| 783 |
+
children = []
|
| 784 |
+
append = children.append
|
| 785 |
+
node = Node(
|
| 786 |
+
open_brace=f"{class_name}(",
|
| 787 |
+
close_brace=")",
|
| 788 |
+
children=children,
|
| 789 |
+
empty=f"{class_name}()",
|
| 790 |
+
)
|
| 791 |
+
for last, (key, value) in loop_last(obj._asdict().items()):
|
| 792 |
+
child_node = _traverse(value, depth=depth + 1)
|
| 793 |
+
child_node.key_repr = key
|
| 794 |
+
child_node.last = last
|
| 795 |
+
child_node.key_separator = "="
|
| 796 |
+
append(child_node)
|
| 797 |
+
pop_visited(obj_id)
|
| 798 |
+
elif _safe_isinstance(obj, _CONTAINERS):
|
| 799 |
+
for container_type in _CONTAINERS:
|
| 800 |
+
if _safe_isinstance(obj, container_type):
|
| 801 |
+
obj_type = container_type
|
| 802 |
+
break
|
| 803 |
+
|
| 804 |
+
push_visited(obj_id)
|
| 805 |
+
|
| 806 |
+
open_brace, close_brace, empty = _BRACES[obj_type](obj)
|
| 807 |
+
|
| 808 |
+
if reached_max_depth:
|
| 809 |
+
node = Node(value_repr=f"{open_brace}...{close_brace}")
|
| 810 |
+
elif obj_type.__repr__ != type(obj).__repr__:
|
| 811 |
+
node = Node(value_repr=to_repr(obj), last=root)
|
| 812 |
+
elif obj:
|
| 813 |
+
children = []
|
| 814 |
+
node = Node(
|
| 815 |
+
open_brace=open_brace,
|
| 816 |
+
close_brace=close_brace,
|
| 817 |
+
children=children,
|
| 818 |
+
last=root,
|
| 819 |
+
)
|
| 820 |
+
append = children.append
|
| 821 |
+
num_items = len(obj)
|
| 822 |
+
last_item_index = num_items - 1
|
| 823 |
+
|
| 824 |
+
if _safe_isinstance(obj, _MAPPING_CONTAINERS):
|
| 825 |
+
iter_items = iter(obj.items())
|
| 826 |
+
if max_length is not None:
|
| 827 |
+
iter_items = islice(iter_items, max_length)
|
| 828 |
+
for index, (key, child) in enumerate(iter_items):
|
| 829 |
+
child_node = _traverse(child, depth=depth + 1)
|
| 830 |
+
child_node.key_repr = to_repr(key)
|
| 831 |
+
child_node.last = index == last_item_index
|
| 832 |
+
append(child_node)
|
| 833 |
+
else:
|
| 834 |
+
iter_values = iter(obj)
|
| 835 |
+
if max_length is not None:
|
| 836 |
+
iter_values = islice(iter_values, max_length)
|
| 837 |
+
for index, child in enumerate(iter_values):
|
| 838 |
+
child_node = _traverse(child, depth=depth + 1)
|
| 839 |
+
child_node.last = index == last_item_index
|
| 840 |
+
append(child_node)
|
| 841 |
+
if max_length is not None and num_items > max_length:
|
| 842 |
+
append(Node(value_repr=f"... +{num_items - max_length}", last=True))
|
| 843 |
+
else:
|
| 844 |
+
node = Node(empty=empty, children=[], last=root)
|
| 845 |
+
|
| 846 |
+
pop_visited(obj_id)
|
| 847 |
+
else:
|
| 848 |
+
node = Node(value_repr=to_repr(obj), last=root)
|
| 849 |
+
node.is_tuple = _safe_isinstance(obj, tuple)
|
| 850 |
+
node.is_namedtuple = _is_namedtuple(obj)
|
| 851 |
+
return node
|
| 852 |
+
|
| 853 |
+
node = _traverse(_object, root=True)
|
| 854 |
+
return node
|
| 855 |
+
|
| 856 |
+
|
| 857 |
+
def pretty_repr(
|
| 858 |
+
_object: Any,
|
| 859 |
+
*,
|
| 860 |
+
max_width: int = 80,
|
| 861 |
+
indent_size: int = 4,
|
| 862 |
+
max_length: Optional[int] = None,
|
| 863 |
+
max_string: Optional[int] = None,
|
| 864 |
+
max_depth: Optional[int] = None,
|
| 865 |
+
expand_all: bool = False,
|
| 866 |
+
) -> str:
|
| 867 |
+
"""Prettify repr string by expanding on to new lines to fit within a given width.
|
| 868 |
+
|
| 869 |
+
Args:
|
| 870 |
+
_object (Any): Object to repr.
|
| 871 |
+
max_width (int, optional): Desired maximum width of repr string. Defaults to 80.
|
| 872 |
+
indent_size (int, optional): Number of spaces to indent. Defaults to 4.
|
| 873 |
+
max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
|
| 874 |
+
Defaults to None.
|
| 875 |
+
max_string (int, optional): Maximum length of string before truncating, or None to disable truncating.
|
| 876 |
+
Defaults to None.
|
| 877 |
+
max_depth (int, optional): Maximum depth of nested data structure, or None for no depth.
|
| 878 |
+
Defaults to None.
|
| 879 |
+
expand_all (bool, optional): Expand all containers regardless of available width. Defaults to False.
|
| 880 |
+
|
| 881 |
+
Returns:
|
| 882 |
+
str: A possibly multi-line representation of the object.
|
| 883 |
+
"""
|
| 884 |
+
|
| 885 |
+
if _safe_isinstance(_object, Node):
|
| 886 |
+
node = _object
|
| 887 |
+
else:
|
| 888 |
+
node = traverse(
|
| 889 |
+
_object, max_length=max_length, max_string=max_string, max_depth=max_depth
|
| 890 |
+
)
|
| 891 |
+
repr_str: str = node.render(
|
| 892 |
+
max_width=max_width, indent_size=indent_size, expand_all=expand_all
|
| 893 |
+
)
|
| 894 |
+
return repr_str
|
| 895 |
+
|
| 896 |
+
|
| 897 |
+
def pprint(
|
| 898 |
+
_object: Any,
|
| 899 |
+
*,
|
| 900 |
+
console: Optional["Console"] = None,
|
| 901 |
+
indent_guides: bool = True,
|
| 902 |
+
max_length: Optional[int] = None,
|
| 903 |
+
max_string: Optional[int] = None,
|
| 904 |
+
max_depth: Optional[int] = None,
|
| 905 |
+
expand_all: bool = False,
|
| 906 |
+
) -> None:
|
| 907 |
+
"""A convenience function for pretty printing.
|
| 908 |
+
|
| 909 |
+
Args:
|
| 910 |
+
_object (Any): Object to pretty print.
|
| 911 |
+
console (Console, optional): Console instance, or None to use default. Defaults to None.
|
| 912 |
+
max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
|
| 913 |
+
Defaults to None.
|
| 914 |
+
max_string (int, optional): Maximum length of strings before truncating, or None to disable. Defaults to None.
|
| 915 |
+
max_depth (int, optional): Maximum depth for nested data structures, or None for unlimited depth. Defaults to None.
|
| 916 |
+
indent_guides (bool, optional): Enable indentation guides. Defaults to True.
|
| 917 |
+
expand_all (bool, optional): Expand all containers. Defaults to False.
|
| 918 |
+
"""
|
| 919 |
+
_console = get_console() if console is None else console
|
| 920 |
+
_console.print(
|
| 921 |
+
Pretty(
|
| 922 |
+
_object,
|
| 923 |
+
max_length=max_length,
|
| 924 |
+
max_string=max_string,
|
| 925 |
+
max_depth=max_depth,
|
| 926 |
+
indent_guides=indent_guides,
|
| 927 |
+
expand_all=expand_all,
|
| 928 |
+
overflow="ignore",
|
| 929 |
+
),
|
| 930 |
+
soft_wrap=True,
|
| 931 |
+
)
|
| 932 |
+
|
| 933 |
+
|
| 934 |
+
if __name__ == "__main__": # pragma: no cover
|
| 935 |
+
|
| 936 |
+
class BrokenRepr:
|
| 937 |
+
def __repr__(self) -> str:
|
| 938 |
+
1 / 0
|
| 939 |
+
return "this will fail"
|
| 940 |
+
|
| 941 |
+
from typing import NamedTuple
|
| 942 |
+
|
| 943 |
+
class StockKeepingUnit(NamedTuple):
|
| 944 |
+
name: str
|
| 945 |
+
description: str
|
| 946 |
+
price: float
|
| 947 |
+
category: str
|
| 948 |
+
reviews: List[str]
|
| 949 |
+
|
| 950 |
+
d = defaultdict(int)
|
| 951 |
+
d["foo"] = 5
|
| 952 |
+
data = {
|
| 953 |
+
"foo": [
|
| 954 |
+
1,
|
| 955 |
+
"Hello World!",
|
| 956 |
+
100.123,
|
| 957 |
+
323.232,
|
| 958 |
+
432324.0,
|
| 959 |
+
{5, 6, 7, (1, 2, 3, 4), 8},
|
| 960 |
+
],
|
| 961 |
+
"bar": frozenset({1, 2, 3}),
|
| 962 |
+
"defaultdict": defaultdict(
|
| 963 |
+
list, {"crumble": ["apple", "rhubarb", "butter", "sugar", "flour"]}
|
| 964 |
+
),
|
| 965 |
+
"counter": Counter(
|
| 966 |
+
[
|
| 967 |
+
"apple",
|
| 968 |
+
"orange",
|
| 969 |
+
"pear",
|
| 970 |
+
"kumquat",
|
| 971 |
+
"kumquat",
|
| 972 |
+
"durian" * 100,
|
| 973 |
+
]
|
| 974 |
+
),
|
| 975 |
+
"atomic": (False, True, None),
|
| 976 |
+
"namedtuple": StockKeepingUnit(
|
| 977 |
+
"Sparkling British Spring Water",
|
| 978 |
+
"Carbonated spring water",
|
| 979 |
+
0.9,
|
| 980 |
+
"water",
|
| 981 |
+
["its amazing!", "its terrible!"],
|
| 982 |
+
),
|
| 983 |
+
"Broken": BrokenRepr(),
|
| 984 |
+
}
|
| 985 |
+
data["foo"].append(data) # type: ignore[attr-defined]
|
| 986 |
+
|
| 987 |
+
from pip._vendor.rich import print
|
| 988 |
+
|
| 989 |
+
print(Pretty(data, indent_guides=True, max_string=20))
|
| 990 |
+
|
| 991 |
+
class Thing:
|
| 992 |
+
def __repr__(self) -> str:
|
| 993 |
+
return "Hello\x1b[38;5;239m World!"
|
| 994 |
+
|
| 995 |
+
print(Pretty(Thing()))
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/progress.py
ADDED
|
@@ -0,0 +1,1699 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import io
|
| 2 |
+
import sys
|
| 3 |
+
import typing
|
| 4 |
+
import warnings
|
| 5 |
+
from abc import ABC, abstractmethod
|
| 6 |
+
from collections import deque
|
| 7 |
+
from dataclasses import dataclass, field
|
| 8 |
+
from datetime import timedelta
|
| 9 |
+
from io import RawIOBase, UnsupportedOperation
|
| 10 |
+
from math import ceil
|
| 11 |
+
from mmap import mmap
|
| 12 |
+
from operator import length_hint
|
| 13 |
+
from os import PathLike, stat
|
| 14 |
+
from threading import Event, RLock, Thread
|
| 15 |
+
from types import TracebackType
|
| 16 |
+
from typing import (
|
| 17 |
+
Any,
|
| 18 |
+
BinaryIO,
|
| 19 |
+
Callable,
|
| 20 |
+
ContextManager,
|
| 21 |
+
Deque,
|
| 22 |
+
Dict,
|
| 23 |
+
Generic,
|
| 24 |
+
Iterable,
|
| 25 |
+
List,
|
| 26 |
+
NamedTuple,
|
| 27 |
+
NewType,
|
| 28 |
+
Optional,
|
| 29 |
+
Sequence,
|
| 30 |
+
TextIO,
|
| 31 |
+
Tuple,
|
| 32 |
+
Type,
|
| 33 |
+
TypeVar,
|
| 34 |
+
Union,
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
if sys.version_info >= (3, 8):
|
| 38 |
+
from typing import Literal
|
| 39 |
+
else:
|
| 40 |
+
from pip._vendor.typing_extensions import Literal # pragma: no cover
|
| 41 |
+
|
| 42 |
+
from . import filesize, get_console
|
| 43 |
+
from .console import Console, Group, JustifyMethod, RenderableType
|
| 44 |
+
from .highlighter import Highlighter
|
| 45 |
+
from .jupyter import JupyterMixin
|
| 46 |
+
from .live import Live
|
| 47 |
+
from .progress_bar import ProgressBar
|
| 48 |
+
from .spinner import Spinner
|
| 49 |
+
from .style import StyleType
|
| 50 |
+
from .table import Column, Table
|
| 51 |
+
from .text import Text, TextType
|
| 52 |
+
|
| 53 |
+
TaskID = NewType("TaskID", int)
|
| 54 |
+
|
| 55 |
+
ProgressType = TypeVar("ProgressType")
|
| 56 |
+
|
| 57 |
+
GetTimeCallable = Callable[[], float]
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
_I = typing.TypeVar("_I", TextIO, BinaryIO)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
class _TrackThread(Thread):
|
| 64 |
+
"""A thread to periodically update progress."""
|
| 65 |
+
|
| 66 |
+
def __init__(self, progress: "Progress", task_id: "TaskID", update_period: float):
|
| 67 |
+
self.progress = progress
|
| 68 |
+
self.task_id = task_id
|
| 69 |
+
self.update_period = update_period
|
| 70 |
+
self.done = Event()
|
| 71 |
+
|
| 72 |
+
self.completed = 0
|
| 73 |
+
super().__init__()
|
| 74 |
+
|
| 75 |
+
def run(self) -> None:
|
| 76 |
+
task_id = self.task_id
|
| 77 |
+
advance = self.progress.advance
|
| 78 |
+
update_period = self.update_period
|
| 79 |
+
last_completed = 0
|
| 80 |
+
wait = self.done.wait
|
| 81 |
+
while not wait(update_period):
|
| 82 |
+
completed = self.completed
|
| 83 |
+
if last_completed != completed:
|
| 84 |
+
advance(task_id, completed - last_completed)
|
| 85 |
+
last_completed = completed
|
| 86 |
+
|
| 87 |
+
self.progress.update(self.task_id, completed=self.completed, refresh=True)
|
| 88 |
+
|
| 89 |
+
def __enter__(self) -> "_TrackThread":
|
| 90 |
+
self.start()
|
| 91 |
+
return self
|
| 92 |
+
|
| 93 |
+
def __exit__(
|
| 94 |
+
self,
|
| 95 |
+
exc_type: Optional[Type[BaseException]],
|
| 96 |
+
exc_val: Optional[BaseException],
|
| 97 |
+
exc_tb: Optional[TracebackType],
|
| 98 |
+
) -> None:
|
| 99 |
+
self.done.set()
|
| 100 |
+
self.join()
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def track(
|
| 104 |
+
sequence: Union[Sequence[ProgressType], Iterable[ProgressType]],
|
| 105 |
+
description: str = "Working...",
|
| 106 |
+
total: Optional[float] = None,
|
| 107 |
+
auto_refresh: bool = True,
|
| 108 |
+
console: Optional[Console] = None,
|
| 109 |
+
transient: bool = False,
|
| 110 |
+
get_time: Optional[Callable[[], float]] = None,
|
| 111 |
+
refresh_per_second: float = 10,
|
| 112 |
+
style: StyleType = "bar.back",
|
| 113 |
+
complete_style: StyleType = "bar.complete",
|
| 114 |
+
finished_style: StyleType = "bar.finished",
|
| 115 |
+
pulse_style: StyleType = "bar.pulse",
|
| 116 |
+
update_period: float = 0.1,
|
| 117 |
+
disable: bool = False,
|
| 118 |
+
show_speed: bool = True,
|
| 119 |
+
) -> Iterable[ProgressType]:
|
| 120 |
+
"""Track progress by iterating over a sequence.
|
| 121 |
+
|
| 122 |
+
Args:
|
| 123 |
+
sequence (Iterable[ProgressType]): A sequence (must support "len") you wish to iterate over.
|
| 124 |
+
description (str, optional): Description of task show next to progress bar. Defaults to "Working".
|
| 125 |
+
total: (float, optional): Total number of steps. Default is len(sequence).
|
| 126 |
+
auto_refresh (bool, optional): Automatic refresh, disable to force a refresh after each iteration. Default is True.
|
| 127 |
+
transient: (bool, optional): Clear the progress on exit. Defaults to False.
|
| 128 |
+
console (Console, optional): Console to write to. Default creates internal Console instance.
|
| 129 |
+
refresh_per_second (float): Number of times per second to refresh the progress information. Defaults to 10.
|
| 130 |
+
style (StyleType, optional): Style for the bar background. Defaults to "bar.back".
|
| 131 |
+
complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete".
|
| 132 |
+
finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished".
|
| 133 |
+
pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse".
|
| 134 |
+
update_period (float, optional): Minimum time (in seconds) between calls to update(). Defaults to 0.1.
|
| 135 |
+
disable (bool, optional): Disable display of progress.
|
| 136 |
+
show_speed (bool, optional): Show speed if total isn't known. Defaults to True.
|
| 137 |
+
Returns:
|
| 138 |
+
Iterable[ProgressType]: An iterable of the values in the sequence.
|
| 139 |
+
|
| 140 |
+
"""
|
| 141 |
+
|
| 142 |
+
columns: List["ProgressColumn"] = (
|
| 143 |
+
[TextColumn("[progress.description]{task.description}")] if description else []
|
| 144 |
+
)
|
| 145 |
+
columns.extend(
|
| 146 |
+
(
|
| 147 |
+
BarColumn(
|
| 148 |
+
style=style,
|
| 149 |
+
complete_style=complete_style,
|
| 150 |
+
finished_style=finished_style,
|
| 151 |
+
pulse_style=pulse_style,
|
| 152 |
+
),
|
| 153 |
+
TaskProgressColumn(show_speed=show_speed),
|
| 154 |
+
TimeRemainingColumn(elapsed_when_finished=True),
|
| 155 |
+
)
|
| 156 |
+
)
|
| 157 |
+
progress = Progress(
|
| 158 |
+
*columns,
|
| 159 |
+
auto_refresh=auto_refresh,
|
| 160 |
+
console=console,
|
| 161 |
+
transient=transient,
|
| 162 |
+
get_time=get_time,
|
| 163 |
+
refresh_per_second=refresh_per_second or 10,
|
| 164 |
+
disable=disable,
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
with progress:
|
| 168 |
+
yield from progress.track(
|
| 169 |
+
sequence, total=total, description=description, update_period=update_period
|
| 170 |
+
)
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
class _Reader(RawIOBase, BinaryIO):
|
| 174 |
+
"""A reader that tracks progress while it's being read from."""
|
| 175 |
+
|
| 176 |
+
def __init__(
|
| 177 |
+
self,
|
| 178 |
+
handle: BinaryIO,
|
| 179 |
+
progress: "Progress",
|
| 180 |
+
task: TaskID,
|
| 181 |
+
close_handle: bool = True,
|
| 182 |
+
) -> None:
|
| 183 |
+
self.handle = handle
|
| 184 |
+
self.progress = progress
|
| 185 |
+
self.task = task
|
| 186 |
+
self.close_handle = close_handle
|
| 187 |
+
self._closed = False
|
| 188 |
+
|
| 189 |
+
def __enter__(self) -> "_Reader":
|
| 190 |
+
self.handle.__enter__()
|
| 191 |
+
return self
|
| 192 |
+
|
| 193 |
+
def __exit__(
|
| 194 |
+
self,
|
| 195 |
+
exc_type: Optional[Type[BaseException]],
|
| 196 |
+
exc_val: Optional[BaseException],
|
| 197 |
+
exc_tb: Optional[TracebackType],
|
| 198 |
+
) -> None:
|
| 199 |
+
self.close()
|
| 200 |
+
|
| 201 |
+
def __iter__(self) -> BinaryIO:
|
| 202 |
+
return self
|
| 203 |
+
|
| 204 |
+
def __next__(self) -> bytes:
|
| 205 |
+
line = next(self.handle)
|
| 206 |
+
self.progress.advance(self.task, advance=len(line))
|
| 207 |
+
return line
|
| 208 |
+
|
| 209 |
+
@property
|
| 210 |
+
def closed(self) -> bool:
|
| 211 |
+
return self._closed
|
| 212 |
+
|
| 213 |
+
def fileno(self) -> int:
|
| 214 |
+
return self.handle.fileno()
|
| 215 |
+
|
| 216 |
+
def isatty(self) -> bool:
|
| 217 |
+
return self.handle.isatty()
|
| 218 |
+
|
| 219 |
+
@property
|
| 220 |
+
def mode(self) -> str:
|
| 221 |
+
return self.handle.mode
|
| 222 |
+
|
| 223 |
+
@property
|
| 224 |
+
def name(self) -> str:
|
| 225 |
+
return self.handle.name
|
| 226 |
+
|
| 227 |
+
def readable(self) -> bool:
|
| 228 |
+
return self.handle.readable()
|
| 229 |
+
|
| 230 |
+
def seekable(self) -> bool:
|
| 231 |
+
return self.handle.seekable()
|
| 232 |
+
|
| 233 |
+
def writable(self) -> bool:
|
| 234 |
+
return False
|
| 235 |
+
|
| 236 |
+
def read(self, size: int = -1) -> bytes:
|
| 237 |
+
block = self.handle.read(size)
|
| 238 |
+
self.progress.advance(self.task, advance=len(block))
|
| 239 |
+
return block
|
| 240 |
+
|
| 241 |
+
def readinto(self, b: Union[bytearray, memoryview, mmap]): # type: ignore[no-untyped-def, override]
|
| 242 |
+
n = self.handle.readinto(b) # type: ignore[attr-defined]
|
| 243 |
+
self.progress.advance(self.task, advance=n)
|
| 244 |
+
return n
|
| 245 |
+
|
| 246 |
+
def readline(self, size: int = -1) -> bytes: # type: ignore[override]
|
| 247 |
+
line = self.handle.readline(size)
|
| 248 |
+
self.progress.advance(self.task, advance=len(line))
|
| 249 |
+
return line
|
| 250 |
+
|
| 251 |
+
def readlines(self, hint: int = -1) -> List[bytes]:
|
| 252 |
+
lines = self.handle.readlines(hint)
|
| 253 |
+
self.progress.advance(self.task, advance=sum(map(len, lines)))
|
| 254 |
+
return lines
|
| 255 |
+
|
| 256 |
+
def close(self) -> None:
|
| 257 |
+
if self.close_handle:
|
| 258 |
+
self.handle.close()
|
| 259 |
+
self._closed = True
|
| 260 |
+
|
| 261 |
+
def seek(self, offset: int, whence: int = 0) -> int:
|
| 262 |
+
pos = self.handle.seek(offset, whence)
|
| 263 |
+
self.progress.update(self.task, completed=pos)
|
| 264 |
+
return pos
|
| 265 |
+
|
| 266 |
+
def tell(self) -> int:
|
| 267 |
+
return self.handle.tell()
|
| 268 |
+
|
| 269 |
+
def write(self, s: Any) -> int:
|
| 270 |
+
raise UnsupportedOperation("write")
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
class _ReadContext(ContextManager[_I], Generic[_I]):
|
| 274 |
+
"""A utility class to handle a context for both a reader and a progress."""
|
| 275 |
+
|
| 276 |
+
def __init__(self, progress: "Progress", reader: _I) -> None:
|
| 277 |
+
self.progress = progress
|
| 278 |
+
self.reader: _I = reader
|
| 279 |
+
|
| 280 |
+
def __enter__(self) -> _I:
|
| 281 |
+
self.progress.start()
|
| 282 |
+
return self.reader.__enter__()
|
| 283 |
+
|
| 284 |
+
def __exit__(
|
| 285 |
+
self,
|
| 286 |
+
exc_type: Optional[Type[BaseException]],
|
| 287 |
+
exc_val: Optional[BaseException],
|
| 288 |
+
exc_tb: Optional[TracebackType],
|
| 289 |
+
) -> None:
|
| 290 |
+
self.progress.stop()
|
| 291 |
+
self.reader.__exit__(exc_type, exc_val, exc_tb)
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
def wrap_file(
|
| 295 |
+
file: BinaryIO,
|
| 296 |
+
total: int,
|
| 297 |
+
*,
|
| 298 |
+
description: str = "Reading...",
|
| 299 |
+
auto_refresh: bool = True,
|
| 300 |
+
console: Optional[Console] = None,
|
| 301 |
+
transient: bool = False,
|
| 302 |
+
get_time: Optional[Callable[[], float]] = None,
|
| 303 |
+
refresh_per_second: float = 10,
|
| 304 |
+
style: StyleType = "bar.back",
|
| 305 |
+
complete_style: StyleType = "bar.complete",
|
| 306 |
+
finished_style: StyleType = "bar.finished",
|
| 307 |
+
pulse_style: StyleType = "bar.pulse",
|
| 308 |
+
disable: bool = False,
|
| 309 |
+
) -> ContextManager[BinaryIO]:
|
| 310 |
+
"""Read bytes from a file while tracking progress.
|
| 311 |
+
|
| 312 |
+
Args:
|
| 313 |
+
file (Union[str, PathLike[str], BinaryIO]): The path to the file to read, or a file-like object in binary mode.
|
| 314 |
+
total (int): Total number of bytes to read.
|
| 315 |
+
description (str, optional): Description of task show next to progress bar. Defaults to "Reading".
|
| 316 |
+
auto_refresh (bool, optional): Automatic refresh, disable to force a refresh after each iteration. Default is True.
|
| 317 |
+
transient: (bool, optional): Clear the progress on exit. Defaults to False.
|
| 318 |
+
console (Console, optional): Console to write to. Default creates internal Console instance.
|
| 319 |
+
refresh_per_second (float): Number of times per second to refresh the progress information. Defaults to 10.
|
| 320 |
+
style (StyleType, optional): Style for the bar background. Defaults to "bar.back".
|
| 321 |
+
complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete".
|
| 322 |
+
finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished".
|
| 323 |
+
pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse".
|
| 324 |
+
disable (bool, optional): Disable display of progress.
|
| 325 |
+
Returns:
|
| 326 |
+
ContextManager[BinaryIO]: A context manager yielding a progress reader.
|
| 327 |
+
|
| 328 |
+
"""
|
| 329 |
+
|
| 330 |
+
columns: List["ProgressColumn"] = (
|
| 331 |
+
[TextColumn("[progress.description]{task.description}")] if description else []
|
| 332 |
+
)
|
| 333 |
+
columns.extend(
|
| 334 |
+
(
|
| 335 |
+
BarColumn(
|
| 336 |
+
style=style,
|
| 337 |
+
complete_style=complete_style,
|
| 338 |
+
finished_style=finished_style,
|
| 339 |
+
pulse_style=pulse_style,
|
| 340 |
+
),
|
| 341 |
+
DownloadColumn(),
|
| 342 |
+
TimeRemainingColumn(),
|
| 343 |
+
)
|
| 344 |
+
)
|
| 345 |
+
progress = Progress(
|
| 346 |
+
*columns,
|
| 347 |
+
auto_refresh=auto_refresh,
|
| 348 |
+
console=console,
|
| 349 |
+
transient=transient,
|
| 350 |
+
get_time=get_time,
|
| 351 |
+
refresh_per_second=refresh_per_second or 10,
|
| 352 |
+
disable=disable,
|
| 353 |
+
)
|
| 354 |
+
|
| 355 |
+
reader = progress.wrap_file(file, total=total, description=description)
|
| 356 |
+
return _ReadContext(progress, reader)
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
@typing.overload
|
| 360 |
+
def open(
|
| 361 |
+
file: Union[str, "PathLike[str]", bytes],
|
| 362 |
+
mode: Union[Literal["rt"], Literal["r"]],
|
| 363 |
+
buffering: int = -1,
|
| 364 |
+
encoding: Optional[str] = None,
|
| 365 |
+
errors: Optional[str] = None,
|
| 366 |
+
newline: Optional[str] = None,
|
| 367 |
+
*,
|
| 368 |
+
total: Optional[int] = None,
|
| 369 |
+
description: str = "Reading...",
|
| 370 |
+
auto_refresh: bool = True,
|
| 371 |
+
console: Optional[Console] = None,
|
| 372 |
+
transient: bool = False,
|
| 373 |
+
get_time: Optional[Callable[[], float]] = None,
|
| 374 |
+
refresh_per_second: float = 10,
|
| 375 |
+
style: StyleType = "bar.back",
|
| 376 |
+
complete_style: StyleType = "bar.complete",
|
| 377 |
+
finished_style: StyleType = "bar.finished",
|
| 378 |
+
pulse_style: StyleType = "bar.pulse",
|
| 379 |
+
disable: bool = False,
|
| 380 |
+
) -> ContextManager[TextIO]:
|
| 381 |
+
pass
|
| 382 |
+
|
| 383 |
+
|
| 384 |
+
@typing.overload
|
| 385 |
+
def open(
|
| 386 |
+
file: Union[str, "PathLike[str]", bytes],
|
| 387 |
+
mode: Literal["rb"],
|
| 388 |
+
buffering: int = -1,
|
| 389 |
+
encoding: Optional[str] = None,
|
| 390 |
+
errors: Optional[str] = None,
|
| 391 |
+
newline: Optional[str] = None,
|
| 392 |
+
*,
|
| 393 |
+
total: Optional[int] = None,
|
| 394 |
+
description: str = "Reading...",
|
| 395 |
+
auto_refresh: bool = True,
|
| 396 |
+
console: Optional[Console] = None,
|
| 397 |
+
transient: bool = False,
|
| 398 |
+
get_time: Optional[Callable[[], float]] = None,
|
| 399 |
+
refresh_per_second: float = 10,
|
| 400 |
+
style: StyleType = "bar.back",
|
| 401 |
+
complete_style: StyleType = "bar.complete",
|
| 402 |
+
finished_style: StyleType = "bar.finished",
|
| 403 |
+
pulse_style: StyleType = "bar.pulse",
|
| 404 |
+
disable: bool = False,
|
| 405 |
+
) -> ContextManager[BinaryIO]:
|
| 406 |
+
pass
|
| 407 |
+
|
| 408 |
+
|
| 409 |
+
def open(
|
| 410 |
+
file: Union[str, "PathLike[str]", bytes],
|
| 411 |
+
mode: Union[Literal["rb"], Literal["rt"], Literal["r"]] = "r",
|
| 412 |
+
buffering: int = -1,
|
| 413 |
+
encoding: Optional[str] = None,
|
| 414 |
+
errors: Optional[str] = None,
|
| 415 |
+
newline: Optional[str] = None,
|
| 416 |
+
*,
|
| 417 |
+
total: Optional[int] = None,
|
| 418 |
+
description: str = "Reading...",
|
| 419 |
+
auto_refresh: bool = True,
|
| 420 |
+
console: Optional[Console] = None,
|
| 421 |
+
transient: bool = False,
|
| 422 |
+
get_time: Optional[Callable[[], float]] = None,
|
| 423 |
+
refresh_per_second: float = 10,
|
| 424 |
+
style: StyleType = "bar.back",
|
| 425 |
+
complete_style: StyleType = "bar.complete",
|
| 426 |
+
finished_style: StyleType = "bar.finished",
|
| 427 |
+
pulse_style: StyleType = "bar.pulse",
|
| 428 |
+
disable: bool = False,
|
| 429 |
+
) -> Union[ContextManager[BinaryIO], ContextManager[TextIO]]:
|
| 430 |
+
"""Read bytes from a file while tracking progress.
|
| 431 |
+
|
| 432 |
+
Args:
|
| 433 |
+
path (Union[str, PathLike[str], BinaryIO]): The path to the file to read, or a file-like object in binary mode.
|
| 434 |
+
mode (str): The mode to use to open the file. Only supports "r", "rb" or "rt".
|
| 435 |
+
buffering (int): The buffering strategy to use, see :func:`io.open`.
|
| 436 |
+
encoding (str, optional): The encoding to use when reading in text mode, see :func:`io.open`.
|
| 437 |
+
errors (str, optional): The error handling strategy for decoding errors, see :func:`io.open`.
|
| 438 |
+
newline (str, optional): The strategy for handling newlines in text mode, see :func:`io.open`
|
| 439 |
+
total: (int, optional): Total number of bytes to read. Must be provided if reading from a file handle. Default for a path is os.stat(file).st_size.
|
| 440 |
+
description (str, optional): Description of task show next to progress bar. Defaults to "Reading".
|
| 441 |
+
auto_refresh (bool, optional): Automatic refresh, disable to force a refresh after each iteration. Default is True.
|
| 442 |
+
transient: (bool, optional): Clear the progress on exit. Defaults to False.
|
| 443 |
+
console (Console, optional): Console to write to. Default creates internal Console instance.
|
| 444 |
+
refresh_per_second (float): Number of times per second to refresh the progress information. Defaults to 10.
|
| 445 |
+
style (StyleType, optional): Style for the bar background. Defaults to "bar.back".
|
| 446 |
+
complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete".
|
| 447 |
+
finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished".
|
| 448 |
+
pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse".
|
| 449 |
+
disable (bool, optional): Disable display of progress.
|
| 450 |
+
encoding (str, optional): The encoding to use when reading in text mode.
|
| 451 |
+
|
| 452 |
+
Returns:
|
| 453 |
+
ContextManager[BinaryIO]: A context manager yielding a progress reader.
|
| 454 |
+
|
| 455 |
+
"""
|
| 456 |
+
|
| 457 |
+
columns: List["ProgressColumn"] = (
|
| 458 |
+
[TextColumn("[progress.description]{task.description}")] if description else []
|
| 459 |
+
)
|
| 460 |
+
columns.extend(
|
| 461 |
+
(
|
| 462 |
+
BarColumn(
|
| 463 |
+
style=style,
|
| 464 |
+
complete_style=complete_style,
|
| 465 |
+
finished_style=finished_style,
|
| 466 |
+
pulse_style=pulse_style,
|
| 467 |
+
),
|
| 468 |
+
DownloadColumn(),
|
| 469 |
+
TimeRemainingColumn(),
|
| 470 |
+
)
|
| 471 |
+
)
|
| 472 |
+
progress = Progress(
|
| 473 |
+
*columns,
|
| 474 |
+
auto_refresh=auto_refresh,
|
| 475 |
+
console=console,
|
| 476 |
+
transient=transient,
|
| 477 |
+
get_time=get_time,
|
| 478 |
+
refresh_per_second=refresh_per_second or 10,
|
| 479 |
+
disable=disable,
|
| 480 |
+
)
|
| 481 |
+
|
| 482 |
+
reader = progress.open(
|
| 483 |
+
file,
|
| 484 |
+
mode=mode,
|
| 485 |
+
buffering=buffering,
|
| 486 |
+
encoding=encoding,
|
| 487 |
+
errors=errors,
|
| 488 |
+
newline=newline,
|
| 489 |
+
total=total,
|
| 490 |
+
description=description,
|
| 491 |
+
)
|
| 492 |
+
return _ReadContext(progress, reader) # type: ignore[return-value, type-var]
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
class ProgressColumn(ABC):
|
| 496 |
+
"""Base class for a widget to use in progress display."""
|
| 497 |
+
|
| 498 |
+
max_refresh: Optional[float] = None
|
| 499 |
+
|
| 500 |
+
def __init__(self, table_column: Optional[Column] = None) -> None:
|
| 501 |
+
self._table_column = table_column
|
| 502 |
+
self._renderable_cache: Dict[TaskID, Tuple[float, RenderableType]] = {}
|
| 503 |
+
self._update_time: Optional[float] = None
|
| 504 |
+
|
| 505 |
+
def get_table_column(self) -> Column:
|
| 506 |
+
"""Get a table column, used to build tasks table."""
|
| 507 |
+
return self._table_column or Column()
|
| 508 |
+
|
| 509 |
+
def __call__(self, task: "Task") -> RenderableType:
|
| 510 |
+
"""Called by the Progress object to return a renderable for the given task.
|
| 511 |
+
|
| 512 |
+
Args:
|
| 513 |
+
task (Task): An object containing information regarding the task.
|
| 514 |
+
|
| 515 |
+
Returns:
|
| 516 |
+
RenderableType: Anything renderable (including str).
|
| 517 |
+
"""
|
| 518 |
+
current_time = task.get_time()
|
| 519 |
+
if self.max_refresh is not None and not task.completed:
|
| 520 |
+
try:
|
| 521 |
+
timestamp, renderable = self._renderable_cache[task.id]
|
| 522 |
+
except KeyError:
|
| 523 |
+
pass
|
| 524 |
+
else:
|
| 525 |
+
if timestamp + self.max_refresh > current_time:
|
| 526 |
+
return renderable
|
| 527 |
+
|
| 528 |
+
renderable = self.render(task)
|
| 529 |
+
self._renderable_cache[task.id] = (current_time, renderable)
|
| 530 |
+
return renderable
|
| 531 |
+
|
| 532 |
+
@abstractmethod
|
| 533 |
+
def render(self, task: "Task") -> RenderableType:
|
| 534 |
+
"""Should return a renderable object."""
|
| 535 |
+
|
| 536 |
+
|
| 537 |
+
class RenderableColumn(ProgressColumn):
|
| 538 |
+
"""A column to insert an arbitrary column.
|
| 539 |
+
|
| 540 |
+
Args:
|
| 541 |
+
renderable (RenderableType, optional): Any renderable. Defaults to empty string.
|
| 542 |
+
"""
|
| 543 |
+
|
| 544 |
+
def __init__(
|
| 545 |
+
self, renderable: RenderableType = "", *, table_column: Optional[Column] = None
|
| 546 |
+
):
|
| 547 |
+
self.renderable = renderable
|
| 548 |
+
super().__init__(table_column=table_column)
|
| 549 |
+
|
| 550 |
+
def render(self, task: "Task") -> RenderableType:
|
| 551 |
+
return self.renderable
|
| 552 |
+
|
| 553 |
+
|
| 554 |
+
class SpinnerColumn(ProgressColumn):
|
| 555 |
+
"""A column with a 'spinner' animation.
|
| 556 |
+
|
| 557 |
+
Args:
|
| 558 |
+
spinner_name (str, optional): Name of spinner animation. Defaults to "dots".
|
| 559 |
+
style (StyleType, optional): Style of spinner. Defaults to "progress.spinner".
|
| 560 |
+
speed (float, optional): Speed factor of spinner. Defaults to 1.0.
|
| 561 |
+
finished_text (TextType, optional): Text used when task is finished. Defaults to " ".
|
| 562 |
+
"""
|
| 563 |
+
|
| 564 |
+
def __init__(
|
| 565 |
+
self,
|
| 566 |
+
spinner_name: str = "dots",
|
| 567 |
+
style: Optional[StyleType] = "progress.spinner",
|
| 568 |
+
speed: float = 1.0,
|
| 569 |
+
finished_text: TextType = " ",
|
| 570 |
+
table_column: Optional[Column] = None,
|
| 571 |
+
):
|
| 572 |
+
self.spinner = Spinner(spinner_name, style=style, speed=speed)
|
| 573 |
+
self.finished_text = (
|
| 574 |
+
Text.from_markup(finished_text)
|
| 575 |
+
if isinstance(finished_text, str)
|
| 576 |
+
else finished_text
|
| 577 |
+
)
|
| 578 |
+
super().__init__(table_column=table_column)
|
| 579 |
+
|
| 580 |
+
def set_spinner(
|
| 581 |
+
self,
|
| 582 |
+
spinner_name: str,
|
| 583 |
+
spinner_style: Optional[StyleType] = "progress.spinner",
|
| 584 |
+
speed: float = 1.0,
|
| 585 |
+
) -> None:
|
| 586 |
+
"""Set a new spinner.
|
| 587 |
+
|
| 588 |
+
Args:
|
| 589 |
+
spinner_name (str): Spinner name, see python -m rich.spinner.
|
| 590 |
+
spinner_style (Optional[StyleType], optional): Spinner style. Defaults to "progress.spinner".
|
| 591 |
+
speed (float, optional): Speed factor of spinner. Defaults to 1.0.
|
| 592 |
+
"""
|
| 593 |
+
self.spinner = Spinner(spinner_name, style=spinner_style, speed=speed)
|
| 594 |
+
|
| 595 |
+
def render(self, task: "Task") -> RenderableType:
|
| 596 |
+
text = (
|
| 597 |
+
self.finished_text
|
| 598 |
+
if task.finished
|
| 599 |
+
else self.spinner.render(task.get_time())
|
| 600 |
+
)
|
| 601 |
+
return text
|
| 602 |
+
|
| 603 |
+
|
| 604 |
+
class TextColumn(ProgressColumn):
|
| 605 |
+
"""A column containing text."""
|
| 606 |
+
|
| 607 |
+
def __init__(
|
| 608 |
+
self,
|
| 609 |
+
text_format: str,
|
| 610 |
+
style: StyleType = "none",
|
| 611 |
+
justify: JustifyMethod = "left",
|
| 612 |
+
markup: bool = True,
|
| 613 |
+
highlighter: Optional[Highlighter] = None,
|
| 614 |
+
table_column: Optional[Column] = None,
|
| 615 |
+
) -> None:
|
| 616 |
+
self.text_format = text_format
|
| 617 |
+
self.justify: JustifyMethod = justify
|
| 618 |
+
self.style = style
|
| 619 |
+
self.markup = markup
|
| 620 |
+
self.highlighter = highlighter
|
| 621 |
+
super().__init__(table_column=table_column or Column(no_wrap=True))
|
| 622 |
+
|
| 623 |
+
def render(self, task: "Task") -> Text:
|
| 624 |
+
_text = self.text_format.format(task=task)
|
| 625 |
+
if self.markup:
|
| 626 |
+
text = Text.from_markup(_text, style=self.style, justify=self.justify)
|
| 627 |
+
else:
|
| 628 |
+
text = Text(_text, style=self.style, justify=self.justify)
|
| 629 |
+
if self.highlighter:
|
| 630 |
+
self.highlighter.highlight(text)
|
| 631 |
+
return text
|
| 632 |
+
|
| 633 |
+
|
| 634 |
+
class BarColumn(ProgressColumn):
|
| 635 |
+
"""Renders a visual progress bar.
|
| 636 |
+
|
| 637 |
+
Args:
|
| 638 |
+
bar_width (Optional[int], optional): Width of bar or None for full width. Defaults to 40.
|
| 639 |
+
style (StyleType, optional): Style for the bar background. Defaults to "bar.back".
|
| 640 |
+
complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete".
|
| 641 |
+
finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished".
|
| 642 |
+
pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse".
|
| 643 |
+
"""
|
| 644 |
+
|
| 645 |
+
def __init__(
|
| 646 |
+
self,
|
| 647 |
+
bar_width: Optional[int] = 40,
|
| 648 |
+
style: StyleType = "bar.back",
|
| 649 |
+
complete_style: StyleType = "bar.complete",
|
| 650 |
+
finished_style: StyleType = "bar.finished",
|
| 651 |
+
pulse_style: StyleType = "bar.pulse",
|
| 652 |
+
table_column: Optional[Column] = None,
|
| 653 |
+
) -> None:
|
| 654 |
+
self.bar_width = bar_width
|
| 655 |
+
self.style = style
|
| 656 |
+
self.complete_style = complete_style
|
| 657 |
+
self.finished_style = finished_style
|
| 658 |
+
self.pulse_style = pulse_style
|
| 659 |
+
super().__init__(table_column=table_column)
|
| 660 |
+
|
| 661 |
+
def render(self, task: "Task") -> ProgressBar:
|
| 662 |
+
"""Gets a progress bar widget for a task."""
|
| 663 |
+
return ProgressBar(
|
| 664 |
+
total=max(0, task.total) if task.total is not None else None,
|
| 665 |
+
completed=max(0, task.completed),
|
| 666 |
+
width=None if self.bar_width is None else max(1, self.bar_width),
|
| 667 |
+
pulse=not task.started,
|
| 668 |
+
animation_time=task.get_time(),
|
| 669 |
+
style=self.style,
|
| 670 |
+
complete_style=self.complete_style,
|
| 671 |
+
finished_style=self.finished_style,
|
| 672 |
+
pulse_style=self.pulse_style,
|
| 673 |
+
)
|
| 674 |
+
|
| 675 |
+
|
| 676 |
+
class TimeElapsedColumn(ProgressColumn):
|
| 677 |
+
"""Renders time elapsed."""
|
| 678 |
+
|
| 679 |
+
def render(self, task: "Task") -> Text:
|
| 680 |
+
"""Show time elapsed."""
|
| 681 |
+
elapsed = task.finished_time if task.finished else task.elapsed
|
| 682 |
+
if elapsed is None:
|
| 683 |
+
return Text("-:--:--", style="progress.elapsed")
|
| 684 |
+
delta = timedelta(seconds=max(0, int(elapsed)))
|
| 685 |
+
return Text(str(delta), style="progress.elapsed")
|
| 686 |
+
|
| 687 |
+
|
| 688 |
+
class TaskProgressColumn(TextColumn):
|
| 689 |
+
"""Show task progress as a percentage.
|
| 690 |
+
|
| 691 |
+
Args:
|
| 692 |
+
text_format (str, optional): Format for percentage display. Defaults to "[progress.percentage]{task.percentage:>3.0f}%".
|
| 693 |
+
text_format_no_percentage (str, optional): Format if percentage is unknown. Defaults to "".
|
| 694 |
+
style (StyleType, optional): Style of output. Defaults to "none".
|
| 695 |
+
justify (JustifyMethod, optional): Text justification. Defaults to "left".
|
| 696 |
+
markup (bool, optional): Enable markup. Defaults to True.
|
| 697 |
+
highlighter (Optional[Highlighter], optional): Highlighter to apply to output. Defaults to None.
|
| 698 |
+
table_column (Optional[Column], optional): Table Column to use. Defaults to None.
|
| 699 |
+
show_speed (bool, optional): Show speed if total is unknown. Defaults to False.
|
| 700 |
+
"""
|
| 701 |
+
|
| 702 |
+
def __init__(
|
| 703 |
+
self,
|
| 704 |
+
text_format: str = "[progress.percentage]{task.percentage:>3.0f}%",
|
| 705 |
+
text_format_no_percentage: str = "",
|
| 706 |
+
style: StyleType = "none",
|
| 707 |
+
justify: JustifyMethod = "left",
|
| 708 |
+
markup: bool = True,
|
| 709 |
+
highlighter: Optional[Highlighter] = None,
|
| 710 |
+
table_column: Optional[Column] = None,
|
| 711 |
+
show_speed: bool = False,
|
| 712 |
+
) -> None:
|
| 713 |
+
self.text_format_no_percentage = text_format_no_percentage
|
| 714 |
+
self.show_speed = show_speed
|
| 715 |
+
super().__init__(
|
| 716 |
+
text_format=text_format,
|
| 717 |
+
style=style,
|
| 718 |
+
justify=justify,
|
| 719 |
+
markup=markup,
|
| 720 |
+
highlighter=highlighter,
|
| 721 |
+
table_column=table_column,
|
| 722 |
+
)
|
| 723 |
+
|
| 724 |
+
@classmethod
|
| 725 |
+
def render_speed(cls, speed: Optional[float]) -> Text:
|
| 726 |
+
"""Render the speed in iterations per second.
|
| 727 |
+
|
| 728 |
+
Args:
|
| 729 |
+
task (Task): A Task object.
|
| 730 |
+
|
| 731 |
+
Returns:
|
| 732 |
+
Text: Text object containing the task speed.
|
| 733 |
+
"""
|
| 734 |
+
if speed is None:
|
| 735 |
+
return Text("", style="progress.percentage")
|
| 736 |
+
unit, suffix = filesize.pick_unit_and_suffix(
|
| 737 |
+
int(speed),
|
| 738 |
+
["", "×10³", "×10⁶", "×10⁹", "×10¹²"],
|
| 739 |
+
1000,
|
| 740 |
+
)
|
| 741 |
+
data_speed = speed / unit
|
| 742 |
+
return Text(f"{data_speed:.1f}{suffix} it/s", style="progress.percentage")
|
| 743 |
+
|
| 744 |
+
def render(self, task: "Task") -> Text:
|
| 745 |
+
if task.total is None and self.show_speed:
|
| 746 |
+
return self.render_speed(task.finished_speed or task.speed)
|
| 747 |
+
text_format = (
|
| 748 |
+
self.text_format_no_percentage if task.total is None else self.text_format
|
| 749 |
+
)
|
| 750 |
+
_text = text_format.format(task=task)
|
| 751 |
+
if self.markup:
|
| 752 |
+
text = Text.from_markup(_text, style=self.style, justify=self.justify)
|
| 753 |
+
else:
|
| 754 |
+
text = Text(_text, style=self.style, justify=self.justify)
|
| 755 |
+
if self.highlighter:
|
| 756 |
+
self.highlighter.highlight(text)
|
| 757 |
+
return text
|
| 758 |
+
|
| 759 |
+
|
| 760 |
+
class TimeRemainingColumn(ProgressColumn):
|
| 761 |
+
"""Renders estimated time remaining.
|
| 762 |
+
|
| 763 |
+
Args:
|
| 764 |
+
compact (bool, optional): Render MM:SS when time remaining is less than an hour. Defaults to False.
|
| 765 |
+
elapsed_when_finished (bool, optional): Render time elapsed when the task is finished. Defaults to False.
|
| 766 |
+
"""
|
| 767 |
+
|
| 768 |
+
# Only refresh twice a second to prevent jitter
|
| 769 |
+
max_refresh = 0.5
|
| 770 |
+
|
| 771 |
+
def __init__(
|
| 772 |
+
self,
|
| 773 |
+
compact: bool = False,
|
| 774 |
+
elapsed_when_finished: bool = False,
|
| 775 |
+
table_column: Optional[Column] = None,
|
| 776 |
+
):
|
| 777 |
+
self.compact = compact
|
| 778 |
+
self.elapsed_when_finished = elapsed_when_finished
|
| 779 |
+
super().__init__(table_column=table_column)
|
| 780 |
+
|
| 781 |
+
def render(self, task: "Task") -> Text:
|
| 782 |
+
"""Show time remaining."""
|
| 783 |
+
if self.elapsed_when_finished and task.finished:
|
| 784 |
+
task_time = task.finished_time
|
| 785 |
+
style = "progress.elapsed"
|
| 786 |
+
else:
|
| 787 |
+
task_time = task.time_remaining
|
| 788 |
+
style = "progress.remaining"
|
| 789 |
+
|
| 790 |
+
if task.total is None:
|
| 791 |
+
return Text("", style=style)
|
| 792 |
+
|
| 793 |
+
if task_time is None:
|
| 794 |
+
return Text("--:--" if self.compact else "-:--:--", style=style)
|
| 795 |
+
|
| 796 |
+
# Based on https://github.com/tqdm/tqdm/blob/master/tqdm/std.py
|
| 797 |
+
minutes, seconds = divmod(int(task_time), 60)
|
| 798 |
+
hours, minutes = divmod(minutes, 60)
|
| 799 |
+
|
| 800 |
+
if self.compact and not hours:
|
| 801 |
+
formatted = f"{minutes:02d}:{seconds:02d}"
|
| 802 |
+
else:
|
| 803 |
+
formatted = f"{hours:d}:{minutes:02d}:{seconds:02d}"
|
| 804 |
+
|
| 805 |
+
return Text(formatted, style=style)
|
| 806 |
+
|
| 807 |
+
|
| 808 |
+
class FileSizeColumn(ProgressColumn):
|
| 809 |
+
"""Renders completed filesize."""
|
| 810 |
+
|
| 811 |
+
def render(self, task: "Task") -> Text:
|
| 812 |
+
"""Show data completed."""
|
| 813 |
+
data_size = filesize.decimal(int(task.completed))
|
| 814 |
+
return Text(data_size, style="progress.filesize")
|
| 815 |
+
|
| 816 |
+
|
| 817 |
+
class TotalFileSizeColumn(ProgressColumn):
|
| 818 |
+
"""Renders total filesize."""
|
| 819 |
+
|
| 820 |
+
def render(self, task: "Task") -> Text:
|
| 821 |
+
"""Show data completed."""
|
| 822 |
+
data_size = filesize.decimal(int(task.total)) if task.total is not None else ""
|
| 823 |
+
return Text(data_size, style="progress.filesize.total")
|
| 824 |
+
|
| 825 |
+
|
| 826 |
+
class MofNCompleteColumn(ProgressColumn):
|
| 827 |
+
"""Renders completed count/total, e.g. ' 10/1000'.
|
| 828 |
+
|
| 829 |
+
Best for bounded tasks with int quantities.
|
| 830 |
+
|
| 831 |
+
Space pads the completed count so that progress length does not change as task progresses
|
| 832 |
+
past powers of 10.
|
| 833 |
+
|
| 834 |
+
Args:
|
| 835 |
+
separator (str, optional): Text to separate completed and total values. Defaults to "/".
|
| 836 |
+
"""
|
| 837 |
+
|
| 838 |
+
def __init__(self, separator: str = "/", table_column: Optional[Column] = None):
|
| 839 |
+
self.separator = separator
|
| 840 |
+
super().__init__(table_column=table_column)
|
| 841 |
+
|
| 842 |
+
def render(self, task: "Task") -> Text:
|
| 843 |
+
"""Show completed/total."""
|
| 844 |
+
completed = int(task.completed)
|
| 845 |
+
total = int(task.total) if task.total is not None else "?"
|
| 846 |
+
total_width = len(str(total))
|
| 847 |
+
return Text(
|
| 848 |
+
f"{completed:{total_width}d}{self.separator}{total}",
|
| 849 |
+
style="progress.download",
|
| 850 |
+
)
|
| 851 |
+
|
| 852 |
+
|
| 853 |
+
class DownloadColumn(ProgressColumn):
|
| 854 |
+
"""Renders file size downloaded and total, e.g. '0.5/2.3 GB'.
|
| 855 |
+
|
| 856 |
+
Args:
|
| 857 |
+
binary_units (bool, optional): Use binary units, KiB, MiB etc. Defaults to False.
|
| 858 |
+
"""
|
| 859 |
+
|
| 860 |
+
def __init__(
|
| 861 |
+
self, binary_units: bool = False, table_column: Optional[Column] = None
|
| 862 |
+
) -> None:
|
| 863 |
+
self.binary_units = binary_units
|
| 864 |
+
super().__init__(table_column=table_column)
|
| 865 |
+
|
| 866 |
+
def render(self, task: "Task") -> Text:
|
| 867 |
+
"""Calculate common unit for completed and total."""
|
| 868 |
+
completed = int(task.completed)
|
| 869 |
+
|
| 870 |
+
unit_and_suffix_calculation_base = (
|
| 871 |
+
int(task.total) if task.total is not None else completed
|
| 872 |
+
)
|
| 873 |
+
if self.binary_units:
|
| 874 |
+
unit, suffix = filesize.pick_unit_and_suffix(
|
| 875 |
+
unit_and_suffix_calculation_base,
|
| 876 |
+
["bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"],
|
| 877 |
+
1024,
|
| 878 |
+
)
|
| 879 |
+
else:
|
| 880 |
+
unit, suffix = filesize.pick_unit_and_suffix(
|
| 881 |
+
unit_and_suffix_calculation_base,
|
| 882 |
+
["bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
|
| 883 |
+
1000,
|
| 884 |
+
)
|
| 885 |
+
precision = 0 if unit == 1 else 1
|
| 886 |
+
|
| 887 |
+
completed_ratio = completed / unit
|
| 888 |
+
completed_str = f"{completed_ratio:,.{precision}f}"
|
| 889 |
+
|
| 890 |
+
if task.total is not None:
|
| 891 |
+
total = int(task.total)
|
| 892 |
+
total_ratio = total / unit
|
| 893 |
+
total_str = f"{total_ratio:,.{precision}f}"
|
| 894 |
+
else:
|
| 895 |
+
total_str = "?"
|
| 896 |
+
|
| 897 |
+
download_status = f"{completed_str}/{total_str} {suffix}"
|
| 898 |
+
download_text = Text(download_status, style="progress.download")
|
| 899 |
+
return download_text
|
| 900 |
+
|
| 901 |
+
|
| 902 |
+
class TransferSpeedColumn(ProgressColumn):
|
| 903 |
+
"""Renders human readable transfer speed."""
|
| 904 |
+
|
| 905 |
+
def render(self, task: "Task") -> Text:
|
| 906 |
+
"""Show data transfer speed."""
|
| 907 |
+
speed = task.finished_speed or task.speed
|
| 908 |
+
if speed is None:
|
| 909 |
+
return Text("?", style="progress.data.speed")
|
| 910 |
+
data_speed = filesize.decimal(int(speed))
|
| 911 |
+
return Text(f"{data_speed}/s", style="progress.data.speed")
|
| 912 |
+
|
| 913 |
+
|
| 914 |
+
class ProgressSample(NamedTuple):
|
| 915 |
+
"""Sample of progress for a given time."""
|
| 916 |
+
|
| 917 |
+
timestamp: float
|
| 918 |
+
"""Timestamp of sample."""
|
| 919 |
+
completed: float
|
| 920 |
+
"""Number of steps completed."""
|
| 921 |
+
|
| 922 |
+
|
| 923 |
+
@dataclass
|
| 924 |
+
class Task:
|
| 925 |
+
"""Information regarding a progress task.
|
| 926 |
+
|
| 927 |
+
This object should be considered read-only outside of the :class:`~Progress` class.
|
| 928 |
+
|
| 929 |
+
"""
|
| 930 |
+
|
| 931 |
+
id: TaskID
|
| 932 |
+
"""Task ID associated with this task (used in Progress methods)."""
|
| 933 |
+
|
| 934 |
+
description: str
|
| 935 |
+
"""str: Description of the task."""
|
| 936 |
+
|
| 937 |
+
total: Optional[float]
|
| 938 |
+
"""Optional[float]: Total number of steps in this task."""
|
| 939 |
+
|
| 940 |
+
completed: float
|
| 941 |
+
"""float: Number of steps completed"""
|
| 942 |
+
|
| 943 |
+
_get_time: GetTimeCallable
|
| 944 |
+
"""Callable to get the current time."""
|
| 945 |
+
|
| 946 |
+
finished_time: Optional[float] = None
|
| 947 |
+
"""float: Time task was finished."""
|
| 948 |
+
|
| 949 |
+
visible: bool = True
|
| 950 |
+
"""bool: Indicates if this task is visible in the progress display."""
|
| 951 |
+
|
| 952 |
+
fields: Dict[str, Any] = field(default_factory=dict)
|
| 953 |
+
"""dict: Arbitrary fields passed in via Progress.update."""
|
| 954 |
+
|
| 955 |
+
start_time: Optional[float] = field(default=None, init=False, repr=False)
|
| 956 |
+
"""Optional[float]: Time this task was started, or None if not started."""
|
| 957 |
+
|
| 958 |
+
stop_time: Optional[float] = field(default=None, init=False, repr=False)
|
| 959 |
+
"""Optional[float]: Time this task was stopped, or None if not stopped."""
|
| 960 |
+
|
| 961 |
+
finished_speed: Optional[float] = None
|
| 962 |
+
"""Optional[float]: The last speed for a finished task."""
|
| 963 |
+
|
| 964 |
+
_progress: Deque[ProgressSample] = field(
|
| 965 |
+
default_factory=lambda: deque(maxlen=1000), init=False, repr=False
|
| 966 |
+
)
|
| 967 |
+
|
| 968 |
+
_lock: RLock = field(repr=False, default_factory=RLock)
|
| 969 |
+
"""Thread lock."""
|
| 970 |
+
|
| 971 |
+
def get_time(self) -> float:
|
| 972 |
+
"""float: Get the current time, in seconds."""
|
| 973 |
+
return self._get_time()
|
| 974 |
+
|
| 975 |
+
@property
|
| 976 |
+
def started(self) -> bool:
|
| 977 |
+
"""bool: Check if the task as started."""
|
| 978 |
+
return self.start_time is not None
|
| 979 |
+
|
| 980 |
+
@property
|
| 981 |
+
def remaining(self) -> Optional[float]:
|
| 982 |
+
"""Optional[float]: Get the number of steps remaining, if a non-None total was set."""
|
| 983 |
+
if self.total is None:
|
| 984 |
+
return None
|
| 985 |
+
return self.total - self.completed
|
| 986 |
+
|
| 987 |
+
@property
|
| 988 |
+
def elapsed(self) -> Optional[float]:
|
| 989 |
+
"""Optional[float]: Time elapsed since task was started, or ``None`` if the task hasn't started."""
|
| 990 |
+
if self.start_time is None:
|
| 991 |
+
return None
|
| 992 |
+
if self.stop_time is not None:
|
| 993 |
+
return self.stop_time - self.start_time
|
| 994 |
+
return self.get_time() - self.start_time
|
| 995 |
+
|
| 996 |
+
@property
|
| 997 |
+
def finished(self) -> bool:
|
| 998 |
+
"""Check if the task has finished."""
|
| 999 |
+
return self.finished_time is not None
|
| 1000 |
+
|
| 1001 |
+
@property
|
| 1002 |
+
def percentage(self) -> float:
|
| 1003 |
+
"""float: Get progress of task as a percentage. If a None total was set, returns 0"""
|
| 1004 |
+
if not self.total:
|
| 1005 |
+
return 0.0
|
| 1006 |
+
completed = (self.completed / self.total) * 100.0
|
| 1007 |
+
completed = min(100.0, max(0.0, completed))
|
| 1008 |
+
return completed
|
| 1009 |
+
|
| 1010 |
+
@property
|
| 1011 |
+
def speed(self) -> Optional[float]:
|
| 1012 |
+
"""Optional[float]: Get the estimated speed in steps per second."""
|
| 1013 |
+
if self.start_time is None:
|
| 1014 |
+
return None
|
| 1015 |
+
with self._lock:
|
| 1016 |
+
progress = self._progress
|
| 1017 |
+
if not progress:
|
| 1018 |
+
return None
|
| 1019 |
+
total_time = progress[-1].timestamp - progress[0].timestamp
|
| 1020 |
+
if total_time == 0:
|
| 1021 |
+
return None
|
| 1022 |
+
iter_progress = iter(progress)
|
| 1023 |
+
next(iter_progress)
|
| 1024 |
+
total_completed = sum(sample.completed for sample in iter_progress)
|
| 1025 |
+
speed = total_completed / total_time
|
| 1026 |
+
return speed
|
| 1027 |
+
|
| 1028 |
+
@property
|
| 1029 |
+
def time_remaining(self) -> Optional[float]:
|
| 1030 |
+
"""Optional[float]: Get estimated time to completion, or ``None`` if no data."""
|
| 1031 |
+
if self.finished:
|
| 1032 |
+
return 0.0
|
| 1033 |
+
speed = self.speed
|
| 1034 |
+
if not speed:
|
| 1035 |
+
return None
|
| 1036 |
+
remaining = self.remaining
|
| 1037 |
+
if remaining is None:
|
| 1038 |
+
return None
|
| 1039 |
+
estimate = ceil(remaining / speed)
|
| 1040 |
+
return estimate
|
| 1041 |
+
|
| 1042 |
+
def _reset(self) -> None:
|
| 1043 |
+
"""Reset progress."""
|
| 1044 |
+
self._progress.clear()
|
| 1045 |
+
self.finished_time = None
|
| 1046 |
+
self.finished_speed = None
|
| 1047 |
+
|
| 1048 |
+
|
| 1049 |
+
class Progress(JupyterMixin):
|
| 1050 |
+
"""Renders an auto-updating progress bar(s).
|
| 1051 |
+
|
| 1052 |
+
Args:
|
| 1053 |
+
console (Console, optional): Optional Console instance. Default will an internal Console instance writing to stdout.
|
| 1054 |
+
auto_refresh (bool, optional): Enable auto refresh. If disabled, you will need to call `refresh()`.
|
| 1055 |
+
refresh_per_second (Optional[float], optional): Number of times per second to refresh the progress information or None to use default (10). Defaults to None.
|
| 1056 |
+
speed_estimate_period: (float, optional): Period (in seconds) used to calculate the speed estimate. Defaults to 30.
|
| 1057 |
+
transient: (bool, optional): Clear the progress on exit. Defaults to False.
|
| 1058 |
+
redirect_stdout: (bool, optional): Enable redirection of stdout, so ``print`` may be used. Defaults to True.
|
| 1059 |
+
redirect_stderr: (bool, optional): Enable redirection of stderr. Defaults to True.
|
| 1060 |
+
get_time: (Callable, optional): A callable that gets the current time, or None to use Console.get_time. Defaults to None.
|
| 1061 |
+
disable (bool, optional): Disable progress display. Defaults to False
|
| 1062 |
+
expand (bool, optional): Expand tasks table to fit width. Defaults to False.
|
| 1063 |
+
"""
|
| 1064 |
+
|
| 1065 |
+
def __init__(
|
| 1066 |
+
self,
|
| 1067 |
+
*columns: Union[str, ProgressColumn],
|
| 1068 |
+
console: Optional[Console] = None,
|
| 1069 |
+
auto_refresh: bool = True,
|
| 1070 |
+
refresh_per_second: float = 10,
|
| 1071 |
+
speed_estimate_period: float = 30.0,
|
| 1072 |
+
transient: bool = False,
|
| 1073 |
+
redirect_stdout: bool = True,
|
| 1074 |
+
redirect_stderr: bool = True,
|
| 1075 |
+
get_time: Optional[GetTimeCallable] = None,
|
| 1076 |
+
disable: bool = False,
|
| 1077 |
+
expand: bool = False,
|
| 1078 |
+
) -> None:
|
| 1079 |
+
assert refresh_per_second > 0, "refresh_per_second must be > 0"
|
| 1080 |
+
self._lock = RLock()
|
| 1081 |
+
self.columns = columns or self.get_default_columns()
|
| 1082 |
+
self.speed_estimate_period = speed_estimate_period
|
| 1083 |
+
|
| 1084 |
+
self.disable = disable
|
| 1085 |
+
self.expand = expand
|
| 1086 |
+
self._tasks: Dict[TaskID, Task] = {}
|
| 1087 |
+
self._task_index: TaskID = TaskID(0)
|
| 1088 |
+
self.live = Live(
|
| 1089 |
+
console=console or get_console(),
|
| 1090 |
+
auto_refresh=auto_refresh,
|
| 1091 |
+
refresh_per_second=refresh_per_second,
|
| 1092 |
+
transient=transient,
|
| 1093 |
+
redirect_stdout=redirect_stdout,
|
| 1094 |
+
redirect_stderr=redirect_stderr,
|
| 1095 |
+
get_renderable=self.get_renderable,
|
| 1096 |
+
)
|
| 1097 |
+
self.get_time = get_time or self.console.get_time
|
| 1098 |
+
self.print = self.console.print
|
| 1099 |
+
self.log = self.console.log
|
| 1100 |
+
|
| 1101 |
+
@classmethod
|
| 1102 |
+
def get_default_columns(cls) -> Tuple[ProgressColumn, ...]:
|
| 1103 |
+
"""Get the default columns used for a new Progress instance:
|
| 1104 |
+
- a text column for the description (TextColumn)
|
| 1105 |
+
- the bar itself (BarColumn)
|
| 1106 |
+
- a text column showing completion percentage (TextColumn)
|
| 1107 |
+
- an estimated-time-remaining column (TimeRemainingColumn)
|
| 1108 |
+
If the Progress instance is created without passing a columns argument,
|
| 1109 |
+
the default columns defined here will be used.
|
| 1110 |
+
|
| 1111 |
+
You can also create a Progress instance using custom columns before
|
| 1112 |
+
and/or after the defaults, as in this example:
|
| 1113 |
+
|
| 1114 |
+
progress = Progress(
|
| 1115 |
+
SpinnerColumn(),
|
| 1116 |
+
*Progress.get_default_columns(),
|
| 1117 |
+
"Elapsed:",
|
| 1118 |
+
TimeElapsedColumn(),
|
| 1119 |
+
)
|
| 1120 |
+
|
| 1121 |
+
This code shows the creation of a Progress display, containing
|
| 1122 |
+
a spinner to the left, the default columns, and a labeled elapsed
|
| 1123 |
+
time column.
|
| 1124 |
+
"""
|
| 1125 |
+
return (
|
| 1126 |
+
TextColumn("[progress.description]{task.description}"),
|
| 1127 |
+
BarColumn(),
|
| 1128 |
+
TaskProgressColumn(),
|
| 1129 |
+
TimeRemainingColumn(),
|
| 1130 |
+
)
|
| 1131 |
+
|
| 1132 |
+
@property
|
| 1133 |
+
def console(self) -> Console:
|
| 1134 |
+
return self.live.console
|
| 1135 |
+
|
| 1136 |
+
@property
|
| 1137 |
+
def tasks(self) -> List[Task]:
|
| 1138 |
+
"""Get a list of Task instances."""
|
| 1139 |
+
with self._lock:
|
| 1140 |
+
return list(self._tasks.values())
|
| 1141 |
+
|
| 1142 |
+
@property
|
| 1143 |
+
def task_ids(self) -> List[TaskID]:
|
| 1144 |
+
"""A list of task IDs."""
|
| 1145 |
+
with self._lock:
|
| 1146 |
+
return list(self._tasks.keys())
|
| 1147 |
+
|
| 1148 |
+
@property
|
| 1149 |
+
def finished(self) -> bool:
|
| 1150 |
+
"""Check if all tasks have been completed."""
|
| 1151 |
+
with self._lock:
|
| 1152 |
+
if not self._tasks:
|
| 1153 |
+
return True
|
| 1154 |
+
return all(task.finished for task in self._tasks.values())
|
| 1155 |
+
|
| 1156 |
+
def start(self) -> None:
|
| 1157 |
+
"""Start the progress display."""
|
| 1158 |
+
if not self.disable:
|
| 1159 |
+
self.live.start(refresh=True)
|
| 1160 |
+
|
| 1161 |
+
def stop(self) -> None:
|
| 1162 |
+
"""Stop the progress display."""
|
| 1163 |
+
self.live.stop()
|
| 1164 |
+
if not self.console.is_interactive:
|
| 1165 |
+
self.console.print()
|
| 1166 |
+
|
| 1167 |
+
def __enter__(self) -> "Progress":
|
| 1168 |
+
self.start()
|
| 1169 |
+
return self
|
| 1170 |
+
|
| 1171 |
+
def __exit__(
|
| 1172 |
+
self,
|
| 1173 |
+
exc_type: Optional[Type[BaseException]],
|
| 1174 |
+
exc_val: Optional[BaseException],
|
| 1175 |
+
exc_tb: Optional[TracebackType],
|
| 1176 |
+
) -> None:
|
| 1177 |
+
self.stop()
|
| 1178 |
+
|
| 1179 |
+
def track(
|
| 1180 |
+
self,
|
| 1181 |
+
sequence: Union[Iterable[ProgressType], Sequence[ProgressType]],
|
| 1182 |
+
total: Optional[float] = None,
|
| 1183 |
+
task_id: Optional[TaskID] = None,
|
| 1184 |
+
description: str = "Working...",
|
| 1185 |
+
update_period: float = 0.1,
|
| 1186 |
+
) -> Iterable[ProgressType]:
|
| 1187 |
+
"""Track progress by iterating over a sequence.
|
| 1188 |
+
|
| 1189 |
+
Args:
|
| 1190 |
+
sequence (Sequence[ProgressType]): A sequence of values you want to iterate over and track progress.
|
| 1191 |
+
total: (float, optional): Total number of steps. Default is len(sequence).
|
| 1192 |
+
task_id: (TaskID): Task to track. Default is new task.
|
| 1193 |
+
description: (str, optional): Description of task, if new task is created.
|
| 1194 |
+
update_period (float, optional): Minimum time (in seconds) between calls to update(). Defaults to 0.1.
|
| 1195 |
+
|
| 1196 |
+
Returns:
|
| 1197 |
+
Iterable[ProgressType]: An iterable of values taken from the provided sequence.
|
| 1198 |
+
"""
|
| 1199 |
+
if total is None:
|
| 1200 |
+
total = float(length_hint(sequence)) or None
|
| 1201 |
+
|
| 1202 |
+
if task_id is None:
|
| 1203 |
+
task_id = self.add_task(description, total=total)
|
| 1204 |
+
else:
|
| 1205 |
+
self.update(task_id, total=total)
|
| 1206 |
+
|
| 1207 |
+
if self.live.auto_refresh:
|
| 1208 |
+
with _TrackThread(self, task_id, update_period) as track_thread:
|
| 1209 |
+
for value in sequence:
|
| 1210 |
+
yield value
|
| 1211 |
+
track_thread.completed += 1
|
| 1212 |
+
else:
|
| 1213 |
+
advance = self.advance
|
| 1214 |
+
refresh = self.refresh
|
| 1215 |
+
for value in sequence:
|
| 1216 |
+
yield value
|
| 1217 |
+
advance(task_id, 1)
|
| 1218 |
+
refresh()
|
| 1219 |
+
|
| 1220 |
+
def wrap_file(
|
| 1221 |
+
self,
|
| 1222 |
+
file: BinaryIO,
|
| 1223 |
+
total: Optional[int] = None,
|
| 1224 |
+
*,
|
| 1225 |
+
task_id: Optional[TaskID] = None,
|
| 1226 |
+
description: str = "Reading...",
|
| 1227 |
+
) -> BinaryIO:
|
| 1228 |
+
"""Track progress file reading from a binary file.
|
| 1229 |
+
|
| 1230 |
+
Args:
|
| 1231 |
+
file (BinaryIO): A file-like object opened in binary mode.
|
| 1232 |
+
total (int, optional): Total number of bytes to read. This must be provided unless a task with a total is also given.
|
| 1233 |
+
task_id (TaskID): Task to track. Default is new task.
|
| 1234 |
+
description (str, optional): Description of task, if new task is created.
|
| 1235 |
+
|
| 1236 |
+
Returns:
|
| 1237 |
+
BinaryIO: A readable file-like object in binary mode.
|
| 1238 |
+
|
| 1239 |
+
Raises:
|
| 1240 |
+
ValueError: When no total value can be extracted from the arguments or the task.
|
| 1241 |
+
"""
|
| 1242 |
+
# attempt to recover the total from the task
|
| 1243 |
+
total_bytes: Optional[float] = None
|
| 1244 |
+
if total is not None:
|
| 1245 |
+
total_bytes = total
|
| 1246 |
+
elif task_id is not None:
|
| 1247 |
+
with self._lock:
|
| 1248 |
+
total_bytes = self._tasks[task_id].total
|
| 1249 |
+
if total_bytes is None:
|
| 1250 |
+
raise ValueError(
|
| 1251 |
+
f"unable to get the total number of bytes, please specify 'total'"
|
| 1252 |
+
)
|
| 1253 |
+
|
| 1254 |
+
# update total of task or create new task
|
| 1255 |
+
if task_id is None:
|
| 1256 |
+
task_id = self.add_task(description, total=total_bytes)
|
| 1257 |
+
else:
|
| 1258 |
+
self.update(task_id, total=total_bytes)
|
| 1259 |
+
|
| 1260 |
+
return _Reader(file, self, task_id, close_handle=False)
|
| 1261 |
+
|
| 1262 |
+
@typing.overload
|
| 1263 |
+
def open(
|
| 1264 |
+
self,
|
| 1265 |
+
file: Union[str, "PathLike[str]", bytes],
|
| 1266 |
+
mode: Literal["rb"],
|
| 1267 |
+
buffering: int = -1,
|
| 1268 |
+
encoding: Optional[str] = None,
|
| 1269 |
+
errors: Optional[str] = None,
|
| 1270 |
+
newline: Optional[str] = None,
|
| 1271 |
+
*,
|
| 1272 |
+
total: Optional[int] = None,
|
| 1273 |
+
task_id: Optional[TaskID] = None,
|
| 1274 |
+
description: str = "Reading...",
|
| 1275 |
+
) -> BinaryIO:
|
| 1276 |
+
pass
|
| 1277 |
+
|
| 1278 |
+
@typing.overload
|
| 1279 |
+
def open(
|
| 1280 |
+
self,
|
| 1281 |
+
file: Union[str, "PathLike[str]", bytes],
|
| 1282 |
+
mode: Union[Literal["r"], Literal["rt"]],
|
| 1283 |
+
buffering: int = -1,
|
| 1284 |
+
encoding: Optional[str] = None,
|
| 1285 |
+
errors: Optional[str] = None,
|
| 1286 |
+
newline: Optional[str] = None,
|
| 1287 |
+
*,
|
| 1288 |
+
total: Optional[int] = None,
|
| 1289 |
+
task_id: Optional[TaskID] = None,
|
| 1290 |
+
description: str = "Reading...",
|
| 1291 |
+
) -> TextIO:
|
| 1292 |
+
pass
|
| 1293 |
+
|
| 1294 |
+
def open(
|
| 1295 |
+
self,
|
| 1296 |
+
file: Union[str, "PathLike[str]", bytes],
|
| 1297 |
+
mode: Union[Literal["rb"], Literal["rt"], Literal["r"]] = "r",
|
| 1298 |
+
buffering: int = -1,
|
| 1299 |
+
encoding: Optional[str] = None,
|
| 1300 |
+
errors: Optional[str] = None,
|
| 1301 |
+
newline: Optional[str] = None,
|
| 1302 |
+
*,
|
| 1303 |
+
total: Optional[int] = None,
|
| 1304 |
+
task_id: Optional[TaskID] = None,
|
| 1305 |
+
description: str = "Reading...",
|
| 1306 |
+
) -> Union[BinaryIO, TextIO]:
|
| 1307 |
+
"""Track progress while reading from a binary file.
|
| 1308 |
+
|
| 1309 |
+
Args:
|
| 1310 |
+
path (Union[str, PathLike[str]]): The path to the file to read.
|
| 1311 |
+
mode (str): The mode to use to open the file. Only supports "r", "rb" or "rt".
|
| 1312 |
+
buffering (int): The buffering strategy to use, see :func:`io.open`.
|
| 1313 |
+
encoding (str, optional): The encoding to use when reading in text mode, see :func:`io.open`.
|
| 1314 |
+
errors (str, optional): The error handling strategy for decoding errors, see :func:`io.open`.
|
| 1315 |
+
newline (str, optional): The strategy for handling newlines in text mode, see :func:`io.open`.
|
| 1316 |
+
total (int, optional): Total number of bytes to read. If none given, os.stat(path).st_size is used.
|
| 1317 |
+
task_id (TaskID): Task to track. Default is new task.
|
| 1318 |
+
description (str, optional): Description of task, if new task is created.
|
| 1319 |
+
|
| 1320 |
+
Returns:
|
| 1321 |
+
BinaryIO: A readable file-like object in binary mode.
|
| 1322 |
+
|
| 1323 |
+
Raises:
|
| 1324 |
+
ValueError: When an invalid mode is given.
|
| 1325 |
+
"""
|
| 1326 |
+
# normalize the mode (always rb, rt)
|
| 1327 |
+
_mode = "".join(sorted(mode, reverse=False))
|
| 1328 |
+
if _mode not in ("br", "rt", "r"):
|
| 1329 |
+
raise ValueError("invalid mode {!r}".format(mode))
|
| 1330 |
+
|
| 1331 |
+
# patch buffering to provide the same behaviour as the builtin `open`
|
| 1332 |
+
line_buffering = buffering == 1
|
| 1333 |
+
if _mode == "br" and buffering == 1:
|
| 1334 |
+
warnings.warn(
|
| 1335 |
+
"line buffering (buffering=1) isn't supported in binary mode, the default buffer size will be used",
|
| 1336 |
+
RuntimeWarning,
|
| 1337 |
+
)
|
| 1338 |
+
buffering = -1
|
| 1339 |
+
elif _mode in ("rt", "r"):
|
| 1340 |
+
if buffering == 0:
|
| 1341 |
+
raise ValueError("can't have unbuffered text I/O")
|
| 1342 |
+
elif buffering == 1:
|
| 1343 |
+
buffering = -1
|
| 1344 |
+
|
| 1345 |
+
# attempt to get the total with `os.stat`
|
| 1346 |
+
if total is None:
|
| 1347 |
+
total = stat(file).st_size
|
| 1348 |
+
|
| 1349 |
+
# update total of task or create new task
|
| 1350 |
+
if task_id is None:
|
| 1351 |
+
task_id = self.add_task(description, total=total)
|
| 1352 |
+
else:
|
| 1353 |
+
self.update(task_id, total=total)
|
| 1354 |
+
|
| 1355 |
+
# open the file in binary mode,
|
| 1356 |
+
handle = io.open(file, "rb", buffering=buffering)
|
| 1357 |
+
reader = _Reader(handle, self, task_id, close_handle=True)
|
| 1358 |
+
|
| 1359 |
+
# wrap the reader in a `TextIOWrapper` if text mode
|
| 1360 |
+
if mode in ("r", "rt"):
|
| 1361 |
+
return io.TextIOWrapper(
|
| 1362 |
+
reader,
|
| 1363 |
+
encoding=encoding,
|
| 1364 |
+
errors=errors,
|
| 1365 |
+
newline=newline,
|
| 1366 |
+
line_buffering=line_buffering,
|
| 1367 |
+
)
|
| 1368 |
+
|
| 1369 |
+
return reader
|
| 1370 |
+
|
| 1371 |
+
def start_task(self, task_id: TaskID) -> None:
|
| 1372 |
+
"""Start a task.
|
| 1373 |
+
|
| 1374 |
+
Starts a task (used when calculating elapsed time). You may need to call this manually,
|
| 1375 |
+
if you called ``add_task`` with ``start=False``.
|
| 1376 |
+
|
| 1377 |
+
Args:
|
| 1378 |
+
task_id (TaskID): ID of task.
|
| 1379 |
+
"""
|
| 1380 |
+
with self._lock:
|
| 1381 |
+
task = self._tasks[task_id]
|
| 1382 |
+
if task.start_time is None:
|
| 1383 |
+
task.start_time = self.get_time()
|
| 1384 |
+
|
| 1385 |
+
def stop_task(self, task_id: TaskID) -> None:
|
| 1386 |
+
"""Stop a task.
|
| 1387 |
+
|
| 1388 |
+
This will freeze the elapsed time on the task.
|
| 1389 |
+
|
| 1390 |
+
Args:
|
| 1391 |
+
task_id (TaskID): ID of task.
|
| 1392 |
+
"""
|
| 1393 |
+
with self._lock:
|
| 1394 |
+
task = self._tasks[task_id]
|
| 1395 |
+
current_time = self.get_time()
|
| 1396 |
+
if task.start_time is None:
|
| 1397 |
+
task.start_time = current_time
|
| 1398 |
+
task.stop_time = current_time
|
| 1399 |
+
|
| 1400 |
+
def update(
|
| 1401 |
+
self,
|
| 1402 |
+
task_id: TaskID,
|
| 1403 |
+
*,
|
| 1404 |
+
total: Optional[float] = None,
|
| 1405 |
+
completed: Optional[float] = None,
|
| 1406 |
+
advance: Optional[float] = None,
|
| 1407 |
+
description: Optional[str] = None,
|
| 1408 |
+
visible: Optional[bool] = None,
|
| 1409 |
+
refresh: bool = False,
|
| 1410 |
+
**fields: Any,
|
| 1411 |
+
) -> None:
|
| 1412 |
+
"""Update information associated with a task.
|
| 1413 |
+
|
| 1414 |
+
Args:
|
| 1415 |
+
task_id (TaskID): Task id (returned by add_task).
|
| 1416 |
+
total (float, optional): Updates task.total if not None.
|
| 1417 |
+
completed (float, optional): Updates task.completed if not None.
|
| 1418 |
+
advance (float, optional): Add a value to task.completed if not None.
|
| 1419 |
+
description (str, optional): Change task description if not None.
|
| 1420 |
+
visible (bool, optional): Set visible flag if not None.
|
| 1421 |
+
refresh (bool): Force a refresh of progress information. Default is False.
|
| 1422 |
+
**fields (Any): Additional data fields required for rendering.
|
| 1423 |
+
"""
|
| 1424 |
+
with self._lock:
|
| 1425 |
+
task = self._tasks[task_id]
|
| 1426 |
+
completed_start = task.completed
|
| 1427 |
+
|
| 1428 |
+
if total is not None and total != task.total:
|
| 1429 |
+
task.total = total
|
| 1430 |
+
task._reset()
|
| 1431 |
+
if advance is not None:
|
| 1432 |
+
task.completed += advance
|
| 1433 |
+
if completed is not None:
|
| 1434 |
+
task.completed = completed
|
| 1435 |
+
if description is not None:
|
| 1436 |
+
task.description = description
|
| 1437 |
+
if visible is not None:
|
| 1438 |
+
task.visible = visible
|
| 1439 |
+
task.fields.update(fields)
|
| 1440 |
+
update_completed = task.completed - completed_start
|
| 1441 |
+
|
| 1442 |
+
current_time = self.get_time()
|
| 1443 |
+
old_sample_time = current_time - self.speed_estimate_period
|
| 1444 |
+
_progress = task._progress
|
| 1445 |
+
|
| 1446 |
+
popleft = _progress.popleft
|
| 1447 |
+
while _progress and _progress[0].timestamp < old_sample_time:
|
| 1448 |
+
popleft()
|
| 1449 |
+
if update_completed > 0:
|
| 1450 |
+
_progress.append(ProgressSample(current_time, update_completed))
|
| 1451 |
+
if (
|
| 1452 |
+
task.total is not None
|
| 1453 |
+
and task.completed >= task.total
|
| 1454 |
+
and task.finished_time is None
|
| 1455 |
+
):
|
| 1456 |
+
task.finished_time = task.elapsed
|
| 1457 |
+
|
| 1458 |
+
if refresh:
|
| 1459 |
+
self.refresh()
|
| 1460 |
+
|
| 1461 |
+
def reset(
|
| 1462 |
+
self,
|
| 1463 |
+
task_id: TaskID,
|
| 1464 |
+
*,
|
| 1465 |
+
start: bool = True,
|
| 1466 |
+
total: Optional[float] = None,
|
| 1467 |
+
completed: int = 0,
|
| 1468 |
+
visible: Optional[bool] = None,
|
| 1469 |
+
description: Optional[str] = None,
|
| 1470 |
+
**fields: Any,
|
| 1471 |
+
) -> None:
|
| 1472 |
+
"""Reset a task so completed is 0 and the clock is reset.
|
| 1473 |
+
|
| 1474 |
+
Args:
|
| 1475 |
+
task_id (TaskID): ID of task.
|
| 1476 |
+
start (bool, optional): Start the task after reset. Defaults to True.
|
| 1477 |
+
total (float, optional): New total steps in task, or None to use current total. Defaults to None.
|
| 1478 |
+
completed (int, optional): Number of steps completed. Defaults to 0.
|
| 1479 |
+
visible (bool, optional): Enable display of the task. Defaults to True.
|
| 1480 |
+
description (str, optional): Change task description if not None. Defaults to None.
|
| 1481 |
+
**fields (str): Additional data fields required for rendering.
|
| 1482 |
+
"""
|
| 1483 |
+
current_time = self.get_time()
|
| 1484 |
+
with self._lock:
|
| 1485 |
+
task = self._tasks[task_id]
|
| 1486 |
+
task._reset()
|
| 1487 |
+
task.start_time = current_time if start else None
|
| 1488 |
+
if total is not None:
|
| 1489 |
+
task.total = total
|
| 1490 |
+
task.completed = completed
|
| 1491 |
+
if visible is not None:
|
| 1492 |
+
task.visible = visible
|
| 1493 |
+
if fields:
|
| 1494 |
+
task.fields = fields
|
| 1495 |
+
if description is not None:
|
| 1496 |
+
task.description = description
|
| 1497 |
+
task.finished_time = None
|
| 1498 |
+
self.refresh()
|
| 1499 |
+
|
| 1500 |
+
def advance(self, task_id: TaskID, advance: float = 1) -> None:
|
| 1501 |
+
"""Advance task by a number of steps.
|
| 1502 |
+
|
| 1503 |
+
Args:
|
| 1504 |
+
task_id (TaskID): ID of task.
|
| 1505 |
+
advance (float): Number of steps to advance. Default is 1.
|
| 1506 |
+
"""
|
| 1507 |
+
current_time = self.get_time()
|
| 1508 |
+
with self._lock:
|
| 1509 |
+
task = self._tasks[task_id]
|
| 1510 |
+
completed_start = task.completed
|
| 1511 |
+
task.completed += advance
|
| 1512 |
+
update_completed = task.completed - completed_start
|
| 1513 |
+
old_sample_time = current_time - self.speed_estimate_period
|
| 1514 |
+
_progress = task._progress
|
| 1515 |
+
|
| 1516 |
+
popleft = _progress.popleft
|
| 1517 |
+
while _progress and _progress[0].timestamp < old_sample_time:
|
| 1518 |
+
popleft()
|
| 1519 |
+
while len(_progress) > 1000:
|
| 1520 |
+
popleft()
|
| 1521 |
+
_progress.append(ProgressSample(current_time, update_completed))
|
| 1522 |
+
if (
|
| 1523 |
+
task.total is not None
|
| 1524 |
+
and task.completed >= task.total
|
| 1525 |
+
and task.finished_time is None
|
| 1526 |
+
):
|
| 1527 |
+
task.finished_time = task.elapsed
|
| 1528 |
+
task.finished_speed = task.speed
|
| 1529 |
+
|
| 1530 |
+
def refresh(self) -> None:
|
| 1531 |
+
"""Refresh (render) the progress information."""
|
| 1532 |
+
if not self.disable and self.live.is_started:
|
| 1533 |
+
self.live.refresh()
|
| 1534 |
+
|
| 1535 |
+
def get_renderable(self) -> RenderableType:
|
| 1536 |
+
"""Get a renderable for the progress display."""
|
| 1537 |
+
renderable = Group(*self.get_renderables())
|
| 1538 |
+
return renderable
|
| 1539 |
+
|
| 1540 |
+
def get_renderables(self) -> Iterable[RenderableType]:
|
| 1541 |
+
"""Get a number of renderables for the progress display."""
|
| 1542 |
+
table = self.make_tasks_table(self.tasks)
|
| 1543 |
+
yield table
|
| 1544 |
+
|
| 1545 |
+
def make_tasks_table(self, tasks: Iterable[Task]) -> Table:
|
| 1546 |
+
"""Get a table to render the Progress display.
|
| 1547 |
+
|
| 1548 |
+
Args:
|
| 1549 |
+
tasks (Iterable[Task]): An iterable of Task instances, one per row of the table.
|
| 1550 |
+
|
| 1551 |
+
Returns:
|
| 1552 |
+
Table: A table instance.
|
| 1553 |
+
"""
|
| 1554 |
+
table_columns = (
|
| 1555 |
+
(
|
| 1556 |
+
Column(no_wrap=True)
|
| 1557 |
+
if isinstance(_column, str)
|
| 1558 |
+
else _column.get_table_column().copy()
|
| 1559 |
+
)
|
| 1560 |
+
for _column in self.columns
|
| 1561 |
+
)
|
| 1562 |
+
table = Table.grid(*table_columns, padding=(0, 1), expand=self.expand)
|
| 1563 |
+
|
| 1564 |
+
for task in tasks:
|
| 1565 |
+
if task.visible:
|
| 1566 |
+
table.add_row(
|
| 1567 |
+
*(
|
| 1568 |
+
(
|
| 1569 |
+
column.format(task=task)
|
| 1570 |
+
if isinstance(column, str)
|
| 1571 |
+
else column(task)
|
| 1572 |
+
)
|
| 1573 |
+
for column in self.columns
|
| 1574 |
+
)
|
| 1575 |
+
)
|
| 1576 |
+
return table
|
| 1577 |
+
|
| 1578 |
+
def __rich__(self) -> RenderableType:
|
| 1579 |
+
"""Makes the Progress class itself renderable."""
|
| 1580 |
+
with self._lock:
|
| 1581 |
+
return self.get_renderable()
|
| 1582 |
+
|
| 1583 |
+
def add_task(
|
| 1584 |
+
self,
|
| 1585 |
+
description: str,
|
| 1586 |
+
start: bool = True,
|
| 1587 |
+
total: Optional[float] = 100.0,
|
| 1588 |
+
completed: int = 0,
|
| 1589 |
+
visible: bool = True,
|
| 1590 |
+
**fields: Any,
|
| 1591 |
+
) -> TaskID:
|
| 1592 |
+
"""Add a new 'task' to the Progress display.
|
| 1593 |
+
|
| 1594 |
+
Args:
|
| 1595 |
+
description (str): A description of the task.
|
| 1596 |
+
start (bool, optional): Start the task immediately (to calculate elapsed time). If set to False,
|
| 1597 |
+
you will need to call `start` manually. Defaults to True.
|
| 1598 |
+
total (float, optional): Number of total steps in the progress if known.
|
| 1599 |
+
Set to None to render a pulsing animation. Defaults to 100.
|
| 1600 |
+
completed (int, optional): Number of steps completed so far. Defaults to 0.
|
| 1601 |
+
visible (bool, optional): Enable display of the task. Defaults to True.
|
| 1602 |
+
**fields (str): Additional data fields required for rendering.
|
| 1603 |
+
|
| 1604 |
+
Returns:
|
| 1605 |
+
TaskID: An ID you can use when calling `update`.
|
| 1606 |
+
"""
|
| 1607 |
+
with self._lock:
|
| 1608 |
+
task = Task(
|
| 1609 |
+
self._task_index,
|
| 1610 |
+
description,
|
| 1611 |
+
total,
|
| 1612 |
+
completed,
|
| 1613 |
+
visible=visible,
|
| 1614 |
+
fields=fields,
|
| 1615 |
+
_get_time=self.get_time,
|
| 1616 |
+
_lock=self._lock,
|
| 1617 |
+
)
|
| 1618 |
+
self._tasks[self._task_index] = task
|
| 1619 |
+
if start:
|
| 1620 |
+
self.start_task(self._task_index)
|
| 1621 |
+
new_task_index = self._task_index
|
| 1622 |
+
self._task_index = TaskID(int(self._task_index) + 1)
|
| 1623 |
+
self.refresh()
|
| 1624 |
+
return new_task_index
|
| 1625 |
+
|
| 1626 |
+
def remove_task(self, task_id: TaskID) -> None:
|
| 1627 |
+
"""Delete a task if it exists.
|
| 1628 |
+
|
| 1629 |
+
Args:
|
| 1630 |
+
task_id (TaskID): A task ID.
|
| 1631 |
+
|
| 1632 |
+
"""
|
| 1633 |
+
with self._lock:
|
| 1634 |
+
del self._tasks[task_id]
|
| 1635 |
+
|
| 1636 |
+
|
| 1637 |
+
if __name__ == "__main__": # pragma: no coverage
|
| 1638 |
+
import random
|
| 1639 |
+
import time
|
| 1640 |
+
|
| 1641 |
+
from .panel import Panel
|
| 1642 |
+
from .rule import Rule
|
| 1643 |
+
from .syntax import Syntax
|
| 1644 |
+
from .table import Table
|
| 1645 |
+
|
| 1646 |
+
syntax = Syntax(
|
| 1647 |
+
'''def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
|
| 1648 |
+
"""Iterate and generate a tuple with a flag for last value."""
|
| 1649 |
+
iter_values = iter(values)
|
| 1650 |
+
try:
|
| 1651 |
+
previous_value = next(iter_values)
|
| 1652 |
+
except StopIteration:
|
| 1653 |
+
return
|
| 1654 |
+
for value in iter_values:
|
| 1655 |
+
yield False, previous_value
|
| 1656 |
+
previous_value = value
|
| 1657 |
+
yield True, previous_value''',
|
| 1658 |
+
"python",
|
| 1659 |
+
line_numbers=True,
|
| 1660 |
+
)
|
| 1661 |
+
|
| 1662 |
+
table = Table("foo", "bar", "baz")
|
| 1663 |
+
table.add_row("1", "2", "3")
|
| 1664 |
+
|
| 1665 |
+
progress_renderables = [
|
| 1666 |
+
"Text may be printed while the progress bars are rendering.",
|
| 1667 |
+
Panel("In fact, [i]any[/i] renderable will work"),
|
| 1668 |
+
"Such as [magenta]tables[/]...",
|
| 1669 |
+
table,
|
| 1670 |
+
"Pretty printed structures...",
|
| 1671 |
+
{"type": "example", "text": "Pretty printed"},
|
| 1672 |
+
"Syntax...",
|
| 1673 |
+
syntax,
|
| 1674 |
+
Rule("Give it a try!"),
|
| 1675 |
+
]
|
| 1676 |
+
|
| 1677 |
+
from itertools import cycle
|
| 1678 |
+
|
| 1679 |
+
examples = cycle(progress_renderables)
|
| 1680 |
+
|
| 1681 |
+
console = Console(record=True)
|
| 1682 |
+
|
| 1683 |
+
with Progress(
|
| 1684 |
+
SpinnerColumn(),
|
| 1685 |
+
*Progress.get_default_columns(),
|
| 1686 |
+
TimeElapsedColumn(),
|
| 1687 |
+
console=console,
|
| 1688 |
+
transient=False,
|
| 1689 |
+
) as progress:
|
| 1690 |
+
task1 = progress.add_task("[red]Downloading", total=1000)
|
| 1691 |
+
task2 = progress.add_task("[green]Processing", total=1000)
|
| 1692 |
+
task3 = progress.add_task("[yellow]Thinking", total=None)
|
| 1693 |
+
|
| 1694 |
+
while not progress.finished:
|
| 1695 |
+
progress.update(task1, advance=0.5)
|
| 1696 |
+
progress.update(task2, advance=0.3)
|
| 1697 |
+
time.sleep(0.01)
|
| 1698 |
+
if random.randint(0, 100) < 1:
|
| 1699 |
+
progress.log(next(examples))
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/rule.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Union
|
| 2 |
+
|
| 3 |
+
from .align import AlignMethod
|
| 4 |
+
from .cells import cell_len, set_cell_size
|
| 5 |
+
from .console import Console, ConsoleOptions, RenderResult
|
| 6 |
+
from .jupyter import JupyterMixin
|
| 7 |
+
from .measure import Measurement
|
| 8 |
+
from .style import Style
|
| 9 |
+
from .text import Text
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class Rule(JupyterMixin):
|
| 13 |
+
"""A console renderable to draw a horizontal rule (line).
|
| 14 |
+
|
| 15 |
+
Args:
|
| 16 |
+
title (Union[str, Text], optional): Text to render in the rule. Defaults to "".
|
| 17 |
+
characters (str, optional): Character(s) used to draw the line. Defaults to "─".
|
| 18 |
+
style (StyleType, optional): Style of Rule. Defaults to "rule.line".
|
| 19 |
+
end (str, optional): Character at end of Rule. defaults to "\\\\n"
|
| 20 |
+
align (str, optional): How to align the title, one of "left", "center", or "right". Defaults to "center".
|
| 21 |
+
"""
|
| 22 |
+
|
| 23 |
+
def __init__(
|
| 24 |
+
self,
|
| 25 |
+
title: Union[str, Text] = "",
|
| 26 |
+
*,
|
| 27 |
+
characters: str = "─",
|
| 28 |
+
style: Union[str, Style] = "rule.line",
|
| 29 |
+
end: str = "\n",
|
| 30 |
+
align: AlignMethod = "center",
|
| 31 |
+
) -> None:
|
| 32 |
+
if cell_len(characters) < 1:
|
| 33 |
+
raise ValueError(
|
| 34 |
+
"'characters' argument must have a cell width of at least 1"
|
| 35 |
+
)
|
| 36 |
+
if align not in ("left", "center", "right"):
|
| 37 |
+
raise ValueError(
|
| 38 |
+
f'invalid value for align, expected "left", "center", "right" (not {align!r})'
|
| 39 |
+
)
|
| 40 |
+
self.title = title
|
| 41 |
+
self.characters = characters
|
| 42 |
+
self.style = style
|
| 43 |
+
self.end = end
|
| 44 |
+
self.align = align
|
| 45 |
+
|
| 46 |
+
def __repr__(self) -> str:
|
| 47 |
+
return f"Rule({self.title!r}, {self.characters!r})"
|
| 48 |
+
|
| 49 |
+
def __rich_console__(
|
| 50 |
+
self, console: Console, options: ConsoleOptions
|
| 51 |
+
) -> RenderResult:
|
| 52 |
+
width = options.max_width
|
| 53 |
+
|
| 54 |
+
characters = (
|
| 55 |
+
"-"
|
| 56 |
+
if (options.ascii_only and not self.characters.isascii())
|
| 57 |
+
else self.characters
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
chars_len = cell_len(characters)
|
| 61 |
+
if not self.title:
|
| 62 |
+
yield self._rule_line(chars_len, width)
|
| 63 |
+
return
|
| 64 |
+
|
| 65 |
+
if isinstance(self.title, Text):
|
| 66 |
+
title_text = self.title
|
| 67 |
+
else:
|
| 68 |
+
title_text = console.render_str(self.title, style="rule.text")
|
| 69 |
+
|
| 70 |
+
title_text.plain = title_text.plain.replace("\n", " ")
|
| 71 |
+
title_text.expand_tabs()
|
| 72 |
+
|
| 73 |
+
required_space = 4 if self.align == "center" else 2
|
| 74 |
+
truncate_width = max(0, width - required_space)
|
| 75 |
+
if not truncate_width:
|
| 76 |
+
yield self._rule_line(chars_len, width)
|
| 77 |
+
return
|
| 78 |
+
|
| 79 |
+
rule_text = Text(end=self.end)
|
| 80 |
+
if self.align == "center":
|
| 81 |
+
title_text.truncate(truncate_width, overflow="ellipsis")
|
| 82 |
+
side_width = (width - cell_len(title_text.plain)) // 2
|
| 83 |
+
left = Text(characters * (side_width // chars_len + 1))
|
| 84 |
+
left.truncate(side_width - 1)
|
| 85 |
+
right_length = width - cell_len(left.plain) - cell_len(title_text.plain)
|
| 86 |
+
right = Text(characters * (side_width // chars_len + 1))
|
| 87 |
+
right.truncate(right_length)
|
| 88 |
+
rule_text.append(left.plain + " ", self.style)
|
| 89 |
+
rule_text.append(title_text)
|
| 90 |
+
rule_text.append(" " + right.plain, self.style)
|
| 91 |
+
elif self.align == "left":
|
| 92 |
+
title_text.truncate(truncate_width, overflow="ellipsis")
|
| 93 |
+
rule_text.append(title_text)
|
| 94 |
+
rule_text.append(" ")
|
| 95 |
+
rule_text.append(characters * (width - rule_text.cell_len), self.style)
|
| 96 |
+
elif self.align == "right":
|
| 97 |
+
title_text.truncate(truncate_width, overflow="ellipsis")
|
| 98 |
+
rule_text.append(characters * (width - title_text.cell_len - 1), self.style)
|
| 99 |
+
rule_text.append(" ")
|
| 100 |
+
rule_text.append(title_text)
|
| 101 |
+
|
| 102 |
+
rule_text.plain = set_cell_size(rule_text.plain, width)
|
| 103 |
+
yield rule_text
|
| 104 |
+
|
| 105 |
+
def _rule_line(self, chars_len: int, width: int) -> Text:
|
| 106 |
+
rule_text = Text(self.characters * ((width // chars_len) + 1), self.style)
|
| 107 |
+
rule_text.truncate(width)
|
| 108 |
+
rule_text.plain = set_cell_size(rule_text.plain, width)
|
| 109 |
+
return rule_text
|
| 110 |
+
|
| 111 |
+
def __rich_measure__(
|
| 112 |
+
self, console: Console, options: ConsoleOptions
|
| 113 |
+
) -> Measurement:
|
| 114 |
+
return Measurement(1, 1)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
if __name__ == "__main__": # pragma: no cover
|
| 118 |
+
import sys
|
| 119 |
+
|
| 120 |
+
from pip._vendor.rich.console import Console
|
| 121 |
+
|
| 122 |
+
try:
|
| 123 |
+
text = sys.argv[1]
|
| 124 |
+
except IndexError:
|
| 125 |
+
text = "Hello, World"
|
| 126 |
+
console = Console()
|
| 127 |
+
console.print(Rule(title=text))
|
| 128 |
+
|
| 129 |
+
console = Console()
|
| 130 |
+
console.print(Rule("foo"), width=4)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/scope.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections.abc import Mapping
|
| 2 |
+
from typing import TYPE_CHECKING, Any, Optional, Tuple
|
| 3 |
+
|
| 4 |
+
from .highlighter import ReprHighlighter
|
| 5 |
+
from .panel import Panel
|
| 6 |
+
from .pretty import Pretty
|
| 7 |
+
from .table import Table
|
| 8 |
+
from .text import Text, TextType
|
| 9 |
+
|
| 10 |
+
if TYPE_CHECKING:
|
| 11 |
+
from .console import ConsoleRenderable
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def render_scope(
|
| 15 |
+
scope: "Mapping[str, Any]",
|
| 16 |
+
*,
|
| 17 |
+
title: Optional[TextType] = None,
|
| 18 |
+
sort_keys: bool = True,
|
| 19 |
+
indent_guides: bool = False,
|
| 20 |
+
max_length: Optional[int] = None,
|
| 21 |
+
max_string: Optional[int] = None,
|
| 22 |
+
) -> "ConsoleRenderable":
|
| 23 |
+
"""Render python variables in a given scope.
|
| 24 |
+
|
| 25 |
+
Args:
|
| 26 |
+
scope (Mapping): A mapping containing variable names and values.
|
| 27 |
+
title (str, optional): Optional title. Defaults to None.
|
| 28 |
+
sort_keys (bool, optional): Enable sorting of items. Defaults to True.
|
| 29 |
+
indent_guides (bool, optional): Enable indentation guides. Defaults to False.
|
| 30 |
+
max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
|
| 31 |
+
Defaults to None.
|
| 32 |
+
max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to None.
|
| 33 |
+
|
| 34 |
+
Returns:
|
| 35 |
+
ConsoleRenderable: A renderable object.
|
| 36 |
+
"""
|
| 37 |
+
highlighter = ReprHighlighter()
|
| 38 |
+
items_table = Table.grid(padding=(0, 1), expand=False)
|
| 39 |
+
items_table.add_column(justify="right")
|
| 40 |
+
|
| 41 |
+
def sort_items(item: Tuple[str, Any]) -> Tuple[bool, str]:
|
| 42 |
+
"""Sort special variables first, then alphabetically."""
|
| 43 |
+
key, _ = item
|
| 44 |
+
return (not key.startswith("__"), key.lower())
|
| 45 |
+
|
| 46 |
+
items = sorted(scope.items(), key=sort_items) if sort_keys else scope.items()
|
| 47 |
+
for key, value in items:
|
| 48 |
+
key_text = Text.assemble(
|
| 49 |
+
(key, "scope.key.special" if key.startswith("__") else "scope.key"),
|
| 50 |
+
(" =", "scope.equals"),
|
| 51 |
+
)
|
| 52 |
+
items_table.add_row(
|
| 53 |
+
key_text,
|
| 54 |
+
Pretty(
|
| 55 |
+
value,
|
| 56 |
+
highlighter=highlighter,
|
| 57 |
+
indent_guides=indent_guides,
|
| 58 |
+
max_length=max_length,
|
| 59 |
+
max_string=max_string,
|
| 60 |
+
),
|
| 61 |
+
)
|
| 62 |
+
return Panel.fit(
|
| 63 |
+
items_table,
|
| 64 |
+
title=title,
|
| 65 |
+
border_style="scope.border",
|
| 66 |
+
padding=(0, 1),
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
if __name__ == "__main__": # pragma: no cover
|
| 71 |
+
from pip._vendor.rich import print
|
| 72 |
+
|
| 73 |
+
print()
|
| 74 |
+
|
| 75 |
+
def test(foo: float, bar: float) -> None:
|
| 76 |
+
list_of_things = [1, 2, 3, None, 4, True, False, "Hello World"]
|
| 77 |
+
dict_of_things = {
|
| 78 |
+
"version": "1.1",
|
| 79 |
+
"method": "confirmFruitPurchase",
|
| 80 |
+
"params": [["apple", "orange", "mangoes", "pomelo"], 1.123],
|
| 81 |
+
"id": "194521489",
|
| 82 |
+
}
|
| 83 |
+
print(render_scope(locals(), title="[i]locals", sort_keys=False))
|
| 84 |
+
|
| 85 |
+
test(20.3423, 3.1427)
|
| 86 |
+
print()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/status.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from types import TracebackType
|
| 2 |
+
from typing import Optional, Type
|
| 3 |
+
|
| 4 |
+
from .console import Console, RenderableType
|
| 5 |
+
from .jupyter import JupyterMixin
|
| 6 |
+
from .live import Live
|
| 7 |
+
from .spinner import Spinner
|
| 8 |
+
from .style import StyleType
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class Status(JupyterMixin):
|
| 12 |
+
"""Displays a status indicator with a 'spinner' animation.
|
| 13 |
+
|
| 14 |
+
Args:
|
| 15 |
+
status (RenderableType): A status renderable (str or Text typically).
|
| 16 |
+
console (Console, optional): Console instance to use, or None for global console. Defaults to None.
|
| 17 |
+
spinner (str, optional): Name of spinner animation (see python -m rich.spinner). Defaults to "dots".
|
| 18 |
+
spinner_style (StyleType, optional): Style of spinner. Defaults to "status.spinner".
|
| 19 |
+
speed (float, optional): Speed factor for spinner animation. Defaults to 1.0.
|
| 20 |
+
refresh_per_second (float, optional): Number of refreshes per second. Defaults to 12.5.
|
| 21 |
+
"""
|
| 22 |
+
|
| 23 |
+
def __init__(
|
| 24 |
+
self,
|
| 25 |
+
status: RenderableType,
|
| 26 |
+
*,
|
| 27 |
+
console: Optional[Console] = None,
|
| 28 |
+
spinner: str = "dots",
|
| 29 |
+
spinner_style: StyleType = "status.spinner",
|
| 30 |
+
speed: float = 1.0,
|
| 31 |
+
refresh_per_second: float = 12.5,
|
| 32 |
+
):
|
| 33 |
+
self.status = status
|
| 34 |
+
self.spinner_style = spinner_style
|
| 35 |
+
self.speed = speed
|
| 36 |
+
self._spinner = Spinner(spinner, text=status, style=spinner_style, speed=speed)
|
| 37 |
+
self._live = Live(
|
| 38 |
+
self.renderable,
|
| 39 |
+
console=console,
|
| 40 |
+
refresh_per_second=refresh_per_second,
|
| 41 |
+
transient=True,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
@property
|
| 45 |
+
def renderable(self) -> Spinner:
|
| 46 |
+
return self._spinner
|
| 47 |
+
|
| 48 |
+
@property
|
| 49 |
+
def console(self) -> "Console":
|
| 50 |
+
"""Get the Console used by the Status objects."""
|
| 51 |
+
return self._live.console
|
| 52 |
+
|
| 53 |
+
def update(
|
| 54 |
+
self,
|
| 55 |
+
status: Optional[RenderableType] = None,
|
| 56 |
+
*,
|
| 57 |
+
spinner: Optional[str] = None,
|
| 58 |
+
spinner_style: Optional[StyleType] = None,
|
| 59 |
+
speed: Optional[float] = None,
|
| 60 |
+
) -> None:
|
| 61 |
+
"""Update status.
|
| 62 |
+
|
| 63 |
+
Args:
|
| 64 |
+
status (Optional[RenderableType], optional): New status renderable or None for no change. Defaults to None.
|
| 65 |
+
spinner (Optional[str], optional): New spinner or None for no change. Defaults to None.
|
| 66 |
+
spinner_style (Optional[StyleType], optional): New spinner style or None for no change. Defaults to None.
|
| 67 |
+
speed (Optional[float], optional): Speed factor for spinner animation or None for no change. Defaults to None.
|
| 68 |
+
"""
|
| 69 |
+
if status is not None:
|
| 70 |
+
self.status = status
|
| 71 |
+
if spinner_style is not None:
|
| 72 |
+
self.spinner_style = spinner_style
|
| 73 |
+
if speed is not None:
|
| 74 |
+
self.speed = speed
|
| 75 |
+
if spinner is not None:
|
| 76 |
+
self._spinner = Spinner(
|
| 77 |
+
spinner, text=self.status, style=self.spinner_style, speed=self.speed
|
| 78 |
+
)
|
| 79 |
+
self._live.update(self.renderable, refresh=True)
|
| 80 |
+
else:
|
| 81 |
+
self._spinner.update(
|
| 82 |
+
text=self.status, style=self.spinner_style, speed=self.speed
|
| 83 |
+
)
|
| 84 |
+
|
| 85 |
+
def start(self) -> None:
|
| 86 |
+
"""Start the status animation."""
|
| 87 |
+
self._live.start()
|
| 88 |
+
|
| 89 |
+
def stop(self) -> None:
|
| 90 |
+
"""Stop the spinner animation."""
|
| 91 |
+
self._live.stop()
|
| 92 |
+
|
| 93 |
+
def __rich__(self) -> RenderableType:
|
| 94 |
+
return self.renderable
|
| 95 |
+
|
| 96 |
+
def __enter__(self) -> "Status":
|
| 97 |
+
self.start()
|
| 98 |
+
return self
|
| 99 |
+
|
| 100 |
+
def __exit__(
|
| 101 |
+
self,
|
| 102 |
+
exc_type: Optional[Type[BaseException]],
|
| 103 |
+
exc_val: Optional[BaseException],
|
| 104 |
+
exc_tb: Optional[TracebackType],
|
| 105 |
+
) -> None:
|
| 106 |
+
self.stop()
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
if __name__ == "__main__": # pragma: no cover
|
| 110 |
+
from time import sleep
|
| 111 |
+
|
| 112 |
+
from .console import Console
|
| 113 |
+
|
| 114 |
+
console = Console()
|
| 115 |
+
with console.status("[magenta]Covid detector booting up") as status:
|
| 116 |
+
sleep(3)
|
| 117 |
+
console.log("Importing advanced AI")
|
| 118 |
+
sleep(3)
|
| 119 |
+
console.log("Advanced Covid AI Ready")
|
| 120 |
+
sleep(3)
|
| 121 |
+
status.update(status="[bold blue] Scanning for Covid", spinner="earth")
|
| 122 |
+
sleep(3)
|
| 123 |
+
console.log("Found 10,000,000,000 copies of Covid32.exe")
|
| 124 |
+
sleep(3)
|
| 125 |
+
status.update(
|
| 126 |
+
status="[bold red]Moving Covid32.exe to Trash",
|
| 127 |
+
spinner="bouncingBall",
|
| 128 |
+
spinner_style="yellow",
|
| 129 |
+
)
|
| 130 |
+
sleep(5)
|
| 131 |
+
console.print("[bold green]Covid deleted successfully")
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/text.py
ADDED
|
@@ -0,0 +1,1357 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
from functools import partial, reduce
|
| 3 |
+
from math import gcd
|
| 4 |
+
from operator import itemgetter
|
| 5 |
+
from typing import (
|
| 6 |
+
TYPE_CHECKING,
|
| 7 |
+
Any,
|
| 8 |
+
Callable,
|
| 9 |
+
Dict,
|
| 10 |
+
Iterable,
|
| 11 |
+
List,
|
| 12 |
+
NamedTuple,
|
| 13 |
+
Optional,
|
| 14 |
+
Tuple,
|
| 15 |
+
Union,
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
from ._loop import loop_last
|
| 19 |
+
from ._pick import pick_bool
|
| 20 |
+
from ._wrap import divide_line
|
| 21 |
+
from .align import AlignMethod
|
| 22 |
+
from .cells import cell_len, set_cell_size
|
| 23 |
+
from .containers import Lines
|
| 24 |
+
from .control import strip_control_codes
|
| 25 |
+
from .emoji import EmojiVariant
|
| 26 |
+
from .jupyter import JupyterMixin
|
| 27 |
+
from .measure import Measurement
|
| 28 |
+
from .segment import Segment
|
| 29 |
+
from .style import Style, StyleType
|
| 30 |
+
|
| 31 |
+
if TYPE_CHECKING: # pragma: no cover
|
| 32 |
+
from .console import Console, ConsoleOptions, JustifyMethod, OverflowMethod
|
| 33 |
+
|
| 34 |
+
DEFAULT_JUSTIFY: "JustifyMethod" = "default"
|
| 35 |
+
DEFAULT_OVERFLOW: "OverflowMethod" = "fold"
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
_re_whitespace = re.compile(r"\s+$")
|
| 39 |
+
|
| 40 |
+
TextType = Union[str, "Text"]
|
| 41 |
+
"""A plain string or a :class:`Text` instance."""
|
| 42 |
+
|
| 43 |
+
GetStyleCallable = Callable[[str], Optional[StyleType]]
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class Span(NamedTuple):
|
| 47 |
+
"""A marked up region in some text."""
|
| 48 |
+
|
| 49 |
+
start: int
|
| 50 |
+
"""Span start index."""
|
| 51 |
+
end: int
|
| 52 |
+
"""Span end index."""
|
| 53 |
+
style: Union[str, Style]
|
| 54 |
+
"""Style associated with the span."""
|
| 55 |
+
|
| 56 |
+
def __repr__(self) -> str:
|
| 57 |
+
return f"Span({self.start}, {self.end}, {self.style!r})"
|
| 58 |
+
|
| 59 |
+
def __bool__(self) -> bool:
|
| 60 |
+
return self.end > self.start
|
| 61 |
+
|
| 62 |
+
def split(self, offset: int) -> Tuple["Span", Optional["Span"]]:
|
| 63 |
+
"""Split a span in to 2 from a given offset."""
|
| 64 |
+
|
| 65 |
+
if offset < self.start:
|
| 66 |
+
return self, None
|
| 67 |
+
if offset >= self.end:
|
| 68 |
+
return self, None
|
| 69 |
+
|
| 70 |
+
start, end, style = self
|
| 71 |
+
span1 = Span(start, min(end, offset), style)
|
| 72 |
+
span2 = Span(span1.end, end, style)
|
| 73 |
+
return span1, span2
|
| 74 |
+
|
| 75 |
+
def move(self, offset: int) -> "Span":
|
| 76 |
+
"""Move start and end by a given offset.
|
| 77 |
+
|
| 78 |
+
Args:
|
| 79 |
+
offset (int): Number of characters to add to start and end.
|
| 80 |
+
|
| 81 |
+
Returns:
|
| 82 |
+
TextSpan: A new TextSpan with adjusted position.
|
| 83 |
+
"""
|
| 84 |
+
start, end, style = self
|
| 85 |
+
return Span(start + offset, end + offset, style)
|
| 86 |
+
|
| 87 |
+
def right_crop(self, offset: int) -> "Span":
|
| 88 |
+
"""Crop the span at the given offset.
|
| 89 |
+
|
| 90 |
+
Args:
|
| 91 |
+
offset (int): A value between start and end.
|
| 92 |
+
|
| 93 |
+
Returns:
|
| 94 |
+
Span: A new (possibly smaller) span.
|
| 95 |
+
"""
|
| 96 |
+
start, end, style = self
|
| 97 |
+
if offset >= end:
|
| 98 |
+
return self
|
| 99 |
+
return Span(start, min(offset, end), style)
|
| 100 |
+
|
| 101 |
+
def extend(self, cells: int) -> "Span":
|
| 102 |
+
"""Extend the span by the given number of cells.
|
| 103 |
+
|
| 104 |
+
Args:
|
| 105 |
+
cells (int): Additional space to add to end of span.
|
| 106 |
+
|
| 107 |
+
Returns:
|
| 108 |
+
Span: A span.
|
| 109 |
+
"""
|
| 110 |
+
if cells:
|
| 111 |
+
start, end, style = self
|
| 112 |
+
return Span(start, end + cells, style)
|
| 113 |
+
else:
|
| 114 |
+
return self
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
class Text(JupyterMixin):
|
| 118 |
+
"""Text with color / style.
|
| 119 |
+
|
| 120 |
+
Args:
|
| 121 |
+
text (str, optional): Default unstyled text. Defaults to "".
|
| 122 |
+
style (Union[str, Style], optional): Base style for text. Defaults to "".
|
| 123 |
+
justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
|
| 124 |
+
overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
|
| 125 |
+
no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None.
|
| 126 |
+
end (str, optional): Character to end text with. Defaults to "\\\\n".
|
| 127 |
+
tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None.
|
| 128 |
+
spans (List[Span], optional). A list of predefined style spans. Defaults to None.
|
| 129 |
+
"""
|
| 130 |
+
|
| 131 |
+
__slots__ = [
|
| 132 |
+
"_text",
|
| 133 |
+
"style",
|
| 134 |
+
"justify",
|
| 135 |
+
"overflow",
|
| 136 |
+
"no_wrap",
|
| 137 |
+
"end",
|
| 138 |
+
"tab_size",
|
| 139 |
+
"_spans",
|
| 140 |
+
"_length",
|
| 141 |
+
]
|
| 142 |
+
|
| 143 |
+
def __init__(
|
| 144 |
+
self,
|
| 145 |
+
text: str = "",
|
| 146 |
+
style: Union[str, Style] = "",
|
| 147 |
+
*,
|
| 148 |
+
justify: Optional["JustifyMethod"] = None,
|
| 149 |
+
overflow: Optional["OverflowMethod"] = None,
|
| 150 |
+
no_wrap: Optional[bool] = None,
|
| 151 |
+
end: str = "\n",
|
| 152 |
+
tab_size: Optional[int] = None,
|
| 153 |
+
spans: Optional[List[Span]] = None,
|
| 154 |
+
) -> None:
|
| 155 |
+
sanitized_text = strip_control_codes(text)
|
| 156 |
+
self._text = [sanitized_text]
|
| 157 |
+
self.style = style
|
| 158 |
+
self.justify: Optional["JustifyMethod"] = justify
|
| 159 |
+
self.overflow: Optional["OverflowMethod"] = overflow
|
| 160 |
+
self.no_wrap = no_wrap
|
| 161 |
+
self.end = end
|
| 162 |
+
self.tab_size = tab_size
|
| 163 |
+
self._spans: List[Span] = spans or []
|
| 164 |
+
self._length: int = len(sanitized_text)
|
| 165 |
+
|
| 166 |
+
def __len__(self) -> int:
|
| 167 |
+
return self._length
|
| 168 |
+
|
| 169 |
+
def __bool__(self) -> bool:
|
| 170 |
+
return bool(self._length)
|
| 171 |
+
|
| 172 |
+
def __str__(self) -> str:
|
| 173 |
+
return self.plain
|
| 174 |
+
|
| 175 |
+
def __repr__(self) -> str:
|
| 176 |
+
return f"<text {self.plain!r} {self._spans!r}>"
|
| 177 |
+
|
| 178 |
+
def __add__(self, other: Any) -> "Text":
|
| 179 |
+
if isinstance(other, (str, Text)):
|
| 180 |
+
result = self.copy()
|
| 181 |
+
result.append(other)
|
| 182 |
+
return result
|
| 183 |
+
return NotImplemented
|
| 184 |
+
|
| 185 |
+
def __eq__(self, other: object) -> bool:
|
| 186 |
+
if not isinstance(other, Text):
|
| 187 |
+
return NotImplemented
|
| 188 |
+
return self.plain == other.plain and self._spans == other._spans
|
| 189 |
+
|
| 190 |
+
def __contains__(self, other: object) -> bool:
|
| 191 |
+
if isinstance(other, str):
|
| 192 |
+
return other in self.plain
|
| 193 |
+
elif isinstance(other, Text):
|
| 194 |
+
return other.plain in self.plain
|
| 195 |
+
return False
|
| 196 |
+
|
| 197 |
+
def __getitem__(self, slice: Union[int, slice]) -> "Text":
|
| 198 |
+
def get_text_at(offset: int) -> "Text":
|
| 199 |
+
_Span = Span
|
| 200 |
+
text = Text(
|
| 201 |
+
self.plain[offset],
|
| 202 |
+
spans=[
|
| 203 |
+
_Span(0, 1, style)
|
| 204 |
+
for start, end, style in self._spans
|
| 205 |
+
if end > offset >= start
|
| 206 |
+
],
|
| 207 |
+
end="",
|
| 208 |
+
)
|
| 209 |
+
return text
|
| 210 |
+
|
| 211 |
+
if isinstance(slice, int):
|
| 212 |
+
return get_text_at(slice)
|
| 213 |
+
else:
|
| 214 |
+
start, stop, step = slice.indices(len(self.plain))
|
| 215 |
+
if step == 1:
|
| 216 |
+
lines = self.divide([start, stop])
|
| 217 |
+
return lines[1]
|
| 218 |
+
else:
|
| 219 |
+
# This would be a bit of work to implement efficiently
|
| 220 |
+
# For now, its not required
|
| 221 |
+
raise TypeError("slices with step!=1 are not supported")
|
| 222 |
+
|
| 223 |
+
@property
|
| 224 |
+
def cell_len(self) -> int:
|
| 225 |
+
"""Get the number of cells required to render this text."""
|
| 226 |
+
return cell_len(self.plain)
|
| 227 |
+
|
| 228 |
+
@property
|
| 229 |
+
def markup(self) -> str:
|
| 230 |
+
"""Get console markup to render this Text.
|
| 231 |
+
|
| 232 |
+
Returns:
|
| 233 |
+
str: A string potentially creating markup tags.
|
| 234 |
+
"""
|
| 235 |
+
from .markup import escape
|
| 236 |
+
|
| 237 |
+
output: List[str] = []
|
| 238 |
+
|
| 239 |
+
plain = self.plain
|
| 240 |
+
markup_spans = [
|
| 241 |
+
(0, False, self.style),
|
| 242 |
+
*((span.start, False, span.style) for span in self._spans),
|
| 243 |
+
*((span.end, True, span.style) for span in self._spans),
|
| 244 |
+
(len(plain), True, self.style),
|
| 245 |
+
]
|
| 246 |
+
markup_spans.sort(key=itemgetter(0, 1))
|
| 247 |
+
position = 0
|
| 248 |
+
append = output.append
|
| 249 |
+
for offset, closing, style in markup_spans:
|
| 250 |
+
if offset > position:
|
| 251 |
+
append(escape(plain[position:offset]))
|
| 252 |
+
position = offset
|
| 253 |
+
if style:
|
| 254 |
+
append(f"[/{style}]" if closing else f"[{style}]")
|
| 255 |
+
markup = "".join(output)
|
| 256 |
+
return markup
|
| 257 |
+
|
| 258 |
+
@classmethod
|
| 259 |
+
def from_markup(
|
| 260 |
+
cls,
|
| 261 |
+
text: str,
|
| 262 |
+
*,
|
| 263 |
+
style: Union[str, Style] = "",
|
| 264 |
+
emoji: bool = True,
|
| 265 |
+
emoji_variant: Optional[EmojiVariant] = None,
|
| 266 |
+
justify: Optional["JustifyMethod"] = None,
|
| 267 |
+
overflow: Optional["OverflowMethod"] = None,
|
| 268 |
+
end: str = "\n",
|
| 269 |
+
) -> "Text":
|
| 270 |
+
"""Create Text instance from markup.
|
| 271 |
+
|
| 272 |
+
Args:
|
| 273 |
+
text (str): A string containing console markup.
|
| 274 |
+
style (Union[str, Style], optional): Base style for text. Defaults to "".
|
| 275 |
+
emoji (bool, optional): Also render emoji code. Defaults to True.
|
| 276 |
+
emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None.
|
| 277 |
+
justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
|
| 278 |
+
overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
|
| 279 |
+
end (str, optional): Character to end text with. Defaults to "\\\\n".
|
| 280 |
+
|
| 281 |
+
Returns:
|
| 282 |
+
Text: A Text instance with markup rendered.
|
| 283 |
+
"""
|
| 284 |
+
from .markup import render
|
| 285 |
+
|
| 286 |
+
rendered_text = render(text, style, emoji=emoji, emoji_variant=emoji_variant)
|
| 287 |
+
rendered_text.justify = justify
|
| 288 |
+
rendered_text.overflow = overflow
|
| 289 |
+
rendered_text.end = end
|
| 290 |
+
return rendered_text
|
| 291 |
+
|
| 292 |
+
@classmethod
|
| 293 |
+
def from_ansi(
|
| 294 |
+
cls,
|
| 295 |
+
text: str,
|
| 296 |
+
*,
|
| 297 |
+
style: Union[str, Style] = "",
|
| 298 |
+
justify: Optional["JustifyMethod"] = None,
|
| 299 |
+
overflow: Optional["OverflowMethod"] = None,
|
| 300 |
+
no_wrap: Optional[bool] = None,
|
| 301 |
+
end: str = "\n",
|
| 302 |
+
tab_size: Optional[int] = 8,
|
| 303 |
+
) -> "Text":
|
| 304 |
+
"""Create a Text object from a string containing ANSI escape codes.
|
| 305 |
+
|
| 306 |
+
Args:
|
| 307 |
+
text (str): A string containing escape codes.
|
| 308 |
+
style (Union[str, Style], optional): Base style for text. Defaults to "".
|
| 309 |
+
justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
|
| 310 |
+
overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
|
| 311 |
+
no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None.
|
| 312 |
+
end (str, optional): Character to end text with. Defaults to "\\\\n".
|
| 313 |
+
tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None.
|
| 314 |
+
"""
|
| 315 |
+
from .ansi import AnsiDecoder
|
| 316 |
+
|
| 317 |
+
joiner = Text(
|
| 318 |
+
"\n",
|
| 319 |
+
justify=justify,
|
| 320 |
+
overflow=overflow,
|
| 321 |
+
no_wrap=no_wrap,
|
| 322 |
+
end=end,
|
| 323 |
+
tab_size=tab_size,
|
| 324 |
+
style=style,
|
| 325 |
+
)
|
| 326 |
+
decoder = AnsiDecoder()
|
| 327 |
+
result = joiner.join(line for line in decoder.decode(text))
|
| 328 |
+
return result
|
| 329 |
+
|
| 330 |
+
@classmethod
|
| 331 |
+
def styled(
|
| 332 |
+
cls,
|
| 333 |
+
text: str,
|
| 334 |
+
style: StyleType = "",
|
| 335 |
+
*,
|
| 336 |
+
justify: Optional["JustifyMethod"] = None,
|
| 337 |
+
overflow: Optional["OverflowMethod"] = None,
|
| 338 |
+
) -> "Text":
|
| 339 |
+
"""Construct a Text instance with a pre-applied styled. A style applied in this way won't be used
|
| 340 |
+
to pad the text when it is justified.
|
| 341 |
+
|
| 342 |
+
Args:
|
| 343 |
+
text (str): A string containing console markup.
|
| 344 |
+
style (Union[str, Style]): Style to apply to the text. Defaults to "".
|
| 345 |
+
justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
|
| 346 |
+
overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
|
| 347 |
+
|
| 348 |
+
Returns:
|
| 349 |
+
Text: A text instance with a style applied to the entire string.
|
| 350 |
+
"""
|
| 351 |
+
styled_text = cls(text, justify=justify, overflow=overflow)
|
| 352 |
+
styled_text.stylize(style)
|
| 353 |
+
return styled_text
|
| 354 |
+
|
| 355 |
+
@classmethod
|
| 356 |
+
def assemble(
|
| 357 |
+
cls,
|
| 358 |
+
*parts: Union[str, "Text", Tuple[str, StyleType]],
|
| 359 |
+
style: Union[str, Style] = "",
|
| 360 |
+
justify: Optional["JustifyMethod"] = None,
|
| 361 |
+
overflow: Optional["OverflowMethod"] = None,
|
| 362 |
+
no_wrap: Optional[bool] = None,
|
| 363 |
+
end: str = "\n",
|
| 364 |
+
tab_size: int = 8,
|
| 365 |
+
meta: Optional[Dict[str, Any]] = None,
|
| 366 |
+
) -> "Text":
|
| 367 |
+
"""Construct a text instance by combining a sequence of strings with optional styles.
|
| 368 |
+
The positional arguments should be either strings, or a tuple of string + style.
|
| 369 |
+
|
| 370 |
+
Args:
|
| 371 |
+
style (Union[str, Style], optional): Base style for text. Defaults to "".
|
| 372 |
+
justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None.
|
| 373 |
+
overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None.
|
| 374 |
+
no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None.
|
| 375 |
+
end (str, optional): Character to end text with. Defaults to "\\\\n".
|
| 376 |
+
tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None.
|
| 377 |
+
meta (Dict[str, Any], optional). Meta data to apply to text, or None for no meta data. Default to None
|
| 378 |
+
|
| 379 |
+
Returns:
|
| 380 |
+
Text: A new text instance.
|
| 381 |
+
"""
|
| 382 |
+
text = cls(
|
| 383 |
+
style=style,
|
| 384 |
+
justify=justify,
|
| 385 |
+
overflow=overflow,
|
| 386 |
+
no_wrap=no_wrap,
|
| 387 |
+
end=end,
|
| 388 |
+
tab_size=tab_size,
|
| 389 |
+
)
|
| 390 |
+
append = text.append
|
| 391 |
+
_Text = Text
|
| 392 |
+
for part in parts:
|
| 393 |
+
if isinstance(part, (_Text, str)):
|
| 394 |
+
append(part)
|
| 395 |
+
else:
|
| 396 |
+
append(*part)
|
| 397 |
+
if meta:
|
| 398 |
+
text.apply_meta(meta)
|
| 399 |
+
return text
|
| 400 |
+
|
| 401 |
+
@property
|
| 402 |
+
def plain(self) -> str:
|
| 403 |
+
"""Get the text as a single string."""
|
| 404 |
+
if len(self._text) != 1:
|
| 405 |
+
self._text[:] = ["".join(self._text)]
|
| 406 |
+
return self._text[0]
|
| 407 |
+
|
| 408 |
+
@plain.setter
|
| 409 |
+
def plain(self, new_text: str) -> None:
|
| 410 |
+
"""Set the text to a new value."""
|
| 411 |
+
if new_text != self.plain:
|
| 412 |
+
sanitized_text = strip_control_codes(new_text)
|
| 413 |
+
self._text[:] = [sanitized_text]
|
| 414 |
+
old_length = self._length
|
| 415 |
+
self._length = len(sanitized_text)
|
| 416 |
+
if old_length > self._length:
|
| 417 |
+
self._trim_spans()
|
| 418 |
+
|
| 419 |
+
@property
|
| 420 |
+
def spans(self) -> List[Span]:
|
| 421 |
+
"""Get a reference to the internal list of spans."""
|
| 422 |
+
return self._spans
|
| 423 |
+
|
| 424 |
+
@spans.setter
|
| 425 |
+
def spans(self, spans: List[Span]) -> None:
|
| 426 |
+
"""Set spans."""
|
| 427 |
+
self._spans = spans[:]
|
| 428 |
+
|
| 429 |
+
def blank_copy(self, plain: str = "") -> "Text":
|
| 430 |
+
"""Return a new Text instance with copied metadata (but not the string or spans)."""
|
| 431 |
+
copy_self = Text(
|
| 432 |
+
plain,
|
| 433 |
+
style=self.style,
|
| 434 |
+
justify=self.justify,
|
| 435 |
+
overflow=self.overflow,
|
| 436 |
+
no_wrap=self.no_wrap,
|
| 437 |
+
end=self.end,
|
| 438 |
+
tab_size=self.tab_size,
|
| 439 |
+
)
|
| 440 |
+
return copy_self
|
| 441 |
+
|
| 442 |
+
def copy(self) -> "Text":
|
| 443 |
+
"""Return a copy of this instance."""
|
| 444 |
+
copy_self = Text(
|
| 445 |
+
self.plain,
|
| 446 |
+
style=self.style,
|
| 447 |
+
justify=self.justify,
|
| 448 |
+
overflow=self.overflow,
|
| 449 |
+
no_wrap=self.no_wrap,
|
| 450 |
+
end=self.end,
|
| 451 |
+
tab_size=self.tab_size,
|
| 452 |
+
)
|
| 453 |
+
copy_self._spans[:] = self._spans
|
| 454 |
+
return copy_self
|
| 455 |
+
|
| 456 |
+
def stylize(
|
| 457 |
+
self,
|
| 458 |
+
style: Union[str, Style],
|
| 459 |
+
start: int = 0,
|
| 460 |
+
end: Optional[int] = None,
|
| 461 |
+
) -> None:
|
| 462 |
+
"""Apply a style to the text, or a portion of the text.
|
| 463 |
+
|
| 464 |
+
Args:
|
| 465 |
+
style (Union[str, Style]): Style instance or style definition to apply.
|
| 466 |
+
start (int): Start offset (negative indexing is supported). Defaults to 0.
|
| 467 |
+
end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None.
|
| 468 |
+
"""
|
| 469 |
+
if style:
|
| 470 |
+
length = len(self)
|
| 471 |
+
if start < 0:
|
| 472 |
+
start = length + start
|
| 473 |
+
if end is None:
|
| 474 |
+
end = length
|
| 475 |
+
if end < 0:
|
| 476 |
+
end = length + end
|
| 477 |
+
if start >= length or end <= start:
|
| 478 |
+
# Span not in text or not valid
|
| 479 |
+
return
|
| 480 |
+
self._spans.append(Span(start, min(length, end), style))
|
| 481 |
+
|
| 482 |
+
def stylize_before(
|
| 483 |
+
self,
|
| 484 |
+
style: Union[str, Style],
|
| 485 |
+
start: int = 0,
|
| 486 |
+
end: Optional[int] = None,
|
| 487 |
+
) -> None:
|
| 488 |
+
"""Apply a style to the text, or a portion of the text. Styles will be applied before other styles already present.
|
| 489 |
+
|
| 490 |
+
Args:
|
| 491 |
+
style (Union[str, Style]): Style instance or style definition to apply.
|
| 492 |
+
start (int): Start offset (negative indexing is supported). Defaults to 0.
|
| 493 |
+
end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None.
|
| 494 |
+
"""
|
| 495 |
+
if style:
|
| 496 |
+
length = len(self)
|
| 497 |
+
if start < 0:
|
| 498 |
+
start = length + start
|
| 499 |
+
if end is None:
|
| 500 |
+
end = length
|
| 501 |
+
if end < 0:
|
| 502 |
+
end = length + end
|
| 503 |
+
if start >= length or end <= start:
|
| 504 |
+
# Span not in text or not valid
|
| 505 |
+
return
|
| 506 |
+
self._spans.insert(0, Span(start, min(length, end), style))
|
| 507 |
+
|
| 508 |
+
def apply_meta(
|
| 509 |
+
self, meta: Dict[str, Any], start: int = 0, end: Optional[int] = None
|
| 510 |
+
) -> None:
|
| 511 |
+
"""Apply metadata to the text, or a portion of the text.
|
| 512 |
+
|
| 513 |
+
Args:
|
| 514 |
+
meta (Dict[str, Any]): A dict of meta information.
|
| 515 |
+
start (int): Start offset (negative indexing is supported). Defaults to 0.
|
| 516 |
+
end (Optional[int], optional): End offset (negative indexing is supported), or None for end of text. Defaults to None.
|
| 517 |
+
|
| 518 |
+
"""
|
| 519 |
+
style = Style.from_meta(meta)
|
| 520 |
+
self.stylize(style, start=start, end=end)
|
| 521 |
+
|
| 522 |
+
def on(self, meta: Optional[Dict[str, Any]] = None, **handlers: Any) -> "Text":
|
| 523 |
+
"""Apply event handlers (used by Textual project).
|
| 524 |
+
|
| 525 |
+
Example:
|
| 526 |
+
>>> from rich.text import Text
|
| 527 |
+
>>> text = Text("hello world")
|
| 528 |
+
>>> text.on(click="view.toggle('world')")
|
| 529 |
+
|
| 530 |
+
Args:
|
| 531 |
+
meta (Dict[str, Any]): Mapping of meta information.
|
| 532 |
+
**handlers: Keyword args are prefixed with "@" to defined handlers.
|
| 533 |
+
|
| 534 |
+
Returns:
|
| 535 |
+
Text: Self is returned to method may be chained.
|
| 536 |
+
"""
|
| 537 |
+
meta = {} if meta is None else meta
|
| 538 |
+
meta.update({f"@{key}": value for key, value in handlers.items()})
|
| 539 |
+
self.stylize(Style.from_meta(meta))
|
| 540 |
+
return self
|
| 541 |
+
|
| 542 |
+
def remove_suffix(self, suffix: str) -> None:
|
| 543 |
+
"""Remove a suffix if it exists.
|
| 544 |
+
|
| 545 |
+
Args:
|
| 546 |
+
suffix (str): Suffix to remove.
|
| 547 |
+
"""
|
| 548 |
+
if self.plain.endswith(suffix):
|
| 549 |
+
self.right_crop(len(suffix))
|
| 550 |
+
|
| 551 |
+
def get_style_at_offset(self, console: "Console", offset: int) -> Style:
|
| 552 |
+
"""Get the style of a character at give offset.
|
| 553 |
+
|
| 554 |
+
Args:
|
| 555 |
+
console (~Console): Console where text will be rendered.
|
| 556 |
+
offset (int): Offset in to text (negative indexing supported)
|
| 557 |
+
|
| 558 |
+
Returns:
|
| 559 |
+
Style: A Style instance.
|
| 560 |
+
"""
|
| 561 |
+
# TODO: This is a little inefficient, it is only used by full justify
|
| 562 |
+
if offset < 0:
|
| 563 |
+
offset = len(self) + offset
|
| 564 |
+
get_style = console.get_style
|
| 565 |
+
style = get_style(self.style).copy()
|
| 566 |
+
for start, end, span_style in self._spans:
|
| 567 |
+
if end > offset >= start:
|
| 568 |
+
style += get_style(span_style, default="")
|
| 569 |
+
return style
|
| 570 |
+
|
| 571 |
+
def extend_style(self, spaces: int) -> None:
|
| 572 |
+
"""Extend the Text given number of spaces where the spaces have the same style as the last character.
|
| 573 |
+
|
| 574 |
+
Args:
|
| 575 |
+
spaces (int): Number of spaces to add to the Text.
|
| 576 |
+
"""
|
| 577 |
+
if spaces <= 0:
|
| 578 |
+
return
|
| 579 |
+
spans = self.spans
|
| 580 |
+
new_spaces = " " * spaces
|
| 581 |
+
if spans:
|
| 582 |
+
end_offset = len(self)
|
| 583 |
+
self._spans[:] = [
|
| 584 |
+
span.extend(spaces) if span.end >= end_offset else span
|
| 585 |
+
for span in spans
|
| 586 |
+
]
|
| 587 |
+
self._text.append(new_spaces)
|
| 588 |
+
self._length += spaces
|
| 589 |
+
else:
|
| 590 |
+
self.plain += new_spaces
|
| 591 |
+
|
| 592 |
+
def highlight_regex(
|
| 593 |
+
self,
|
| 594 |
+
re_highlight: str,
|
| 595 |
+
style: Optional[Union[GetStyleCallable, StyleType]] = None,
|
| 596 |
+
*,
|
| 597 |
+
style_prefix: str = "",
|
| 598 |
+
) -> int:
|
| 599 |
+
"""Highlight text with a regular expression, where group names are
|
| 600 |
+
translated to styles.
|
| 601 |
+
|
| 602 |
+
Args:
|
| 603 |
+
re_highlight (str): A regular expression.
|
| 604 |
+
style (Union[GetStyleCallable, StyleType]): Optional style to apply to whole match, or a callable
|
| 605 |
+
which accepts the matched text and returns a style. Defaults to None.
|
| 606 |
+
style_prefix (str, optional): Optional prefix to add to style group names.
|
| 607 |
+
|
| 608 |
+
Returns:
|
| 609 |
+
int: Number of regex matches
|
| 610 |
+
"""
|
| 611 |
+
count = 0
|
| 612 |
+
append_span = self._spans.append
|
| 613 |
+
_Span = Span
|
| 614 |
+
plain = self.plain
|
| 615 |
+
for match in re.finditer(re_highlight, plain):
|
| 616 |
+
get_span = match.span
|
| 617 |
+
if style:
|
| 618 |
+
start, end = get_span()
|
| 619 |
+
match_style = style(plain[start:end]) if callable(style) else style
|
| 620 |
+
if match_style is not None and end > start:
|
| 621 |
+
append_span(_Span(start, end, match_style))
|
| 622 |
+
|
| 623 |
+
count += 1
|
| 624 |
+
for name in match.groupdict().keys():
|
| 625 |
+
start, end = get_span(name)
|
| 626 |
+
if start != -1 and end > start:
|
| 627 |
+
append_span(_Span(start, end, f"{style_prefix}{name}"))
|
| 628 |
+
return count
|
| 629 |
+
|
| 630 |
+
def highlight_words(
|
| 631 |
+
self,
|
| 632 |
+
words: Iterable[str],
|
| 633 |
+
style: Union[str, Style],
|
| 634 |
+
*,
|
| 635 |
+
case_sensitive: bool = True,
|
| 636 |
+
) -> int:
|
| 637 |
+
"""Highlight words with a style.
|
| 638 |
+
|
| 639 |
+
Args:
|
| 640 |
+
words (Iterable[str]): Words to highlight.
|
| 641 |
+
style (Union[str, Style]): Style to apply.
|
| 642 |
+
case_sensitive (bool, optional): Enable case sensitive matching. Defaults to True.
|
| 643 |
+
|
| 644 |
+
Returns:
|
| 645 |
+
int: Number of words highlighted.
|
| 646 |
+
"""
|
| 647 |
+
re_words = "|".join(re.escape(word) for word in words)
|
| 648 |
+
add_span = self._spans.append
|
| 649 |
+
count = 0
|
| 650 |
+
_Span = Span
|
| 651 |
+
for match in re.finditer(
|
| 652 |
+
re_words, self.plain, flags=0 if case_sensitive else re.IGNORECASE
|
| 653 |
+
):
|
| 654 |
+
start, end = match.span(0)
|
| 655 |
+
add_span(_Span(start, end, style))
|
| 656 |
+
count += 1
|
| 657 |
+
return count
|
| 658 |
+
|
| 659 |
+
def rstrip(self) -> None:
|
| 660 |
+
"""Strip whitespace from end of text."""
|
| 661 |
+
self.plain = self.plain.rstrip()
|
| 662 |
+
|
| 663 |
+
def rstrip_end(self, size: int) -> None:
|
| 664 |
+
"""Remove whitespace beyond a certain width at the end of the text.
|
| 665 |
+
|
| 666 |
+
Args:
|
| 667 |
+
size (int): The desired size of the text.
|
| 668 |
+
"""
|
| 669 |
+
text_length = len(self)
|
| 670 |
+
if text_length > size:
|
| 671 |
+
excess = text_length - size
|
| 672 |
+
whitespace_match = _re_whitespace.search(self.plain)
|
| 673 |
+
if whitespace_match is not None:
|
| 674 |
+
whitespace_count = len(whitespace_match.group(0))
|
| 675 |
+
self.right_crop(min(whitespace_count, excess))
|
| 676 |
+
|
| 677 |
+
def set_length(self, new_length: int) -> None:
|
| 678 |
+
"""Set new length of the text, clipping or padding is required."""
|
| 679 |
+
length = len(self)
|
| 680 |
+
if length != new_length:
|
| 681 |
+
if length < new_length:
|
| 682 |
+
self.pad_right(new_length - length)
|
| 683 |
+
else:
|
| 684 |
+
self.right_crop(length - new_length)
|
| 685 |
+
|
| 686 |
+
def __rich_console__(
|
| 687 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 688 |
+
) -> Iterable[Segment]:
|
| 689 |
+
tab_size: int = console.tab_size if self.tab_size is None else self.tab_size
|
| 690 |
+
justify = self.justify or options.justify or DEFAULT_JUSTIFY
|
| 691 |
+
|
| 692 |
+
overflow = self.overflow or options.overflow or DEFAULT_OVERFLOW
|
| 693 |
+
|
| 694 |
+
lines = self.wrap(
|
| 695 |
+
console,
|
| 696 |
+
options.max_width,
|
| 697 |
+
justify=justify,
|
| 698 |
+
overflow=overflow,
|
| 699 |
+
tab_size=tab_size or 8,
|
| 700 |
+
no_wrap=pick_bool(self.no_wrap, options.no_wrap, False),
|
| 701 |
+
)
|
| 702 |
+
all_lines = Text("\n").join(lines)
|
| 703 |
+
yield from all_lines.render(console, end=self.end)
|
| 704 |
+
|
| 705 |
+
def __rich_measure__(
|
| 706 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 707 |
+
) -> Measurement:
|
| 708 |
+
text = self.plain
|
| 709 |
+
lines = text.splitlines()
|
| 710 |
+
max_text_width = max(cell_len(line) for line in lines) if lines else 0
|
| 711 |
+
words = text.split()
|
| 712 |
+
min_text_width = (
|
| 713 |
+
max(cell_len(word) for word in words) if words else max_text_width
|
| 714 |
+
)
|
| 715 |
+
return Measurement(min_text_width, max_text_width)
|
| 716 |
+
|
| 717 |
+
def render(self, console: "Console", end: str = "") -> Iterable["Segment"]:
|
| 718 |
+
"""Render the text as Segments.
|
| 719 |
+
|
| 720 |
+
Args:
|
| 721 |
+
console (Console): Console instance.
|
| 722 |
+
end (Optional[str], optional): Optional end character.
|
| 723 |
+
|
| 724 |
+
Returns:
|
| 725 |
+
Iterable[Segment]: Result of render that may be written to the console.
|
| 726 |
+
"""
|
| 727 |
+
_Segment = Segment
|
| 728 |
+
text = self.plain
|
| 729 |
+
if not self._spans:
|
| 730 |
+
yield Segment(text)
|
| 731 |
+
if end:
|
| 732 |
+
yield _Segment(end)
|
| 733 |
+
return
|
| 734 |
+
get_style = partial(console.get_style, default=Style.null())
|
| 735 |
+
|
| 736 |
+
enumerated_spans = list(enumerate(self._spans, 1))
|
| 737 |
+
style_map = {index: get_style(span.style) for index, span in enumerated_spans}
|
| 738 |
+
style_map[0] = get_style(self.style)
|
| 739 |
+
|
| 740 |
+
spans = [
|
| 741 |
+
(0, False, 0),
|
| 742 |
+
*((span.start, False, index) for index, span in enumerated_spans),
|
| 743 |
+
*((span.end, True, index) for index, span in enumerated_spans),
|
| 744 |
+
(len(text), True, 0),
|
| 745 |
+
]
|
| 746 |
+
spans.sort(key=itemgetter(0, 1))
|
| 747 |
+
|
| 748 |
+
stack: List[int] = []
|
| 749 |
+
stack_append = stack.append
|
| 750 |
+
stack_pop = stack.remove
|
| 751 |
+
|
| 752 |
+
style_cache: Dict[Tuple[Style, ...], Style] = {}
|
| 753 |
+
style_cache_get = style_cache.get
|
| 754 |
+
combine = Style.combine
|
| 755 |
+
|
| 756 |
+
def get_current_style() -> Style:
|
| 757 |
+
"""Construct current style from stack."""
|
| 758 |
+
styles = tuple(style_map[_style_id] for _style_id in sorted(stack))
|
| 759 |
+
cached_style = style_cache_get(styles)
|
| 760 |
+
if cached_style is not None:
|
| 761 |
+
return cached_style
|
| 762 |
+
current_style = combine(styles)
|
| 763 |
+
style_cache[styles] = current_style
|
| 764 |
+
return current_style
|
| 765 |
+
|
| 766 |
+
for (offset, leaving, style_id), (next_offset, _, _) in zip(spans, spans[1:]):
|
| 767 |
+
if leaving:
|
| 768 |
+
stack_pop(style_id)
|
| 769 |
+
else:
|
| 770 |
+
stack_append(style_id)
|
| 771 |
+
if next_offset > offset:
|
| 772 |
+
yield _Segment(text[offset:next_offset], get_current_style())
|
| 773 |
+
if end:
|
| 774 |
+
yield _Segment(end)
|
| 775 |
+
|
| 776 |
+
def join(self, lines: Iterable["Text"]) -> "Text":
|
| 777 |
+
"""Join text together with this instance as the separator.
|
| 778 |
+
|
| 779 |
+
Args:
|
| 780 |
+
lines (Iterable[Text]): An iterable of Text instances to join.
|
| 781 |
+
|
| 782 |
+
Returns:
|
| 783 |
+
Text: A new text instance containing join text.
|
| 784 |
+
"""
|
| 785 |
+
|
| 786 |
+
new_text = self.blank_copy()
|
| 787 |
+
|
| 788 |
+
def iter_text() -> Iterable["Text"]:
|
| 789 |
+
if self.plain:
|
| 790 |
+
for last, line in loop_last(lines):
|
| 791 |
+
yield line
|
| 792 |
+
if not last:
|
| 793 |
+
yield self
|
| 794 |
+
else:
|
| 795 |
+
yield from lines
|
| 796 |
+
|
| 797 |
+
extend_text = new_text._text.extend
|
| 798 |
+
append_span = new_text._spans.append
|
| 799 |
+
extend_spans = new_text._spans.extend
|
| 800 |
+
offset = 0
|
| 801 |
+
_Span = Span
|
| 802 |
+
|
| 803 |
+
for text in iter_text():
|
| 804 |
+
extend_text(text._text)
|
| 805 |
+
if text.style:
|
| 806 |
+
append_span(_Span(offset, offset + len(text), text.style))
|
| 807 |
+
extend_spans(
|
| 808 |
+
_Span(offset + start, offset + end, style)
|
| 809 |
+
for start, end, style in text._spans
|
| 810 |
+
)
|
| 811 |
+
offset += len(text)
|
| 812 |
+
new_text._length = offset
|
| 813 |
+
return new_text
|
| 814 |
+
|
| 815 |
+
def expand_tabs(self, tab_size: Optional[int] = None) -> None:
|
| 816 |
+
"""Converts tabs to spaces.
|
| 817 |
+
|
| 818 |
+
Args:
|
| 819 |
+
tab_size (int, optional): Size of tabs. Defaults to 8.
|
| 820 |
+
|
| 821 |
+
"""
|
| 822 |
+
if "\t" not in self.plain:
|
| 823 |
+
return
|
| 824 |
+
if tab_size is None:
|
| 825 |
+
tab_size = self.tab_size
|
| 826 |
+
if tab_size is None:
|
| 827 |
+
tab_size = 8
|
| 828 |
+
|
| 829 |
+
new_text: List[Text] = []
|
| 830 |
+
append = new_text.append
|
| 831 |
+
|
| 832 |
+
for line in self.split("\n", include_separator=True):
|
| 833 |
+
if "\t" not in line.plain:
|
| 834 |
+
append(line)
|
| 835 |
+
else:
|
| 836 |
+
cell_position = 0
|
| 837 |
+
parts = line.split("\t", include_separator=True)
|
| 838 |
+
for part in parts:
|
| 839 |
+
if part.plain.endswith("\t"):
|
| 840 |
+
part._text[-1] = part._text[-1][:-1] + " "
|
| 841 |
+
cell_position += part.cell_len
|
| 842 |
+
tab_remainder = cell_position % tab_size
|
| 843 |
+
if tab_remainder:
|
| 844 |
+
spaces = tab_size - tab_remainder
|
| 845 |
+
part.extend_style(spaces)
|
| 846 |
+
cell_position += spaces
|
| 847 |
+
else:
|
| 848 |
+
cell_position += part.cell_len
|
| 849 |
+
append(part)
|
| 850 |
+
|
| 851 |
+
result = Text("").join(new_text)
|
| 852 |
+
|
| 853 |
+
self._text = [result.plain]
|
| 854 |
+
self._length = len(self.plain)
|
| 855 |
+
self._spans[:] = result._spans
|
| 856 |
+
|
| 857 |
+
def truncate(
|
| 858 |
+
self,
|
| 859 |
+
max_width: int,
|
| 860 |
+
*,
|
| 861 |
+
overflow: Optional["OverflowMethod"] = None,
|
| 862 |
+
pad: bool = False,
|
| 863 |
+
) -> None:
|
| 864 |
+
"""Truncate text if it is longer that a given width.
|
| 865 |
+
|
| 866 |
+
Args:
|
| 867 |
+
max_width (int): Maximum number of characters in text.
|
| 868 |
+
overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None, to use self.overflow.
|
| 869 |
+
pad (bool, optional): Pad with spaces if the length is less than max_width. Defaults to False.
|
| 870 |
+
"""
|
| 871 |
+
_overflow = overflow or self.overflow or DEFAULT_OVERFLOW
|
| 872 |
+
if _overflow != "ignore":
|
| 873 |
+
length = cell_len(self.plain)
|
| 874 |
+
if length > max_width:
|
| 875 |
+
if _overflow == "ellipsis":
|
| 876 |
+
self.plain = set_cell_size(self.plain, max_width - 1) + "…"
|
| 877 |
+
else:
|
| 878 |
+
self.plain = set_cell_size(self.plain, max_width)
|
| 879 |
+
if pad and length < max_width:
|
| 880 |
+
spaces = max_width - length
|
| 881 |
+
self._text = [f"{self.plain}{' ' * spaces}"]
|
| 882 |
+
self._length = len(self.plain)
|
| 883 |
+
|
| 884 |
+
def _trim_spans(self) -> None:
|
| 885 |
+
"""Remove or modify any spans that are over the end of the text."""
|
| 886 |
+
max_offset = len(self.plain)
|
| 887 |
+
_Span = Span
|
| 888 |
+
self._spans[:] = [
|
| 889 |
+
(
|
| 890 |
+
span
|
| 891 |
+
if span.end < max_offset
|
| 892 |
+
else _Span(span.start, min(max_offset, span.end), span.style)
|
| 893 |
+
)
|
| 894 |
+
for span in self._spans
|
| 895 |
+
if span.start < max_offset
|
| 896 |
+
]
|
| 897 |
+
|
| 898 |
+
def pad(self, count: int, character: str = " ") -> None:
|
| 899 |
+
"""Pad left and right with a given number of characters.
|
| 900 |
+
|
| 901 |
+
Args:
|
| 902 |
+
count (int): Width of padding.
|
| 903 |
+
character (str): The character to pad with. Must be a string of length 1.
|
| 904 |
+
"""
|
| 905 |
+
assert len(character) == 1, "Character must be a string of length 1"
|
| 906 |
+
if count:
|
| 907 |
+
pad_characters = character * count
|
| 908 |
+
self.plain = f"{pad_characters}{self.plain}{pad_characters}"
|
| 909 |
+
_Span = Span
|
| 910 |
+
self._spans[:] = [
|
| 911 |
+
_Span(start + count, end + count, style)
|
| 912 |
+
for start, end, style in self._spans
|
| 913 |
+
]
|
| 914 |
+
|
| 915 |
+
def pad_left(self, count: int, character: str = " ") -> None:
|
| 916 |
+
"""Pad the left with a given character.
|
| 917 |
+
|
| 918 |
+
Args:
|
| 919 |
+
count (int): Number of characters to pad.
|
| 920 |
+
character (str, optional): Character to pad with. Defaults to " ".
|
| 921 |
+
"""
|
| 922 |
+
assert len(character) == 1, "Character must be a string of length 1"
|
| 923 |
+
if count:
|
| 924 |
+
self.plain = f"{character * count}{self.plain}"
|
| 925 |
+
_Span = Span
|
| 926 |
+
self._spans[:] = [
|
| 927 |
+
_Span(start + count, end + count, style)
|
| 928 |
+
for start, end, style in self._spans
|
| 929 |
+
]
|
| 930 |
+
|
| 931 |
+
def pad_right(self, count: int, character: str = " ") -> None:
|
| 932 |
+
"""Pad the right with a given character.
|
| 933 |
+
|
| 934 |
+
Args:
|
| 935 |
+
count (int): Number of characters to pad.
|
| 936 |
+
character (str, optional): Character to pad with. Defaults to " ".
|
| 937 |
+
"""
|
| 938 |
+
assert len(character) == 1, "Character must be a string of length 1"
|
| 939 |
+
if count:
|
| 940 |
+
self.plain = f"{self.plain}{character * count}"
|
| 941 |
+
|
| 942 |
+
def align(self, align: AlignMethod, width: int, character: str = " ") -> None:
|
| 943 |
+
"""Align text to a given width.
|
| 944 |
+
|
| 945 |
+
Args:
|
| 946 |
+
align (AlignMethod): One of "left", "center", or "right".
|
| 947 |
+
width (int): Desired width.
|
| 948 |
+
character (str, optional): Character to pad with. Defaults to " ".
|
| 949 |
+
"""
|
| 950 |
+
self.truncate(width)
|
| 951 |
+
excess_space = width - cell_len(self.plain)
|
| 952 |
+
if excess_space:
|
| 953 |
+
if align == "left":
|
| 954 |
+
self.pad_right(excess_space, character)
|
| 955 |
+
elif align == "center":
|
| 956 |
+
left = excess_space // 2
|
| 957 |
+
self.pad_left(left, character)
|
| 958 |
+
self.pad_right(excess_space - left, character)
|
| 959 |
+
else:
|
| 960 |
+
self.pad_left(excess_space, character)
|
| 961 |
+
|
| 962 |
+
def append(
|
| 963 |
+
self, text: Union["Text", str], style: Optional[Union[str, "Style"]] = None
|
| 964 |
+
) -> "Text":
|
| 965 |
+
"""Add text with an optional style.
|
| 966 |
+
|
| 967 |
+
Args:
|
| 968 |
+
text (Union[Text, str]): A str or Text to append.
|
| 969 |
+
style (str, optional): A style name. Defaults to None.
|
| 970 |
+
|
| 971 |
+
Returns:
|
| 972 |
+
Text: Returns self for chaining.
|
| 973 |
+
"""
|
| 974 |
+
|
| 975 |
+
if not isinstance(text, (str, Text)):
|
| 976 |
+
raise TypeError("Only str or Text can be appended to Text")
|
| 977 |
+
|
| 978 |
+
if len(text):
|
| 979 |
+
if isinstance(text, str):
|
| 980 |
+
sanitized_text = strip_control_codes(text)
|
| 981 |
+
self._text.append(sanitized_text)
|
| 982 |
+
offset = len(self)
|
| 983 |
+
text_length = len(sanitized_text)
|
| 984 |
+
if style:
|
| 985 |
+
self._spans.append(Span(offset, offset + text_length, style))
|
| 986 |
+
self._length += text_length
|
| 987 |
+
elif isinstance(text, Text):
|
| 988 |
+
_Span = Span
|
| 989 |
+
if style is not None:
|
| 990 |
+
raise ValueError(
|
| 991 |
+
"style must not be set when appending Text instance"
|
| 992 |
+
)
|
| 993 |
+
text_length = self._length
|
| 994 |
+
if text.style:
|
| 995 |
+
self._spans.append(
|
| 996 |
+
_Span(text_length, text_length + len(text), text.style)
|
| 997 |
+
)
|
| 998 |
+
self._text.append(text.plain)
|
| 999 |
+
self._spans.extend(
|
| 1000 |
+
_Span(start + text_length, end + text_length, style)
|
| 1001 |
+
for start, end, style in text._spans
|
| 1002 |
+
)
|
| 1003 |
+
self._length += len(text)
|
| 1004 |
+
return self
|
| 1005 |
+
|
| 1006 |
+
def append_text(self, text: "Text") -> "Text":
|
| 1007 |
+
"""Append another Text instance. This method is more performant that Text.append, but
|
| 1008 |
+
only works for Text.
|
| 1009 |
+
|
| 1010 |
+
Args:
|
| 1011 |
+
text (Text): The Text instance to append to this instance.
|
| 1012 |
+
|
| 1013 |
+
Returns:
|
| 1014 |
+
Text: Returns self for chaining.
|
| 1015 |
+
"""
|
| 1016 |
+
_Span = Span
|
| 1017 |
+
text_length = self._length
|
| 1018 |
+
if text.style:
|
| 1019 |
+
self._spans.append(_Span(text_length, text_length + len(text), text.style))
|
| 1020 |
+
self._text.append(text.plain)
|
| 1021 |
+
self._spans.extend(
|
| 1022 |
+
_Span(start + text_length, end + text_length, style)
|
| 1023 |
+
for start, end, style in text._spans
|
| 1024 |
+
)
|
| 1025 |
+
self._length += len(text)
|
| 1026 |
+
return self
|
| 1027 |
+
|
| 1028 |
+
def append_tokens(
|
| 1029 |
+
self, tokens: Iterable[Tuple[str, Optional[StyleType]]]
|
| 1030 |
+
) -> "Text":
|
| 1031 |
+
"""Append iterable of str and style. Style may be a Style instance or a str style definition.
|
| 1032 |
+
|
| 1033 |
+
Args:
|
| 1034 |
+
tokens (Iterable[Tuple[str, Optional[StyleType]]]): An iterable of tuples containing str content and style.
|
| 1035 |
+
|
| 1036 |
+
Returns:
|
| 1037 |
+
Text: Returns self for chaining.
|
| 1038 |
+
"""
|
| 1039 |
+
append_text = self._text.append
|
| 1040 |
+
append_span = self._spans.append
|
| 1041 |
+
_Span = Span
|
| 1042 |
+
offset = len(self)
|
| 1043 |
+
for content, style in tokens:
|
| 1044 |
+
append_text(content)
|
| 1045 |
+
if style:
|
| 1046 |
+
append_span(_Span(offset, offset + len(content), style))
|
| 1047 |
+
offset += len(content)
|
| 1048 |
+
self._length = offset
|
| 1049 |
+
return self
|
| 1050 |
+
|
| 1051 |
+
def copy_styles(self, text: "Text") -> None:
|
| 1052 |
+
"""Copy styles from another Text instance.
|
| 1053 |
+
|
| 1054 |
+
Args:
|
| 1055 |
+
text (Text): A Text instance to copy styles from, must be the same length.
|
| 1056 |
+
"""
|
| 1057 |
+
self._spans.extend(text._spans)
|
| 1058 |
+
|
| 1059 |
+
def split(
|
| 1060 |
+
self,
|
| 1061 |
+
separator: str = "\n",
|
| 1062 |
+
*,
|
| 1063 |
+
include_separator: bool = False,
|
| 1064 |
+
allow_blank: bool = False,
|
| 1065 |
+
) -> Lines:
|
| 1066 |
+
"""Split rich text in to lines, preserving styles.
|
| 1067 |
+
|
| 1068 |
+
Args:
|
| 1069 |
+
separator (str, optional): String to split on. Defaults to "\\\\n".
|
| 1070 |
+
include_separator (bool, optional): Include the separator in the lines. Defaults to False.
|
| 1071 |
+
allow_blank (bool, optional): Return a blank line if the text ends with a separator. Defaults to False.
|
| 1072 |
+
|
| 1073 |
+
Returns:
|
| 1074 |
+
List[RichText]: A list of rich text, one per line of the original.
|
| 1075 |
+
"""
|
| 1076 |
+
assert separator, "separator must not be empty"
|
| 1077 |
+
|
| 1078 |
+
text = self.plain
|
| 1079 |
+
if separator not in text:
|
| 1080 |
+
return Lines([self.copy()])
|
| 1081 |
+
|
| 1082 |
+
if include_separator:
|
| 1083 |
+
lines = self.divide(
|
| 1084 |
+
match.end() for match in re.finditer(re.escape(separator), text)
|
| 1085 |
+
)
|
| 1086 |
+
else:
|
| 1087 |
+
|
| 1088 |
+
def flatten_spans() -> Iterable[int]:
|
| 1089 |
+
for match in re.finditer(re.escape(separator), text):
|
| 1090 |
+
start, end = match.span()
|
| 1091 |
+
yield start
|
| 1092 |
+
yield end
|
| 1093 |
+
|
| 1094 |
+
lines = Lines(
|
| 1095 |
+
line for line in self.divide(flatten_spans()) if line.plain != separator
|
| 1096 |
+
)
|
| 1097 |
+
|
| 1098 |
+
if not allow_blank and text.endswith(separator):
|
| 1099 |
+
lines.pop()
|
| 1100 |
+
|
| 1101 |
+
return lines
|
| 1102 |
+
|
| 1103 |
+
def divide(self, offsets: Iterable[int]) -> Lines:
|
| 1104 |
+
"""Divide text in to a number of lines at given offsets.
|
| 1105 |
+
|
| 1106 |
+
Args:
|
| 1107 |
+
offsets (Iterable[int]): Offsets used to divide text.
|
| 1108 |
+
|
| 1109 |
+
Returns:
|
| 1110 |
+
Lines: New RichText instances between offsets.
|
| 1111 |
+
"""
|
| 1112 |
+
_offsets = list(offsets)
|
| 1113 |
+
|
| 1114 |
+
if not _offsets:
|
| 1115 |
+
return Lines([self.copy()])
|
| 1116 |
+
|
| 1117 |
+
text = self.plain
|
| 1118 |
+
text_length = len(text)
|
| 1119 |
+
divide_offsets = [0, *_offsets, text_length]
|
| 1120 |
+
line_ranges = list(zip(divide_offsets, divide_offsets[1:]))
|
| 1121 |
+
|
| 1122 |
+
style = self.style
|
| 1123 |
+
justify = self.justify
|
| 1124 |
+
overflow = self.overflow
|
| 1125 |
+
_Text = Text
|
| 1126 |
+
new_lines = Lines(
|
| 1127 |
+
_Text(
|
| 1128 |
+
text[start:end],
|
| 1129 |
+
style=style,
|
| 1130 |
+
justify=justify,
|
| 1131 |
+
overflow=overflow,
|
| 1132 |
+
)
|
| 1133 |
+
for start, end in line_ranges
|
| 1134 |
+
)
|
| 1135 |
+
if not self._spans:
|
| 1136 |
+
return new_lines
|
| 1137 |
+
|
| 1138 |
+
_line_appends = [line._spans.append for line in new_lines._lines]
|
| 1139 |
+
line_count = len(line_ranges)
|
| 1140 |
+
_Span = Span
|
| 1141 |
+
|
| 1142 |
+
for span_start, span_end, style in self._spans:
|
| 1143 |
+
lower_bound = 0
|
| 1144 |
+
upper_bound = line_count
|
| 1145 |
+
start_line_no = (lower_bound + upper_bound) // 2
|
| 1146 |
+
|
| 1147 |
+
while True:
|
| 1148 |
+
line_start, line_end = line_ranges[start_line_no]
|
| 1149 |
+
if span_start < line_start:
|
| 1150 |
+
upper_bound = start_line_no - 1
|
| 1151 |
+
elif span_start > line_end:
|
| 1152 |
+
lower_bound = start_line_no + 1
|
| 1153 |
+
else:
|
| 1154 |
+
break
|
| 1155 |
+
start_line_no = (lower_bound + upper_bound) // 2
|
| 1156 |
+
|
| 1157 |
+
if span_end < line_end:
|
| 1158 |
+
end_line_no = start_line_no
|
| 1159 |
+
else:
|
| 1160 |
+
end_line_no = lower_bound = start_line_no
|
| 1161 |
+
upper_bound = line_count
|
| 1162 |
+
|
| 1163 |
+
while True:
|
| 1164 |
+
line_start, line_end = line_ranges[end_line_no]
|
| 1165 |
+
if span_end < line_start:
|
| 1166 |
+
upper_bound = end_line_no - 1
|
| 1167 |
+
elif span_end > line_end:
|
| 1168 |
+
lower_bound = end_line_no + 1
|
| 1169 |
+
else:
|
| 1170 |
+
break
|
| 1171 |
+
end_line_no = (lower_bound + upper_bound) // 2
|
| 1172 |
+
|
| 1173 |
+
for line_no in range(start_line_no, end_line_no + 1):
|
| 1174 |
+
line_start, line_end = line_ranges[line_no]
|
| 1175 |
+
new_start = max(0, span_start - line_start)
|
| 1176 |
+
new_end = min(span_end - line_start, line_end - line_start)
|
| 1177 |
+
if new_end > new_start:
|
| 1178 |
+
_line_appends[line_no](_Span(new_start, new_end, style))
|
| 1179 |
+
|
| 1180 |
+
return new_lines
|
| 1181 |
+
|
| 1182 |
+
def right_crop(self, amount: int = 1) -> None:
|
| 1183 |
+
"""Remove a number of characters from the end of the text."""
|
| 1184 |
+
max_offset = len(self.plain) - amount
|
| 1185 |
+
_Span = Span
|
| 1186 |
+
self._spans[:] = [
|
| 1187 |
+
(
|
| 1188 |
+
span
|
| 1189 |
+
if span.end < max_offset
|
| 1190 |
+
else _Span(span.start, min(max_offset, span.end), span.style)
|
| 1191 |
+
)
|
| 1192 |
+
for span in self._spans
|
| 1193 |
+
if span.start < max_offset
|
| 1194 |
+
]
|
| 1195 |
+
self._text = [self.plain[:-amount]]
|
| 1196 |
+
self._length -= amount
|
| 1197 |
+
|
| 1198 |
+
def wrap(
|
| 1199 |
+
self,
|
| 1200 |
+
console: "Console",
|
| 1201 |
+
width: int,
|
| 1202 |
+
*,
|
| 1203 |
+
justify: Optional["JustifyMethod"] = None,
|
| 1204 |
+
overflow: Optional["OverflowMethod"] = None,
|
| 1205 |
+
tab_size: int = 8,
|
| 1206 |
+
no_wrap: Optional[bool] = None,
|
| 1207 |
+
) -> Lines:
|
| 1208 |
+
"""Word wrap the text.
|
| 1209 |
+
|
| 1210 |
+
Args:
|
| 1211 |
+
console (Console): Console instance.
|
| 1212 |
+
width (int): Number of cells available per line.
|
| 1213 |
+
justify (str, optional): Justify method: "default", "left", "center", "full", "right". Defaults to "default".
|
| 1214 |
+
overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None.
|
| 1215 |
+
tab_size (int, optional): Default tab size. Defaults to 8.
|
| 1216 |
+
no_wrap (bool, optional): Disable wrapping, Defaults to False.
|
| 1217 |
+
|
| 1218 |
+
Returns:
|
| 1219 |
+
Lines: Number of lines.
|
| 1220 |
+
"""
|
| 1221 |
+
wrap_justify = justify or self.justify or DEFAULT_JUSTIFY
|
| 1222 |
+
wrap_overflow = overflow or self.overflow or DEFAULT_OVERFLOW
|
| 1223 |
+
|
| 1224 |
+
no_wrap = pick_bool(no_wrap, self.no_wrap, False) or overflow == "ignore"
|
| 1225 |
+
|
| 1226 |
+
lines = Lines()
|
| 1227 |
+
for line in self.split(allow_blank=True):
|
| 1228 |
+
if "\t" in line:
|
| 1229 |
+
line.expand_tabs(tab_size)
|
| 1230 |
+
if no_wrap:
|
| 1231 |
+
new_lines = Lines([line])
|
| 1232 |
+
else:
|
| 1233 |
+
offsets = divide_line(str(line), width, fold=wrap_overflow == "fold")
|
| 1234 |
+
new_lines = line.divide(offsets)
|
| 1235 |
+
for line in new_lines:
|
| 1236 |
+
line.rstrip_end(width)
|
| 1237 |
+
if wrap_justify:
|
| 1238 |
+
new_lines.justify(
|
| 1239 |
+
console, width, justify=wrap_justify, overflow=wrap_overflow
|
| 1240 |
+
)
|
| 1241 |
+
for line in new_lines:
|
| 1242 |
+
line.truncate(width, overflow=wrap_overflow)
|
| 1243 |
+
lines.extend(new_lines)
|
| 1244 |
+
return lines
|
| 1245 |
+
|
| 1246 |
+
def fit(self, width: int) -> Lines:
|
| 1247 |
+
"""Fit the text in to given width by chopping in to lines.
|
| 1248 |
+
|
| 1249 |
+
Args:
|
| 1250 |
+
width (int): Maximum characters in a line.
|
| 1251 |
+
|
| 1252 |
+
Returns:
|
| 1253 |
+
Lines: Lines container.
|
| 1254 |
+
"""
|
| 1255 |
+
lines: Lines = Lines()
|
| 1256 |
+
append = lines.append
|
| 1257 |
+
for line in self.split():
|
| 1258 |
+
line.set_length(width)
|
| 1259 |
+
append(line)
|
| 1260 |
+
return lines
|
| 1261 |
+
|
| 1262 |
+
def detect_indentation(self) -> int:
|
| 1263 |
+
"""Auto-detect indentation of code.
|
| 1264 |
+
|
| 1265 |
+
Returns:
|
| 1266 |
+
int: Number of spaces used to indent code.
|
| 1267 |
+
"""
|
| 1268 |
+
|
| 1269 |
+
_indentations = {
|
| 1270 |
+
len(match.group(1))
|
| 1271 |
+
for match in re.finditer(r"^( *)(.*)$", self.plain, flags=re.MULTILINE)
|
| 1272 |
+
}
|
| 1273 |
+
|
| 1274 |
+
try:
|
| 1275 |
+
indentation = (
|
| 1276 |
+
reduce(gcd, [indent for indent in _indentations if not indent % 2]) or 1
|
| 1277 |
+
)
|
| 1278 |
+
except TypeError:
|
| 1279 |
+
indentation = 1
|
| 1280 |
+
|
| 1281 |
+
return indentation
|
| 1282 |
+
|
| 1283 |
+
def with_indent_guides(
|
| 1284 |
+
self,
|
| 1285 |
+
indent_size: Optional[int] = None,
|
| 1286 |
+
*,
|
| 1287 |
+
character: str = "│",
|
| 1288 |
+
style: StyleType = "dim green",
|
| 1289 |
+
) -> "Text":
|
| 1290 |
+
"""Adds indent guide lines to text.
|
| 1291 |
+
|
| 1292 |
+
Args:
|
| 1293 |
+
indent_size (Optional[int]): Size of indentation, or None to auto detect. Defaults to None.
|
| 1294 |
+
character (str, optional): Character to use for indentation. Defaults to "│".
|
| 1295 |
+
style (Union[Style, str], optional): Style of indent guides.
|
| 1296 |
+
|
| 1297 |
+
Returns:
|
| 1298 |
+
Text: New text with indentation guides.
|
| 1299 |
+
"""
|
| 1300 |
+
|
| 1301 |
+
_indent_size = self.detect_indentation() if indent_size is None else indent_size
|
| 1302 |
+
|
| 1303 |
+
text = self.copy()
|
| 1304 |
+
text.expand_tabs()
|
| 1305 |
+
indent_line = f"{character}{' ' * (_indent_size - 1)}"
|
| 1306 |
+
|
| 1307 |
+
re_indent = re.compile(r"^( *)(.*)$")
|
| 1308 |
+
new_lines: List[Text] = []
|
| 1309 |
+
add_line = new_lines.append
|
| 1310 |
+
blank_lines = 0
|
| 1311 |
+
for line in text.split(allow_blank=True):
|
| 1312 |
+
match = re_indent.match(line.plain)
|
| 1313 |
+
if not match or not match.group(2):
|
| 1314 |
+
blank_lines += 1
|
| 1315 |
+
continue
|
| 1316 |
+
indent = match.group(1)
|
| 1317 |
+
full_indents, remaining_space = divmod(len(indent), _indent_size)
|
| 1318 |
+
new_indent = f"{indent_line * full_indents}{' ' * remaining_space}"
|
| 1319 |
+
line.plain = new_indent + line.plain[len(new_indent) :]
|
| 1320 |
+
line.stylize(style, 0, len(new_indent))
|
| 1321 |
+
if blank_lines:
|
| 1322 |
+
new_lines.extend([Text(new_indent, style=style)] * blank_lines)
|
| 1323 |
+
blank_lines = 0
|
| 1324 |
+
add_line(line)
|
| 1325 |
+
if blank_lines:
|
| 1326 |
+
new_lines.extend([Text("", style=style)] * blank_lines)
|
| 1327 |
+
|
| 1328 |
+
new_text = text.blank_copy("\n").join(new_lines)
|
| 1329 |
+
return new_text
|
| 1330 |
+
|
| 1331 |
+
|
| 1332 |
+
if __name__ == "__main__": # pragma: no cover
|
| 1333 |
+
from pip._vendor.rich.console import Console
|
| 1334 |
+
|
| 1335 |
+
text = Text(
|
| 1336 |
+
"""\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n"""
|
| 1337 |
+
)
|
| 1338 |
+
text.highlight_words(["Lorem"], "bold")
|
| 1339 |
+
text.highlight_words(["ipsum"], "italic")
|
| 1340 |
+
|
| 1341 |
+
console = Console()
|
| 1342 |
+
|
| 1343 |
+
console.rule("justify='left'")
|
| 1344 |
+
console.print(text, style="red")
|
| 1345 |
+
console.print()
|
| 1346 |
+
|
| 1347 |
+
console.rule("justify='center'")
|
| 1348 |
+
console.print(text, style="green", justify="center")
|
| 1349 |
+
console.print()
|
| 1350 |
+
|
| 1351 |
+
console.rule("justify='right'")
|
| 1352 |
+
console.print(text, style="blue", justify="right")
|
| 1353 |
+
console.print()
|
| 1354 |
+
|
| 1355 |
+
console.rule("justify='full'")
|
| 1356 |
+
console.print(text, style="magenta", justify="full")
|
| 1357 |
+
console.print()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: MIT
|
| 2 |
+
# SPDX-FileCopyrightText: 2021 Taneli Hukkinen
|
| 3 |
+
# Licensed to PSF under a Contributor Agreement.
|
| 4 |
+
|
| 5 |
+
__all__ = ("loads", "load", "TOMLDecodeError")
|
| 6 |
+
__version__ = "2.0.1" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT
|
| 7 |
+
|
| 8 |
+
from ._parser import TOMLDecodeError, load, loads
|
| 9 |
+
|
| 10 |
+
# Pretend this exception was created here.
|
| 11 |
+
TOMLDecodeError.__module__ = __name__
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (434 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-311.pyc
ADDED
|
Binary file (30.9 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-311.pyc
ADDED
|
Binary file (4.51 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-311.pyc
ADDED
|
Binary file (426 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/_parser.py
ADDED
|
@@ -0,0 +1,691 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: MIT
|
| 2 |
+
# SPDX-FileCopyrightText: 2021 Taneli Hukkinen
|
| 3 |
+
# Licensed to PSF under a Contributor Agreement.
|
| 4 |
+
|
| 5 |
+
from __future__ import annotations
|
| 6 |
+
|
| 7 |
+
from collections.abc import Iterable
|
| 8 |
+
import string
|
| 9 |
+
from types import MappingProxyType
|
| 10 |
+
from typing import Any, BinaryIO, NamedTuple
|
| 11 |
+
|
| 12 |
+
from ._re import (
|
| 13 |
+
RE_DATETIME,
|
| 14 |
+
RE_LOCALTIME,
|
| 15 |
+
RE_NUMBER,
|
| 16 |
+
match_to_datetime,
|
| 17 |
+
match_to_localtime,
|
| 18 |
+
match_to_number,
|
| 19 |
+
)
|
| 20 |
+
from ._types import Key, ParseFloat, Pos
|
| 21 |
+
|
| 22 |
+
ASCII_CTRL = frozenset(chr(i) for i in range(32)) | frozenset(chr(127))
|
| 23 |
+
|
| 24 |
+
# Neither of these sets include quotation mark or backslash. They are
|
| 25 |
+
# currently handled as separate cases in the parser functions.
|
| 26 |
+
ILLEGAL_BASIC_STR_CHARS = ASCII_CTRL - frozenset("\t")
|
| 27 |
+
ILLEGAL_MULTILINE_BASIC_STR_CHARS = ASCII_CTRL - frozenset("\t\n")
|
| 28 |
+
|
| 29 |
+
ILLEGAL_LITERAL_STR_CHARS = ILLEGAL_BASIC_STR_CHARS
|
| 30 |
+
ILLEGAL_MULTILINE_LITERAL_STR_CHARS = ILLEGAL_MULTILINE_BASIC_STR_CHARS
|
| 31 |
+
|
| 32 |
+
ILLEGAL_COMMENT_CHARS = ILLEGAL_BASIC_STR_CHARS
|
| 33 |
+
|
| 34 |
+
TOML_WS = frozenset(" \t")
|
| 35 |
+
TOML_WS_AND_NEWLINE = TOML_WS | frozenset("\n")
|
| 36 |
+
BARE_KEY_CHARS = frozenset(string.ascii_letters + string.digits + "-_")
|
| 37 |
+
KEY_INITIAL_CHARS = BARE_KEY_CHARS | frozenset("\"'")
|
| 38 |
+
HEXDIGIT_CHARS = frozenset(string.hexdigits)
|
| 39 |
+
|
| 40 |
+
BASIC_STR_ESCAPE_REPLACEMENTS = MappingProxyType(
|
| 41 |
+
{
|
| 42 |
+
"\\b": "\u0008", # backspace
|
| 43 |
+
"\\t": "\u0009", # tab
|
| 44 |
+
"\\n": "\u000A", # linefeed
|
| 45 |
+
"\\f": "\u000C", # form feed
|
| 46 |
+
"\\r": "\u000D", # carriage return
|
| 47 |
+
'\\"': "\u0022", # quote
|
| 48 |
+
"\\\\": "\u005C", # backslash
|
| 49 |
+
}
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
class TOMLDecodeError(ValueError):
|
| 54 |
+
"""An error raised if a document is not valid TOML."""
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def load(__fp: BinaryIO, *, parse_float: ParseFloat = float) -> dict[str, Any]:
|
| 58 |
+
"""Parse TOML from a binary file object."""
|
| 59 |
+
b = __fp.read()
|
| 60 |
+
try:
|
| 61 |
+
s = b.decode()
|
| 62 |
+
except AttributeError:
|
| 63 |
+
raise TypeError(
|
| 64 |
+
"File must be opened in binary mode, e.g. use `open('foo.toml', 'rb')`"
|
| 65 |
+
) from None
|
| 66 |
+
return loads(s, parse_float=parse_float)
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def loads(__s: str, *, parse_float: ParseFloat = float) -> dict[str, Any]: # noqa: C901
|
| 70 |
+
"""Parse TOML from a string."""
|
| 71 |
+
|
| 72 |
+
# The spec allows converting "\r\n" to "\n", even in string
|
| 73 |
+
# literals. Let's do so to simplify parsing.
|
| 74 |
+
src = __s.replace("\r\n", "\n")
|
| 75 |
+
pos = 0
|
| 76 |
+
out = Output(NestedDict(), Flags())
|
| 77 |
+
header: Key = ()
|
| 78 |
+
parse_float = make_safe_parse_float(parse_float)
|
| 79 |
+
|
| 80 |
+
# Parse one statement at a time
|
| 81 |
+
# (typically means one line in TOML source)
|
| 82 |
+
while True:
|
| 83 |
+
# 1. Skip line leading whitespace
|
| 84 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 85 |
+
|
| 86 |
+
# 2. Parse rules. Expect one of the following:
|
| 87 |
+
# - end of file
|
| 88 |
+
# - end of line
|
| 89 |
+
# - comment
|
| 90 |
+
# - key/value pair
|
| 91 |
+
# - append dict to list (and move to its namespace)
|
| 92 |
+
# - create dict (and move to its namespace)
|
| 93 |
+
# Skip trailing whitespace when applicable.
|
| 94 |
+
try:
|
| 95 |
+
char = src[pos]
|
| 96 |
+
except IndexError:
|
| 97 |
+
break
|
| 98 |
+
if char == "\n":
|
| 99 |
+
pos += 1
|
| 100 |
+
continue
|
| 101 |
+
if char in KEY_INITIAL_CHARS:
|
| 102 |
+
pos = key_value_rule(src, pos, out, header, parse_float)
|
| 103 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 104 |
+
elif char == "[":
|
| 105 |
+
try:
|
| 106 |
+
second_char: str | None = src[pos + 1]
|
| 107 |
+
except IndexError:
|
| 108 |
+
second_char = None
|
| 109 |
+
out.flags.finalize_pending()
|
| 110 |
+
if second_char == "[":
|
| 111 |
+
pos, header = create_list_rule(src, pos, out)
|
| 112 |
+
else:
|
| 113 |
+
pos, header = create_dict_rule(src, pos, out)
|
| 114 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 115 |
+
elif char != "#":
|
| 116 |
+
raise suffixed_err(src, pos, "Invalid statement")
|
| 117 |
+
|
| 118 |
+
# 3. Skip comment
|
| 119 |
+
pos = skip_comment(src, pos)
|
| 120 |
+
|
| 121 |
+
# 4. Expect end of line or end of file
|
| 122 |
+
try:
|
| 123 |
+
char = src[pos]
|
| 124 |
+
except IndexError:
|
| 125 |
+
break
|
| 126 |
+
if char != "\n":
|
| 127 |
+
raise suffixed_err(
|
| 128 |
+
src, pos, "Expected newline or end of document after a statement"
|
| 129 |
+
)
|
| 130 |
+
pos += 1
|
| 131 |
+
|
| 132 |
+
return out.data.dict
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
class Flags:
|
| 136 |
+
"""Flags that map to parsed keys/namespaces."""
|
| 137 |
+
|
| 138 |
+
# Marks an immutable namespace (inline array or inline table).
|
| 139 |
+
FROZEN = 0
|
| 140 |
+
# Marks a nest that has been explicitly created and can no longer
|
| 141 |
+
# be opened using the "[table]" syntax.
|
| 142 |
+
EXPLICIT_NEST = 1
|
| 143 |
+
|
| 144 |
+
def __init__(self) -> None:
|
| 145 |
+
self._flags: dict[str, dict] = {}
|
| 146 |
+
self._pending_flags: set[tuple[Key, int]] = set()
|
| 147 |
+
|
| 148 |
+
def add_pending(self, key: Key, flag: int) -> None:
|
| 149 |
+
self._pending_flags.add((key, flag))
|
| 150 |
+
|
| 151 |
+
def finalize_pending(self) -> None:
|
| 152 |
+
for key, flag in self._pending_flags:
|
| 153 |
+
self.set(key, flag, recursive=False)
|
| 154 |
+
self._pending_flags.clear()
|
| 155 |
+
|
| 156 |
+
def unset_all(self, key: Key) -> None:
|
| 157 |
+
cont = self._flags
|
| 158 |
+
for k in key[:-1]:
|
| 159 |
+
if k not in cont:
|
| 160 |
+
return
|
| 161 |
+
cont = cont[k]["nested"]
|
| 162 |
+
cont.pop(key[-1], None)
|
| 163 |
+
|
| 164 |
+
def set(self, key: Key, flag: int, *, recursive: bool) -> None: # noqa: A003
|
| 165 |
+
cont = self._flags
|
| 166 |
+
key_parent, key_stem = key[:-1], key[-1]
|
| 167 |
+
for k in key_parent:
|
| 168 |
+
if k not in cont:
|
| 169 |
+
cont[k] = {"flags": set(), "recursive_flags": set(), "nested": {}}
|
| 170 |
+
cont = cont[k]["nested"]
|
| 171 |
+
if key_stem not in cont:
|
| 172 |
+
cont[key_stem] = {"flags": set(), "recursive_flags": set(), "nested": {}}
|
| 173 |
+
cont[key_stem]["recursive_flags" if recursive else "flags"].add(flag)
|
| 174 |
+
|
| 175 |
+
def is_(self, key: Key, flag: int) -> bool:
|
| 176 |
+
if not key:
|
| 177 |
+
return False # document root has no flags
|
| 178 |
+
cont = self._flags
|
| 179 |
+
for k in key[:-1]:
|
| 180 |
+
if k not in cont:
|
| 181 |
+
return False
|
| 182 |
+
inner_cont = cont[k]
|
| 183 |
+
if flag in inner_cont["recursive_flags"]:
|
| 184 |
+
return True
|
| 185 |
+
cont = inner_cont["nested"]
|
| 186 |
+
key_stem = key[-1]
|
| 187 |
+
if key_stem in cont:
|
| 188 |
+
cont = cont[key_stem]
|
| 189 |
+
return flag in cont["flags"] or flag in cont["recursive_flags"]
|
| 190 |
+
return False
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
class NestedDict:
|
| 194 |
+
def __init__(self) -> None:
|
| 195 |
+
# The parsed content of the TOML document
|
| 196 |
+
self.dict: dict[str, Any] = {}
|
| 197 |
+
|
| 198 |
+
def get_or_create_nest(
|
| 199 |
+
self,
|
| 200 |
+
key: Key,
|
| 201 |
+
*,
|
| 202 |
+
access_lists: bool = True,
|
| 203 |
+
) -> dict:
|
| 204 |
+
cont: Any = self.dict
|
| 205 |
+
for k in key:
|
| 206 |
+
if k not in cont:
|
| 207 |
+
cont[k] = {}
|
| 208 |
+
cont = cont[k]
|
| 209 |
+
if access_lists and isinstance(cont, list):
|
| 210 |
+
cont = cont[-1]
|
| 211 |
+
if not isinstance(cont, dict):
|
| 212 |
+
raise KeyError("There is no nest behind this key")
|
| 213 |
+
return cont
|
| 214 |
+
|
| 215 |
+
def append_nest_to_list(self, key: Key) -> None:
|
| 216 |
+
cont = self.get_or_create_nest(key[:-1])
|
| 217 |
+
last_key = key[-1]
|
| 218 |
+
if last_key in cont:
|
| 219 |
+
list_ = cont[last_key]
|
| 220 |
+
if not isinstance(list_, list):
|
| 221 |
+
raise KeyError("An object other than list found behind this key")
|
| 222 |
+
list_.append({})
|
| 223 |
+
else:
|
| 224 |
+
cont[last_key] = [{}]
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
class Output(NamedTuple):
|
| 228 |
+
data: NestedDict
|
| 229 |
+
flags: Flags
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
def skip_chars(src: str, pos: Pos, chars: Iterable[str]) -> Pos:
|
| 233 |
+
try:
|
| 234 |
+
while src[pos] in chars:
|
| 235 |
+
pos += 1
|
| 236 |
+
except IndexError:
|
| 237 |
+
pass
|
| 238 |
+
return pos
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
def skip_until(
|
| 242 |
+
src: str,
|
| 243 |
+
pos: Pos,
|
| 244 |
+
expect: str,
|
| 245 |
+
*,
|
| 246 |
+
error_on: frozenset[str],
|
| 247 |
+
error_on_eof: bool,
|
| 248 |
+
) -> Pos:
|
| 249 |
+
try:
|
| 250 |
+
new_pos = src.index(expect, pos)
|
| 251 |
+
except ValueError:
|
| 252 |
+
new_pos = len(src)
|
| 253 |
+
if error_on_eof:
|
| 254 |
+
raise suffixed_err(src, new_pos, f"Expected {expect!r}") from None
|
| 255 |
+
|
| 256 |
+
if not error_on.isdisjoint(src[pos:new_pos]):
|
| 257 |
+
while src[pos] not in error_on:
|
| 258 |
+
pos += 1
|
| 259 |
+
raise suffixed_err(src, pos, f"Found invalid character {src[pos]!r}")
|
| 260 |
+
return new_pos
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
def skip_comment(src: str, pos: Pos) -> Pos:
|
| 264 |
+
try:
|
| 265 |
+
char: str | None = src[pos]
|
| 266 |
+
except IndexError:
|
| 267 |
+
char = None
|
| 268 |
+
if char == "#":
|
| 269 |
+
return skip_until(
|
| 270 |
+
src, pos + 1, "\n", error_on=ILLEGAL_COMMENT_CHARS, error_on_eof=False
|
| 271 |
+
)
|
| 272 |
+
return pos
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def skip_comments_and_array_ws(src: str, pos: Pos) -> Pos:
|
| 276 |
+
while True:
|
| 277 |
+
pos_before_skip = pos
|
| 278 |
+
pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE)
|
| 279 |
+
pos = skip_comment(src, pos)
|
| 280 |
+
if pos == pos_before_skip:
|
| 281 |
+
return pos
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
def create_dict_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]:
|
| 285 |
+
pos += 1 # Skip "["
|
| 286 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 287 |
+
pos, key = parse_key(src, pos)
|
| 288 |
+
|
| 289 |
+
if out.flags.is_(key, Flags.EXPLICIT_NEST) or out.flags.is_(key, Flags.FROZEN):
|
| 290 |
+
raise suffixed_err(src, pos, f"Cannot declare {key} twice")
|
| 291 |
+
out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False)
|
| 292 |
+
try:
|
| 293 |
+
out.data.get_or_create_nest(key)
|
| 294 |
+
except KeyError:
|
| 295 |
+
raise suffixed_err(src, pos, "Cannot overwrite a value") from None
|
| 296 |
+
|
| 297 |
+
if not src.startswith("]", pos):
|
| 298 |
+
raise suffixed_err(src, pos, "Expected ']' at the end of a table declaration")
|
| 299 |
+
return pos + 1, key
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
def create_list_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]:
|
| 303 |
+
pos += 2 # Skip "[["
|
| 304 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 305 |
+
pos, key = parse_key(src, pos)
|
| 306 |
+
|
| 307 |
+
if out.flags.is_(key, Flags.FROZEN):
|
| 308 |
+
raise suffixed_err(src, pos, f"Cannot mutate immutable namespace {key}")
|
| 309 |
+
# Free the namespace now that it points to another empty list item...
|
| 310 |
+
out.flags.unset_all(key)
|
| 311 |
+
# ...but this key precisely is still prohibited from table declaration
|
| 312 |
+
out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False)
|
| 313 |
+
try:
|
| 314 |
+
out.data.append_nest_to_list(key)
|
| 315 |
+
except KeyError:
|
| 316 |
+
raise suffixed_err(src, pos, "Cannot overwrite a value") from None
|
| 317 |
+
|
| 318 |
+
if not src.startswith("]]", pos):
|
| 319 |
+
raise suffixed_err(src, pos, "Expected ']]' at the end of an array declaration")
|
| 320 |
+
return pos + 2, key
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def key_value_rule(
|
| 324 |
+
src: str, pos: Pos, out: Output, header: Key, parse_float: ParseFloat
|
| 325 |
+
) -> Pos:
|
| 326 |
+
pos, key, value = parse_key_value_pair(src, pos, parse_float)
|
| 327 |
+
key_parent, key_stem = key[:-1], key[-1]
|
| 328 |
+
abs_key_parent = header + key_parent
|
| 329 |
+
|
| 330 |
+
relative_path_cont_keys = (header + key[:i] for i in range(1, len(key)))
|
| 331 |
+
for cont_key in relative_path_cont_keys:
|
| 332 |
+
# Check that dotted key syntax does not redefine an existing table
|
| 333 |
+
if out.flags.is_(cont_key, Flags.EXPLICIT_NEST):
|
| 334 |
+
raise suffixed_err(src, pos, f"Cannot redefine namespace {cont_key}")
|
| 335 |
+
# Containers in the relative path can't be opened with the table syntax or
|
| 336 |
+
# dotted key/value syntax in following table sections.
|
| 337 |
+
out.flags.add_pending(cont_key, Flags.EXPLICIT_NEST)
|
| 338 |
+
|
| 339 |
+
if out.flags.is_(abs_key_parent, Flags.FROZEN):
|
| 340 |
+
raise suffixed_err(
|
| 341 |
+
src, pos, f"Cannot mutate immutable namespace {abs_key_parent}"
|
| 342 |
+
)
|
| 343 |
+
|
| 344 |
+
try:
|
| 345 |
+
nest = out.data.get_or_create_nest(abs_key_parent)
|
| 346 |
+
except KeyError:
|
| 347 |
+
raise suffixed_err(src, pos, "Cannot overwrite a value") from None
|
| 348 |
+
if key_stem in nest:
|
| 349 |
+
raise suffixed_err(src, pos, "Cannot overwrite a value")
|
| 350 |
+
# Mark inline table and array namespaces recursively immutable
|
| 351 |
+
if isinstance(value, (dict, list)):
|
| 352 |
+
out.flags.set(header + key, Flags.FROZEN, recursive=True)
|
| 353 |
+
nest[key_stem] = value
|
| 354 |
+
return pos
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
def parse_key_value_pair(
|
| 358 |
+
src: str, pos: Pos, parse_float: ParseFloat
|
| 359 |
+
) -> tuple[Pos, Key, Any]:
|
| 360 |
+
pos, key = parse_key(src, pos)
|
| 361 |
+
try:
|
| 362 |
+
char: str | None = src[pos]
|
| 363 |
+
except IndexError:
|
| 364 |
+
char = None
|
| 365 |
+
if char != "=":
|
| 366 |
+
raise suffixed_err(src, pos, "Expected '=' after a key in a key/value pair")
|
| 367 |
+
pos += 1
|
| 368 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 369 |
+
pos, value = parse_value(src, pos, parse_float)
|
| 370 |
+
return pos, key, value
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
def parse_key(src: str, pos: Pos) -> tuple[Pos, Key]:
|
| 374 |
+
pos, key_part = parse_key_part(src, pos)
|
| 375 |
+
key: Key = (key_part,)
|
| 376 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 377 |
+
while True:
|
| 378 |
+
try:
|
| 379 |
+
char: str | None = src[pos]
|
| 380 |
+
except IndexError:
|
| 381 |
+
char = None
|
| 382 |
+
if char != ".":
|
| 383 |
+
return pos, key
|
| 384 |
+
pos += 1
|
| 385 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 386 |
+
pos, key_part = parse_key_part(src, pos)
|
| 387 |
+
key += (key_part,)
|
| 388 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 389 |
+
|
| 390 |
+
|
| 391 |
+
def parse_key_part(src: str, pos: Pos) -> tuple[Pos, str]:
|
| 392 |
+
try:
|
| 393 |
+
char: str | None = src[pos]
|
| 394 |
+
except IndexError:
|
| 395 |
+
char = None
|
| 396 |
+
if char in BARE_KEY_CHARS:
|
| 397 |
+
start_pos = pos
|
| 398 |
+
pos = skip_chars(src, pos, BARE_KEY_CHARS)
|
| 399 |
+
return pos, src[start_pos:pos]
|
| 400 |
+
if char == "'":
|
| 401 |
+
return parse_literal_str(src, pos)
|
| 402 |
+
if char == '"':
|
| 403 |
+
return parse_one_line_basic_str(src, pos)
|
| 404 |
+
raise suffixed_err(src, pos, "Invalid initial character for a key part")
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
def parse_one_line_basic_str(src: str, pos: Pos) -> tuple[Pos, str]:
|
| 408 |
+
pos += 1
|
| 409 |
+
return parse_basic_str(src, pos, multiline=False)
|
| 410 |
+
|
| 411 |
+
|
| 412 |
+
def parse_array(src: str, pos: Pos, parse_float: ParseFloat) -> tuple[Pos, list]:
|
| 413 |
+
pos += 1
|
| 414 |
+
array: list = []
|
| 415 |
+
|
| 416 |
+
pos = skip_comments_and_array_ws(src, pos)
|
| 417 |
+
if src.startswith("]", pos):
|
| 418 |
+
return pos + 1, array
|
| 419 |
+
while True:
|
| 420 |
+
pos, val = parse_value(src, pos, parse_float)
|
| 421 |
+
array.append(val)
|
| 422 |
+
pos = skip_comments_and_array_ws(src, pos)
|
| 423 |
+
|
| 424 |
+
c = src[pos : pos + 1]
|
| 425 |
+
if c == "]":
|
| 426 |
+
return pos + 1, array
|
| 427 |
+
if c != ",":
|
| 428 |
+
raise suffixed_err(src, pos, "Unclosed array")
|
| 429 |
+
pos += 1
|
| 430 |
+
|
| 431 |
+
pos = skip_comments_and_array_ws(src, pos)
|
| 432 |
+
if src.startswith("]", pos):
|
| 433 |
+
return pos + 1, array
|
| 434 |
+
|
| 435 |
+
|
| 436 |
+
def parse_inline_table(src: str, pos: Pos, parse_float: ParseFloat) -> tuple[Pos, dict]:
|
| 437 |
+
pos += 1
|
| 438 |
+
nested_dict = NestedDict()
|
| 439 |
+
flags = Flags()
|
| 440 |
+
|
| 441 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 442 |
+
if src.startswith("}", pos):
|
| 443 |
+
return pos + 1, nested_dict.dict
|
| 444 |
+
while True:
|
| 445 |
+
pos, key, value = parse_key_value_pair(src, pos, parse_float)
|
| 446 |
+
key_parent, key_stem = key[:-1], key[-1]
|
| 447 |
+
if flags.is_(key, Flags.FROZEN):
|
| 448 |
+
raise suffixed_err(src, pos, f"Cannot mutate immutable namespace {key}")
|
| 449 |
+
try:
|
| 450 |
+
nest = nested_dict.get_or_create_nest(key_parent, access_lists=False)
|
| 451 |
+
except KeyError:
|
| 452 |
+
raise suffixed_err(src, pos, "Cannot overwrite a value") from None
|
| 453 |
+
if key_stem in nest:
|
| 454 |
+
raise suffixed_err(src, pos, f"Duplicate inline table key {key_stem!r}")
|
| 455 |
+
nest[key_stem] = value
|
| 456 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 457 |
+
c = src[pos : pos + 1]
|
| 458 |
+
if c == "}":
|
| 459 |
+
return pos + 1, nested_dict.dict
|
| 460 |
+
if c != ",":
|
| 461 |
+
raise suffixed_err(src, pos, "Unclosed inline table")
|
| 462 |
+
if isinstance(value, (dict, list)):
|
| 463 |
+
flags.set(key, Flags.FROZEN, recursive=True)
|
| 464 |
+
pos += 1
|
| 465 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 466 |
+
|
| 467 |
+
|
| 468 |
+
def parse_basic_str_escape(
|
| 469 |
+
src: str, pos: Pos, *, multiline: bool = False
|
| 470 |
+
) -> tuple[Pos, str]:
|
| 471 |
+
escape_id = src[pos : pos + 2]
|
| 472 |
+
pos += 2
|
| 473 |
+
if multiline and escape_id in {"\\ ", "\\\t", "\\\n"}:
|
| 474 |
+
# Skip whitespace until next non-whitespace character or end of
|
| 475 |
+
# the doc. Error if non-whitespace is found before newline.
|
| 476 |
+
if escape_id != "\\\n":
|
| 477 |
+
pos = skip_chars(src, pos, TOML_WS)
|
| 478 |
+
try:
|
| 479 |
+
char = src[pos]
|
| 480 |
+
except IndexError:
|
| 481 |
+
return pos, ""
|
| 482 |
+
if char != "\n":
|
| 483 |
+
raise suffixed_err(src, pos, "Unescaped '\\' in a string")
|
| 484 |
+
pos += 1
|
| 485 |
+
pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE)
|
| 486 |
+
return pos, ""
|
| 487 |
+
if escape_id == "\\u":
|
| 488 |
+
return parse_hex_char(src, pos, 4)
|
| 489 |
+
if escape_id == "\\U":
|
| 490 |
+
return parse_hex_char(src, pos, 8)
|
| 491 |
+
try:
|
| 492 |
+
return pos, BASIC_STR_ESCAPE_REPLACEMENTS[escape_id]
|
| 493 |
+
except KeyError:
|
| 494 |
+
raise suffixed_err(src, pos, "Unescaped '\\' in a string") from None
|
| 495 |
+
|
| 496 |
+
|
| 497 |
+
def parse_basic_str_escape_multiline(src: str, pos: Pos) -> tuple[Pos, str]:
|
| 498 |
+
return parse_basic_str_escape(src, pos, multiline=True)
|
| 499 |
+
|
| 500 |
+
|
| 501 |
+
def parse_hex_char(src: str, pos: Pos, hex_len: int) -> tuple[Pos, str]:
|
| 502 |
+
hex_str = src[pos : pos + hex_len]
|
| 503 |
+
if len(hex_str) != hex_len or not HEXDIGIT_CHARS.issuperset(hex_str):
|
| 504 |
+
raise suffixed_err(src, pos, "Invalid hex value")
|
| 505 |
+
pos += hex_len
|
| 506 |
+
hex_int = int(hex_str, 16)
|
| 507 |
+
if not is_unicode_scalar_value(hex_int):
|
| 508 |
+
raise suffixed_err(src, pos, "Escaped character is not a Unicode scalar value")
|
| 509 |
+
return pos, chr(hex_int)
|
| 510 |
+
|
| 511 |
+
|
| 512 |
+
def parse_literal_str(src: str, pos: Pos) -> tuple[Pos, str]:
|
| 513 |
+
pos += 1 # Skip starting apostrophe
|
| 514 |
+
start_pos = pos
|
| 515 |
+
pos = skip_until(
|
| 516 |
+
src, pos, "'", error_on=ILLEGAL_LITERAL_STR_CHARS, error_on_eof=True
|
| 517 |
+
)
|
| 518 |
+
return pos + 1, src[start_pos:pos] # Skip ending apostrophe
|
| 519 |
+
|
| 520 |
+
|
| 521 |
+
def parse_multiline_str(src: str, pos: Pos, *, literal: bool) -> tuple[Pos, str]:
|
| 522 |
+
pos += 3
|
| 523 |
+
if src.startswith("\n", pos):
|
| 524 |
+
pos += 1
|
| 525 |
+
|
| 526 |
+
if literal:
|
| 527 |
+
delim = "'"
|
| 528 |
+
end_pos = skip_until(
|
| 529 |
+
src,
|
| 530 |
+
pos,
|
| 531 |
+
"'''",
|
| 532 |
+
error_on=ILLEGAL_MULTILINE_LITERAL_STR_CHARS,
|
| 533 |
+
error_on_eof=True,
|
| 534 |
+
)
|
| 535 |
+
result = src[pos:end_pos]
|
| 536 |
+
pos = end_pos + 3
|
| 537 |
+
else:
|
| 538 |
+
delim = '"'
|
| 539 |
+
pos, result = parse_basic_str(src, pos, multiline=True)
|
| 540 |
+
|
| 541 |
+
# Add at maximum two extra apostrophes/quotes if the end sequence
|
| 542 |
+
# is 4 or 5 chars long instead of just 3.
|
| 543 |
+
if not src.startswith(delim, pos):
|
| 544 |
+
return pos, result
|
| 545 |
+
pos += 1
|
| 546 |
+
if not src.startswith(delim, pos):
|
| 547 |
+
return pos, result + delim
|
| 548 |
+
pos += 1
|
| 549 |
+
return pos, result + (delim * 2)
|
| 550 |
+
|
| 551 |
+
|
| 552 |
+
def parse_basic_str(src: str, pos: Pos, *, multiline: bool) -> tuple[Pos, str]:
|
| 553 |
+
if multiline:
|
| 554 |
+
error_on = ILLEGAL_MULTILINE_BASIC_STR_CHARS
|
| 555 |
+
parse_escapes = parse_basic_str_escape_multiline
|
| 556 |
+
else:
|
| 557 |
+
error_on = ILLEGAL_BASIC_STR_CHARS
|
| 558 |
+
parse_escapes = parse_basic_str_escape
|
| 559 |
+
result = ""
|
| 560 |
+
start_pos = pos
|
| 561 |
+
while True:
|
| 562 |
+
try:
|
| 563 |
+
char = src[pos]
|
| 564 |
+
except IndexError:
|
| 565 |
+
raise suffixed_err(src, pos, "Unterminated string") from None
|
| 566 |
+
if char == '"':
|
| 567 |
+
if not multiline:
|
| 568 |
+
return pos + 1, result + src[start_pos:pos]
|
| 569 |
+
if src.startswith('"""', pos):
|
| 570 |
+
return pos + 3, result + src[start_pos:pos]
|
| 571 |
+
pos += 1
|
| 572 |
+
continue
|
| 573 |
+
if char == "\\":
|
| 574 |
+
result += src[start_pos:pos]
|
| 575 |
+
pos, parsed_escape = parse_escapes(src, pos)
|
| 576 |
+
result += parsed_escape
|
| 577 |
+
start_pos = pos
|
| 578 |
+
continue
|
| 579 |
+
if char in error_on:
|
| 580 |
+
raise suffixed_err(src, pos, f"Illegal character {char!r}")
|
| 581 |
+
pos += 1
|
| 582 |
+
|
| 583 |
+
|
| 584 |
+
def parse_value( # noqa: C901
|
| 585 |
+
src: str, pos: Pos, parse_float: ParseFloat
|
| 586 |
+
) -> tuple[Pos, Any]:
|
| 587 |
+
try:
|
| 588 |
+
char: str | None = src[pos]
|
| 589 |
+
except IndexError:
|
| 590 |
+
char = None
|
| 591 |
+
|
| 592 |
+
# IMPORTANT: order conditions based on speed of checking and likelihood
|
| 593 |
+
|
| 594 |
+
# Basic strings
|
| 595 |
+
if char == '"':
|
| 596 |
+
if src.startswith('"""', pos):
|
| 597 |
+
return parse_multiline_str(src, pos, literal=False)
|
| 598 |
+
return parse_one_line_basic_str(src, pos)
|
| 599 |
+
|
| 600 |
+
# Literal strings
|
| 601 |
+
if char == "'":
|
| 602 |
+
if src.startswith("'''", pos):
|
| 603 |
+
return parse_multiline_str(src, pos, literal=True)
|
| 604 |
+
return parse_literal_str(src, pos)
|
| 605 |
+
|
| 606 |
+
# Booleans
|
| 607 |
+
if char == "t":
|
| 608 |
+
if src.startswith("true", pos):
|
| 609 |
+
return pos + 4, True
|
| 610 |
+
if char == "f":
|
| 611 |
+
if src.startswith("false", pos):
|
| 612 |
+
return pos + 5, False
|
| 613 |
+
|
| 614 |
+
# Arrays
|
| 615 |
+
if char == "[":
|
| 616 |
+
return parse_array(src, pos, parse_float)
|
| 617 |
+
|
| 618 |
+
# Inline tables
|
| 619 |
+
if char == "{":
|
| 620 |
+
return parse_inline_table(src, pos, parse_float)
|
| 621 |
+
|
| 622 |
+
# Dates and times
|
| 623 |
+
datetime_match = RE_DATETIME.match(src, pos)
|
| 624 |
+
if datetime_match:
|
| 625 |
+
try:
|
| 626 |
+
datetime_obj = match_to_datetime(datetime_match)
|
| 627 |
+
except ValueError as e:
|
| 628 |
+
raise suffixed_err(src, pos, "Invalid date or datetime") from e
|
| 629 |
+
return datetime_match.end(), datetime_obj
|
| 630 |
+
localtime_match = RE_LOCALTIME.match(src, pos)
|
| 631 |
+
if localtime_match:
|
| 632 |
+
return localtime_match.end(), match_to_localtime(localtime_match)
|
| 633 |
+
|
| 634 |
+
# Integers and "normal" floats.
|
| 635 |
+
# The regex will greedily match any type starting with a decimal
|
| 636 |
+
# char, so needs to be located after handling of dates and times.
|
| 637 |
+
number_match = RE_NUMBER.match(src, pos)
|
| 638 |
+
if number_match:
|
| 639 |
+
return number_match.end(), match_to_number(number_match, parse_float)
|
| 640 |
+
|
| 641 |
+
# Special floats
|
| 642 |
+
first_three = src[pos : pos + 3]
|
| 643 |
+
if first_three in {"inf", "nan"}:
|
| 644 |
+
return pos + 3, parse_float(first_three)
|
| 645 |
+
first_four = src[pos : pos + 4]
|
| 646 |
+
if first_four in {"-inf", "+inf", "-nan", "+nan"}:
|
| 647 |
+
return pos + 4, parse_float(first_four)
|
| 648 |
+
|
| 649 |
+
raise suffixed_err(src, pos, "Invalid value")
|
| 650 |
+
|
| 651 |
+
|
| 652 |
+
def suffixed_err(src: str, pos: Pos, msg: str) -> TOMLDecodeError:
|
| 653 |
+
"""Return a `TOMLDecodeError` where error message is suffixed with
|
| 654 |
+
coordinates in source."""
|
| 655 |
+
|
| 656 |
+
def coord_repr(src: str, pos: Pos) -> str:
|
| 657 |
+
if pos >= len(src):
|
| 658 |
+
return "end of document"
|
| 659 |
+
line = src.count("\n", 0, pos) + 1
|
| 660 |
+
if line == 1:
|
| 661 |
+
column = pos + 1
|
| 662 |
+
else:
|
| 663 |
+
column = pos - src.rindex("\n", 0, pos)
|
| 664 |
+
return f"line {line}, column {column}"
|
| 665 |
+
|
| 666 |
+
return TOMLDecodeError(f"{msg} (at {coord_repr(src, pos)})")
|
| 667 |
+
|
| 668 |
+
|
| 669 |
+
def is_unicode_scalar_value(codepoint: int) -> bool:
|
| 670 |
+
return (0 <= codepoint <= 55295) or (57344 <= codepoint <= 1114111)
|
| 671 |
+
|
| 672 |
+
|
| 673 |
+
def make_safe_parse_float(parse_float: ParseFloat) -> ParseFloat:
|
| 674 |
+
"""A decorator to make `parse_float` safe.
|
| 675 |
+
|
| 676 |
+
`parse_float` must not return dicts or lists, because these types
|
| 677 |
+
would be mixed with parsed TOML tables and arrays, thus confusing
|
| 678 |
+
the parser. The returned decorated callable raises `ValueError`
|
| 679 |
+
instead of returning illegal types.
|
| 680 |
+
"""
|
| 681 |
+
# The default `float` callable never returns illegal types. Optimize it.
|
| 682 |
+
if parse_float is float: # type: ignore[comparison-overlap]
|
| 683 |
+
return float
|
| 684 |
+
|
| 685 |
+
def safe_parse_float(float_str: str) -> Any:
|
| 686 |
+
float_value = parse_float(float_str)
|
| 687 |
+
if isinstance(float_value, (dict, list)):
|
| 688 |
+
raise ValueError("parse_float must not return dicts or lists")
|
| 689 |
+
return float_value
|
| 690 |
+
|
| 691 |
+
return safe_parse_float
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/tomli/_re.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: MIT
|
| 2 |
+
# SPDX-FileCopyrightText: 2021 Taneli Hukkinen
|
| 3 |
+
# Licensed to PSF under a Contributor Agreement.
|
| 4 |
+
|
| 5 |
+
from __future__ import annotations
|
| 6 |
+
|
| 7 |
+
from datetime import date, datetime, time, timedelta, timezone, tzinfo
|
| 8 |
+
from functools import lru_cache
|
| 9 |
+
import re
|
| 10 |
+
from typing import Any
|
| 11 |
+
|
| 12 |
+
from ._types import ParseFloat
|
| 13 |
+
|
| 14 |
+
# E.g.
|
| 15 |
+
# - 00:32:00.999999
|
| 16 |
+
# - 00:32:00
|
| 17 |
+
_TIME_RE_STR = r"([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:\.([0-9]{1,6})[0-9]*)?"
|
| 18 |
+
|
| 19 |
+
RE_NUMBER = re.compile(
|
| 20 |
+
r"""
|
| 21 |
+
0
|
| 22 |
+
(?:
|
| 23 |
+
x[0-9A-Fa-f](?:_?[0-9A-Fa-f])* # hex
|
| 24 |
+
|
|
| 25 |
+
b[01](?:_?[01])* # bin
|
| 26 |
+
|
|
| 27 |
+
o[0-7](?:_?[0-7])* # oct
|
| 28 |
+
)
|
| 29 |
+
|
|
| 30 |
+
[+-]?(?:0|[1-9](?:_?[0-9])*) # dec, integer part
|
| 31 |
+
(?P<floatpart>
|
| 32 |
+
(?:\.[0-9](?:_?[0-9])*)? # optional fractional part
|
| 33 |
+
(?:[eE][+-]?[0-9](?:_?[0-9])*)? # optional exponent part
|
| 34 |
+
)
|
| 35 |
+
""",
|
| 36 |
+
flags=re.VERBOSE,
|
| 37 |
+
)
|
| 38 |
+
RE_LOCALTIME = re.compile(_TIME_RE_STR)
|
| 39 |
+
RE_DATETIME = re.compile(
|
| 40 |
+
rf"""
|
| 41 |
+
([0-9]{{4}})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01]) # date, e.g. 1988-10-27
|
| 42 |
+
(?:
|
| 43 |
+
[Tt ]
|
| 44 |
+
{_TIME_RE_STR}
|
| 45 |
+
(?:([Zz])|([+-])([01][0-9]|2[0-3]):([0-5][0-9]))? # optional time offset
|
| 46 |
+
)?
|
| 47 |
+
""",
|
| 48 |
+
flags=re.VERBOSE,
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def match_to_datetime(match: re.Match) -> datetime | date:
|
| 53 |
+
"""Convert a `RE_DATETIME` match to `datetime.datetime` or `datetime.date`.
|
| 54 |
+
|
| 55 |
+
Raises ValueError if the match does not correspond to a valid date
|
| 56 |
+
or datetime.
|
| 57 |
+
"""
|
| 58 |
+
(
|
| 59 |
+
year_str,
|
| 60 |
+
month_str,
|
| 61 |
+
day_str,
|
| 62 |
+
hour_str,
|
| 63 |
+
minute_str,
|
| 64 |
+
sec_str,
|
| 65 |
+
micros_str,
|
| 66 |
+
zulu_time,
|
| 67 |
+
offset_sign_str,
|
| 68 |
+
offset_hour_str,
|
| 69 |
+
offset_minute_str,
|
| 70 |
+
) = match.groups()
|
| 71 |
+
year, month, day = int(year_str), int(month_str), int(day_str)
|
| 72 |
+
if hour_str is None:
|
| 73 |
+
return date(year, month, day)
|
| 74 |
+
hour, minute, sec = int(hour_str), int(minute_str), int(sec_str)
|
| 75 |
+
micros = int(micros_str.ljust(6, "0")) if micros_str else 0
|
| 76 |
+
if offset_sign_str:
|
| 77 |
+
tz: tzinfo | None = cached_tz(
|
| 78 |
+
offset_hour_str, offset_minute_str, offset_sign_str
|
| 79 |
+
)
|
| 80 |
+
elif zulu_time:
|
| 81 |
+
tz = timezone.utc
|
| 82 |
+
else: # local date-time
|
| 83 |
+
tz = None
|
| 84 |
+
return datetime(year, month, day, hour, minute, sec, micros, tzinfo=tz)
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
@lru_cache(maxsize=None)
|
| 88 |
+
def cached_tz(hour_str: str, minute_str: str, sign_str: str) -> timezone:
|
| 89 |
+
sign = 1 if sign_str == "+" else -1
|
| 90 |
+
return timezone(
|
| 91 |
+
timedelta(
|
| 92 |
+
hours=sign * int(hour_str),
|
| 93 |
+
minutes=sign * int(minute_str),
|
| 94 |
+
)
|
| 95 |
+
)
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def match_to_localtime(match: re.Match) -> time:
|
| 99 |
+
hour_str, minute_str, sec_str, micros_str = match.groups()
|
| 100 |
+
micros = int(micros_str.ljust(6, "0")) if micros_str else 0
|
| 101 |
+
return time(int(hour_str), int(minute_str), int(sec_str), micros)
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def match_to_number(match: re.Match, parse_float: ParseFloat) -> Any:
|
| 105 |
+
if match.group("floatpart"):
|
| 106 |
+
return parse_float(match.group())
|
| 107 |
+
return int(match.group(), 0)
|