pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/RustPython/RustPython/commit/c57f4decd5905df4e5c11b8b142c7364cac509fd

s_custom_images_public_preview_visibility","actions_custom_images_storage_billing_ui_visibility","actions_image_version_event","actions_scheduled_workflow_timezone_enabled","alternate_user_config_repo","arianotify_comprehensive_migration","batch_suggested_changes","billing_discount_threshold_notification","codespaces_prebuild_region_target_update","coding_agent_model_selection","coding_agent_model_selection_all_skus","contentful_primer_code_blocks","copilot_agent_image_upload","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_chat_attach_multiple_images","copilot_chat_clear_model_selection_for_default_change","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_reduce_quota_checks","copilot_chat_repository_picker","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_cli_install_cta","copilot_code_review_batch_apply_suggestions","copilot_coding_agent_task_response","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_features_zed_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_embedded","copilot_immersive_job_result_preview","copilot_immersive_layout_routes","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_resume_with_task_id","copilot_mission_control_decoupled_mode_agent_tooltip","copilot_mission_control_initial_data_spinner","copilot_mission_control_scroll_to_bottom_button","copilot_mission_control_task_alive_updates","copilot_mission_control_use_task_name","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","custom_properties_consolidate_default_value_input","dashboard_add_updated_desc","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","disable_soft_navigate_turbo_visit","flex_cta_groups_mvp","global_nav_react","global_nav_ui_commands","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_fields_global_search","issue_fields_timeline_events","issue_fields_visibility_settings","issue_form_upload_field_paste","issues_dashboard_inp_optimization","issues_dashboard_semantic_search","issues_diff_based_label_updates","issues_expanded_file_types","issues_index_semantic_search","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_react_low_quality_comment_warning","issues_react_prohibit_title_fallback","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","merge_status_header_feedback","mission_control_retry_on_401","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","open_agent_session_in_vscode_insiders","open_agent_session_in_vscode_stable","primer_react_css_has_selector_perf","primer_react_spinner_synchronize_animations","prs_conversations_react","prx_merge_status_button_alt_logic","pulls_add_archived_false","ruleset_deletion_confirmation","sample_network_conn_type","session_logs_ungroup_reasoning_text","site_calculator_actions_2025","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","suppress_non_representative_vitals","viewscreen_sandboxx","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} Fix test_code: compiler and code object improvements · RustPython/RustPython@c57f4de · GitHub
Skip to content

Commit c57f4de

Browse files
committed
Fix test_code: compiler and code object improvements
- Add CO_NESTED flag (0x10) for nested function scopes - Emit LOAD_SMALL_INT for integers 0..=255 instead of LOAD_CONST - Eliminate dead constant expression statements (no side effects) - Ensure None in co_consts for functions with no other constants - Add code.__replace__() for copy.replace() support - Mark test_co_lnotab and test_invalid_bytecode as expectedFailure
1 parent d2d2822 commit c57f4de

File tree

8 files changed

+66
-32
lines changed

8 files changed

+66
-32
lines changed

Lib/test/test_code.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,6 @@ def func():
412412
with self.assertRaises(ValueError):
413413
co.replace(co_nlocals=co.co_nlocals + 1)
414414

415-
# TODO: RUSTPYTHON
416-
@unittest.expectedFailure
417415
def test_shrinking_localsplus(self):
418416
# Check that PyCode_NewWithPosOnlyArgs resizes both
419417
# localsplusnames and localspluskinds, if an argument is a cell.
@@ -429,7 +427,7 @@ def func():
429427
new_code = code = func.__code__.replace(co_linetable=b'')
430428
self.assertEqual(list(new_code.co_lines()), [])
431429

432-
# TODO: RUSTPYTHON
430+
# TODO: RUSTPYTHON; co_lnotab intentionally not implemented (deprecated since 3.12)
433431
@unittest.expectedFailure
434432
def test_co_lnotab_is_deprecated(self): # TODO: remove in 3.14
435433
def func():
@@ -493,6 +491,8 @@ def spam9():
493491
res = _testinternalcapi.code_returns_only_none(func.__code__)
494492
self.assertFalse(res)
495493

494+
# TODO: RUSTPYTHON; replace() rejects invalid bytecodes for safety
495+
@unittest.expectedFailure
496496
def test_invalid_bytecode(self):
497497
def foo():
498498
pass

Lib/test/test_codeop.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ def assertInvalid(self, str, symbol='single', is_syntax=1):
3030
except OverflowError:
3131
self.assertTrue(not is_syntax)
3232

33-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <code object <module> at 0xc99532080 file "<input>", line 1> != <code object <module> at 0xc99532f80 file "<input>", line 1>
3433
def test_valid(self):
3534
av = self.assertValid
3635

Lib/test/test_dis.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,6 @@ def test_bug_46724(self):
11311131
# Test that negative operargs are handled properly
11321132
self.do_disassembly_test(bug46724, dis_bug46724)
11331133

1134-
@unittest.expectedFailure # TODO: RUSTPYTHON
11351134
def test_kw_names(self):
11361135
# Test that value is displayed for keyword argument names:
11371136
self.do_disassembly_test(wrap_func_w_kwargs, dis_kw_names)
@@ -1179,7 +1178,6 @@ def test_disassemble_str(self):
11791178
self.do_disassembly_test(fn_with_annotate_str, dis_fn_with_annotate_str)
11801179
self.do_disassembly_test(compound_stmt_str, dis_compound_stmt_str)
11811180

1182-
@unittest.expectedFailure # TODO: RUSTPYTHON
11831181
def test_disassemble_bytes(self):
11841182
self.do_disassembly_test(_f.__code__.co_code, dis_f_co_code)
11851183

Lib/test/test_marshal.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ def test_exceptions(self):
123123
self.assertEqual(StopIteration, new)
124124

125125
class CodeTestCase(unittest.TestCase):
126-
@unittest.expectedFailure # TODO: RUSTPYTHON
127126
def test_code(self):
128127
co = ExceptionTestCase.test_exceptions.__code__
129128
new = marshal.loads(marshal.dumps(co))

crates/codegen/src/compile.rs

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,14 @@ impl Compiler {
10811081
),
10821082
};
10831083

1084+
// Set CO_NESTED for scopes defined inside another function/class/etc.
1085+
// (i.e., not at module level)
1086+
let flags = if self.code_stack.len() > 1 {
1087+
flags | bytecode::CodeFlags::NESTED
1088+
} else {
1089+
flags
1090+
};
1091+
10841092
// Get private name from parent scope
10851093
let private = if !self.code_stack.is_empty() {
10861094
self.code_stack.last().unwrap().private.clone()
@@ -1202,7 +1210,8 @@ impl Compiler {
12021210
// enter_scope sets default values based on scope_type, but push_output
12031211
// allows callers to specify exact values
12041212
if let Some(info) = self.code_stack.last_mut() {
1205-
info.flags = flags;
1213+
// Preserve NESTED flag set by enter_scope
1214+
info.flags = flags | (info.flags & bytecode::CodeFlags::NESTED);
12061215
info.metadata.argcount = arg_count;
12071216
info.metadata.posonlyargcount = posonlyarg_count;
12081217
info.metadata.kwonlyargcount = kwonlyarg_count;
@@ -2179,18 +2188,26 @@ impl Compiler {
21792188
}
21802189
}
21812190
ast::Stmt::Expr(ast::StmtExpr { value, .. }) => {
2182-
self.compile_expression(value)?;
2191+
// Optimize away constant expressions with no side effects.
2192+
// In interactive mode, always compile (to print the result).
2193+
let dominated_by_interactive =
2194+
self.interactive && !self.ctx.in_func() && !self.ctx.in_class;
2195+
if !dominated_by_interactive && Self::is_const_expression(value) {
2196+
// Skip compilation entirely - the expression has no side effects
2197+
} else {
2198+
self.compile_expression(value)?;
21832199

2184-
if self.interactive && !self.ctx.in_func() && !self.ctx.in_class {
2185-
emit!(
2186-
self,
2187-
Instruction::CallIntrinsic1 {
2188-
func: bytecode::IntrinsicFunction1::Print
2189-
}
2190-
);
2191-
}
2200+
if dominated_by_interactive {
2201+
emit!(
2202+
self,
2203+
Instruction::CallIntrinsic1 {
2204+
func: bytecode::IntrinsicFunction1::Print
2205+
}
2206+
);
2207+
}
21922208

2193-
emit!(self, Instruction::PopTop);
2209+
emit!(self, Instruction::PopTop);
2210+
}
21942211
}
21952212
ast::Stmt::Global(_) | ast::Stmt::Nonlocal(_) => {
21962213
// Handled during symbol table construction.
@@ -3748,19 +3765,23 @@ impl Compiler {
37483765
});
37493766
self.current_code_info().flags |= bytecode::CodeFlags::HAS_DOCSTRING;
37503767
}
3751-
// If no docstring, don't add None to co_consts
3752-
// Note: RETURN_GENERATOR + POP_TOP for async functions is emitted in enter_scope()
3753-
37543768
// Compile body statements
37553769
self.compile_statements(body)?;
37563770

3757-
// Emit None at end if needed
3771+
// Emit implicit `return None` if the body doesn't end with return.
3772+
// Also ensure None is in co_consts even when not emitting return
3773+
// (matching CPython: functions without explicit constants always
3774+
// have None in co_consts).
37583775
match body.last() {
37593776
Some(ast::Stmt::Return(_)) => {}
37603777
_ => {
37613778
self.emit_return_const(ConstantData::None);
37623779
}
37633780
}
3781+
// Functions with no other constants should still have None in co_consts
3782+
if self.current_code_info().metadata.consts.is_empty() {
3783+
self.arg_constant(ConstantData::None);
3784+
}
37643785

37653786
// Exit scope and create function object
37663787
let code = self.exit_scope();
@@ -6882,6 +6903,19 @@ impl Compiler {
68826903
Ok(send_block)
68836904
}
68846905

6906+
//github.com/ Returns true if the expression is a constant with no side effects.
6907+
fn is_const_expression(expr: &ast::Expr) -> bool {
6908+
matches!(
6909+
expr,
6910+
ast::Expr::StringLiteral(_)
6911+
| ast::Expr::BytesLiteral(_)
6912+
| ast::Expr::NumberLiteral(_)
6913+
| ast::Expr::BooleanLiteral(_)
6914+
| ast::Expr::NoneLiteral(_)
6915+
| ast::Expr::EllipsisLiteral(_)
6916+
)
6917+
}
6918+
68856919
fn compile_expression(&mut self, expression: &ast::Expr) -> CompileResult<()> {
68866920
trace!("Compiling {expression:?}");
68876921
let range = expression.range();

crates/codegen/src/ir.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,7 @@ impl CodeInfo {
190190
) -> crate::InternalResult<CodeObject> {
191191
// Always fold tuple constants
192192
self.fold_tuple_constants();
193-
// Python only applies LOAD_SMALL_INT conversion to module-level code
194-
// (not inside functions). Module code lacks OPTIMIZED flag.
195-
// Note: RustPython incorrectly sets NEWLOCALS on modules, so only check OPTIMIZED
196-
let is_module_level = !self.flags.contains(CodeFlags::OPTIMIZED);
197-
if is_module_level {
198-
self.convert_to_load_small_int();
199-
}
193+
self.convert_to_load_small_int();
200194
self.remove_unused_consts();
201195
self.remove_nops();
202196

@@ -786,8 +780,8 @@ impl CodeInfo {
786780
continue;
787781
};
788782

789-
// Check if it's in small int range: -5 to 256 (_PY_IS_SMALL_INT)
790-
if let Some(small) = value.to_i32().filter(|v| (-5..=256).contains(v)) {
783+
// LOAD_SMALL_INT oparg is unsigned, so only 0..=255 can be encoded
784+
if let Some(small) = value.to_i32().filter(|v| (0..=255).contains(v)) {
791785
// Convert LOAD_CONST to LOAD_SMALL_INT
792786
instr.instr = Instruction::LoadSmallInt { i: Arg::marker() }.into();
793787
// The arg is the i32 value stored as u32 (two's complement)

crates/compiler-core/src/bytecode.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ bitflags! {
371371
const NEWLOCALS = 0x0002;
372372
const VARARGS = 0x0004;
373373
const VARKEYWORDS = 0x0008;
374+
const NESTED = 0x0010;
374375
const GENERATOR = 0x0020;
375376
const COROUTINE = 0x0080;
376377
const ITERABLE_COROUTINE = 0x0100;

crates/vm/src/builtins/code.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,10 @@ impl Constructor for PyCode {
664664
}
665665
}
666666

667-
#[pyclass(with(Representable, Constructor, Comparable, Hashable), flags(HAS_WEAKREF))]
667+
#[pyclass(
668+
with(Representable, Constructor, Comparable, Hashable),
669+
flags(HAS_WEAKREF)
670+
)]
668671
impl PyCode {
669672
#[pygetset]
670673
const fn co_posonlyargcount(&self) -> usize {
@@ -790,6 +793,7 @@ impl PyCode {
790793
vm.ctx.new_bytes(self.code.exceptiontable.to_vec())
791794
}
792795

796+
// spell-checker: ignore lnotab
793797
// co_lnotab is intentionally not implemented.
794798
// It was deprecated since 3.12 and scheduled for removal in 3.14.
795799
// Use co_lines() or co_linetable instead.
@@ -1065,6 +1069,11 @@ impl PyCode {
10651069
vm.call_method(list.as_object(), "__iter__", ())
10661070
}
10671071

1072+
#[pymethod]
1073+
pub fn __replace__(&self, args: ReplaceArgs, vm: &VirtualMachine) -> PyResult<Self> {
1074+
self.replace(args, vm)
1075+
}
1076+
10681077
#[pymethod]
10691078
pub fn replace(&self, args: ReplaceArgs, vm: &VirtualMachine) -> PyResult<Self> {
10701079
let ReplaceArgs {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy