aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Python/Python-tokenize.c
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2024-07-02 22:47:57 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2024-07-02 22:59:47 +0300
commit96b239778766d32d5158aca805e08199b3c0a743 (patch)
treea9c8679261a62138ec4735d878a11f6478cd196a /contrib/tools/python3/Python/Python-tokenize.c
parent292e7317266c2136a1e1bd027e16e6eefb639028 (diff)
downloadydb-96b239778766d32d5158aca805e08199b3c0a743.tar.gz
Update contrib/tools/python3 to 3.12.4
6e8edffbef193b35b45ddccdc3beda6bb2627186
Diffstat (limited to 'contrib/tools/python3/Python/Python-tokenize.c')
-rw-r--r--contrib/tools/python3/Python/Python-tokenize.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/contrib/tools/python3/Python/Python-tokenize.c b/contrib/tools/python3/Python/Python-tokenize.c
index 179f71aa1f..664e7d8a50 100644
--- a/contrib/tools/python3/Python/Python-tokenize.c
+++ b/contrib/tools/python3/Python/Python-tokenize.c
@@ -31,6 +31,11 @@ typedef struct
{
PyObject_HEAD struct tok_state *tok;
int done;
+
+ /* Needed to cache line for performance */
+ PyObject *last_line;
+ Py_ssize_t last_lineno;
+ Py_ssize_t byte_col_offset_diff;
} tokenizeriterobject;
/*[clinic input]
@@ -67,6 +72,11 @@ tokenizeriter_new_impl(PyTypeObject *type, PyObject *readline,
self->tok->tok_extra_tokens = 1;
}
self->done = 0;
+
+ self->last_line = NULL;
+ self->byte_col_offset_diff = 0;
+ self->last_lineno = 0;
+
return (PyObject *)self;
}
@@ -209,7 +219,18 @@ tokenizeriter_next(tokenizeriterobject *it)
if (size >= 1 && it->tok->implicit_newline) {
size -= 1;
}
- line = PyUnicode_DecodeUTF8(line_start, size, "replace");
+
+ if (it->tok->lineno != it->last_lineno) {
+ // Line has changed since last token, so we fetch the new line and cache it
+ // in the iter object.
+ Py_XDECREF(it->last_line);
+ line = PyUnicode_DecodeUTF8(line_start, size, "replace");
+ it->last_line = line;
+ it->byte_col_offset_diff = 0;
+ } else {
+ // Line hasn't changed so we reuse the cached one.
+ line = it->last_line;
+ }
}
if (line == NULL) {
Py_DECREF(str);
@@ -218,13 +239,28 @@ tokenizeriter_next(tokenizeriterobject *it)
Py_ssize_t lineno = ISSTRINGLIT(type) ? it->tok->first_lineno : it->tok->lineno;
Py_ssize_t end_lineno = it->tok->lineno;
+ it->last_lineno = lineno;
+
Py_ssize_t col_offset = -1;
Py_ssize_t end_col_offset = -1;
+ Py_ssize_t byte_offset = -1;
if (token.start != NULL && token.start >= line_start) {
- col_offset = _PyPegen_byte_offset_to_character_offset(line, token.start - line_start);
+ byte_offset = token.start - line_start;
+ col_offset = byte_offset - it->byte_col_offset_diff;
}
if (token.end != NULL && token.end >= it->tok->line_start) {
- end_col_offset = _PyPegen_byte_offset_to_character_offset_raw(it->tok->line_start, token.end - it->tok->line_start);
+ Py_ssize_t end_byte_offset = token.end - it->tok->line_start;
+ if (lineno == end_lineno) {
+ // If the whole token is at the same line, we can just use the token.start
+ // buffer for figuring out the new column offset, since using line is not
+ // performant for very long lines.
+ Py_ssize_t token_col_offset = _PyPegen_byte_offset_to_character_offset_line(line, byte_offset, end_byte_offset);
+ end_col_offset = col_offset + token_col_offset;
+ it->byte_col_offset_diff += token.end - token.start - token_col_offset;
+ } else {
+ end_col_offset = _PyPegen_byte_offset_to_character_offset_raw(it->tok->line_start, end_byte_offset);
+ it->byte_col_offset_diff += end_byte_offset - end_col_offset;
+ }
}
if (it->tok->tok_extra_tokens) {
@@ -264,7 +300,7 @@ tokenizeriter_next(tokenizeriterobject *it)
}
}
- result = Py_BuildValue("(iN(nn)(nn)N)", type, str, lineno, col_offset, end_lineno, end_col_offset, line);
+ result = Py_BuildValue("(iN(nn)(nn)O)", type, str, lineno, col_offset, end_lineno, end_col_offset, line);
exit:
_PyToken_Free(&token);
if (type == ENDMARKER) {
@@ -277,6 +313,7 @@ static void
tokenizeriter_dealloc(tokenizeriterobject *it)
{
PyTypeObject *tp = Py_TYPE(it);
+ Py_XDECREF(it->last_line);
_PyTokenizer_Free(it->tok);
tp->tp_free(it);
Py_DECREF(tp);