Edit Book: Fix groups in replace template being interpreted backwards when search direction is up

This commit is contained in:
Kovid Goyal 2015-06-10 18:54:39 +05:30
parent b51b73b530
commit 7d172200b3
2 changed files with 55 additions and 7 deletions

View File

@ -225,7 +225,7 @@ __all__ = ["compile", "escape", "findall", "finditer", "fullmatch", "match",
"V0", "VERSION0", "V1", "VERSION1", "X", "VERBOSE", "W", "WORD", "error", "V0", "VERSION0", "V1", "VERSION1", "X", "VERBOSE", "W", "WORD", "error",
"Regex"] "Regex"]
__version__ = "2.4.64" __version__ = "2.4.66"
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Public interface. # Public interface.

View File

@ -11577,6 +11577,8 @@ advance:
if (try_body) { if (try_body) {
body_status = try_match(state, &node->next_1, state->text_pos, body_status = try_match(state, &node->next_1, state->text_pos,
&next_body_position); &next_body_position);
if (body_status < 0)
return body_status;
if (body_status == RE_ERROR_FAILURE) if (body_status == RE_ERROR_FAILURE)
try_body = FALSE; try_body = FALSE;
@ -11589,6 +11591,8 @@ advance:
if(try_tail) { if(try_tail) {
tail_status = try_match(state, &node->nonstring.next_2, tail_status = try_match(state, &node->nonstring.next_2,
state->text_pos, &next_tail_position); state->text_pos, &next_tail_position);
if (tail_status < 0)
return tail_status;
if (tail_status == RE_ERROR_FAILURE) if (tail_status == RE_ERROR_FAILURE)
try_tail = FALSE; try_tail = FALSE;
@ -11738,6 +11742,8 @@ advance:
if (try_body) { if (try_body) {
body_status = try_match(state, &node->next_1, state->text_pos, body_status = try_match(state, &node->next_1, state->text_pos,
&next_body_position); &next_body_position);
if (body_status < 0)
return body_status;
if (body_status == RE_ERROR_FAILURE) if (body_status == RE_ERROR_FAILURE)
try_body = FALSE; try_body = FALSE;
@ -11748,6 +11754,8 @@ advance:
if (try_tail) { if (try_tail) {
tail_status = try_match(state, &node->nonstring.next_2, tail_status = try_match(state, &node->nonstring.next_2,
state->text_pos, &next_tail_position); state->text_pos, &next_tail_position);
if (tail_status < 0)
return tail_status;
if (tail_status == RE_ERROR_FAILURE) if (tail_status == RE_ERROR_FAILURE)
try_tail = FALSE; try_tail = FALSE;
@ -12029,6 +12037,8 @@ advance:
if (try_body) { if (try_body) {
body_status = try_match(state, &node->next_1, state->text_pos, body_status = try_match(state, &node->next_1, state->text_pos,
&next_body_position); &next_body_position);
if (body_status < 0)
return body_status;
if (body_status == RE_ERROR_FAILURE) if (body_status == RE_ERROR_FAILURE)
try_body = FALSE; try_body = FALSE;
@ -12039,6 +12049,8 @@ advance:
if (try_tail) { if (try_tail) {
tail_status = try_match(state, &node->nonstring.next_2, tail_status = try_match(state, &node->nonstring.next_2,
state->text_pos, &next_tail_position); state->text_pos, &next_tail_position);
if (tail_status < 0)
return tail_status;
if (tail_status == RE_ERROR_FAILURE) if (tail_status == RE_ERROR_FAILURE)
try_tail = FALSE; try_tail = FALSE;
@ -12289,6 +12301,8 @@ advance:
if (try_body) { if (try_body) {
body_status = try_match(state, &node->next_1, state->text_pos, body_status = try_match(state, &node->next_1, state->text_pos,
&next_body_position); &next_body_position);
if (body_status < 0)
return body_status;
if (body_status == RE_ERROR_FAILURE) if (body_status == RE_ERROR_FAILURE)
try_body = FALSE; try_body = FALSE;
@ -12299,6 +12313,8 @@ advance:
if(try_tail) { if(try_tail) {
tail_status = try_match(state, &node->nonstring.next_2, tail_status = try_match(state, &node->nonstring.next_2,
state->text_pos, &next_tail_position); state->text_pos, &next_tail_position);
if (tail_status < 0)
return tail_status;
if (tail_status == RE_ERROR_FAILURE) if (tail_status == RE_ERROR_FAILURE)
try_tail = FALSE; try_tail = FALSE;
@ -14200,11 +14216,17 @@ backtrack:
if (test->status & RE_STATUS_FUZZY) { if (test->status & RE_STATUS_FUZZY) {
for (;;) { for (;;) {
int status;
RE_Position next_position; RE_Position next_position;
pos -= step; pos -= step;
if (try_match(state, &node->next_1, pos, &next_position) && status = try_match(state, &node->next_1, pos,
&next_position);
if (status < 0)
return status;
if (status != RE_ERROR_FAILURE &&
!is_repeat_guarded(safe_state, index, pos, !is_repeat_guarded(safe_state, index, pos,
RE_STATUS_TAIL)) { RE_STATUS_TAIL)) {
match = TRUE; match = TRUE;
@ -15742,6 +15764,14 @@ Py_LOCAL_INLINE(int) do_match(RE_SafeState* safe_state, BOOL search) {
state->lastgroup = -1; state->lastgroup = -1;
max_end_index = -1; max_end_index = -1;
if (status == RE_ERROR_PARTIAL) {
/* We've matched up to the limit of the slice. */
if (state->reverse)
state->text_pos = state->slice_start;
else
state->text_pos = state->slice_end;
}
/* Store the capture groups. */ /* Store the capture groups. */
group_info = pattern->group_info; group_info = pattern->group_info;
@ -19332,17 +19362,32 @@ Py_LOCAL_INLINE(PyObject*) pattern_subx(PatternObject* self, PyObject*
#endif #endif
} else if (is_template) { } else if (is_template) {
/* The replacement is a list template. */ /* The replacement is a list template. */
Py_ssize_t size; Py_ssize_t count;
Py_ssize_t i; Py_ssize_t index;
Py_ssize_t step;
/* Add each part of the template to the list. */ /* Add each part of the template to the list. */
size = PyList_GET_SIZE(replacement); count = PyList_GET_SIZE(replacement);
for (i = 0; i < size; i++) { if (join_info.reversed) {
/* We're searching backwards, so we'll be reversing the list
* when it's complete. Therefore, we need to add the items of
* the template in reverse order for them to be in the correct
* order after the reversal.
*/
index = count - 1;
step = -1;
} else {
/* We're searching forwards. */
index = 0;
step = 1;
}
while (count > 0) {
PyObject* item; PyObject* item;
PyObject* str_item; PyObject* str_item;
/* PyList_GET_ITEM borrows a reference. */ /* PyList_GET_ITEM borrows a reference. */
item = PyList_GET_ITEM(replacement, i); item = PyList_GET_ITEM(replacement, index);
str_item = get_sub_replacement(item, string, &state, str_item = get_sub_replacement(item, string, &state,
self->public_group_count); self->public_group_count);
if (!str_item) if (!str_item)
@ -19358,6 +19403,9 @@ Py_LOCAL_INLINE(PyObject*) pattern_subx(PatternObject* self, PyObject*
if (status < 0) if (status < 0)
goto error; goto error;
} }
--count;
index += step;
} }
} else if (is_callable) { } else if (is_callable) {
/* Pass a MatchObject to the replacement function. */ /* Pass a MatchObject to the replacement function. */