8000 test_builtin.py test_compile unit test fix (#5251) · RustPython/RustPython@3313fde · GitHub
[go: up one dir, main page]

Skip to content

Commit 3313fde

Browse files
authored
test_builtin.py test_compile unit test fix (#5251)
* compile accepts memoryview now * Update test_compile to what it is in CPython3.12 * compile optimize flag * added undocumented flags to flag validator
1 parent 2bd8ff0 commit 3313fde

File tree

3 files changed

+81
-13
lines changed

3 files changed

+81
-13
lines changed

Lib/test/test_builtin.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ def test_chr(self):
327327
def test_cmp(self):
328328
self.assertTrue(not hasattr(builtins, "cmp"))
329329

330-
# TODO: RUSTPYTHON
330+
# TODO: RUSTPYTHON optval=2 does not remove docstrings
331331
@unittest.expectedFailure
332332
def test_compile(self):
333333
compile('print(1)\n', '', 'exec')
@@ -340,11 +340,10 @@ def test_compile(self):
340340
self.assertRaises(TypeError, compile)
341341
self.assertRaises(ValueError, compile, 'print(42)\n', '<string>', 'badmode')
8000
342342
self.assertRaises(ValueError, compile, 'print(42)\n', '<string>', 'single', 0xff)
343-
self.assertRaises(ValueError, compile, chr(0), 'f', 'exec')
344343
self.assertRaises(TypeError, compile, 'pass', '?', 'exec',
345344
mode='eval', source='0', filename='tmp')
346345
compile('print("\xe5")\n', '', 'exec')
347-
self.assertRaises(ValueError, compile, chr(0), 'f', 'exec')
346+
self.assertRaises(SyntaxError, compile, chr(0), 'f', 'exec')
348347
self.assertRaises(ValueError, compile, str('a = 1'), 'f', 'bad')
349348

350349
# test the optimize argument

vm/src/stdlib/ast.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,13 @@ pub(crate) fn compile(
341341
object: PyObjectRef,
342342
filename: &str,
343343
mode: crate::compiler::Mode,
344+
optimize: Option<u8>,
344345
) -> PyResult {
345-
let opts = vm.compile_opts();
346+
let mut opts = vm.compile_opts();
347+
if let Some(optimize) = optimize {
348+
opts.optimize = optimize;
349+
}
350+
346351
let ast = Node::ast_from_object(vm, object)?;
347352
let code = codegen::compile::compile_top(&ast, filename.to_owned(), mode, opts)
348353
.map_err(|err| (CompileError::from(err), None).to_pyexception(vm))?; // FIXME source
@@ -354,6 +359,43 @@ pub(crate) use _ast::NodeAst;
354359
// Used by builtins::compile()
355360
pub const PY_COMPILE_FLAG_AST_ONLY: i32 = 0x0400;
356361

362+
// The following flags match the values from Include/cpython/compile.h
363+
// Caveat emptor: These flags are undocumented on purpose and depending
364+
// on their effect outside the standard library is **unsupported**.
365+
const PY_CF_DONT_IMPLY_DEDENT: i32 = 0x200;
366+
const PY_CF_ALLOW_INCOMPLETE_INPUT: i32 = 0x4000;
367+
368+
// __future__ flags - sync with Lib/__future__.py
369+
// TODO: These flags aren't being used in rust code
370+
// CO_FUTURE_ANNOTATIONS does make a difference in the codegen,
371+
// so it should be used in compile().
372+
// see compiler/codegen/src/compile.rs
373+
const CO_NESTED: i32 = 0x0010;
374+
const CO_GENERATOR_ALLOWED: i32 = 0;
375+
const CO_FUTURE_DIVISION: i32 = 0x20000;
376+
const CO_FUTURE_ABSOLUTE_IMPORT: i32 = 0x40000;
377+
const CO_FUTURE_WITH_STATEMENT: i32 = 0x80000;
378+
const CO_FUTURE_PRINT_FUNCTION: i32 = 0x100000;
379+
const CO_FUTURE_UNICODE_LITERALS: i32 = 0x200000;
380+
const CO_FUTURE_BARRY_AS_BDFL: i32 = 0x400000;
381+
const CO_FUTURE_GENERATOR_STOP: i32 = 0x800000;
382+
const CO_FUTURE_ANNOTATIONS: i32 = 0x1000000;
383+
384+
// Used by builtins::compile() - the summary of all flags
385+
pub const PY_COMPILE_FLAGS_MASK: i32 = PY_COMPILE_FLAG_AST_ONLY
386+
| PY_CF_DONT_IMPLY_DEDENT
387+
| PY_CF_ALLOW_INCOMPLETE_INPUT
388+
| CO_NESTED
389+
| CO_GENERATOR_ALLOWED
390+
| CO_FUTURE_DIVISION
391+
| CO_FUTURE_ABSOLUTE_IMPORT
392+
| CO_FUTURE_WITH_STATEMENT
393+
| CO_FUTURE_PRINT_FUNCTION
394+
| CO_FUTURE_UNICODE_LITERALS
395+
| CO_FUTURE_BARRY_AS_BDFL
396+
| CO_FUTURE_GENERATOR_STOP
397+
| CO_FUTURE_ANNOTATIONS;
398+
357399
pub fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
358400
let module = _ast::make_module(vm);
359401
gen::extend_module_nodes(vm, &module);

vm/src/stdlib/builtins.rs

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ mod builtins {
121121

122122
let mode_str = args.mode.as_str();
123123

124+
let optimize: i32 = args.optimize.map_or(Ok(-1), |v| v.try_to_primitive(vm))?;
125+
let optimize: u8 = if optimize == -1 {
126+
vm.state.settings.optimize
127+
} else {
128+
optimize.try_into().map_err(|_| {
129+
vm.new_value_error("compile() optimize value invalid".to_owned())
130+
})?
131+
};
132+
124133
if args
125134
.source
126135
.fast_isinstance(&ast::NodeAst::make_class(&vm.ctx))
@@ -134,7 +143,13 @@ mod builtins {
134143
let mode = mode_str
135144
.parse::<crate::compiler::Mode>()
136145
.map_err(|err| vm.new_value_error(err.to_string()))?;
137-
return ast::compile(vm, args.source, args.filename.as_str(), mode);
146+
return ast::compile(
147+
vm,
148+
args.source,
149+
args.filename.as_str(),
150+
mode,
151+
Some(optimize),
152+
);
138153
}
139154
}
140155

@@ -146,20 +161,23 @@ mod builtins {
146161
}
147162
#[cfg(feature = "rustpython-parser")]
148163
{
149-
use crate::{builtins::PyBytesRef, convert::ToPyException};
164+
use crate::convert::ToPyException;
150165
use num_traits::Zero;
151166
use rustpython_parser as parser;
152167

153-
let source = Either::<PyStrRef, PyBytesRef>::try_from_object(vm, args.source)?;
168+
let source = ArgStrOrBytesLike::try_from_object(vm, args.source)?;
169+
let source = source.borrow_bytes();
170+
154171
// TODO: compiler::compile should probably get bytes
155-
let source = match &source {
156-
Either::A(string) => string.as_str(),
157-
Either::B(bytes) => std::str::from_utf8(bytes)
158-
.map_err(|e| vm.new_unicode_decode_error(e.to_string()))?,
159-
};
172+
let source = std::str::from_utf8(&source)
173+
.map_err(|e| vm.new_unicode_decode_error(e.to_string()))?;
160174

161175
let flags = args.flags.map_or(Ok(0), |v| v.try_to_primitive(vm))?;
162176

177+
if !(flags & !ast::PY_COMPILE_FLAGS_MASK).is_zero() {
178+
return Err(vm.new_value_error("compile() unrecognized flags".to_owned()));
179+
}
180+
163181
if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() {
164182
#[cfg(not(feature = "rustpython-compiler"))]
165183
{
@@ -170,8 +188,17 @@ mod builtins {
170188
let mode = mode_str
171189
.parse::<crate::compiler::Mode>()
172190
.map_err(|err| vm.new_value_error(err.to_string()))?;
191+
192+
let mut opts = vm.compile_opts();
193+
opts.optimize = optimize;
194+
173195
let code = vm
174-
.compile(source, mode, args.filename.as_str().to_owned())
196+
.compile_with_opts(
197+
source,
198+
mode,
199+
args.filename.as_str().to_owned(),
200+
opts,
201+
)
175202
.map_err(|err| (err, Some(source)).to_pyexception(vm))?;
176203
Ok(code.into())
177204
}

0 commit comments

Comments
 (0)
0