1
- # Copyright (c) 2023 Project CHIP Authors
1
+ #!/usr/local/bin/python3
2
+ # Copyright (c) 2022 Project CHIP Authors
2
3
#
3
4
# Licensed under the Apache License, Version 2.0 (the "License");
4
5
# you may not use this file except in compliance with the License.
17
18
import re
18
19
import yaml
19
20
from typing import Optional
20
-
21
+ from typing import Dict
22
+ from typing import List
23
+ from typing import Union
21
24
22
25
@dataclass
23
26
class Metadata :
@@ -38,27 +41,67 @@ class Metadata:
38
41
39
42
40
43
class Metadata_Reader :
41
- # This class will be initialized with
42
- # the name of the script folder and the environment
43
- # file name
44
+ """
45
+ A class to parse run arguments from the test scripts and
46
+ resolve them to environment specific values.
47
+
48
+ Attributes:
49
+
50
+ env: str
51
+ A dictionary that reprsents a environment configuration in
52
+ YAML format.
53
+ """
44
54
45
- def __init__ (self , script_folder , env_file_name ):
46
- print (env_file_name )
47
- self .script_folder = script_folder
55
+ def __init__ (self , env_file_name : str ):
56
+ """
57
+ Constructs the environment object
58
+
59
+ Parameters:
60
+
61
+ env_file_name: str
62
+ Path to the environment file that contains the YAML configuration.
63
+ """
48
64
self .env = self .__build_env_object__ (env_file_name )
65
+
49
66
50
- # builds the environment object
51
- def __build_env_object__ (self , env_file_name ):
67
+
68
+ def __build_env_object__ (self , env_yaml_file_path : str ) -> Dict [str , Union [str , int , Dict ]]:
69
+ """
70
+ Reads a YAML file and converts it into a dictionary
71
+
72
+ Parameters:
73
+
74
+ env_yaml_file_path: str
75
+ path to the YAML file that contains environment configuration
76
+
77
+ Returns:
78
+ Dict - a Python Dictionary representation of the environment YAML file
52
79
53
- with open (env_file_name ) as stream :
80
+ """
81
+ with open (env_yaml_file_path ) as stream :
54
82
return yaml .safe_load (stream )
55
83
56
- # resolves the run arguments associated with the environment
57
- def __resolve_env_vals__ (self , metadata_dict ):
84
+
85
+ def __resolve_env_vals__ (self , metadata_dict : Dict [str , str ]) -> None :
86
+ """
87
+ Resolves the argument defined in the test script to environment values.
88
+ For example, if a test script defines "all_clusters" as the value for app
89
+ name, we will check the environment configuration to see what raw value is
90
+ assocaited with the "all_cluster" variable and set the value for "app" option
91
+ to this raw value.
92
+
93
+ Parameter:
94
+
95
+ metadata_dict: Dict[str, str]
96
+ Dictionary where each key represent a particular argument and its value represent
97
+ the value for that argument defined in the test script.
58
98
59
- for run_arg in metadata_dict :
99
+ Return :
60
100
61
- run_arg_val = metadata_dict [run_arg ]
101
+ None
102
+ """
103
+
104
+ for run_arg ,run_arg_val in metadata_dict .items ():
62
105
63
106
if not type (run_arg_val )== str or run_arg == "run" :
64
107
metadata_dict [run_arg ]= run_arg_val
@@ -68,6 +111,15 @@ def __resolve_env_vals__(self, metadata_dict):
68
111
continue
69
112
70
113
sub_args = run_arg_val .split ('/' )
114
+
115
+ if len (sub_args ) not in [1 ,2 ]:
116
+ err = """The argument is not in the correct format.
117
+ The argument must follow the format of arg1 or arg1/arg2.
118
+ For example, arg1 represents the argument type and optionally arg2
119
+ represents a specific variable defined in the environment file whose
120
+ value should be used as the argument value. If arg2 is not specified,
121
+ we will just use the first value associated with arg1 in the environment file."""
122
+ raise Exception (err )
71
123
72
124
if len (sub_args )== 1 :
73
125
run_arg_val = self .env .get (sub_args [0 ])
@@ -83,13 +135,57 @@ def __resolve_env_vals__(self, metadata_dict):
83
135
84
136
metadata_dict [run_arg ] = run_arg_val
85
137
138
+
139
+
140
+ def __read_args__ (self ,run_args_lines : List [str ],metadata_dict : Dict [str , str ]) -> None :
141
+ """
142
+ Goes these each raw line in argument header of a test script and extracts argument
143
+ values from it.
144
+
145
+ Parameters:
146
+
147
+ run_args_lines: List[str]
148
+ Raw lines in argument header
86
149
87
- # reads the test script file and parses out the run arguments defined in the file
88
- def __parse_script__ (self , py_script_path , runs_metadata ):
150
+ metadata_dict: Dict[str, str]
151
+ Dictionary where the extracted arguments will be stored.
152
+ This represents the side effect of this function.
153
+
154
+ Return:
155
+ None
156
+
157
+ """
158
+ for run_line in run_args_lines :
159
+ for run_arg_word in run_line .strip ().split ():
160
+ run_arg = run_arg_word .split ('/' ,1 )[0 ]
161
+ if run_arg in metadata_dict :
162
+ metadata_dict [run_arg ] = run_arg_word
163
+
164
+
165
+ def parse_script (self , py_script_path : str ) -> List [Metadata ]:
166
+ """
167
+ Parses a script and returns a list of metadata object where
168
+ each element of that list representing run arguments associated
169
+ with a particular run.
170
+
171
+ Parameter:
172
+
173
+ py_script_path: str
174
+ path to the python test script
175
+
176
+ Return:
177
+
178
+ List[Metadata]
179
+ List of Metadata object where each Metadata element represents
180
+ the run arguments associated with a particular run defined in
181
+ the script file.
182
+ """
183
+
89
184
runs_def_ptrn = re .compile (r'^\s*#\s*test-runner-runs:\s*(.*)$' )
90
- args_def_ptrn = re .compile (r'^\s*#\s*test-runner-run/([a-zA-Z0-9_]+)/(script|app) :\s*(.*)$' )
185
+ args_def_ptrn = re .compile (r'^\s*#\s*test-runner-run/([a-zA-Z0-9_]+):\s*(.*)$' )
91
186
92
187
runs_arg_lines = {}
188
+ runs_metadata = []
93
189
94
190
95
191
with open (py_script_path , 'r' , encoding = 'utf8' ) as py_script :
@@ -103,34 +199,24 @@ def __parse_script__(self, py_script_path, runs_metadata):
103
199
runs_arg_lines [run ]= []
104
200
105
201
elif args_match :
106
- runs_arg_lines [args_match .group (1 )].append (args_match .group (3 ))
202
+ runs_arg_lines [args_match .group (1 )].append (args_match .group (2 ))
107
203
108
204
for run in runs_arg_lines :
109
205
metadata = Metadata ()
110
206
metadata_dict = vars (metadata )
207
+ self .__read_args__ (runs_arg_lines [run ], metadata_dict )
208
+ self .__resolve_env_vals__ (metadata_dict )
209
+
210
+ # store the run value and script location in the
211
+ # metadata object
111
212
metadata_dict ['py_script_path' ] = str (py_script_path )
112
213
metadata_dict ['run' ] = str (run )
113
- self .read_args (runs_arg_lines [run ], metadata_dict )
114
- self .__resolve_env_vals__ (metadata_dict )
115
- runs_metadata [str (metadata .py_script_path )+ "+" + str (metadata .run )] = metadata
214
+
215
+ runs_metadata .append (metadata )
116
216
217
+ return runs_metadata
117
218
118
- # gets the run metadata associated with all the test scripts in a particular folder
119
- def get_runs_metadata (self ):
120
- runs_metadata = {}
121
- for path in Path (self .script_folder ).glob ('*.py' ):
122
- self .__parse_script__ (path , runs_metadata )
123
219
124
- return runs_metadata
125
-
126
-
127
- # goes through run argument definition and extracts run arguments from it
128
- def read_args (self ,run_args_lines ,metadata_dict ):
129
- for run_line in run_args_lines :
130
- for run_arg_word in run_line .strip ().split ():
131
- run_arg = run_arg_word .split ('/' ,1 )[0 ]
132
- if run_arg in metadata_dict :
133
- metadata_dict [run_arg ] = run_arg_word
134
220
135
221
136
222
0 commit comments