1
- from argparse import Namespace
2
1
from typing import TextIO , Dict , Any , Optional
3
2
4
3
import os
5
4
import argparse
6
5
from os .path import expanduser
7
6
import toml
7
+ from colorama import Fore
8
+
9
+ from atcodertools .common .language import Language
8
10
from atcodertools .common .logging import logger
9
11
10
- from atcodertools .codegen .code_style_config import CodeStyleConfig
12
+ from atcodertools .codegen .code_style_config import CodeStyleConfig , DEFAULT_LANGUAGE
11
13
from atcodertools .config .etc_config import EtcConfig
12
14
from atcodertools .config .postprocess_config import PostprocessConfig
15
+ from atcodertools .config .run_config import RunConfig
13
16
from atcodertools .tools import get_default_config_path
17
+ from atcodertools .tools .utils import with_color
18
+
19
+ _POST_PROCESS_CONFIG_KEY = "postprocess"
20
+
21
+ _CODE_STYLE_CONFIG_KEY = "codestyle"
22
+
23
+ _RUN_CONFIG_KEY = "run"
24
+
25
+
26
+ class ProgramArgs :
27
+ def __init__ (
28
+ self ,
29
+ template : Optional [str ] = None ,
30
+ workspace : Optional [str ] = None ,
31
+ without_login : Optional [bool ] = None ,
32
+ parallel : Optional [bool ] = None ,
33
+ save_no_session_cache : Optional [bool ] = None ,
34
+ lang : Optional [str ] = None ,
35
+ compile_before_testing : Optional [bool ] = None ,
36
+ compile_only_when_diff_detected : Optional [bool ] = None
37
+ ):
38
+ self .template = template
39
+ self .workspace = workspace
40
+ self .without_login = without_login
41
+ self .parallel = parallel
42
+ self .save_no_session_cache = save_no_session_cache
43
+ self .lang = lang
44
+ self .compile_before_testing = compile_before_testing
45
+ self .compile_only_when_diff_detected = compile_only_when_diff_detected
46
+
47
+ @classmethod
48
+ def load (cls , program_args : argparse .Namespace ):
49
+ return ProgramArgs (
50
+ ** {k : v for k , v in program_args .__dict__ .items () if k in (
51
+ "template" ,
52
+ "workspace" ,
53
+ "without_login" ,
54
+ "parallel" ,
55
+ "save_no_session_cache" ,
56
+ "lang" ,
57
+ "compile_before_testing" ,
58
+ "compile_only_when_diff_detected"
59
+ )})
14
60
15
61
16
62
def _update_config_dict (target_dic : Dict [str , Any ], update_dic : Dict [str , Any ]):
@@ -25,66 +71,101 @@ class Config:
25
71
def __init__ (self ,
26
72
code_style_config : CodeStyleConfig = CodeStyleConfig (),
27
73
postprocess_config : PostprocessConfig = PostprocessConfig (),
28
- etc_config : EtcConfig = EtcConfig ()
74
+ etc_config : EtcConfig = EtcConfig (),
75
+ run_config : RunConfig = RunConfig ()
29
76
):
30
77
self .code_style_config = code_style_config
31
78
self .postprocess_config = postprocess_config
32
79
self .etc_config = etc_config
80
+ self .run_config = run_config
33
81
34
82
@classmethod
35
- def load (cls , fp : TextIO , args : Optional [Namespace ] = None ):
83
+ def load (cls , fp : TextIO , args : Optional [ProgramArgs ] = None ):
36
84
"""
37
85
:param fp: .toml file's file pointer
38
86
:param args: command line arguments
39
87
:return: Config instance
40
88
"""
41
89
config_dic = toml .load (fp )
90
+ # Root 'codestyle' is common code style
91
+ common_code_style_config_dic = config_dic .get (
92
+ _CODE_STYLE_CONFIG_KEY , {})
42
93
43
- code_style_config_dic = config_dic .get ('codestyle' , {})
44
- postprocess_config_dic = config_dic .get ('postprocess' , {})
94
+ postprocess_config_dic = config_dic .get (_POST_PROCESS_CONFIG_KEY , {})
45
95
etc_config_dic = config_dic .get ('etc' , {})
96
+ run_config_dic = config_dic .get (_RUN_CONFIG_KEY , {})
97
+ code_style_config_dic = {** common_code_style_config_dic }
98
+
99
+ # Handle config override strategy in the following code
100
+ # (Most preferred) program arguments > lang-specific > common config (Least preferred)
101
+ lang = (args and args .lang ) or common_code_style_config_dic .get (
102
+ "lang" , DEFAULT_LANGUAGE )
103
+ code_style_config_dic = _update_config_dict (
104
+ code_style_config_dic , dict (lang = lang ))
105
+
106
+ if lang in config_dic :
107
+ lang_specific_config_dic = config_dic [lang ] # e.g. [cpp.codestyle]
108
+ if _CODE_STYLE_CONFIG_KEY in lang_specific_config_dic :
109
+ lang_code_style = lang_specific_config_dic [_CODE_STYLE_CONFIG_KEY ]
110
+ if "lang" in lang_code_style :
111
+ logger .warn (
112
+ with_color ("'lang' is only valid in common code style config, "
113
+ "but detected in language-specific code style config. It will be ignored." ,
114
+ Fore .RED ))
115
+ del lang_code_style ["lang" ]
116
+
117
+ code_style_config_dic = _update_config_dict (code_style_config_dic ,
118
+ lang_code_style )
119
+
120
+ # e.g. [cpp.postprocess]
121
+ if _POST_PROCESS_CONFIG_KEY in lang_specific_config_dic :
122
+ postprocess_config_dic = _update_config_dict (postprocess_config_dic ,
123
+ lang_specific_config_dic [_POST_PROCESS_CONFIG_KEY ])
124
+
125
+ if _RUN_CONFIG_KEY in lang_specific_config_dic : # e.g. [cpp.run]
126
+ run_config_dic = _update_config_dict (run_config_dic ,
127
+ lang_specific_config_dic [_RUN_CONFIG_KEY ])
46
128
47
129
if args :
48
- d = dict ()
49
- if hasattr (args , 'template' ):
50
- d ['template_file' ] = args .template
51
- if hasattr (args , 'workspace' ):
52
- d ['workspace_dir' ] = args .workspace
53
- if hasattr (args , 'lang' ):
54
- d ['lang' ] = args .lang
55
130
code_style_config_dic = _update_config_dict (
56
- code_style_config_dic , d )
57
-
58
- lang = code_style_config_dic ['lang' ]
59
- if lang in config_dic :
60
- code_style_config_dic = _update_config_dict (
61
- code_style_config_dic , config_dic [lang ])
62
-
63
- d = dict ()
64
- if hasattr (args , 'without_login' ):
65
- d ['download_without_login' ] = args .without_login
66
- if hasattr (args , 'parallel' ):
67
- d ['parallel_download' ] = args .parallel
68
- if hasattr (args , 'save_no_session_cache' ):
69
- d ['save_no_session_cache' ] = args .save_no_session_cache
70
-
71
- etc_config_dic = _update_config_dict (etc_config_dic , d )
131
+ code_style_config_dic ,
132
+ dict (template_file = args .template ,
133
+ workspace_dir = args .workspace )
134
+ )
135
+ etc_config_dic = _update_config_dict (
136
+ etc_config_dic ,
137
+ dict (
138
+ download_without_login = args .without_login ,
139
+ parallel_download = args .parallel ,
140
+ save_no_session_cache = args .save_no_session_cache ,
141
+ compile_before_testing = args .compile_before_testing ,
142
+ compile_only_when_diff_detected = args .compile_only_when_diff_detected
143
+ )
144
+ )
145
+
72
146
return Config (
73
147
code_style_config = CodeStyleConfig (** code_style_config_dic ),
74
148
postprocess_config = PostprocessConfig (** postprocess_config_dic ),
75
- etc_config = EtcConfig (** etc_config_dic )
149
+ etc_config = EtcConfig (** etc_config_dic ),
150
+ run_config = RunConfig (** run_config_dic )
76
151
)
77
152
78
153
79
154
USER_CONFIG_PATH = os .path .join (
80
155
expanduser ("~" ), ".atcodertools.toml" )
81
156
82
157
83
- def get_config (args : argparse .Namespace ) -> Config :
158
+ def get_config (args : argparse .Namespace , language : Language = None ) -> Config :
84
159
def _load (path : str ) -> Config :
85
160
logger .info ("Going to load {} as config" .format (path ))
86
161
with open (path , 'r' ) as f :
87
- return Config .load (f , args )
162
+ program_args = ProgramArgs .load (args )
163
+
164
+ if language is not None :
165
+ assert program_args .lang is None
166
+ program_args .lang = language .name
167
+
168
+ return Config .load (f , program_args )
88
169
89
170
if args .config :
90
171
return _load (args .config )
0 commit comments