mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Match.expand delegated to re._expand, which CPython removed in 3.12 during the template-expansion refactor. With the 3.14 stdlib that helper no longer exists, so expand raised AttributeError. Route expand through the compiled-template path (Template::compile -> re._compile_template) and share the template-filling logic with Pattern.sub via a Match::expand_template helper. Each caller still compiles the template once, so sub keeps its no-recompile-per-match fast path. Remove the expectedFailure marker on test_re.test_expand. Assisted-by: Claude Code:claude-opus-4-8
This commit is contained in:
1 parent
b1cfa575c4
commit
af0fa212cc
2 files changed
+34
-14
No files matched your search
Vendored
-1
@@ -726,7 +726,6 @@ class ReTests(unittest.TestCase):
|
||||
'first second').groupdict(),
|
||||
{'first':'first', 'second':'second'})
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_expand(self):
|
||||
self.assertEqual(re.match("(?P<first>first) (?P<second>second)",
|
||||
"first second")
|
||||
|
||||
@@ -471,15 +471,7 @@ mod _sre {
|
||||
}
|
||||
FilterType::Template(template) => {
|
||||
let m = Match::new(&mut iter.state, zelf.clone(), string.clone());
|
||||
// template.expand(m)?
|
||||
// let mut list = vec![template.literal.clone()];
|
||||
sub_list.push(template.literal.clone());
|
||||
for (index, literal) in template.items.iter().cloned() {
|
||||
if let Some(item) = m.get_slice(index, s, vm) {
|
||||
sub_list.push(item);
|
||||
}
|
||||
sub_list.push(literal);
|
||||
}
|
||||
m.expand_template(template, s, &mut sub_list, vm);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -702,10 +694,19 @@ mod _sre {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn expand(zelf: PyRef<Self>, template: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
let re = vm.import("re", 0)?;
|
||||
let func = re.get_attr("_expand", vm)?;
|
||||
func.call((zelf.pattern.clone(), zelf, template), vm)
|
||||
fn expand(zelf: PyRef<Self>, template: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let template = Template::compile(zelf.pattern.clone(), template, vm)?;
|
||||
with_sre_str!(zelf.pattern, &zelf.string, vm, |s| {
|
||||
let mut list: Vec<PyObjectRef> = Vec::new();
|
||||
zelf.expand_template(&template, s, &mut list, vm);
|
||||
|
||||
let join_type: PyObjectRef = if zelf.pattern.isbytes {
|
||||
vm.ctx.new_bytes(vec![]).into()
|
||||
} else {
|
||||
vm.ctx.new_str(ascii!("")).into()
|
||||
};
|
||||
vm.call_method(&join_type, "join", (PyList::from(list).into_pyobject(vm),))
|
||||
})
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -820,6 +821,26 @@ mod _sre {
|
||||
Some(str_drive.slice(start as usize, end as usize, vm))
|
||||
}
|
||||
|
||||
/// Expand an already-compiled template against this match, appending the
|
||||
/// resulting literal/group segments to `list`. Shared by `expand` and
|
||||
/// `Pattern.sub` so the template-filling logic lives in one place; the
|
||||
/// caller is responsible for compiling the template (once) beforehand.
|
||||
fn expand_template<S: SreStr>(
|
||||
&self,
|
||||
template: &Template,
|
||||
str_drive: S,
|
||||
list: &mut Vec<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) {
|
||||
list.push(template.literal.clone());
|
||||
for (index, literal) in template.items.iter().cloned() {
|
||||
if let Some(item) = self.get_slice(index, str_drive, vm) {
|
||||
list.push(item);
|
||||
}
|
||||
list.push(literal);
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclassmethod]
|
||||
fn __class_getitem__(
|
||||
cls: PyTypeRef,
|
||||
|
||||
Reference in new issue
Block a user