Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit59b8d48

Browse files
committed
Allow configuring .NET runtimes via environment variables
1 parentf5de0bf commit59b8d48

File tree

4 files changed

+141
-74
lines changed

4 files changed

+141
-74
lines changed

‎.github/workflows/ARM.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
run:python -m pytest --runtime mono
4646

4747
-name:Python Tests (.NET Core)
48-
run:python -m pytest --runtimenetcore
48+
run:python -m pytest --runtimecoreclr
4949

5050
-name:Python tests run from .NET
5151
run:dotnet test src/python_tests_runner/

‎.github/workflows/main.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name:Main (x64)
1+
name:Main
22

33
on:
44
push:
@@ -73,9 +73,10 @@ jobs:
7373
if:${{ matrix.os != 'windows' }}
7474
run:pytest --runtime mono
7575

76+
# TODO: Run these tests on Windows x86
7677
-name:Python Tests (.NET Core)
7778
if:${{ matrix.platform == 'x64' }}
78-
run:pytest --runtimenetcore
79+
run:pytest --runtimecoreclr
7980

8081
-name:Python Tests (.NET Framework)
8182
if:${{ matrix.os == 'windows' }}

‎pythonnet/__init__.py

Lines changed: 96 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,115 @@
11
importsys
2+
frompathlibimportPath
3+
fromtypingimportDict,Optional,Union
24
importclr_loader
35

4-
_RUNTIME=None
5-
_LOADER_ASSEMBLY=None
6-
_FFI=None
7-
_LOADED=False
6+
__all__= ["set_runtime","set_default_runtime","load"]
87

8+
_RUNTIME:Optional[clr_loader.Runtime]=None
9+
_LOADER_ASSEMBLY:Optional[clr_loader.wrappers.Assembly]=None
10+
_LOADED:bool=False
11+
12+
13+
defset_runtime(runtime:Union[clr_loader.Runtime,str],**params:str)->None:
14+
"""Set up a clr_loader runtime without loading it
15+
16+
:param runtime: Either an already initialised `clr_loader` runtime, or one
17+
of netfx, coreclr, mono, or default. If a string parameter is given, the
18+
runtime will be created."""
919

10-
defset_runtime(runtime):
1120
global_RUNTIME
1221
if_LOADED:
13-
raiseRuntimeError("The runtime {} has already been loaded".format(_RUNTIME))
22+
raiseRuntimeError(f"The runtime{_RUNTIME} has already been loaded")
23+
24+
ifisinstance(runtime,str):
25+
runtime=_create_runtime_from_spec(runtime,params)
1426

1527
_RUNTIME=runtime
1628

1729

18-
defset_default_runtime()->None:
19-
ifsys.platform=="win32":
20-
set_runtime(clr_loader.get_netfx())
30+
def_get_params_from_env(prefix:str)->Dict[str,str]:
31+
fromosimportenviron
32+
33+
full_prefix=f"PYTHONNET_{prefix.upper()}"
34+
len_=len(full_prefix)
35+
36+
env_vars= {
37+
(k[len_:].lower()):v
38+
fork,vinenviron.items()
39+
ifk.upper().startswith(full_prefix)
40+
}
41+
42+
returnenv_vars
43+
44+
45+
def_create_runtime_from_spec(
46+
spec:str,params:Optional[Dict[str,str]]=None
47+
)->clr_loader.Runtime:
48+
ifspec=="default":
49+
ifsys.platform=="win32":
50+
spec="netfx"
51+
else:
52+
spec="mono"
53+
54+
params=paramsor_get_params_from_env(spec)
55+
56+
ifspec=="netfx":
57+
returnclr_loader.get_netfx(**params)
58+
elifspec=="mono":
59+
returnclr_loader.get_mono(**params)
60+
elifspec=="coreclr":
61+
returnclr_loader.get_coreclr(**params)
2162
else:
22-
set_runtime(clr_loader.get_mono())
63+
raiseRuntimeError(f"Invalid runtime name: '{spec}'")
2364

2465

25-
defload():
26-
global_FFI,_LOADED,_LOADER_ASSEMBLY
66+
defset_default_runtime()->None:
67+
"""Set up the default runtime
68+
69+
This will use the environment variable PYTHONNET_RUNTIME to decide the
70+
runtime to use, which may be one of netfx, coreclr or mono. The parameters
71+
of the respective clr_loader.get_<runtime> functions can also be given as
72+
environment variables, named `PYTHONNET_<RUNTIME>_<PARAM_NAME>`. In
73+
particular, to use `PYTHONNET_RUNTIME=coreclr`, the variable
74+
`PYTHONNET_CORECLR_RUNTIME_CONFIG` has to be set to a valid
75+
`.runtimeconfig.json`.
76+
77+
If no environment variable is specified, a globally installed Mono is used
78+
for all environments but Windows, on Windows the legacy .NET Framework is
79+
used.
80+
"""
81+
fromosimportenviron
82+
83+
print("Set default RUNTIME")
84+
raiseRuntimeError("Shouldn't be called here")
85+
86+
spec=environ.get("PYTHONNET_RUNTIME","default")
87+
runtime=_create_runtime_from_spec(spec)
88+
set_runtime(runtime)
89+
90+
91+
defload(
92+
runtime:Union[clr_loader.Runtime,str]="default",**params:Dict[str,str]
93+
)->None:
94+
"""Load Python.NET in the specified runtime
95+
96+
The same parameters as for `set_runtime` can be used. By default,
97+
`set_default_runtime` is called if no environment has been set yet and no
98+
parameters are passed."""
99+
global_LOADED,_LOADER_ASSEMBLY
27100

28101
if_LOADED:
29102
return
30103

31-
fromos.pathimportjoin,dirname
104+
if_RUNTIMEisNone:
105+
set_runtime(runtime,**params)
32106

33107
if_RUNTIMEisNone:
34-
# TODO: Warn, in the future the runtime must be set explicitly, either
35-
# as a config/env variable or via set_runtime
36-
set_default_runtime()
108+
raiseRuntimeError("No valid runtime selected")
37109

38-
dll_path=join(dirname(__file__),"runtime","Python.Runtime.dll")
110+
dll_path=Path(__file__).parent/"runtime"/"Python.Runtime.dll"
39111

40-
_LOADER_ASSEMBLY=_RUNTIME.get_assembly(dll_path)
112+
_LOADER_ASSEMBLY=_RUNTIME.get_assembly(str(dll_path))
41113

42114
func=_LOADER_ASSEMBLY["Python.Runtime.Loader.Initialize"]
43115
iffunc(b"")!=0:
@@ -48,13 +120,17 @@ def load():
48120
atexit.register(unload)
49121

50122

51-
defunload():
52-
global_RUNTIME
123+
defunload()->None:
124+
"""Explicitly unload a laoded runtime and shut down Python.NET"""
125+
126+
global_RUNTIME,_LOADER_ASSEMBLY
53127
if_LOADER_ASSEMBLYisnotNone:
54128
func=_LOADER_ASSEMBLY["Python.Runtime.Loader.Shutdown"]
55129
iffunc(b"full_shutdown")!=0:
56130
raiseRuntimeError("Failed to call Python.NET shutdown")
57131

132+
_LOADER_ASSEMBLY=None
133+
58134
if_RUNTIMEisnotNone:
59135
# TODO: Add explicit `close` to clr_loader
60136
_RUNTIME=None

‎tests/conftest.py

Lines changed: 41 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,91 +8,83 @@
88
importos
99
importsys
1010
importsysconfig
11+
frompathlibimportPath
1112
fromsubprocessimportcheck_call
1213
fromtempfileimportmkdtemp
1314
importshutil
1415

1516
importpytest
1617

17-
frompythonnetimportset_runtime
18-
1918
# Add path for `Python.Test`
20-
cwd=os.path.dirname(__file__)
21-
fixtures_path=os.path.join(cwd,"fixtures")
22-
sys.path.append(fixtures_path)
19+
cwd=Path(__file__).parent
20+
fixtures_path=cwd/"fixtures"
21+
sys.path.append(str(fixtures_path))
22+
2323

2424
defpytest_addoption(parser):
2525
parser.addoption(
2626
"--runtime",
2727
action="store",
2828
default="default",
29-
help="Must be one of default,netcore, netfx and mono"
29+
help="Must be one of default,coreclr, netfx and mono",
3030
)
3131

32+
3233
collect_ignore= []
3334

35+
3436
defpytest_configure(config):
3537
globalbin_path
3638
if"clr"insys.modules:
3739
# Already loaded (e.g. by the C# test runner), skip build
3840
importclr
41+
3942
clr.AddReference("Python.Test")
4043
return
4144

4245
runtime_opt=config.getoption("runtime")
43-
44-
test_proj_path=os.path.join(cwd,"..","src","testing")
45-
46-
ifruntime_optnotin ["netcore","netfx","mono","default"]:
46+
ifruntime_optnotin ["coreclr","netfx","mono","default"]:
4747
raiseRuntimeError(f"Invalid runtime:{runtime_opt}")
4848

49-
bin_path=mkdtemp()
50-
51-
# tmpdir_factory.mktemp(f"pythonnet-{runtime_opt}")
52-
53-
fw="net6.0"ifruntime_opt=="netcore"else"netstandard2.0"
54-
55-
check_call(["dotnet","publish","-f",fw,"-o",bin_path,test_proj_path])
56-
57-
sys.path.append(bin_path)
58-
59-
ifruntime_opt=="default":
60-
pass
61-
elifruntime_opt=="netfx":
62-
fromclr_loaderimportget_netfx
63-
runtime=get_netfx()
64-
set_runtime(runtime)
65-
elifruntime_opt=="mono":
66-
fromclr_loaderimportget_mono
67-
runtime=get_mono()
68-
set_runtime(runtime)
69-
elifruntime_opt=="netcore":
70-
fromclr_loaderimportget_coreclr
71-
rt_config_path=os.path.join(bin_path,"Python.Test.runtimeconfig.json")
72-
runtime=get_coreclr(rt_config_path)
73-
set_runtime(runtime)
74-
75-
importclr
76-
clr.AddReference("Python.Test")
49+
test_proj_path=cwd.parent/"src/testing"
50+
bin_path=Path(mkdtemp())
7751

78-
soft_mode=False
79-
try:
80-
os.environ['PYTHONNET_SHUTDOWN_MODE']=='Soft'
81-
except:pass
52+
fw="netstandard2.0"
53+
runtime_params= {}
8254

83-
ifconfig.getoption("--runtime")=="netcore"orsoft_mode\
84-
:
55+
ifruntime_opt=="coreclr":
56+
fw="net6.0"
57+
runtime_params["runtime_config"]=str(
58+
bin_path/"Python.Test.runtimeconfig.json"
59+
)
8560
collect_ignore.append("domain_tests/test_domain_reload.py")
8661
else:
87-
domain_tests_dir=os.path.join(os.path.dirname(__file__),"domain_tests")
88-
bin_path=os.path.join(domain_tests_dir,"bin")
89-
build_cmd= ["dotnet","build",domain_tests_dir,"-o",bin_path]
62+
domain_tests_dir=cwd/"domain_tests"
63+
domain_bin_path=domain_tests_dir/"bin"
64+
build_cmd= [
65+
"dotnet",
66+
"build",
67+
str(domain_tests_dir),
68+
"-o",
69+
str(domain_bin_path),
70+
]
9071
is_64bits=sys.maxsize>2**32
9172
ifnotis_64bits:
9273
build_cmd+= ["/p:Prefer32Bit=True"]
9374
check_call(build_cmd)
9475

76+
check_call(
77+
["dotnet","publish","-f",fw,"-o",str(bin_path),str(test_proj_path)]
78+
)
79+
80+
frompythonnetimportload
81+
82+
load(runtime_opt,**runtime_params)
83+
84+
importclr
9585

86+
sys.path.append(str(bin_path))
87+
clr.AddReference("Python.Test")
9688

9789

9890
defpytest_unconfigure(config):
@@ -102,18 +94,16 @@ def pytest_unconfigure(config):
10294
exceptException:
10395
pass
10496

97+
10598
defpytest_report_header(config):
10699
"""Generate extra report headers"""
107100
# FIXME: https://github.com/pytest-dev/pytest/issues/2257
108101
is_64bits=sys.maxsize>2**32
109102
arch="x64"ifis_64bitselse"x86"
110103
ucs=ctypes.sizeof(ctypes.c_wchar)
111104
libdir=sysconfig.get_config_var("LIBDIR")
112-
shared=bool(sysconfig.get_config_var("Py_ENABLE_SHARED"))
113105

114-
header= ("Arch: {arch}, UCS: {ucs}, LIBDIR: {libdir}, "
115-
"Py_ENABLE_SHARED: {shared}".format(**locals()))
116-
returnheader
106+
returnf"Arch:{arch}, UCS:{ucs}, LIBDIR:{libdir}"
117107

118108

119109
@pytest.fixture()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp