@@ -117,13 +117,15 @@ def get_var_naming_matcherror(
117
117
ident : str ,
118
118
* ,
119
119
prefix : Prefix | None = None ,
120
+ file : Lintable ,
120
121
) -> MatchError | None :
121
122
"""Return a MatchError if the variable name is not valid, otherwise None."""
122
123
if not isinstance (ident , str ): # pragma: no cover
123
124
return MatchError (
124
125
tag = "var-naming[non-string]" ,
125
126
message = "Variables names must be strings." ,
126
127
rule = self ,
128
+ lintable = file ,
127
129
)
128
130
129
131
if ident in ANNOTATION_KEYS or ident in self .allowed_special_names :
@@ -136,27 +138,31 @@ def get_var_naming_matcherror(
136
138
tag = "var-naming[non-ascii]" ,
137
139
message = f"Variables names must be ASCII. ({ ident } )" ,
138
140
rule = self ,
141
+ lintable = file ,
139
142
)
140
143
141
144
if keyword .iskeyword (ident ):
142
145
return MatchError (
143
146
tag = "var-naming[no-keyword]" ,
144
147
message = f"Variables names must not be Python keywords. ({ ident } )" ,
145
148
rule = self ,
149
+ lintable = file ,
146
150
)
147
151
148
152
if ident in self .reserved_names :
149
153
return MatchError (
150
154
tag = "var-naming[no-reserved]" ,
151
155
message = f"Variables names must not be Ansible reserved names. ({ ident } )" ,
152
156
rule = self ,
157
+ lintable = file ,
153
158
)
154
159
155
160
if ident in self .read_only_names :
156
161
return MatchError (
157
162
tag = "var-naming[read-only]" ,
158
163
message = f"This special variable is read-only. ({ ident } )" ,
159
164
rule = self ,
165
+ lintable = file ,
160
166
)
161
167
162
168
# We want to allow use of jinja2 templating for variable names
@@ -165,6 +171,7 @@ def get_var_naming_matcherror(
165
171
tag = "var-naming[no-jinja]" ,
166
172
message = "Variables names must not contain jinja2 templating." ,
167
173
rule = self ,
174
+ lintable = file ,
168
175
)
169
176
170
177
if not bool (self .re_pattern .match (ident )) and (
@@ -174,6 +181,7 @@ def get_var_naming_matcherror(
174
181
tag = "var-naming[pattern]" ,
175
182
message = f"Variables names should match { self .re_pattern_str } regex. ({ ident } )" ,
176
183
rule = self ,
184
+ lintable = file ,
177
185
)
178
186
179
187
if (
@@ -186,6 +194,7 @@ def get_var_naming_matcherror(
186
194
tag = "var-naming[no-role-prefix]" ,
187
195
message = f"Variables names from within roles should use { prefix .value } _ as a prefix." ,
188
196
rule = self ,
197
+ lintable = file ,
189
198
)
190
199
return None
191
200
@@ -199,9 +208,8 @@ def matchplay(self, file: Lintable, data: dict[str, Any]) -> list[MatchError]:
199
208
# If the Play uses the 'vars' section to set variables
200
209
our_vars = data .get ("vars" , {})
201
210
for key in our_vars :
202
- match_error = self .get_var_naming_matcherror (key )
211
+ match_error = self .get_var_naming_matcherror (key , file = file )
203
212
if match_error :
204
- match_error .filename = str (file .path )
205
213
match_error .lineno = (
206
214
key .ansible_pos [1 ]
207
215
if isinstance (key , AnsibleUnicode )
@@ -219,9 +227,9 @@ def matchplay(self, file: Lintable, data: dict[str, Any]) -> list[MatchError]:
219
227
match_error = self .get_var_naming_matcherror (
220
228
key ,
221
229
prefix = prefix ,
230
+ file = file ,
222
231
)
223
232
if match_error :
224
- match_error .filename = str (file .path )
225
233
match_error .message += f" (vars: { key } )"
226
234
match_error .lineno = (
227
235
key .ansible_pos [1 ]
@@ -235,9 +243,9 @@ def matchplay(self, file: Lintable, data: dict[str, Any]) -> list[MatchError]:
235
243
match_error = self .get_var_naming_matcherror (
236
244
key ,
237
245
prefix = prefix ,
246
+ file = file ,
238
247
)
239
248
if match_error :
240
- match_error .filename = str (file .path )
241
249
match_error .message += f" (vars: { key } )"
242
250
match_error .lineno = (
243
251
key .ansible_pos [1 ]
@@ -266,7 +274,6 @@ def matchtask(
266
274
"""Return matches for task based variables."""
267
275
results = []
268
276
prefix = Prefix ()
269
- filename = "" if file is None else str (file .path )
270
277
if file and file .parent and file .parent .kind == "role" :
271
278
prefix = Prefix (file .parent .path .name )
272
279
ansible_module = task ["action" ]["__ansible_module__" ]
@@ -283,9 +290,9 @@ def matchtask(
283
290
match_error = self .get_var_naming_matcherror (
284
291
key ,
285
292
prefix = prefix ,
293
+ file = file or Lintable ("" ),
286
294
)
287
295
if match_error :
288
- match_error .filename = filename
289
296
match_error .lineno = our_vars [LINE_NUMBER_KEY ]
290
297
match_error .message += f" (vars: { key } )"
291
298
results .append (match_error )
@@ -298,9 +305,12 @@ def matchtask(
298
305
and x != "cacheable" ,
299
306
task ["action" ].keys (),
300
307
):
301
- match_error = self .get_var_naming_matcherror (key , prefix = prefix )
308
+ match_error = self .get_var_naming_matcherror (
309
+ key ,
310
+ prefix = prefix ,
311
+ file = file or Lintable ("" ),
312
+ )
302
313
if match_error :
303
- match_error .filename = filename
304
314
match_error .lineno = task ["action" ][LINE_NUMBER_KEY ]
305
315
match_error .message += f" (set_fact: { key } )"
306
316
results .append (match_error )
@@ -311,10 +321,10 @@ def matchtask(
311
321
match_error = self .get_var_naming_matcherror (
312
322
registered_var ,
313
323
prefix = prefix ,
324
+ file = file or Lintable ("" ),
314
325
)
315
326
if match_error :
316
327
match_error .message += f" (register: { registered_var } )"
317
- match_error .filename = filename
318
328
match_error .lineno = task [LINE_NUMBER_KEY ]
319
329
results .append (match_error )
320
330
@@ -325,15 +335,17 @@ def matchyaml(self, file: Lintable) -> list[MatchError]:
325
335
results : list [MatchError ] = []
326
336
raw_results : list [MatchError ] = []
327
337
meta_data : dict [AnsibleUnicode , Any ] = {}
328
- filename = "" if file is None else str (file .path )
329
338
330
339
if str (file .kind ) == "vars" and file .data :
331
340
meta_data = parse_yaml_from_file (str (file .path ))
332
341
for key in meta_data :
333
342
prefix = Prefix (file .role ) if file .role else Prefix ()
334
- match_error = self .get_var_naming_matcherror (key , prefix = prefix )
343
+ match_error = self .get_var_naming_matcherror (
344
+ key ,
345
+ prefix = prefix ,
346
+ file = file ,
347
+ )
335
348
if match_error :
336
- match_error .filename = filename
337
349
match_error .lineno = key .ansible_pos [1 ]
338
350
match_error .message += f" (vars: { key } )"
339
351
raw_results .append (match_error )
@@ -413,6 +425,25 @@ def test_invalid_var_name_varsfile(
413
425
assert result .tag == expected_errors [idx ][0 ]
414
426
assert result .lineno == expected_errors [idx ][1 ]
415
427
428
+ def test_invalid_vars_diff_files (
429
+ default_rules_collection : RulesCollection ,
430
+ ) -> None :
431
+ """Test rule matches."""
432
+ results = Runner (
433
+ Lintable ("examples/playbooks/vars/rule_var_naming_fails_files" ),
434
+ rules = default_rules_collection ,
435
+ ).run ()
436
+ expected_errors = (
437
+ ("var-naming[pattern]" , 2 ),
438
+ ("var-naming[pattern]" , 3 ),
439
+ ("var-naming[pattern]" , 2 ),
440
+ ("var-naming[pattern]" , 3 ),
441
+ )
442
+ assert len (results ) == len (expected_errors )
443
+ for idx , result in enumerate (results ):
444
+ assert result .tag == expected_errors [idx ][0 ]
445
+ assert result .lineno == expected_errors [idx ][1 ]
446
+
416
447
def test_var_naming_with_role_prefix (
417
448
default_rules_collection : RulesCollection ,
418
449
) -> None :
0 commit comments