McRogueFace/tests/regression
John McCardle ce15469ffc fix(bindings): route every drawable wrapper through PythonObjectCache
`.parent` allocated a brand-new Python wrapper on every read, so object
identity never held: `kid.parent is parent` was False, and so was
`kid.parent is kid.parent`. A Frame/Grid subclass reached through .parent
came back as the base type with its Python attributes gone, and `.parent`
could not be used as a dict key or set member.

The cache-aware converter already existed -- convertDrawableToPython in
UICollection.cpp -- but was file-local, so three other paths hand-rolled
their own tp_alloc switch and skipped the cache:

  - UIDrawable::get_parent      (the filed bug)
  - find_in_collection          (mcrfpy.find / find_all)
  - UIEntityCollection concat and slice __getitem__

The entity sites were the worst of them: a duplicate wrapper's tp_dealloc
unconditionally clears UIEntity::pyobject, destroying the #266 subclass
identity ref held by the *original* wrapper.

Promote the converter to UIDrawable::pyobject_for and route all sites
through it; add the matching convertEntityToPython for entities. This also
gives .parent the Line/Circle/Arc/Viewport3D arms it never had (they
previously fell through to None).

Residual gap, deliberately not closed here: the cache holds weakrefs, so a
subclass wrapper GC'd while only C++ holds the object still resurrects as
the base type. Closing that needs an owner-held strong ref (the #348
pattern) and is a lifetime design decision; filed separately.

Verified A/B: 17 of the new test's 22 checks fail pre-fix, all pass after.
Suite 330/330. Also corrects CLAUDE.md, which documented the long-deleted
RET_PY_INSTANCE macro and recommended bare tp_alloc as the "most common"
pattern -- i.e. taught this exact bug.

closes #369
2026-07-13 23:37:01 -04:00
..
frame_children_mutation_test.py Add regression tests for Frame.children mutation and parent=None removal 2026-04-01 11:27:47 -04:00
grid_backward_compat_test.py Phase 4.3: Grid auto-creates GridView with rendering property sync 2026-03-19 11:24:47 -04:00
issue_9_rendertexture_resize_test.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_37_simple_test.py update tests: new scene API 2026-01-03 10:59:52 -05:00
issue_76_test.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_79_color_properties_test.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_99_texture_font_properties_test.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_123_chunk_system_test.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_146_fov_returns_none.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_147_grid_layers.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_148_layer_dirty_flags.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_176_entity_position_test.py Phase 2: Entity data model extensions for behavior system 2026-03-15 22:05:06 -04:00
issue_177_gridpoint_grid_pos_test.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_179_181_grid_vectors_test.py Remove redundant Grid.position alias, keep only Grid.pos, closes #308 2026-04-09 22:18:30 -04:00
issue_180_timer_orphan_test.py Organize test suite: add README, move loose tests to proper directories 2026-01-21 21:34:22 -05:00
issue_180_timer_stopped_test.py Organize test suite: add README, move loose tests to proper directories 2026-01-21 21:34:22 -05:00
issue_182_caption_size_test.py Organize test suite: add README, move loose tests to proper directories 2026-01-21 21:34:22 -05:00
issue_183_parent_quirks_test.py tests for the last few issues (these test scripts should work with recent APIs, while the rest of the test suite needs an overhaul) 2026-01-08 10:31:21 -05:00
issue_184_189_module_test.py Organize test suite: add README, move loose tests to proper directories 2026-01-21 21:34:22 -05:00
issue_185_188_bounds_test.py Organize test suite: add README, move loose tests to proper directories 2026-01-21 21:34:22 -05:00
issue_190_layer_docs_test.py Test suite modernization 2026-02-09 08:15:18 -05:00
issue_212_to_217_test.py Add input validation and fix Entity repr 2026-01-16 19:18:27 -05:00
issue_223_clip_children_test.py Fix UIFrame RenderTexture positioning and toggling issues 2026-01-22 22:54:50 -05:00
issue_251_callback_gc_test.py Fix callback/timer GC: prevent premature destruction of Python callbacks 2026-02-19 20:53:50 -05:00
issue_251_timer_gc_test.py Fix callback/timer GC: prevent premature destruction of Python callbacks 2026-02-19 20:53:50 -05:00
issue_253_spatial_hash_test.py Phase 1: Safety & performance foundation for Grid/Entity overhaul 2026-03-15 21:48:24 -04:00
issue_254_tilelayer_texture_test.py Phase 1: Safety & performance foundation for Grid/Entity overhaul 2026-03-15 21:48:24 -04:00
issue_256_animation_spatial_hash_test.py Update spatial hash in animation setProperty for entity position, closes #256 2026-04-10 01:40:29 -04:00
issue_258_gridstate_resize_test.py Fix gridstate heap overflows and spatial hash cleanup 2026-03-07 22:56:16 -05:00
issue_264_gridpoint_dangle_test.py Convert raw pointers to coordinate-based access (closes #264, closes #265) 2026-03-07 23:30:32 -05:00
issue_266_entity_lifecycle_test.py Remove entity self-reference cycle 2026-03-07 23:22:58 -05:00
issue_266_subclass_identity_test.py Preserve Python subclass identity for entities in grids (reopens #266) 2026-03-09 00:24:26 -04:00
issue_267_275_refcount_test.py Add regression tests for GridPointState dangle and refcount leaks, refs #287 2026-04-10 02:06:10 -04:00
issue_268_vector_null_test.py Add regression tests for vector NULL safety and uniform owner validity, closes #287 2026-04-10 02:57:32 -04:00
issue_270_277_parent_grid_dangle_test.py Null parent_grid pointers in GridData destructor, closes #270, closes #271, closes #277 2026-04-10 01:34:33 -04:00
issue_272_uniform_owner_test.py Add regression tests for vector NULL safety and uniform owner validity, closes #287 2026-04-10 02:57:32 -04:00
issue_273_die_during_iteration_test.py Add regression test for entity.die() during iteration, refs #273 2026-04-10 01:45:23 -04:00
issue_274_set_grid_spatial_hash_test.py Add missing spatial_hash.insert() in set_grid() grid transfer, closes #274 2026-04-10 01:45:18 -04:00
issue_288_291_dirty_flags_test.py Add missing markDirty()/markCompositeDirty() to all Python property setters 2026-04-10 01:01:41 -04:00
issue_292_fov_dedup_test.py Phase 1: Safety & performance foundation for Grid/Entity overhaul 2026-03-15 21:48:24 -04:00
issue_294_perspective_map_test.py Replace UIEntity gridstate with DiscreteMap perspective_map; closes #294 2026-04-17 23:04:27 -04:00
issue_295_cell_pos_test.py Phase 2: Entity data model extensions for behavior system 2026-03-15 22:05:06 -04:00
issue_307_color_eq_test.py Fix audit type count (44->46) and add regression test for Color __eq__, refs #307 2026-04-09 21:45:12 -04:00
issue_309_caption_numeric_setter_test.py Clamp Caption numeric setters to prevent UBSan float->uint UB 2026-04-16 23:31:58 -04:00
issue_310_compute_fov_enum_test.py Route Grid.compute_fov algorithm through PyFOV::from_arg 2026-04-16 23:32:09 -04:00
issue_311_dijkstra_bounds_test.py Bounds-check DijkstraMap coordinates at the Python boundary 2026-04-16 23:32:19 -04:00
issue_313_entity_grid_data_test.py refactor(grid): GridData is a map, not a widget -- delete UIGrid's drawable half 2026-07-13 07:14:43 -04:00
issue_315_path_provider_test.py Refactor EntityBehavior SEEK/FLEE to use PathProvider strategy; refs #315 2026-04-18 09:19:05 -04:00
issue_316_sparse_perspective_test.py Windowed perspective writeback in UIEntity::updateVisibility; closes #316 2026-06-21 09:40:05 -04:00
issue_317_scroll_position_test.py Fix verify-pass code bugs #317/#318/#319 2026-06-21 10:12:41 -04:00
issue_318_gridview_texture_test.py Fix verify-pass code bugs #317/#318/#319 2026-06-21 10:12:41 -04:00
issue_319_visible_entities_radius_none_test.py Fix verify-pass code bugs #317/#318/#319 2026-06-21 10:12:41 -04:00
issue_320_caption_positional_font_test.py Add read-only Caption.font getter; addresses #320 2026-06-21 12:18:53 -04:00
issue_322_terrain_enum_bad_utf8_test.py Check Python C-API returns in terrain_enum builders; closes #322 2026-06-26 23:52:38 -04:00
issue_323_pitch_shift_nonfinite_test.py Reject non-finite floats before int casts; closes #323, closes #324, closes #325 2026-06-26 23:53:02 -04:00
issue_324_hsl_shift_nonfinite_test.py Reject non-finite floats before int casts; closes #323, closes #324, closes #325 2026-06-26 23:53:02 -04:00
issue_325_vector_int_nonfinite_test.py Reject non-finite floats before int casts; closes #323, closes #324, closes #325 2026-06-26 23:53:02 -04:00
issue_329_entity_index_perf_test.py Add tests pinning EntityCollection semantics and O(1) indexing (#329) 2026-07-02 20:13:18 -04:00
issue_332_soa_storage_test.py refactor(grid): GridData SoA -- dense uint8 planes for walkable/transparent; closes #332 2026-07-11 01:43:30 -04:00
issue_334_discretemap_buffer_test.py feat(discretemap): buffer protocol for zero-copy numpy views; closes #334 2026-07-11 01:00:53 -04:00
issue_335_layer_edit_test.py feat(grid): numpy buffer views for ColorLayer/TileLayer via layer.edit(); closes #335 2026-07-11 02:04:42 -04:00
issue_338_drawable_footprint_test.py perf(grid): lazily allocate rotationTexture; footprint measurement; addresses #338 2026-07-11 01:31:18 -04:00
issue_342_animation_float_fastpath_test.py perf(animation): scalar-float fast path skipping variant visits; closes #342 2026-07-10 22:59:28 -04:00
issue_344_key_enum_cache_test.py perf(input): cache Key/InputState enum members per event; closes #344 2026-07-10 22:59:47 -04:00
issue_348_gridview_wrapper_identity_test.py perf(grid): cache internal Grid wrapper in GridView; closes #348 2026-07-10 22:59:17 -04:00
issue_351_gridview_early_out_test.py perf(grid): clean-state render early-out for UIGridView; closes #351 2026-07-11 00:55:32 -04:00
issue_351_step_movement_render_test.py fix(grid): turn manager invalidates view render cache on entity move; addresses #351 2026-07-11 10:15:36 -04:00
issue_355_camera_rotation_hit_test.py fix(grid): revive Grid input — move cell callbacks and hit-testing to GridView; N-view registry 2026-07-12 18:01:40 -04:00
issue_355_grid_cell_dispatch_test.py fix(grid): revive Grid input — move cell callbacks and hit-testing to GridView; N-view registry 2026-07-12 18:01:40 -04:00
issue_355_grid_input_test.py fix(grid): revive Grid input — move cell callbacks and hit-testing to GridView; N-view registry 2026-07-12 18:01:40 -04:00
issue_355_gridview_position_sync_test.py fix(grid): revive Grid input — move cell callbacks and hit-testing to GridView; N-view registry 2026-07-12 18:01:40 -04:00
issue_355_perspective_overlay_test.py fix(grid): revive Grid input — move cell callbacks and hit-testing to GridView; N-view registry 2026-07-12 18:01:40 -04:00
issue_357_find_in_grid_test.py fix(grid): find()/findAll() descend into grids again 2026-07-12 18:02:04 -04:00
issue_359_shared_griddata_test.py refactor(grid): GridData is a map, not a widget -- delete UIGrid's drawable half 2026-07-13 07:14:43 -04:00
issue_361_griddata_is_not_a_widget_test.py refactor(grid): GridData is a map, not a widget -- delete UIGrid's drawable half 2026-07-13 07:14:43 -04:00
issue_363_hover_exit_on_window_leave_test.py fix(input): dispatch hover-exit when the cursor leaves the window 2026-07-12 21:12:58 -04:00
issue_364_grid_children_on_view_test.py fix(bindings): route every drawable wrapper through PythonObjectCache 2026-07-13 23:37:01 -04:00
issue_365_stale_clicked_cell_test.py fix(grid): never dispatch a stale cell from UIGridView::click_at 2026-07-12 20:26:59 -04:00
issue_366_collection_repr_grid_test.py fix(grid): UICollection.repr names Grids again instead of "UIDrawable" 2026-07-12 20:26:32 -04:00
issue_367_hover_exit_on_focus_loss_test.py fix(render): content invalidation propagates again; clear hover on focus loss 2026-07-13 07:40:20 -04:00
issue_368_cache_subtree_content_dirty_test.py fix(render): content invalidation propagates again; clear hover on focus loss 2026-07-13 07:40:20 -04:00
issue_369_parent_identity_test.py fix(bindings): route every drawable wrapper through PythonObjectCache 2026-07-13 23:37:01 -04:00
issue_callback_refcount_test.py Simplify on_enter/on_exit callbacks to position-only signature 2026-01-28 17:36:02 -05:00
parent_none_removal_test.py Add regression tests for Frame.children mutation and parent=None removal 2026-04-01 11:27:47 -04:00
recursive_animation_callback_segfault.py fix: animations modifying animations during callback is now safe 2026-02-04 10:25:59 -05:00
subclass_callback_segfault_test.py Remove legacy string enum comparisons from InputState/Key/MouseButton, closes #306 2026-04-09 22:19:02 -04:00
test_type_preservation_solution.py Test suite modernization 2026-02-09 08:15:18 -05:00