11import sys
22from pathlib import Path
3- from typing import Dict , Optional , Union
3+ from typing import Dict , Optional , Union , Any
44import clr_loader
55
66__all__ = ["set_runtime" , "set_runtime_from_env" , "load" ]
77
88_RUNTIME : Optional [clr_loader .Runtime ] = None
9- _LOADER_ASSEMBLY : Optional [clr_loader .wrappers . Assembly ] = None
9+ _LOADER_ASSEMBLY : Optional [clr_loader .Assembly ] = None
1010_LOADED : bool = False
1111
1212
@@ -27,6 +27,15 @@ def set_runtime(runtime: Union[clr_loader.Runtime, str], **params: str) -> None:
2727 _RUNTIME = runtime
2828
2929
30+ def get_runtime_info () -> Optional [clr_loader .RuntimeInfo ]:
31+ """Retrieve information on the configured runtime"""
32+
33+ if _RUNTIME is None :
34+ return None
35+ else :
36+ return _RUNTIME .info ()
37+
38+
3039def _get_params_from_env (prefix : str ) -> Dict [str , str ]:
3140 from os import environ
3241
@@ -43,24 +52,41 @@ def _get_params_from_env(prefix: str) -> Dict[str, str]:
4352
4453
4554def _create_runtime_from_spec (
46- spec : str , params : Optional [Dict [str , str ]] = None
55+ spec : str , params : Optional [Dict [str , Any ]] = None
4756) -> clr_loader .Runtime :
57+ was_default = False
4858 if spec == "default" :
59+ was_default = True
4960 if sys .platform == "win32" :
5061 spec = "netfx"
5162 else :
5263 spec = "mono"
5364
5465 params = params or _get_params_from_env (spec )
5566
56- if spec == "netfx" :
57- return clr_loader .get_netfx (** params )
58- elif spec == "mono" :
59- return clr_loader .get_mono (** params )
60- elif spec == "coreclr" :
61- return clr_loader .get_coreclr (** params )
62- else :
63- raise RuntimeError (f"Invalid runtime name: '{ spec } '" )
67+ try :
68+ if spec == "netfx" :
69+ return clr_loader .get_netfx (** params )
70+ elif spec == "mono" :
71+ return clr_loader .get_mono (** params )
72+ elif spec == "coreclr" :
73+ return clr_loader .get_coreclr (** params )
74+ else :
75+ raise RuntimeError (f"Invalid runtime name: '{ spec } '" )
76+ except Exception as exc :
77+ if was_default :
78+ raise RuntimeError (
79+ f"""Failed to create a default .NET runtime, which would
80+ have been "{ spec } " on this system. Either install a
81+ compatible runtime or configure it explicitly via
82+ `set_runtime` or the `PYTHONNET_*` environment variables
83+ (see set_runtime_from_env)."""
84+ ) from exc
85+ else :
86+ raise RuntimeError (
87+ f"""Failed to create a .NET runtime ({ spec } ) using the
88+ parameters { params } ."""
89+ ) from exc
6490
6591
6692def set_runtime_from_env () -> None :
@@ -85,9 +111,7 @@ def set_runtime_from_env() -> None:
85111 set_runtime (runtime )
86112
87113
88- def load (
89- runtime : Union [clr_loader .Runtime , str , None ] = None , ** params : str
90- ) -> None :
114+ def load (runtime : Union [clr_loader .Runtime , str , None ] = None , ** params : str ) -> None :
91115 """Load Python.NET in the specified runtime
92116
93117 The same parameters as for `set_runtime` can be used. By default,
@@ -109,9 +133,9 @@ def load(
109133
110134 dll_path = Path (__file__ ).parent / "runtime" / "Python.Runtime.dll"
111135
112- _LOADER_ASSEMBLY = _RUNTIME .get_assembly (str (dll_path ))
136+ _LOADER_ASSEMBLY = assembly = _RUNTIME .get_assembly (str (dll_path ))
137+ func = assembly .get_function ("Python.Runtime.Loader.Initialize" )
113138
114- func = _LOADER_ASSEMBLY ["Python.Runtime.Loader.Initialize" ]
115139 if func (b"" ) != 0 :
116140 raise RuntimeError ("Failed to initialize Python.Runtime.dll" )
117141
@@ -125,12 +149,12 @@ def unload() -> None:
125149
126150 global _RUNTIME , _LOADER_ASSEMBLY
127151 if _LOADER_ASSEMBLY is not None :
128- func = _LOADER_ASSEMBLY [ "Python.Runtime.Loader.Shutdown" ]
152+ func = _LOADER_ASSEMBLY . get_function ( "Python.Runtime.Loader.Shutdown" )
129153 if func (b"full_shutdown" ) != 0 :
130154 raise RuntimeError ("Failed to call Python.NET shutdown" )
131155
132156 _LOADER_ASSEMBLY = None
133157
134158 if _RUNTIME is not None :
135- # TODO: Add explicit `close` to clr_loader
159+ _RUNTIME . shutdown ()
136160 _RUNTIME = None
0 commit comments