"""Python.NET runtime loading and configuration"""
import sys
from pathlib import Path
from typing import Dict, Optional, Union, Any
import clr_loader
__all__ = ["set_runtime", "set_runtime_from_env", "load", "unload", "get_runtime_info"]
_RUNTIME: Optional[clr_loader.Runtime] = None
_LOADER_ASSEMBLY: Optional[clr_loader.Assembly] = None
_LOADED: bool = False
def set_runtime(runtime: Union[clr_loader.Runtime, str], **params: str) -> None:
"""Set up a clr_loader runtime without loading it
:param runtime:
Either an already initialised `clr_loader` runtime, or one of netfx,
coreclr, mono, or default. If a string parameter is given, the runtime
will be created.
"""
global _RUNTIME
if _LOADED:
raise RuntimeError(f"The runtime {_RUNTIME} has already been loaded")
if isinstance(runtime, str):
runtime = _create_runtime_from_spec(runtime, params)
_RUNTIME = runtime
def get_runtime_info() -> Optional[clr_loader.RuntimeInfo]:
"""Retrieve information on the configured runtime"""
if _RUNTIME is None:
return None
else:
return _RUNTIME.info()
def _get_params_from_env(prefix: str) -> Dict[str, str]:
from os import environ
full_prefix = f"PYTHONNET_{prefix.upper()}_"
len_ = len(full_prefix)
env_vars = {
(k[len_:].lower()): v
for k, v in environ.items()
if k.upper().startswith(full_prefix)
}
return env_vars
def _create_runtime_from_spec(
spec: str, params: Optional[Dict[str, Any]] = None
) -> clr_loader.Runtime:
was_default = False
if spec == "default":
was_default = True
if sys.platform == "win32":
spec = "netfx"
else:
spec = "mono"
params = params or _get_params_from_env(spec)
try:
if spec == "netfx":
return clr_loader.get_netfx(**params)
elif spec == "mono":
return clr_loader.get_mono(**params)
elif spec == "coreclr":
return clr_loader.get_coreclr(**params)
else:
raise RuntimeError(f"Invalid runtime name: '{spec}'")
except Exception as exc:
if was_default:
raise RuntimeError(
f"""Failed to create a default .NET runtime, which would
have been "{spec}" on this system. Either install a
compatible runtime or configure it explicitly via
`set_runtime` or the `PYTHONNET_*` environment variables
(see set_runtime_from_env)."""
) from exc
else:
raise RuntimeError(
f"""Failed to create a .NET runtime ({spec}) using the
parameters {params}."""
) from exc
def set_runtime_from_env() -> None:
"""Set up the runtime using the environment
This will use the environment variable PYTHONNET_RUNTIME to decide the
runtime to use, which may be one of netfx, coreclr or mono. The parameters
of the respective clr_loader.get_