1
1
# Python Version: 3.x
2
+ import distutils .version
2
3
import functools
3
4
import json
4
5
import os
5
6
import pathlib
7
+ import shutil
6
8
import subprocess
9
+ import xml .etree .ElementTree as ET
7
10
from logging import getLogger
8
- from turtle import st
9
11
from typing import *
10
- import distutils .version
11
- import shutil
12
- import xml .etree .ElementTree as ET
13
12
14
13
import onlinejudge_verify .languages .special_comments as special_comments
15
14
from onlinejudge_verify .languages .models import Language , LanguageEnvironment
@@ -34,15 +33,13 @@ def _check_dotnet_version() -> None:
34
33
@functools .lru_cache (maxsize = 1 )
35
34
def _check_expander_console () -> None :
36
35
if not shutil .which ('dotnet-source-expand' ):
37
- raise RuntimeError (
38
- '`dotnet-source-expand` not in $PATH. Run `dotnet tool install -g SourceExpander.Console`' )
36
+ raise RuntimeError ('`dotnet-source-expand` not in $PATH. Run `dotnet tool install -g SourceExpander.Console`' )
39
37
command = ['dotnet-source-expand' , 'version' ]
40
38
logger .info ('$ %s' , ' ' .join (command ))
41
39
res = subprocess .check_output (command ).decode ().strip ()
42
40
logger .info ('dotnet-source-expand version: %s' , res )
43
41
if distutils .version .LooseVersion (res ) < distutils .version .LooseVersion ("5" ):
44
- raise RuntimeError (
45
- '`dotnet-source-expand` version must be 5.0.0 or newer. Update SourceExpander.Console. `dotnet tool update -g SourceExpander.Console`' )
42
+ raise RuntimeError ('`dotnet-source-expand` version must be 5.0.0 or newer. Update SourceExpander.Console. `dotnet tool update -g SourceExpander.Console`' )
46
43
47
44
48
45
class EmbeddedLibrary :
@@ -58,7 +55,7 @@ def __repr__(self) -> str:
58
55
def _list_embedded (csproj_path : pathlib .Path ) -> List [EmbeddedLibrary ]:
59
56
_check_expander_console ()
60
57
if csproj_path is None or csproj_path .suffix != ".csproj" :
61
- raise None
58
+ raise RuntimeError ( 'csproj_path must be .csproj' )
62
59
command = ['dotnet-source-expand' , 'library-list' , str (csproj_path )]
63
60
logger .info ('$ %s' , ' ' .join (command ))
64
61
@@ -68,10 +65,7 @@ def enumerate_library(lines: List[str]):
68
65
if len (sp ) >= 2 :
69
66
yield EmbeddedLibrary (sp [0 ], sp [1 ])
70
67
71
- res = list (enumerate_library (
72
- subprocess .check_output (
73
- command , encoding = 'utf-8'
74
- ).strip ().splitlines ()))
68
+ res = list (enumerate_library (subprocess .check_output (command , encoding = 'utf-8' ).strip ().splitlines ()))
75
69
logger .debug ('libraries: %s' , res )
76
70
return res
77
71
@@ -83,8 +77,7 @@ def _check_embedded_existing(csproj_path: pathlib.Path) -> None:
83
77
subprocess .check_output (command )
84
78
l = _list_embedded (csproj_path )
85
79
if len (l ) == 0 :
86
- raise RuntimeError (
87
- 'Library needs SourceExpander.Embedder' )
80
+ raise RuntimeError ('Library needs SourceExpander.Embedder' )
88
81
89
82
90
83
def _check_env (path : pathlib .Path ):
@@ -97,8 +90,7 @@ def _check_env(path: pathlib.Path):
97
90
def _check_no_embedder (csproj_path : pathlib .Path ) -> None :
98
91
root = ET .parse (csproj_path ).getroot ()
99
92
if root .find ('.//PackageReference[@Include="SourceExpander.Embedder"]' ):
100
- logger .error (
101
- " Test project(%s) has `SourceExpander.Embedder` reference. Libraries and tests should not be in same project." , str (csproj_path ))
93
+ logger .error (" Test project(%s) has `SourceExpander.Embedder` reference. Libraries and tests should not be in same project." , str (csproj_path ))
102
94
103
95
104
96
@functools .lru_cache (maxsize = None )
@@ -122,8 +114,7 @@ def _expand_code_dict(csproj_path: pathlib.Path) -> Dict[pathlib.Path, str]:
122
114
command = ['dotnet-source-expand' , 'expand-all' , str (csproj_path )]
123
115
logger .info ('$ %s' , ' ' .join (command ))
124
116
json_res = subprocess .check_output (command )
125
- return {pathlib .Path (t ['FilePath' ]): t ['ExpandedCode' ]
126
- for t in json .loads (json_res )}
117
+ return {pathlib .Path (t ['FilePath' ]): t ['ExpandedCode' ] for t in json .loads (json_res )}
127
118
128
119
129
120
@functools .lru_cache (maxsize = None )
@@ -150,14 +141,12 @@ def _dependency_info_list(csproj_path: pathlib.Path) -> List[DependencyInfo]:
150
141
_check_expander_console ()
151
142
_check_embedded_existing (csproj_path )
152
143
if csproj_path is None or csproj_path .suffix != ".csproj" :
153
- raise None
144
+ raise RuntimeError ( 'csproj_path must be .csproj' )
154
145
155
146
command = ['dotnet-source-expand' , 'dependency' , '-p' , str (csproj_path )]
156
147
logger .info ('$ %s' , ' ' .join (command ))
157
148
res = subprocess .check_output (command )
158
- return json .loads (
159
- res ,
160
- object_hook = lambda d : DependencyInfo (d ['FileName' ], d ['Dependencies' ], set (d ['TypeNames' ])))
149
+ return json .loads (res , object_hook = lambda d : DependencyInfo (d ['FileName' ], d ['Dependencies' ], set (d ['TypeNames' ])))
161
150
162
151
163
152
@functools .lru_cache (maxsize = None )
@@ -174,62 +163,57 @@ def _dependency_info_dict(csproj_path: pathlib.Path) -> Dict[pathlib.Path, Depen
174
163
def _list_dependencies (path : pathlib .Path ) -> List [pathlib .Path ]:
175
164
path = path .resolve ()
176
165
depinfo = _dependency_info_dict (_resolve_csproj (path ))
177
- return [p
178
- for p in (
179
- pathlib .Path (dep )
180
- for dep in depinfo [path ].dependencies
181
- ) if p .exists ()]
166
+ return [p for p in (pathlib .Path (dep ) for dep in depinfo [path ].dependencies ) if p .exists ()]
182
167
183
168
184
169
@functools .lru_cache (maxsize = None )
185
- def _get_target_framework (csproj_path : pathlib .Path ) -> bytes :
170
+ def _get_target_framework (csproj_path : pathlib .Path ) -> str :
186
171
root = ET .parse (csproj_path ).getroot ()
187
172
target = root .findtext ('.//TargetFramework' )
173
+ if target is None :
174
+ raise RuntimeError ('<TargetFramework> is not found' )
188
175
return target
189
176
190
177
191
178
class CSharpLanguageEnvironment (LanguageEnvironment ):
192
179
@staticmethod
193
180
def _create_runner_project (code : bytes , target_framework : str , output_dir ):
194
181
os .makedirs (str (output_dir ), exist_ok = True )
195
- with open (output_dir / 'runner.csproj' , 'w' ) as f :
182
+ with open (output_dir / 'runner.csproj' , 'w' ) as f :
196
183
f .write ('''<Project Sdk="Microsoft.NET.Sdk">
197
184
<PropertyGroup>
198
185
<OutputType>Exe</OutputType>
199
186
<TargetFramework>{}</TargetFramework>
200
187
</PropertyGroup>
201
188
</Project>''' .format (target_framework ))
202
189
203
- with open (output_dir / 'main.cs' , 'wb' ) as f :
190
+ with open (output_dir / 'main.cs' , 'wb' ) as f :
204
191
f .write (code )
205
192
206
193
def compile (self , path : pathlib .Path , * , basedir : pathlib .Path , tempdir : pathlib .Path ) -> None :
207
194
path = path .resolve ()
208
- output_dir = tempdir / 'dotnet'
195
+ output_dir = tempdir / 'dotnet'
209
196
_check_env (path )
210
197
target_framework = _get_target_framework (_resolve_csproj (path ))
211
198
logger .info ('build: TargetFramework = %s' , target_framework )
212
- self ._create_runner_project (
213
- _expand_code (path ), target_framework , output_dir )
199
+ self ._create_runner_project (_expand_code (path ), target_framework , output_dir )
214
200
215
- command = ['dotnet' , 'build' , str (output_dir / 'runner.csproj' ),
216
- '-c' , 'Release' ,
217
- '-o' , str (output_dir / 'bin' )]
201
+ command = ['dotnet' , 'build' , str (output_dir / 'runner.csproj' ), '-c' , 'Release' , '-o' , str (output_dir / 'bin' )]
218
202
logger .info ('$ %s' , ' ' .join (command ))
219
203
subprocess .check_output (command )
220
204
221
205
def get_execute_command (self , path : pathlib .Path , * , basedir : pathlib .Path , tempdir : pathlib .Path ) -> List [str ]:
222
206
path = path .resolve ()
223
- output_dir = tempdir / 'dotnet'
207
+ output_dir = tempdir / 'dotnet'
224
208
path = path .resolve ()
225
209
_check_env (path )
226
- return [str (output_dir / 'bin' / 'runner' )]
210
+ return [str (output_dir / 'bin' / 'runner' )]
227
211
228
212
229
213
class CSharpLanguage (Language ):
230
214
def list_attributes (self , path : pathlib .Path , * , basedir : pathlib .Path ) -> Dict [str , Any ]:
231
215
path = path .resolve ()
232
- attributes = special_comments .list_special_comments (path )
216
+ attributes : Dict [ str , Any ] = special_comments .list_special_comments (path )
233
217
attributes .setdefault ('links' , [])
234
218
attributes ['links' ].extend (special_comments .list_embedded_urls (path ))
235
219
return attributes
0 commit comments