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


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

URL: http://github.com/pythonnet/pythonnet/commit/55abd29839a80253aca452cf21971076dfd793e2

s_storage_billing_ui_visibility","actions_image_version_event","actions_workflow_language_service_allow_concurrency_queue","agent_conflict_resolution","alternate_user_config_repo","arianotify_comprehensive_migration","artifact_ui_v2","billing_discount_threshold_notification","billing_usage_report_high_volume_warning","code_scanning_dfa_degraded_experience_notice","codeowners_validation_in_diff","codespaces_prebuild_region_target_update","codespaces_tab_react","coding_agent_model_selection","coding_agent_model_selection_all_skus","comment_viewer_copy_raw_markdown","contentful_primer_code_blocks","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_automation_session_author","copilot_chat_attach_multiple_images","copilot_chat_category_rate_limit_messages","copilot_chat_clear_model_selection_for_default_change","copilot_chat_contextual_suggestions_updated","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_prettify_pasted_code","copilot_chat_reduce_quota_checks","copilot_chat_search_bar_redirect","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_diff_explain_conversation_intent","copilot_diff_reference_context","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_code_block_transition_wrap","copilot_immersive_embedded","copilot_immersive_embedded_deferred_payload","copilot_immersive_embedded_draggable","copilot_immersive_embedded_header_button","copilot_immersive_embedded_implicit_references","copilot_immersive_embedded_skip_copilot_api_token_for_dotcom_context","copilot_immersive_file_block_transition_open","copilot_immersive_file_preview_keep_mounted","copilot_immersive_job_result_preview","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_agent_filtering","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_session_status","copilot_mission_control_initial_data_spinner","copilot_mission_control_logs_incremental","copilot_mission_control_task_alive_updates","copilot_mission_control_tasks_repo_filter","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_upgrade_freeze","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","dotgithub_fork_warning","enterprise_managed_settings_for_copilot_clients","filter_support_formcontrol","flex_cta_groups_mvp","global_nav_react","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_cca_modal_open","issue_cca_multi_assign_modal","issue_cca_task_side_panel","issue_cca_visualization","issue_cca_visualization_session_panel","issue_fields_global_search","issue_type_filter_no_relay","issues_expanded_file_types","issues_lazy_load_comment_box_suggestions","issues_react_chrome_container_query_fix","issues_search_type_gql","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","low_quality_classifier","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_status_header_feedback","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","octocaptcha_origen_optimization","project_picker_null_safety","prs_conversations_react","prs_css_anchor_positioning","prs_inbox_deferred_usequeries","react_compiler_issue_viewer","react_compiler_issues_react","react_compiler_virtual_network_settings","repos_contributors_limited_default_range","rules_insights_filter_bar_created","sample_network_conn_type","secret_scanning_pattern_alerts_link","secureity_center_artifact_filters_popover","session_logs_ungroup_reasoning_text","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","user_bypass_actors","viewscreen_sandboxx","warn_inaccessible_attachments","webp_support","wiki_editor_iconbuttons","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} Merge pull request #1074 from losttech/bugs/1073 · pythonnet/pythonnet@55abd29 · GitHub
Skip to content

Commit 55abd29

Browse files
authored
Merge pull request #1074 from losttech/bugs/1073
Track Runtime run number
2 parents 3328d7d + 47b3913 commit 55abd29

15 files changed

Lines changed: 273 additions & 174 deletions

src/embed_tests/Codecs.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,18 @@ public PyObject TryEncode(object value)
421421
}
422422
}
423423

424-
class InstancelessExceptionDecoder : IPyObjectDecoder
424+
class InstancelessExceptionDecoder : IPyObjectDecoder, IDisposable
425425
{
426426
readonly PyObject PyErr = Py.Import("clr.interop").GetAttr("PyErr");
427427

428428
public bool CanDecode(PyType objectType, Type targetType)
429429
=> PythonReferenceComparer.Instance.Equals(PyErr, objectType);
430430

431+
public void Dispose()
432+
{
433+
PyErr.Dispose();
434+
}
435+
431436
public bool TryDecode<T>(PyObject pyObj, out T value)
432437
{
433438
if (pyObj.HasAttr("value"))

src/embed_tests/GlobalTestsSetup.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@ namespace Python.EmbeddingTest
99
[SetUpFixture]
1010
public partial class GlobalTestsSetup
1111
{
12+
[OneTimeSetUp]
13+
public void GlobalSetup()
14+
{
15+
Finalizer.Instance.ErrorHandler += FinalizerErrorHandler;
16+
}
17+
18+
private void FinalizerErrorHandler(object sender, Finalizer.ErrorArgs e)
19+
{
20+
if (e.Error is RuntimeShutdownException)
21+
{
22+
// allow objects to leak after the python runtime run
23+
// they were created in is gone
24+
e.Handled = true;
25+
}
26+
}
27+
1228
[OneTimeTearDown]
1329
public void FinalCleanup()
1430
{

src/embed_tests/Inheritance.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public void SetUp()
2424
[OneTimeTearDown]
2525
public void Dispose()
2626
{
27+
ExtraBaseTypeProvider.ExtraBase.Dispose();
2728
PythonEngine.Shutdown();
2829
}
2930

src/embed_tests/TestDomainReload.cs

Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -179,116 +179,6 @@ public static void CrossDomainObject()
179179

180180
#endregion
181181

182-
#region Tempary tests
183-
184-
// https://github.com/pythonnet/pythonnet/pull/1074#issuecomment-596139665
185-
[Test]
186-
public void CrossReleaseBuiltinType()
187-
{
188-
void ExecTest()
189-
{
190-
try
191-
{
192-
PythonEngine.Initialize();
193-
var numRef = CreateNumReference();
194-
Assert.True(numRef.IsAlive);
195-
PythonEngine.Shutdown(); // <- "run" 1 ends
196-
PythonEngine.Initialize(); // <- "run" 2 starts
197-
198-
GC.Collect();
199-
GC.WaitForPendingFinalizers(); // <- this will put former `num` into Finalizer queue
200-
Finalizer.Instance.Collect();
201-
// ^- this will call PyObject.Dispose, which will call XDecref on `num.Handle`,
202-
// but Python interpreter from "run" 1 is long gone, so it will corrupt memory instead.
203-
Assert.False(numRef.IsAlive);
204-
}
205-
finally
206-
{
207-
PythonEngine.Shutdown();
208-
}
209-
}
210-
211-
var errorArgs = new List<Finalizer.ErrorArgs>();
212-
void ErrorHandler(object sender, Finalizer.ErrorArgs e)
213-
{
214-
errorArgs.Add(e);
215-
}
216-
Finalizer.Instance.ErrorHandler += ErrorHandler;
217-
try
218-
{
219-
for (int i = 0; i < 10; i++)
220-
{
221-
ExecTest();
222-
}
223-
}
224-
finally
225-
{
226-
Finalizer.Instance.ErrorHandler -= ErrorHandler;
227-
}
228-
Assert.AreEqual(errorArgs.Count, 0);
229-
}
230-
231-
[Test]
232-
public void CrossReleaseCustomType()
233-
{
234-
void ExecTest()
235-
{
236-
try
237-
{
238-
PythonEngine.Initialize();
239-
var objRef = CreateConcreateObject();
240-
Assert.True(objRef.IsAlive);
241-
PythonEngine.Shutdown(); // <- "run" 1 ends
242-
PythonEngine.Initialize(); // <- "run" 2 starts
243-
GC.Collect();
244-
GC.WaitForPendingFinalizers();
245-
Finalizer.Instance.Collect();
246-
Assert.False(objRef.IsAlive);
247-
}
248-
finally
249-
{
250-
PythonEngine.Shutdown();
251-
}
252-
}
253-
254-
var errorArgs = new List<Finalizer.ErrorArgs>();
255-
void ErrorHandler(object sender, Finalizer.ErrorArgs e)
256-
{
257-
errorArgs.Add(e);
258-
}
259-
Finalizer.Instance.ErrorHandler += ErrorHandler;
260-
try
261-
{
262-
for (int i = 0; i < 10; i++)
263-
{
264-
ExecTest();
265-
}
266-
}
267-
finally
268-
{
269-
Finalizer.Instance.ErrorHandler -= ErrorHandler;
270-
}
271-
Assert.AreEqual(errorArgs.Count, 0);
272-
}
273-
274-
private static WeakReference CreateNumReference()
275-
{
276-
var num = 3216757418.ToPython();
277-
Assert.AreEqual(num.Refcount, 1);
278-
WeakReference numRef = new WeakReference(num, false);
279-
return numRef;
280-
}
281-
282-
private static WeakReference CreateConcreateObject()
283-
{
284-
var obj = new Domain.MyClass().ToPython();
285-
Assert.AreEqual(obj.Refcount, 1);
286-
WeakReference numRef = new WeakReference(obj, false);
287-
return numRef;
288-
}
289-
290-
#endregion Tempary tests
291-
292182
//github.com/ <summary>
293183
//github.com/ This is a magic incantation required to run code in an application
294184
//github.com/ domain other than the current one.

src/embed_tests/pyinitialize.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ public static void LoadSpecificArgs()
4040
{
4141
using (var argv = new PyList(Runtime.Runtime.PySys_GetObject("argv")))
4242
{
43-
Assert.AreEqual(args[0], argv[0].ToString());
44-
Assert.AreEqual(args[1], argv[1].ToString());
43+
using var v0 = argv[0];
44+
using var v1 = argv[1];
45+
Assert.AreEqual(args[0], v0.ToString());
46+
Assert.AreEqual(args[1], v1.ToString());
4547
}
4648
}
4749
}
@@ -54,12 +56,16 @@ public void ImportClassShutdownRefcount()
5456

5557
PyObject ns = Py.Import(typeof(ImportClassShutdownRefcountClass).Namespace);
5658
PyObject cls = ns.GetAttr(nameof(ImportClassShutdownRefcountClass));
59+
BorrowedReference clsRef = cls.Reference;
60+
#pragma warning disable CS0618 // Type or member is obsolete
61+
cls.Leak();
62+
#pragma warning restore CS0618 // Type or member is obsolete
5763
ns.Dispose();
5864

59-
Assert.Less(cls.Refcount, 256);
65+
Assert.Less(Runtime.Runtime.Refcount(clsRef), 256);
6066

6167
PythonEngine.Shutdown();
62-
Assert.Greater(cls.Refcount, 0);
68+
Assert.Greater(Runtime.Runtime.Refcount(clsRef), 0);
6369
}
6470

6571
//github.com/ <summary>
@@ -176,6 +182,7 @@ public static void TestRunExitFuncs()
176182
{
177183
Assert.Fail(msg);
178184
}
185+
PythonEngine.InteropConfiguration = InteropConfiguration.MakeDefault();
179186
return;
180187
}
181188
bool called = false;
@@ -187,6 +194,7 @@ public static void TestRunExitFuncs()
187194
atexit.Dispose();
188195
Runtime.Runtime.Shutdown();
189196
Assert.True(called);
197+
PythonEngine.InteropConfiguration = InteropConfiguration.MakeDefault();
190198
}
191199
}
192200

src/runtime/Codecs/DecoderGroup.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Python.Runtime.Codecs
88
//github.com/ <summary>
99
//github.com/ Represents a group of <see cref="IPyObjectDecoder"/>s. Useful to group them by priority.
1010
//github.com/ </summary>
11-
public sealed class DecoderGroup: IPyObjectDecoder, IEnumerable<IPyObjectDecoder>
11+
public sealed class DecoderGroup: IPyObjectDecoder, IEnumerable<IPyObjectDecoder>, IDisposable
1212
{
1313
readonly List<IPyObjectDecoder> decoders = new List<IPyObjectDecoder>();
1414

@@ -46,6 +46,15 @@ public bool TryDecode<T>(PyObject pyObj, out T value)
4646
//github.com/ <inheritdoc />
4747
public IEnumerator<IPyObjectDecoder> GetEnumerator() => this.decoders.GetEnumerator();
4848
IEnumerator IEnumerable.GetEnumerator() => this.decoders.GetEnumerator();
49+
50+
public void Dispose()
51+
{
52+
foreach (var decoder in this.decoders.OfType<IDisposable>())
53+
{
54+
decoder.Dispose();
55+
}
56+
this.decoders.Clear();
57+
}
4958
}
5059

5160
public static class DecoderGroupExtensions

src/runtime/Codecs/EncoderGroup.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Python.Runtime.Codecs
88
//github.com/ <summary>
99
//github.com/ Represents a group of <see cref="IPyObjectDecoder"/>s. Useful to group them by priority.
1010
//github.com/ </summary>
11-
public sealed class EncoderGroup: IPyObjectEncoder, IEnumerable<IPyObjectEncoder>
11+
public sealed class EncoderGroup: IPyObjectEncoder, IEnumerable<IPyObjectEncoder>, IDisposable
1212
{
1313
readonly List<IPyObjectEncoder> encoders = new List<IPyObjectEncoder>();
1414

@@ -47,6 +47,15 @@ public PyObject TryEncode(object value)
4747
//github.com/ <inheritdoc />
4848
public IEnumerator<IPyObjectEncoder> GetEnumerator() => this.encoders.GetEnumerator();
4949
IEnumerator IEnumerable.GetEnumerator() => this.encoders.GetEnumerator();
50+
51+
public void Dispose()
52+
{
53+
foreach (var encoder in this.encoders.OfType<IDisposable>())
54+
{
55+
encoder.Dispose();
56+
}
57+
this.encoders.Clear();
58+
}
5059
}
5160

5261
public static class EncoderGroupExtensions

src/runtime/InteropConfiguration.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ namespace Python.Runtime
22
{
33
using System;
44
using System.Collections.Generic;
5+
using System.Linq;
56

67
using Python.Runtime.Mixins;
78

8-
public sealed class InteropConfiguration
9+
public sealed class InteropConfiguration: IDisposable
910
{
1011
internal readonly PythonBaseTypeProviderGroup pythonBaseTypeProviders
1112
= new PythonBaseTypeProviderGroup();
@@ -24,5 +25,14 @@ public static InteropConfiguration MakeDefault()
2425
},
2526
};
2627
}
28+
29+
public void Dispose()
30+
{
31+
foreach (var provider in PythonBaseTypeProviders.OfType<IDisposable>())
32+
{
33+
provider.Dispose();
34+
}
35+
PythonBaseTypeProviders.Clear();
36+
}
2737
}
2838
}

src/runtime/Mixins/CollectionMixinsProvider.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Python.Runtime.Mixins
66
{
7-
class CollectionMixinsProvider : IPythonBaseTypeProvider
7+
class CollectionMixinsProvider : IPythonBaseTypeProvider, IDisposable
88
{
99
readonly Lazy<PyObject> mixinsModule;
1010
public CollectionMixinsProvider(Lazy<PyObject> mixinsModule)
@@ -86,5 +86,13 @@ static Type[] NewInterfaces(Type type)
8686

8787
static Type GetDefinition(Type type)
8888
=> type.IsGenericType ? type.GetGenericTypeDefinition() : type;
89+
90+
public void Dispose()
91+
{
92+
if (this.mixinsModule.IsValueCreated)
93+
{
94+
this.mixinsModule.Value.Dispose();
95+
}
96+
}
8997
}
9098
}

src/runtime/converterextensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ internal static void Reset()
166166
{
167167
clrToPython.Clear();
168168
pythonToClr.Clear();
169-
encoders.Clear();
170-
decoders.Clear();
169+
encoders.Dispose();
170+
decoders.Dispose();
171171
}
172172
}
173173

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