1use crate::{Py, VirtualMachine, builtins::PyModule, class::PyClassImpl};
5pub(crate) use builtins::{DOC, module_def};
6pub use builtins::{ascii, print, reversed};
7
8#[pymodule]
9mod builtins {
10 use crate::{
11 AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
12 VirtualMachine,
13 builtins::{
14 PyByteArray, PyBytes, PyDictRef, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType,
15 PyUtf8StrRef,
16 enumerate::PyReverseSequenceIterator,
17 function::{PyCell, PyCellRef, PyFunction},
18 iter::PyCallableIterator,
19 list::{PyList, SortOptions},
20 },
21 bytecode,
22 common::hash::PyHash,
23 function::{
24 ArgCallable, ArgIndex, ArgIntoBool, ArgIterable, ArgMapping, ArgStrOrBytesLike, Either,
25 FsPath, FuncArgs, KwArgs, NameKws, OptionalArg, PosArgs,
26 },
27 protocol::{PyIter, PyIterReturn},
28 py_io,
29 readline::{Readline, ReadlineResult},
30 stdlib::sys,
31 types::PyComparisonOp,
32 vm::compile_mode::{CompileStart, CompilerFlags, compile_future_features_from_flags},
33 };
34 use itertools::Itertools;
35 use num_traits::{Signed, ToPrimitive};
36 use rustpython_common::wtf8::CodePoint;
37
38 #[cfg(not(feature = "rustpython-compiler"))]
39 const CODEGEN_NOT_SUPPORTED: &str =
40 "can't compile() to bytecode when the `codegen` feature of rustpython is disabled";
41
42 #[pyfunction]
43 fn abs(x: PyObjectRef, vm: &VirtualMachine) -> PyResult {
44 vm._abs(&x)
45 }
46
47 #[pyfunction]
48 fn all(iterable: ArgIterable<ArgIntoBool>, vm: &VirtualMachine) -> PyResult<bool> {
49 for item in iterable.iter(vm)? {
50 if !item?.into_bool() {
51 return Ok(false);
52 }
53 }
54 Ok(true)
55 }
56
57 #[pyfunction]
58 fn any(iterable: ArgIterable<ArgIntoBool>, vm: &VirtualMachine) -> PyResult<bool> {
59 for item in iterable.iter(vm)? {
60 if item?.into_bool() {
61 return Ok(true);
62 }
63 }
64 Ok(false)
65 }
66
67 #[pyfunction]
68 pub fn ascii(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
69 obj.ascii(vm)
70 }
71
72 #[pyfunction]
73 fn bin(number: ArgIndex) -> String {
74 let number = number.into_int_ref();
75 let x = number.as_bigint();
76 if x.is_negative() {
77 format!("-0b{:b}", x.abs())
78 } else {
79 format!("0b{x:b}")
80 }
81 }
82
83 #[pyfunction]
84 fn callable(obj: PyObjectRef) -> bool {
85 obj.is_callable()
86 }
87
88 #[pyfunction]
89 fn chr(i: ArgIndex, vm: &VirtualMachine) -> PyResult<CodePoint> {
90 let i = i.into_int_ref();
91 let value = i
92 .as_bigint()
93 .to_u32()
94 .and_then(CodePoint::from_u32)
95 .ok_or_else(|| vm.new_value_error("chr() arg not in range(0x110000)"))?;
96 Ok(value)
97 }
98
99 #[derive(FromArgs)]
100 #[allow(dead_code)]
101 struct CompileArgs {
102 source: PyObjectRef,
103 filename: PyObjectRef,
107 mode: PyUtf8StrRef,
108 #[pyarg(any, default = 0)]
113 flags: i32,
114 #[pyarg(any, default = false)]
118 dont_inherit: ArgIntoBool,
119 #[pyarg(any, default = -1)]
120 optimize: i32,
121 #[pyarg(named, default = -1)]
122 _feature_version: i32,
123 }
124
125 fn merge_compile_future_features(
126 flags: i32,
127 dont_inherit: bool,
128 _vm: &VirtualMachine,
129 ) -> bytecode::CodeFlags {
130 let mut future_features = compile_future_features_from_flags(flags);
131 if !dont_inherit && let Some(code) = crate::frame::current_code() {
132 future_features |= code.flags & bytecode::CodeFlags::FUTURE_MASK;
133 }
134 future_features
135 }
136
137 fn audit_compile_source(vm: &VirtualMachine, source: &[u8], filename: &str) -> PyResult<()> {
138 vm.audit("compile", || {
139 (vm.ctx.new_bytes(source.to_vec()), vm.ctx.new_str(filename))
140 })
141 }
142
143 fn trim_eval_source_bytes(mut source: &[u8]) -> &[u8] {
144 while let Some((&first, rest)) = source.split_first()
145 && matches!(first, b' ' | b'\t')
146 {
147 source = rest;
148 }
149 source
150 }
151
152 fn decode_eval_exec_source_bytes(
153 vm: &VirtualMachine,
154 source: &[u8],
155 filename: &str,
156 ) -> PyResult<String> {
157 #[cfg(feature = "parser")]
158 {
159 vm.decode_source_bytes(source, filename, false)
160 }
161 #[cfg(not(feature = "parser"))]
162 {
163 _ = filename;
164 core::str::from_utf8(source)
165 .map(str::to_owned)
166 .map_err(|err| {
167 let msg = format!(
168 "(unicode error) 'utf-8' codec can't decode byte 0x{:x?} in position {}: invalid start byte",
169 source[err.valid_up_to()],
170 err.valid_up_to()
171 );
172 vm.new_exception_msg(vm.ctx.exceptions.syntax_error.to_owned(), msg.into())
173 })
174 }
175 }
176
177 #[cfg(any(feature = "parser", feature = "compiler"))]
178 #[pyfunction]
179 fn compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult {
180 #[cfg(not(feature = "ast"))]
181 {
182 _ = args; return Err(vm.new_type_error("AST Not Supported"));
184 }
185 #[cfg(feature = "ast")]
186 {
187 let filename = FsPath::try_from_path_like(args.filename, true, vm)?;
192
193 use crate::{class::PyClassImpl, stdlib::_ast};
194
195 let feature_version = args._feature_version;
196
197 let mode_str = args.mode.as_str();
198 let flags: i32 = args.flags;
199 let cf = CompilerFlags::from_bits_retain(flags);
200
201 if (flags & !CompilerFlags::ALLOWED_FLAGS.bits()) != 0 {
202 return Err(vm.new_value_error("compile(): unrecognised flags"));
203 }
204
205 let optimize: i32 = args.optimize;
206 let optimize: u8 = match optimize {
207 -1 => vm.state.config.settings.optimize.min(2),
208 0..=2 => optimize as u8,
209 _ => return Err(vm.new_value_error("compile(): invalid optimize value")),
210 };
211 let dont_inherit = args.dont_inherit.into_bool();
212 let is_ast_only = cf.contains(CompilerFlags::ONLY_AST);
213 let future_features = merge_compile_future_features(flags, dont_inherit, vm);
214
215 let start = if mode_str == "exec" {
216 CompileStart::File
217 } else if mode_str == "eval" {
218 CompileStart::Eval
219 } else if mode_str == "single" {
220 CompileStart::Single
221 } else if mode_str == "func_type" {
222 if !is_ast_only {
223 return Err(vm.new_value_error(
224 "compile() mode 'func_type' requires flag PyCF_ONLY_AST",
225 ));
226 }
227 CompileStart::FuncType
228 } else {
229 let msg = if is_ast_only {
230 "compile() mode must be 'exec', 'eval', 'single' or 'func_type'"
231 } else {
232 "compile() mode must be 'exec', 'eval' or 'single'"
233 };
234 return Err(vm.new_value_error(msg));
235 };
236
237 let ast_type = _ast::NodeAst::make_static_type().as_object().to_owned();
238 if args.source.is_instance(&ast_type, vm)? {
239 let explicit_future_annotations =
240 future_features.contains(bytecode::CodeFlags::FUTURE_ANNOTATIONS);
241 vm.audit("compile", || (args.source.clone(), vm.ctx.none()))?;
242
243 if is_ast_only {
245 let (expected_type, expected_name) = _ast::mode_type_and_name(mode_str)
246 .ok_or_else(|| {
247 vm.new_value_error(
248 "compile() mode must be 'exec', 'eval', 'single' or 'func_type'",
249 )
250 })?;
251 if !args.source.is_instance(expected_type.as_object(), vm)? {
252 return Err(vm.new_type_error(format!(
253 "expected {} node, got {}",
254 expected_name,
255 args.source.class().name()
256 )));
257 }
258 #[cfg(not(feature = "rustpython-codegen"))]
259 {
260 _ast::validate_ast_object(vm, args.source.clone())?;
261 return Ok(args.source);
262 }
263 #[cfg(feature = "rustpython-codegen")]
264 {
265 return _ast::preprocess_ast_object(
266 vm,
267 args.source,
268 &filename.to_string_lossy(),
269 optimize,
270 cf.contains(CompilerFlags::OPTIMIZED_AST),
271 explicit_future_annotations,
272 );
273 }
274 }
275
276 #[cfg(not(feature = "rustpython-codegen"))]
277 {
278 return Err(vm.new_type_error(CODEGEN_NOT_SUPPORTED));
279 }
280 #[cfg(feature = "rustpython-codegen")]
281 {
282 let (expected_type, expected_name) = _ast::mode_type_and_name(mode_str)
283 .ok_or_else(|| {
284 vm.new_value_error("compile() mode must be 'exec', 'eval' or 'single'")
285 })?;
286 if !args.source.is_instance(expected_type.as_object(), vm)? {
287 return Err(vm.new_type_error(format!(
288 "expected {} node, got {}",
289 expected_name,
290 args.source.class().name()
291 )));
292 }
293 let mode = mode_str
294 .parse::<crate::compiler::Mode>()
295 .map_err(|err| vm.new_value_error(err.to_string()))?;
296 let mut opts = vm.compile_opts();
297 opts.optimize = optimize;
298 opts.allow_top_level_await = cf.contains(CompilerFlags::ALLOW_TOP_LEVEL_AWAIT);
299 opts.future_features = future_features;
300 return _ast::compile(vm, args.source, &filename.to_string_lossy(), mode, opts);
301 }
302 }
303
304 #[cfg(not(feature = "parser"))]
305 {
306 Err(vm.new_type_error(
307 "can't compile() source code when the `parser` feature of rustpython is disabled",
308 ))
309 }
310 #[cfg(feature = "parser")]
311 {
312 let source = ArgStrOrBytesLike::try_from_object(vm, args.source)?;
313
314 let mut compile_flags = flags | future_features.bits() as i32;
315 #[cfg(feature = "rustpython-compiler")]
316 let compile_source = |source: &[u8], compile_flags: i32| {
317 vm.compile_string_object_with_flags(
318 source,
319 &filename.to_string_lossy(),
320 start.as_i32(),
321 compile_flags,
322 feature_version,
323 optimize as i32,
324 )
325 };
326 match &source {
327 ArgStrOrBytesLike::Str(source) => {
328 let source = source.try_as_utf8(vm)?.as_str();
329 if source.as_bytes().contains(&0) {
330 return Err(vm.new_exception_msg(
331 vm.ctx.exceptions.syntax_error.to_owned(),
332 "source code string cannot contain null bytes".into(),
333 ));
334 }
335 audit_compile_source(
336 vm,
337 source.as_bytes(),
338 filename.to_string_lossy().as_ref(),
339 )?;
340 compile_flags |= CompilerFlags::IGNORE_COOKIE.bits();
341 #[cfg(feature = "rustpython-compiler")]
342 {
343 compile_source(source.as_bytes(), compile_flags)
344 }
345 #[cfg(not(feature = "rustpython-compiler"))]
346 {
347 Err(vm.new_value_error(CODEGEN_NOT_SUPPORTED))
348 }
349 }
350 ArgStrOrBytesLike::Buf(source) => {
351 let source_bytes = source.borrow_buf();
352 let source_bytes: &[u8] = &source_bytes;
353 if source_bytes.contains(&0) {
354 return Err(vm.new_exception_msg(
355 vm.ctx.exceptions.syntax_error.to_owned(),
356 "source code string cannot contain null bytes".into(),
357 ));
358 }
359 audit_compile_source(
360 vm,
361 source_bytes,
362 filename.to_string_lossy().as_ref(),
363 )?;
364 #[cfg(feature = "rustpython-compiler")]
365 {
366 compile_source(source_bytes, compile_flags)
367 }
368 #[cfg(not(feature = "rustpython-compiler"))]
369 {
370 Err(vm.new_value_error(CODEGEN_NOT_SUPPORTED))
371 }
372 }
373 }
374 }
375 }
376 }
377
378 #[pyfunction]
379 fn delattr(obj: PyObjectRef, name: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
380 let attr = name.try_to_ref::<PyStr>(vm).map_err(|_e| {
381 vm.new_type_error(format!(
382 "attribute name must be string, not '{}'",
383 name.class().name()
384 ))
385 })?;
386 obj.del_attr(attr, vm)
387 }
388
389 #[pyfunction]
390 fn dir(obj: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult<PyList> {
391 vm.dir(obj.into_option())
392 }
393
394 #[pyfunction]
395 fn divmod(x: PyObjectRef, y: PyObjectRef, vm: &VirtualMachine) -> PyResult {
396 vm._divmod(&x, &y)
397 }
398
399 #[derive(FromArgs)]
400 struct ScopeArgs {
401 #[pyarg(any, optional)]
402 globals: Option<PyObjectRef>,
403 #[pyarg(any, optional)]
404 locals: Option<ArgMapping>,
405 }
406
407 impl ScopeArgs {
408 fn make_scope(
409 self,
410 vm: &VirtualMachine,
411 func_name: &'static str,
412 ) -> PyResult<crate::scope::Scope> {
413 fn validate_globals_dict(
414 globals: &PyObject,
415 vm: &VirtualMachine,
416 func_name: &'static str,
417 ) -> PyResult<()> {
418 if !globals.fast_isinstance(vm.ctx.types.dict_type) {
419 return Err(match func_name {
420 "eval" => {
421 let is_mapping = globals.mapping_unchecked().check();
422 vm.new_type_error(if is_mapping {
423 "globals must be a real dict; try eval(expr, {}, mapping)"
424 } else {
425 "globals must be a dict"
426 })
427 }
428 "exec" => vm.new_type_error(format!(
429 "exec() globals must be a dict, not {}",
430 globals.class().name()
431 )),
432 _ => vm.new_type_error("globals must be a dict"),
433 });
434 }
435 Ok(())
436 }
437
438 let (globals, locals) = match self.globals {
439 Some(globals) => {
440 validate_globals_dict(&globals, vm, func_name)?;
441
442 let globals = PyDictRef::try_from_object(vm, globals)?;
443 if !globals.contains_key(identifier!(vm, __builtins__), vm) {
444 let builtins_dict = vm.builtins.dict().into();
445 globals.set_item(identifier!(vm, __builtins__), builtins_dict, vm)?;
446 }
447 (
448 globals.clone(),
449 self.locals
450 .unwrap_or_else(|| ArgMapping::from_dict_exact(globals.clone())),
451 )
452 }
453 None => (
454 vm.current_globals(),
455 if let Some(locals) = self.locals {
456 locals
457 } else {
458 vm.current_locals()?
459 },
460 ),
461 };
462
463 let scope = crate::scope::Scope::with_builtins(Some(locals), globals, vm);
464 Ok(scope)
465 }
466 }
467
468 #[derive(FromArgs)]
469 struct ExecArgs {
470 #[pyarg(positional)]
471 source: Either<PyRef<crate::builtins::PyCode>, ArgStrOrBytesLike>,
472 #[pyarg(any, optional)]
473 globals: Option<PyObjectRef>,
474 #[pyarg(any, optional)]
475 locals: Option<ArgMapping>,
476 #[pyarg(named, optional)]
477 closure: Option<PyObjectRef>,
478 }
479
480 fn exec_closure(
481 code_obj: &Py<crate::builtins::PyCode>,
482 closure: Option<PyObjectRef>,
483 vm: &VirtualMachine,
484 ) -> PyResult<Option<PyRef<PyTuple<PyCellRef>>>> {
485 let num_free = code_obj.freevars.len();
486 let Some(closure) = closure else {
487 if num_free == 0 {
488 return Ok(None);
489 }
490 return Err(vm.new_type_error(format!(
491 "code object requires a closure of exactly length {num_free}"
492 )));
493 };
494
495 if num_free == 0 {
496 return Err(vm.new_type_error("cannot use a closure with this code object"));
497 }
498
499 let closure_tuple = closure
500 .downcast_exact::<PyTuple>(vm)
501 .map_err(|_| {
502 vm.new_type_error(format!(
503 "code object requires a closure of exactly length {num_free}"
504 ))
505 })?
506 .into_pyref();
507 if closure_tuple.as_slice().len() != num_free {
508 return Err(vm.new_type_error(format!(
509 "code object requires a closure of exactly length {num_free}"
510 )));
511 }
512
513 closure_tuple
514 .try_into_typed::<PyCell>(vm)
515 .map(Some)
516 .map_err(|_| {
517 vm.new_type_error(format!(
518 "code object requires a closure of exactly length {num_free}"
519 ))
520 })
521 }
522
523 #[pyfunction]
524 fn eval(
525 source: Either<PyRef<crate::builtins::PyCode>, ArgStrOrBytesLike>,
526 scope: ScopeArgs,
527 vm: &VirtualMachine,
528 ) -> PyResult {
529 let scope = scope.make_scope(vm, "eval")?;
530
531 let code = match source {
533 Either::B(either) => {
534 let source = match &either {
535 ArgStrOrBytesLike::Str(source) => {
536 let source = source.try_as_utf8(vm)?.as_str();
537 if source.as_bytes().contains(&0) {
538 return Err(vm.new_exception_msg(
539 vm.ctx.exceptions.syntax_error.to_owned(),
540 "source code string cannot contain null bytes".into(),
541 ));
542 }
543 let source = source.trim_start_matches([' ', '\t']);
544 audit_compile_source(vm, source.as_bytes(), "<string>")?;
545 source.to_owned()
546 }
547 ArgStrOrBytesLike::Buf(source) => {
548 let source: &[u8] = &source.borrow_buf();
549 if source.contains(&0) {
550 return Err(vm.new_exception_msg(
551 vm.ctx.exceptions.syntax_error.to_owned(),
552 "source code string cannot contain null bytes".into(),
553 ));
554 }
555 let source = trim_eval_source_bytes(source);
556 audit_compile_source(vm, source, "<string>")?;
557 decode_eval_exec_source_bytes(vm, source, "eval")?
558 }
559 };
560 Ok(Either::B(vm.ctx.new_utf8_str(source)))
561 }
562 Either::A(code) => Ok(Either::A(code)),
563 }?;
564 run_code(vm, code, scope, crate::compiler::Mode::Eval, "eval", None)
565 }
566
567 #[pyfunction]
568 fn exec(args: ExecArgs, vm: &VirtualMachine) -> PyResult {
569 let ExecArgs {
570 source,
571 globals,
572 locals,
573 closure,
574 } = args;
575 let scope = ScopeArgs { globals, locals }.make_scope(vm, "exec")?;
576 let (source, closure) = match source {
577 Either::B(either) => {
578 if closure.is_some() {
579 return Err(
580 vm.new_type_error("closure can only be used when source is a code object")
581 );
582 }
583 let source = match &either {
584 ArgStrOrBytesLike::Str(source) => {
585 let source = source.try_as_utf8(vm)?.as_str();
586 if source.as_bytes().contains(&0) {
587 return Err(vm.new_exception_msg(
588 vm.ctx.exceptions.syntax_error.to_owned(),
589 "source code string cannot contain null bytes".into(),
590 ));
591 }
592 audit_compile_source(vm, source.as_bytes(), "<string>")?;
593 source.to_owned()
594 }
595 ArgStrOrBytesLike::Buf(source) => {
596 let source: &[u8] = &source.borrow_buf();
597 if source.contains(&0) {
598 return Err(vm.new_exception_msg(
599 vm.ctx.exceptions.syntax_error.to_owned(),
600 "source code string cannot contain null bytes".into(),
601 ));
602 }
603 audit_compile_source(vm, source, "<string>")?;
604 decode_eval_exec_source_bytes(vm, source, "exec")?
605 }
606 };
607 (Either::B(vm.ctx.new_utf8_str(source)), None)
608 }
609 Either::A(code) => {
610 let closure = exec_closure(&code, closure, vm)?;
611 (Either::A(code), closure)
612 }
613 };
614 run_code(
615 vm,
616 source,
617 scope,
618 crate::compiler::Mode::Exec,
619 "exec",
620 closure,
621 )
622 }
623
624 fn run_code(
625 vm: &VirtualMachine,
626 source: Either<PyRef<crate::builtins::PyCode>, PyUtf8StrRef>,
627 scope: crate::scope::Scope,
628 #[allow(unused_variables)] mode: crate::compiler::Mode,
629 func: &str,
630 closure: Option<PyRef<PyTuple<PyCellRef>>>,
631 ) -> PyResult {
632 let code_obj = match source {
634 #[cfg(feature = "rustpython-compiler")]
635 Either::B(string) => {
636 let source = string.as_str();
637 let mut opts = vm.compile_opts();
638 if let Some(code) = crate::frame::current_code() {
639 opts.future_features = code.flags & bytecode::CodeFlags::FUTURE_MASK;
640 }
641 vm.compile_with_opts(source, mode, "<string>", opts)
642 .map_err(|err| err.into_pyexception(vm, Some(source)))?
643 }
644 #[cfg(not(feature = "rustpython-compiler"))]
645 Either::B(_) => return Err(vm.new_type_error(CODEGEN_NOT_SUPPORTED)),
646 Either::A(code_obj) => code_obj,
647 };
648
649 vm.audit("exec", || (code_obj.clone(),))?;
650
651 if closure.is_none() && !code_obj.freevars.is_empty() {
652 return Err(vm.new_type_error(format!(
653 "code object passed to {func}() may not contain free variables"
654 )));
655 }
656
657 vm.run_code_obj_with_closure(code_obj, scope, closure)
659 }
660
661 #[derive(FromArgs)]
662 struct FormatArgs {
663 #[pyarg(positional)]
664 value: PyObjectRef,
665 #[pyarg(positional, default = "")]
666 format_spec: PyStrRef,
667 }
668
669 #[derive(FromArgs)]
670 struct InputArgs {
671 #[pyarg(positional, optional, py_default = "''")]
673 prompt: OptionalArg<PyStrRef>,
674 }
675
676 #[pyfunction]
677 fn format(args: FormatArgs, vm: &VirtualMachine) -> PyResult<PyStrRef> {
678 vm.format(&args.value, args.format_spec)
679 }
680
681 #[pyfunction]
682 fn getattr(
683 obj: PyObjectRef,
684 attr: PyObjectRef,
685 default: OptionalArg<PyObjectRef>,
686 vm: &VirtualMachine,
687 ) -> PyResult {
688 let attr = attr.try_to_ref::<PyStr>(vm).map_err(|_e| {
689 vm.new_type_error(format!(
690 "attribute name must be string, not '{}'",
691 attr.class().name()
692 ))
693 })?;
694
695 if let OptionalArg::Present(default) = default {
696 Ok(vm.get_attribute_opt(&obj, attr)?.unwrap_or(default))
697 } else {
698 obj.get_attr(attr, vm)
699 }
700 }
701
702 #[pyfunction]
703 fn globals(vm: &VirtualMachine) -> PyDictRef {
704 vm.current_globals()
705 }
706
707 #[pyfunction]
708 fn hasattr(obj: PyObjectRef, name: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
709 let attr = name.try_to_ref::<PyStr>(vm).map_err(|_e| {
710 vm.new_type_error(format!(
711 "attribute name must be string, not '{}'",
712 name.class().name()
713 ))
714 })?;
715 obj.has_attr(attr, vm)
716 }
717
718 #[pyfunction]
719 fn hash(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyHash> {
720 obj.hash(vm)
721 }
722
723 #[pyfunction]
724 fn breakpoint(
725 args: PosArgs,
726 kws: KwArgs<PyObjectRef, NameKws>,
727 vm: &VirtualMachine,
728 ) -> PyResult {
729 let args = FuncArgs {
730 args: args.into_vec(),
731 kwargs: kws.into_default(),
732 };
733 match vm
734 .sys_module
735 .get_attr(vm.ctx.intern_str("breakpointhook"), vm)
736 {
737 Ok(hook) => hook.as_ref().call(args, vm),
738 Err(_) => Err(vm.new_runtime_error("lost sys.breakpointhook")),
739 }
740 }
741
742 #[pyfunction]
743 fn hex(number: ArgIndex) -> String {
744 let number = number.into_int_ref();
745 let n = number.as_bigint();
746 format!("{n:#x}")
747 }
748
749 #[pyfunction]
750 fn id(obj: PyObjectRef) -> usize {
751 obj.get_id()
752 }
753
754 #[pyfunction]
755 fn input(args: InputArgs, vm: &VirtualMachine) -> PyResult {
756 let prompt = args.prompt;
757 use std::io::IsTerminal;
758
759 let stdin = sys::get_stdin(vm)?;
760 let stdout = sys::get_stdout(vm)?;
761 let stderr = sys::get_stderr(vm)?;
762
763 let _ = vm.call_method(&stderr, "flush", ());
764
765 let fd_matches = |obj, expected| {
766 vm.call_method(obj, "fileno", ())
767 .and_then(|o| i64::try_from_object(vm, o))
768 .is_ok_and(|fd| fd == expected)
769 };
770
771 let tty = fd_matches(&stdin, 0)
772 && fd_matches(&stdout, 1)
773 && std::io::stdin().is_terminal()
774 && std::io::stdout().is_terminal();
775
776 if tty && let OptionalArg::Present(prompt) = &prompt {
779 let _ = vm.call_method(&stdout, "flush", ());
780 let encoding = stdout.get_attr("encoding", vm)?;
781 let errors = stdout.get_attr("errors", vm)?;
782 if !vm.is_none(&encoding) {
783 let encoded = vm.call_method(prompt.as_object(), "encode", (encoding, errors))?;
784 let bytes = encoded
785 .downcast::<PyBytes>()
786 .map_err(|_| vm.new_type_error("encode() must return bytes".to_owned()))?;
787 if bytes.as_bytes().contains(&0) {
788 return Err(vm.new_value_error(
789 "input: prompt string cannot contain null characters".to_owned(),
790 ));
791 }
792 }
793 }
794
795 let prompt_str = match &prompt {
798 OptionalArg::Present(s) => s.to_str(),
799 OptionalArg::Missing => Some(""),
800 };
801 let use_rustyline = tty && !is_pty_child() && prompt_str.is_some();
802
803 if use_rustyline {
804 let prompt = prompt_str.unwrap();
805 let mut readline = Readline::new(());
806 match readline.readline(prompt) {
807 ReadlineResult::Line(s) => Ok(vm.ctx.new_str(s).into()),
808 ReadlineResult::Eof => {
809 Err(vm.new_exception_empty(vm.ctx.exceptions.eof_error.to_owned()))
810 }
811 ReadlineResult::Interrupt => {
812 Err(vm.new_exception_empty(vm.ctx.exceptions.keyboard_interrupt.to_owned()))
813 }
814 ReadlineResult::Io(e) => Err(vm.new_os_error(e.to_string())),
815 #[cfg(unix)]
816 ReadlineResult::OsError(num) => Err(vm.new_os_error(num)),
817 ReadlineResult::Other(e) => Err(vm.new_runtime_error(e.to_string())),
818 }
819 } else {
820 if let OptionalArg::Present(prompt) = prompt {
821 vm.call_method(&stdout, "write", (prompt,))?;
822 }
823 let _ = vm.call_method(&stdout, "flush", ());
824 py_io::file_readline(&stdin, None, vm)
825 }
826 }
827
828 #[cfg(unix)]
832 fn is_pty_child() -> bool {
833 crate::host_env::posix::is_session_leader()
834 }
835
836 #[cfg(not(unix))]
837 fn is_pty_child() -> bool {
838 false
839 }
840
841 #[pyfunction]
842 fn isinstance(
843 obj: PyObjectRef,
844 class_or_tuple: PyObjectRef,
845 vm: &VirtualMachine,
846 ) -> PyResult<bool> {
847 obj.is_instance(&class_or_tuple, vm)
848 }
849
850 #[pyfunction]
851 fn issubclass(
852 cls: PyObjectRef,
853 class_or_tuple: PyObjectRef,
854 vm: &VirtualMachine,
855 ) -> PyResult<bool> {
856 cls.is_subclass(&class_or_tuple, vm)
857 }
858
859 #[pyfunction]
860 fn iter(
861 iter_target: PyObjectRef,
862 sentinel: OptionalArg<PyObjectRef>,
863 vm: &VirtualMachine,
864 ) -> PyResult<PyIter> {
865 if let OptionalArg::Present(sentinel) = sentinel {
866 let callable = ArgCallable::try_from_object(vm, iter_target)?;
867 let iterator = PyCallableIterator::new(callable, sentinel)
868 .into_ref(&vm.ctx)
869 .into();
870 Ok(PyIter::new(iterator))
871 } else {
872 PyIter::try_from_object(vm, iter_target)
873 }
874 }
875
876 #[pyfunction]
877 fn aiter(async_iterable: PyObjectRef, vm: &VirtualMachine) -> PyResult {
878 async_iterable.get_aiter(vm)
879 }
880
881 #[pyfunction]
882 fn anext(
883 aiter: PyObjectRef,
884 default_value: OptionalArg<PyObjectRef>,
885 vm: &VirtualMachine,
886 ) -> PyResult {
887 use crate::builtins::asyncgenerator::PyAnextAwaitable;
888
889 if !aiter.class().has_attr(identifier!(vm, __anext__)) {
891 return Err(vm.new_type_error(format!(
892 "'{}' object is not an async iterator",
893 aiter.class().name()
894 )));
895 }
896
897 let awaitable = vm.call_method(&aiter, "__anext__", ())?;
898
899 if let OptionalArg::Present(default) = default_value {
900 Ok(PyAnextAwaitable::new(awaitable, default)
901 .into_ref(&vm.ctx)
902 .into())
903 } else {
904 Ok(awaitable)
905 }
906 }
907
908 #[pyfunction]
909 fn len(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
910 obj.length(vm)
911 }
912
913 #[pyfunction]
914 fn locals(vm: &VirtualMachine) -> PyResult<ArgMapping> {
915 vm.current_locals()
916 }
917
918 fn min_or_max(
919 mut args: FuncArgs,
920 vm: &VirtualMachine,
921 func_name: &'static str,
922 op: PyComparisonOp,
923 ) -> PyResult {
924 if args.args.is_empty() {
926 return Err(vm.new_arity_type_error(func_name, 1..=usize::MAX, 0));
927 }
928
929 let default = args.take_keyword("default");
930 let key_func = args.take_keyword("key");
931
932 if let Some(err) = args.check_kwargs_empty_for(vm, func_name) {
933 return Err(err);
934 }
935
936 let candidates = if args.args.len() > 1 {
937 if default.is_some() {
938 return Err(vm.new_type_error(format!(
939 "Cannot specify a default for {func_name}() with multiple positional arguments"
940 )));
941 }
942 args.args
943 } else {
944 args.args[0].try_to_value(vm)?
945 };
946
947 let mut candidates_iter = candidates.into_iter();
948 let mut x = match candidates_iter.next() {
949 Some(x) => x,
950 None => {
951 return default.ok_or_else(|| {
952 vm.new_value_error(format!("{func_name}() iterable argument is empty"))
953 });
954 }
955 };
956
957 let key_func = key_func.filter(|f| !vm.is_none(f));
958 if let Some(ref key_func) = key_func {
959 let mut x_key = key_func.call((x.clone(),), vm)?;
960 for y in candidates_iter {
961 let y_key = key_func.call((y.clone(),), vm)?;
962 if y_key.rich_compare_bool(&x_key, op, vm)? {
963 x = y;
964 x_key = y_key;
965 }
966 }
967 } else {
968 for y in candidates_iter {
969 if y.rich_compare_bool(&x, op, vm)? {
970 x = y;
971 }
972 }
973 }
974
975 Ok(x)
976 }
977
978 #[pyfunction]
979 fn max(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
980 min_or_max(args, vm, "max", PyComparisonOp::Gt)
981 }
982
983 #[pyfunction]
984 fn min(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
985 min_or_max(args, vm, "min", PyComparisonOp::Lt)
986 }
987
988 #[pyfunction]
989 fn next(
990 iterator: PyObjectRef,
991 default_value: OptionalArg<PyObjectRef>,
992 vm: &VirtualMachine,
993 ) -> PyResult<PyIterReturn> {
994 if !PyIter::check(&iterator) {
995 return Err(vm.new_type_error(format!(
996 "'{}' object is not an iterator",
997 iterator.class().slot_name()
998 )));
999 }
1000 PyIter::new(iterator)
1001 .next(vm)
1002 .map(|iter_ret| match iter_ret {
1003 PyIterReturn::Return(obj) => PyIterReturn::Return(obj),
1004 PyIterReturn::StopIteration(v) => {
1005 default_value.map_or(PyIterReturn::StopIteration(v), PyIterReturn::Return)
1006 }
1007 })
1008 }
1009
1010 #[pyfunction]
1011 fn oct(number: ArgIndex, vm: &VirtualMachine) -> PyObjectRef {
1012 let number = number.into_int_ref();
1013 let n = number.as_bigint();
1014 let s = if n.is_negative() {
1015 format!("-0o{:o}", n.abs())
1016 } else {
1017 format!("0o{n:o}")
1018 };
1019
1020 vm.ctx.new_str(s).into()
1021 }
1022
1023 #[pyfunction]
1024 fn ord(character: PyObjectRef, vm: &VirtualMachine) -> PyResult<u32> {
1026 let bytes = if let Some(string) = character.downcast_ref::<PyStr>() {
1027 return match string.as_wtf8().code_points().exactly_one() {
1028 Ok(character) => Ok(character.to_u32()),
1029 Err(_) => {
1030 let string_len = string.char_len();
1031 Err(vm.new_type_error(format!(
1032 "ord() expected a character, but string of length {string_len} found"
1033 )))
1034 }
1035 };
1036 } else if let Some(bytes) = character.downcast_ref::<PyBytes>() {
1037 bytes.as_bytes().to_vec()
1038 } else if let Some(bytearray) = character.downcast_ref::<PyByteArray>() {
1039 bytearray.borrow_buf().to_vec()
1040 } else {
1041 return Err(vm.new_type_error(format!(
1042 "ord() expected string of length 1, but {} found",
1043 character.class().name()
1044 )));
1045 };
1046 let bytes_len = bytes.len();
1047 if bytes_len != 1 {
1048 return Err(vm.new_type_error(format!(
1049 "ord() expected a character, but string of length {bytes_len} found"
1050 )));
1051 }
1052 Ok(u32::from(bytes[0]))
1053 }
1054
1055 #[derive(FromArgs)]
1056 struct PowArgs {
1057 base: PyObjectRef,
1058 exp: PyObjectRef,
1059 #[pyarg(any, optional, name = "mod")]
1060 modulus: Option<PyObjectRef>,
1061 }
1062
1063 #[pyfunction]
1064 fn pow(args: PowArgs, vm: &VirtualMachine) -> PyResult {
1065 let PowArgs {
1066 base: x,
1067 exp: y,
1068 modulus,
1069 } = args;
1070 let modulus = modulus
1071 .as_deref()
1072 .unwrap_or_else(|| vm.ctx.none.as_object());
1073 vm._pow(&x, &y, modulus)
1074 }
1075
1076 #[pyfunction]
1077 pub(super) fn exit(exit_code_arg: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult {
1078 let code = exit_code_arg.unwrap_or_else(|| vm.ctx.new_int(0).into());
1079 Err(vm.new_system_exit(vec![code].into()))
1080 }
1081
1082 #[derive(Debug, Default, FromArgs)]
1083 pub struct PrintOptions {
1084 #[pyarg(named, default, py_default = "' '")]
1086 sep: Option<PyStrRef>,
1087 #[pyarg(named, default, py_default = "'\\n'")]
1089 end: Option<PyStrRef>,
1090 #[pyarg(named, optional)]
1091 file: Option<PyObjectRef>,
1092 #[pyarg(named, default = ArgIntoBool::FALSE)]
1093 flush: ArgIntoBool,
1094 }
1095
1096 #[pyfunction]
1097 pub fn print(objects: PosArgs, options: PrintOptions, vm: &VirtualMachine) -> PyResult<()> {
1098 let file = match options.file {
1099 Some(f) => f,
1100 None => sys::get_stdout(vm)?,
1101 };
1102 let write = |obj: PyStrRef| vm.call_method(&file, "write", (obj,));
1103
1104 let sep = options.sep.unwrap_or_else(|| vm.ctx.new_str(" "));
1105
1106 let mut first = true;
1107 for object in objects {
1108 if first {
1109 first = false;
1110 } else {
1111 write(sep.clone())?;
1112 }
1113
1114 write(object.str(vm)?)?;
1115 }
1116
1117 let end = options.end.unwrap_or_else(|| vm.ctx.new_str("\n"));
1118 write(end)?;
1119
1120 if options.flush.into() {
1121 vm.call_method(&file, "flush", ())?;
1122 }
1123
1124 Ok(())
1125 }
1126
1127 #[pyfunction]
1128 fn repr(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
1129 obj.repr(vm)
1130 }
1131
1132 #[pyfunction]
1133 pub fn reversed(sequence: PyObjectRef, vm: &VirtualMachine) -> PyResult {
1134 if let Some(reversed_method) =
1135 vm.get_method(sequence.clone(), identifier!(vm, __reversed__))
1136 {
1137 reversed_method?.call((), vm)
1138 } else {
1139 vm.get_method_or_type_error(sequence.clone(), identifier!(vm, __getitem__), || {
1140 "argument to reversed() must be a sequence".to_owned()
1141 })?;
1142 let len = sequence.length(vm)?;
1143 let obj_iterator = PyReverseSequenceIterator::new(sequence, len);
1144 Ok(obj_iterator.into_pyobject(vm))
1145 }
1146 }
1147
1148 #[derive(FromArgs)]
1149 pub(super) struct RoundArgs {
1150 number: PyObjectRef,
1151 #[pyarg(any, optional)]
1152 ndigits: Option<PyObjectRef>,
1153 }
1154
1155 #[pyfunction]
1156 fn round(RoundArgs { number, ndigits }: RoundArgs, vm: &VirtualMachine) -> PyResult {
1157 let meth = vm
1158 .get_special_method(&number, identifier!(vm, __round__))?
1159 .ok_or_else(|| {
1160 vm.new_type_error(format!(
1161 "type {} doesn't define __round__ method",
1162 number.class().slot_name()
1163 ))
1164 })?;
1165 match ndigits {
1166 Some(obj) => {
1167 let ndigits = obj.try_index(vm)?;
1168 meth.invoke((ndigits,), vm)
1169 }
1170 None => {
1171 meth.invoke((), vm)
1173 }
1174 }
1175 }
1176
1177 #[pyfunction]
1178 fn setattr(
1179 obj: PyObjectRef,
1180 name: PyObjectRef,
1181 value: PyObjectRef,
1182 vm: &VirtualMachine,
1183 ) -> PyResult<()> {
1184 let attr = name.try_to_ref::<PyStr>(vm).map_err(|_e| {
1185 vm.new_type_error(format!(
1186 "attribute name must be string, not '{}'",
1187 name.class().name()
1188 ))
1189 })?;
1190 obj.set_attr(attr, value, vm)?;
1191 Ok(())
1192 }
1193
1194 #[pyfunction]
1197 fn sorted(iterable: PyObjectRef, opts: SortOptions, vm: &VirtualMachine) -> PyResult<PyList> {
1198 let items = vm.extract_elements_sized(&iterable, &|| 0, Ok)?;
1201 let lst = PyList::from(items);
1202 lst.sort(opts, vm)?;
1203 Ok(lst)
1204 }
1205
1206 #[derive(FromArgs)]
1207 pub(super) struct SumArgs {
1208 #[pyarg(positional)]
1209 iterable: ArgIterable,
1210 #[pyarg(any, default = 0)]
1212 start: PyObjectRef,
1213 }
1214
1215 #[pyfunction]
1216 fn sum(SumArgs { iterable, start }: SumArgs, vm: &VirtualMachine) -> PyResult {
1217 let mut sum = start;
1218
1219 match_class!(match sum {
1220 PyStr =>
1221 return Err(vm.new_type_error("sum() can't sum strings [use ''.join(seq) instead]")),
1222 PyBytes =>
1223 return Err(vm.new_type_error("sum() can't sum bytes [use b''.join(seq) instead]")),
1224 PyByteArray =>
1225 return Err(
1226 vm.new_type_error("sum() can't sum bytearray [use b''.join(seq) instead]")
1227 ),
1228 _ => (),
1229 });
1230
1231 for item in iterable.iter(vm)? {
1232 sum = vm._add(&sum, &*item?)?;
1233 }
1234 Ok(sum)
1235 }
1236
1237 #[derive(FromArgs)]
1238 struct ImportArgs {
1239 #[pyarg(any)]
1240 name: PyObjectRef,
1241 #[pyarg(any, optional)]
1242 globals: Option<PyObjectRef>,
1243 #[allow(dead_code)]
1244 #[pyarg(any, optional)]
1245 locals: Option<PyObjectRef>,
1246 #[pyarg(any, default, py_default = "()")]
1248 fromlist: Option<PyObjectRef>,
1249 #[pyarg(any, default)]
1250 level: i32,
1251 }
1252
1253 #[pyfunction]
1254 fn __import__(args: ImportArgs, vm: &VirtualMachine) -> PyResult {
1255 let name = args
1258 .name
1259 .downcast_ref::<PyStr>()
1260 .ok_or_else(|| vm.new_type_error("module name must be a string"))?;
1261 crate::import::import_module_level(
1262 name,
1263 args.globals.as_deref(),
1264 args.fromlist,
1265 args.level,
1266 vm,
1267 )
1268 }
1269
1270 #[pyfunction]
1271 fn vars(obj: OptionalArg, vm: &VirtualMachine) -> PyResult {
1272 if let OptionalArg::Present(obj) = obj {
1273 obj.get_attr(identifier!(vm, __dict__), vm)
1274 .map_err(|_| vm.new_type_error("vars() argument must have __dict__ attribute"))
1275 } else {
1276 Ok(vm.current_locals()?.into())
1277 }
1278 }
1279
1280 #[pyfunction]
1281 pub(super) fn __build_class__(
1282 function: PyRef<PyFunction>,
1283 name: PyStrRef,
1284 bases: PosArgs,
1285 mut kwargs: KwArgs,
1286 vm: &VirtualMachine,
1287 ) -> PyResult {
1288 let name_obj: PyObjectRef = name.clone().into();
1289
1290 let mut new_bases: Option<Vec<PyObjectRef>> = None;
1292 let bases = PyTuple::new_ref(bases.into_vec(), &vm.ctx);
1293 for (i, base) in bases.as_slice().iter().enumerate() {
1294 if base.fast_isinstance(vm.ctx.types.type_type) {
1295 if let Some(bases) = &mut new_bases {
1296 bases.push(base.clone());
1297 }
1298 continue;
1299 }
1300 let mro_entries = vm.get_attribute_opt(base, identifier!(vm, __mro_entries__))?;
1301 let entries = match mro_entries {
1302 Some(meth) => meth.call((bases.clone(),), vm)?,
1303 None => {
1304 if let Some(bases) = &mut new_bases {
1305 bases.push(base.clone());
1306 }
1307 continue;
1308 }
1309 };
1310 let entries: PyTupleRef = entries
1311 .downcast()
1312 .map_err(|_| vm.new_type_error("__mro_entries__ must return a tuple"))?;
1313 let new_bases = new_bases.get_or_insert_with(|| bases.as_slice()[..i].to_vec());
1314 new_bases.extend_from_slice(entries.as_slice());
1315 }
1316
1317 let new_bases = new_bases.map(|v| PyTuple::new_ref(v, &vm.ctx));
1318 let (orig_bases, bases) = match new_bases {
1319 Some(new) => (Some(bases), new),
1320 None => (None, bases),
1321 };
1322
1323 let metaclass = kwargs.pop_kwarg("metaclass").map_or_else(
1325 || {
1326 Ok(if bases.as_slice().is_empty() {
1328 vm.ctx.types.type_type.to_owned()
1329 } else {
1330 bases.as_slice().first().unwrap().class().to_owned()
1331 })
1332 },
1333 |metaclass| {
1334 metaclass
1335 .downcast_exact::<PyType>(vm)
1336 .map(|m| m.into_pyref())
1337 },
1338 );
1339
1340 let (metaclass, meta_name) = match metaclass {
1341 Ok(mut metaclass) => {
1342 for base in bases.as_slice() {
1343 let base_class = base.class();
1344 if metaclass.fast_issubclass(base_class) {
1346 continue;
1347 }
1348 if base_class.fast_issubclass(&metaclass) {
1350 metaclass = base_class.to_owned();
1351 continue;
1352 }
1353 return Err(vm.new_type_error(
1355 "metaclass conflict: the metaclass of a derived class must be a (non-strict) \
1356 subclass of the metaclasses of all its bases",
1357 ));
1358 }
1359 let meta_name = metaclass.slot_name();
1360 (metaclass.to_owned().into(), meta_name.to_owned())
1361 }
1362 Err(obj) => (obj, "<metaclass>".to_owned()),
1363 };
1364
1365 let bases: PyObjectRef = bases.into();
1366
1367 let namespace = vm
1369 .get_attribute_opt(&metaclass, identifier!(vm, __prepare__))?
1370 .map_or(Ok(vm.ctx.new_dict().into()), |prepare| {
1371 let args = FuncArgs::new(vec![name_obj.clone(), bases.clone()], kwargs.clone());
1372 prepare.call(args, vm)
1373 })?;
1374
1375 let namespace = ArgMapping::try_from_object(vm, namespace.clone()).map_err(|_| {
1377 vm.new_type_error(format!(
1378 "{}.__prepare__() must return a mapping, not {}",
1379 meta_name,
1380 namespace.class()
1381 ))
1382 })?;
1383
1384 if let Ok(type_params) = function
1386 .as_object()
1387 .get_attr(identifier!(vm, __type_params__), vm)
1388 && let Some(type_params_tuple) = type_params.downcast_ref::<PyTuple>()
1389 && !type_params_tuple.as_slice().is_empty()
1390 {
1391 namespace
1393 .as_object()
1394 .set_item(vm.ctx.intern_str(".type_params"), type_params, vm)?;
1395 }
1396
1397 let classcell = function.invoke_with_locals(().into(), Some(namespace.clone()), vm)?;
1398 let classcell = <Option<PyCellRef>>::try_from_object(vm, classcell)?;
1399
1400 if let Some(orig_bases) = orig_bases {
1401 namespace.as_object().set_item(
1402 identifier!(vm, __orig_bases__),
1403 orig_bases.into(),
1404 vm,
1405 )?;
1406 }
1407
1408 namespace
1410 .as_object()
1411 .del_item(vm.ctx.intern_str(".type_params"), vm)
1412 .ok();
1413
1414 let args = FuncArgs::new(vec![name_obj, bases, namespace.into()], kwargs);
1415 let class = metaclass.call(args, vm)?;
1416
1417 if let Ok(type_params) = function
1419 .as_object()
1420 .get_attr(identifier!(vm, __type_params__), vm)
1421 && let Some(type_params_tuple) = type_params.downcast_ref::<PyTuple>()
1422 && !type_params_tuple.as_slice().is_empty()
1423 {
1424 class.set_attr(identifier!(vm, __type_params__), type_params.clone(), vm)?;
1425 class.set_attr(identifier!(vm, __parameters__), type_params, vm)?;
1427 }
1428
1429 if let Some(ref classcell) = classcell
1431 && class.fast_isinstance(vm.ctx.types.type_type)
1432 {
1433 let cell_value = classcell.get().ok_or_else(|| {
1434 vm.new_runtime_error(format!(
1435 "__class__ not set defining {name:?} as {class:?}. Was __classcell__ propagated to type.__new__?"
1436 ))
1437 })?;
1438
1439 if !cell_value.is(&class) {
1440 return Err(vm.new_type_error(format!(
1441 "__class__ set to {cell_value:?} defining {name:?} as {class:?}"
1442 )));
1443 }
1444 }
1445
1446 Ok(class)
1447 }
1448}
1449
1450pub fn init_module(vm: &VirtualMachine, module: &Py<PyModule>) {
1451 let ctx = &vm.ctx;
1452
1453 let _ = crate::protocol::VecBuffer::make_static_type();
1454
1455 module.__init_methods(vm).unwrap();
1456 builtins::module_exec(vm, module).unwrap();
1457
1458 let debug_mode: bool = vm.state.config.settings.optimize == 0;
1459 let exception_group = crate::exception_group::exception_group();
1461
1462 extend_module!(vm, module, {
1463 "__debug__" => ctx.new_bool(debug_mode),
1464
1465 "bool" => ctx.types.bool_type.to_owned(),
1466 "bytearray" => ctx.types.bytearray_type.to_owned(),
1467 "bytes" => ctx.types.bytes_type.to_owned(),
1468 "classmethod" => ctx.types.classmethod_type.to_owned(),
1469 "complex" => ctx.types.complex_type.to_owned(),
1470 "dict" => ctx.types.dict_type.to_owned(),
1471 "enumerate" => ctx.types.enumerate_type.to_owned(),
1472 "float" => ctx.types.float_type.to_owned(),
1473 "frozenset" => ctx.types.frozenset_type.to_owned(),
1474 "filter" => ctx.types.filter_type.to_owned(),
1475 "int" => ctx.types.int_type.to_owned(),
1476 "list" => ctx.types.list_type.to_owned(),
1477 "map" => ctx.types.map_type.to_owned(),
1478 "memoryview" => ctx.types.memoryview_type.to_owned(),
1479 "object" => ctx.types.object_type.to_owned(),
1480 "property" => ctx.types.property_type.to_owned(),
1481 "range" => ctx.types.range_type.to_owned(),
1482 "set" => ctx.types.set_type.to_owned(),
1483 "slice" => ctx.types.slice_type.to_owned(),
1484 "staticmethod" => ctx.types.staticmethod_type.to_owned(),
1485 "str" => ctx.types.str_type.to_owned(),
1486 "super" => ctx.types.super_type.to_owned(),
1487 "tuple" => ctx.types.tuple_type.to_owned(),
1488 "type" => ctx.types.type_type.to_owned(),
1489 "zip" => ctx.types.zip_type.to_owned(),
1490
1491 "None" => ctx.none(),
1493 "True" => ctx.new_bool(true),
1494 "False" => ctx.new_bool(false),
1495 "NotImplemented" => ctx.not_implemented(),
1496 "Ellipsis" => vm.ctx.ellipsis.clone(),
1497
1498 "BaseException" => ctx.exceptions.base_exception_type.to_owned(),
1501 "BaseExceptionGroup" => ctx.exceptions.base_exception_group.to_owned(),
1502 "ExceptionGroup" => exception_group.to_owned(),
1503 "SystemExit" => ctx.exceptions.system_exit.to_owned(),
1504 "KeyboardInterrupt" => ctx.exceptions.keyboard_interrupt.to_owned(),
1505 "GeneratorExit" => ctx.exceptions.generator_exit.to_owned(),
1506 "Exception" => ctx.exceptions.exception_type.to_owned(),
1507 "StopIteration" => ctx.exceptions.stop_iteration.to_owned(),
1508 "StopAsyncIteration" => ctx.exceptions.stop_async_iteration.to_owned(),
1509 "ArithmeticError" => ctx.exceptions.arithmetic_error.to_owned(),
1510 "FloatingPointError" => ctx.exceptions.floating_point_error.to_owned(),
1511 "OverflowError" => ctx.exceptions.overflow_error.to_owned(),
1512 "ZeroDivisionError" => ctx.exceptions.zero_division_error.to_owned(),
1513 "AssertionError" => ctx.exceptions.assertion_error.to_owned(),
1514 "AttributeError" => ctx.exceptions.attribute_error.to_owned(),
1515 "BufferError" => ctx.exceptions.buffer_error.to_owned(),
1516 "EOFError" => ctx.exceptions.eof_error.to_owned(),
1517 "ImportError" => ctx.exceptions.import_error.to_owned(),
1518 "ModuleNotFoundError" => ctx.exceptions.module_not_found_error.to_owned(),
1519 "LookupError" => ctx.exceptions.lookup_error.to_owned(),
1520 "IndexError" => ctx.exceptions.index_error.to_owned(),
1521 "KeyError" => ctx.exceptions.key_error.to_owned(),
1522 "MemoryError" => ctx.exceptions.memory_error.to_owned(),
1523 "NameError" => ctx.exceptions.name_error.to_owned(),
1524 "UnboundLocalError" => ctx.exceptions.unbound_local_error.to_owned(),
1525 "OSError" => ctx.exceptions.os_error.to_owned(),
1526 "IOError" => ctx.exceptions.os_error.to_owned(),
1528 "EnvironmentError" => ctx.exceptions.os_error.to_owned(),
1529 "BlockingIOError" => ctx.exceptions.blocking_io_error.to_owned(),
1530 "ChildProcessError" => ctx.exceptions.child_process_error.to_owned(),
1531 "ConnectionError" => ctx.exceptions.connection_error.to_owned(),
1532 "BrokenPipeError" => ctx.exceptions.broken_pipe_error.to_owned(),
1533 "ConnectionAbortedError" => ctx.exceptions.connection_aborted_error.to_owned(),
1534 "ConnectionRefusedError" => ctx.exceptions.connection_refused_error.to_owned(),
1535 "ConnectionResetError" => ctx.exceptions.connection_reset_error.to_owned(),
1536 "FileExistsError" => ctx.exceptions.file_exists_error.to_owned(),
1537 "FileNotFoundError" => ctx.exceptions.file_not_found_error.to_owned(),
1538 "InterruptedError" => ctx.exceptions.interrupted_error.to_owned(),
1539 "IsADirectoryError" => ctx.exceptions.is_a_directory_error.to_owned(),
1540 "NotADirectoryError" => ctx.exceptions.not_a_directory_error.to_owned(),
1541 "PermissionError" => ctx.exceptions.permission_error.to_owned(),
1542 "ProcessLookupError" => ctx.exceptions.process_lookup_error.to_owned(),
1543 "TimeoutError" => ctx.exceptions.timeout_error.to_owned(),
1544 "ReferenceError" => ctx.exceptions.reference_error.to_owned(),
1545 "RuntimeError" => ctx.exceptions.runtime_error.to_owned(),
1546 "PythonFinalizationError" => ctx.exceptions.python_finalization_error.to_owned(),
1547 "NotImplementedError" => ctx.exceptions.not_implemented_error.to_owned(),
1548 "RecursionError" => ctx.exceptions.recursion_error.to_owned(),
1549 "SyntaxError" => ctx.exceptions.syntax_error.to_owned(),
1550 "_IncompleteInputError" => ctx.exceptions.incomplete_input_error.to_owned(),
1551 "IndentationError" => ctx.exceptions.indentation_error.to_owned(),
1552 "TabError" => ctx.exceptions.tab_error.to_owned(),
1553 "SystemError" => ctx.exceptions.system_error.to_owned(),
1554 "TypeError" => ctx.exceptions.type_error.to_owned(),
1555 "ValueError" => ctx.exceptions.value_error.to_owned(),
1556 "UnicodeError" => ctx.exceptions.unicode_error.to_owned(),
1557 "UnicodeDecodeError" => ctx.exceptions.unicode_decode_error.to_owned(),
1558 "UnicodeEncodeError" => ctx.exceptions.unicode_encode_error.to_owned(),
1559 "UnicodeTranslateError" => ctx.exceptions.unicode_translate_error.to_owned(),
1560
1561 "Warning" => ctx.exceptions.warning.to_owned(),
1563 "DeprecationWarning" => ctx.exceptions.deprecation_warning.to_owned(),
1564 "PendingDeprecationWarning" => ctx.exceptions.pending_deprecation_warning.to_owned(),
1565 "RuntimeWarning" => ctx.exceptions.runtime_warning.to_owned(),
1566 "SyntaxWarning" => ctx.exceptions.syntax_warning.to_owned(),
1567 "UserWarning" => ctx.exceptions.user_warning.to_owned(),
1568 "FutureWarning" => ctx.exceptions.future_warning.to_owned(),
1569 "ImportWarning" => ctx.exceptions.import_warning.to_owned(),
1570 "UnicodeWarning" => ctx.exceptions.unicode_warning.to_owned(),
1571 "BytesWarning" => ctx.exceptions.bytes_warning.to_owned(),
1572 "ResourceWarning" => ctx.exceptions.resource_warning.to_owned(),
1573 "EncodingWarning" => ctx.exceptions.encoding_warning.to_owned(),
1574 });
1575
1576 #[cfg(feature = "jit")]
1577 extend_module!(vm, module, {
1578 "JitError" => ctx.exceptions.jit_error.to_owned(),
1579 });
1580
1581 #[cfg(windows)]
1582 extend_module!(vm, module, {
1583 "WindowsError" => ctx.exceptions.os_error.to_owned(),
1585 });
1586}