@@ -80,6 +80,42 @@ def get_files(filter=None, paths=None):
80
80
files .remove (file )
81
81
return files
82
82
83
+ def get_module_setting_root (root , settings_file ):
84
+ """
85
+ Parse the Zephyr module generated settings file given by 'settings_file'
86
+ and return all root settings defined by 'root'.
87
+ """
88
+ # Invoke the script directly using the Python executable since this is
89
+ # not a module nor a pip-installed Python utility
90
+ root_paths = []
91
+
92
+ if os .path .exists (settings_file ):
93
+ with open (settings_file , 'r' ) as fp_setting_file :
94
+ content = fp_setting_file .read ()
95
+
96
+ lines = content .strip ().split ('\n ' )
97
+ for line in lines :
98
+ root = root .upper ()
99
+ if line .startswith (f'"{ root } _ROOT":' ):
100
+ _ , root_path = line .split (":" , 1 )
101
+ root_paths .append (Path (root_path .strip ('"' )))
102
+ return root_paths
103
+
104
+ def get_vendor_prefixes (path , errfn = print ) -> set [str ]:
105
+ vendor_prefixes = set ()
106
+ with open (path ) as fp :
107
+ for line in fp .readlines ():
108
+ line = line .strip ()
109
+ if not line or line .startswith ("#" ):
110
+ continue
111
+ try :
112
+ vendor , _ = line .split ("\t " , 2 )
113
+ vendor_prefixes .add (vendor )
114
+ except ValueError :
115
+ errfn (f"Invalid line in { path } :\" { line } \" ." )
116
+ errfn ("Did you forget the tab character?" )
117
+ return vendor_prefixes
118
+
83
119
class FmtdFailure (Failure ):
84
120
def __init__ (
85
121
self , severity , title , file , line = None , col = None , desc = "" , end_line = None , end_col = None
@@ -120,19 +156,21 @@ class ComplianceTest:
120
156
Link to documentation related to what's being tested
121
157
122
158
path_hint:
123
- The path the test runs itself in. This is just informative and used in
124
- the message that gets printed when running the test .
125
-
126
- There are two magic strings that can be used instead of a path:
127
- - The magic string "<zephyr-base>" can be used to refer to the
128
- environment variable ZEPHYR_BASE or, when missing, the calculated base of
129
- the zephyr tree
130
- - The magic string "<git-top>" refers to the top-level repository
131
- directory. This avoids running 'git' to find the top-level directory
132
- before main() runs (class variable assignments run when the 'class ...'
133
- statement runs). That avoids swallowing errors, because main() reports
134
- them to GitHub
159
+ The path the test runs itself in. By default it uses the magic string
160
+ "<git-top>" which refers to the top-level repository directory .
161
+
162
+ This avoids running 'git' to find the top-level directory before main()
163
+ runs (class variable assignments run when the 'class ...' statement
164
+ runs). That avoids swallowing errors, because main() reports them to
165
+ GitHub.
166
+
167
+ Subclasses may override the default with a specific path or one of the
168
+ magic strings below:
169
+ - "<zephyr-base>" can be used to refer to the environment variable
170
+ ZEPHYR_BASE or, when missing, the calculated base of the zephyr tree.
135
171
"""
172
+ path_hint = "<git-top>"
173
+
136
174
def __init__ (self ):
137
175
self .case = TestCase (type (self ).name , "Guidelines" )
138
176
# This is necessary because Failure can be subclassed, but since it is
@@ -204,7 +242,6 @@ class CheckPatch(ComplianceTest):
204
242
"""
205
243
name = "Checkpatch"
206
244
doc = "See https://docs.zephyrproject.org/latest/contribute/guidelines.html#coding-style for more details."
207
- path_hint = "<git-top>"
208
245
209
246
def run (self ):
210
247
checkpatch = ZEPHYR_BASE / 'scripts' / 'checkpatch.pl'
@@ -263,7 +300,6 @@ class BoardYmlCheck(ComplianceTest):
263
300
"""
264
301
name = "BoardYml"
265
302
doc = "Check the board.yml file format"
266
- path_hint = "<zephyr-base>"
267
303
268
304
def check_board_file (self , file , vendor_prefixes ):
269
305
"""Validate a single board file."""
@@ -278,20 +314,19 @@ def check_board_file(self, file, vendor_prefixes):
278
314
desc = desc )
279
315
280
316
def run (self ):
281
- vendor_prefixes = ["others" ]
282
- with open (os .path .join (ZEPHYR_BASE , "dts" , "bindings" , "vendor-prefixes.txt" )) as fp :
283
- for line in fp .readlines ():
284
- line = line .strip ()
285
- if not line or line .startswith ("#" ):
286
- continue
287
- try :
288
- vendor , _ = line .split ("\t " , 2 )
289
- vendor_prefixes .append (vendor )
290
- except ValueError :
291
- self .error (f"Invalid line in vendor-prefixes.txt:\" { line } \" ." )
292
- self .error ("Did you forget the tab character?" )
293
-
294
- path = Path (ZEPHYR_BASE )
317
+ path = resolve_path_hint (self .path_hint )
318
+
319
+ vendor_prefixes = {"others" }
320
+ # add vendor prefixes from the main zephyr repo
321
+ vendor_prefixes |= get_vendor_prefixes (ZEPHYR_BASE / "dts" / "bindings" / "vendor-prefixes.txt" , self .error )
322
+
323
+ # add vendor prefixes from the current repo
324
+ dts_roots = get_module_setting_root ('dts' , path / "zephyr" / "module.yml" )
325
+ for dts_root in dts_roots :
326
+ vendor_prefix_file = dts_root / "dts" / "bindings" / "vendor-prefixes.txt"
327
+ if vendor_prefix_file .exists ():
328
+ vendor_prefixes |= get_vendor_prefixes (vendor_prefix_file , self .error )
329
+
295
330
for file in path .glob ("**/board.yml" ):
296
331
self .check_board_file (file , vendor_prefixes )
297
332
@@ -302,7 +337,6 @@ class ClangFormatCheck(ComplianceTest):
302
337
"""
303
338
name = "ClangFormat"
304
339
doc = "See https://docs.zephyrproject.org/latest/contribute/guidelines.html#clang-format for more details."
305
- path_hint = "<git-top>"
306
340
307
341
def run (self ):
308
342
exe = f"clang-format-diff.{ 'exe' if platform .system () == 'Windows' else 'py' } "
@@ -344,7 +378,6 @@ class DevicetreeBindingsCheck(ComplianceTest):
344
378
"""
345
379
name = "DevicetreeBindings"
346
380
doc = "See https://docs.zephyrproject.org/latest/build/dts/bindings.html for more details."
347
- path_hint = "<zephyr-base>"
348
381
349
382
def run (self , full = True ):
350
383
dts_bindings = self .parse_dt_bindings ()
@@ -381,7 +414,6 @@ class KconfigCheck(ComplianceTest):
381
414
"""
382
415
name = "Kconfig"
383
416
doc = "See https://docs.zephyrproject.org/latest/build/kconfig/tips.html for more details."
384
- path_hint = "<zephyr-base>"
385
417
386
418
# Top-level Kconfig file. The path can be relative to srctree (ZEPHYR_BASE).
387
419
FILENAME = "Kconfig"
@@ -437,27 +469,6 @@ def get_modules(self, modules_file, sysbuild_modules_file, settings_file):
437
469
))
438
470
fp_module_file .write (content )
439
471
440
- def get_module_setting_root (self , root , settings_file ):
441
- """
442
- Parse the Zephyr module generated settings file given by 'settings_file'
443
- and return all root settings defined by 'root'.
444
- """
445
- # Invoke the script directly using the Python executable since this is
446
- # not a module nor a pip-installed Python utility
447
- root_paths = []
448
-
449
- if os .path .exists (settings_file ):
450
- with open (settings_file , 'r' ) as fp_setting_file :
451
- content = fp_setting_file .read ()
452
-
453
- lines = content .strip ().split ('\n ' )
454
- for line in lines :
455
- root = root .upper ()
456
- if line .startswith (f'"{ root } _ROOT":' ):
457
- _ , root_path = line .split (":" , 1 )
458
- root_paths .append (Path (root_path .strip ('"' )))
459
- return root_paths
460
-
461
472
def get_kconfig_dts (self , kconfig_dts_file , settings_file ):
462
473
"""
463
474
Generate the Kconfig.dts using dts/bindings as the source.
@@ -1146,6 +1157,7 @@ class KconfigBasicNoModulesCheck(KconfigBasicCheck):
1146
1157
defined only in a module.
1147
1158
"""
1148
1159
name = "KconfigBasicNoModules"
1160
+ path_hint = "<zephyr-base>"
1149
1161
1150
1162
def get_modules (self , modules_file , sysbuild_modules_file , settings_file ):
1151
1163
with open (modules_file , 'w' ) as fp_module_file :
@@ -1212,6 +1224,7 @@ class SysbuildKconfigBasicNoModulesCheck(SysbuildKconfigCheck, KconfigBasicNoMod
1212
1224
but defined only in a module.
1213
1225
"""
1214
1226
name = "SysbuildKconfigBasicNoModules"
1227
+ path_hint = "<zephyr-base>"
1215
1228
1216
1229
1217
1230
class Nits (ComplianceTest ):
@@ -1221,7 +1234,6 @@ class Nits(ComplianceTest):
1221
1234
"""
1222
1235
name = "Nits"
1223
1236
doc = "See https://docs.zephyrproject.org/latest/contribute/guidelines.html#coding-style for more details."
1224
- path_hint = "<git-top>"
1225
1237
1226
1238
def run (self ):
1227
1239
# Loop through added/modified files
@@ -1315,7 +1327,6 @@ class GitDiffCheck(ComplianceTest):
1315
1327
"""
1316
1328
name = "GitDiffCheck"
1317
1329
doc = "Git conflict markers and whitespace errors are not allowed in added changes"
1318
- path_hint = "<git-top>"
1319
1330
1320
1331
def run (self ):
1321
1332
offending_lines = []
@@ -1343,7 +1354,6 @@ class GitLint(ComplianceTest):
1343
1354
"""
1344
1355
name = "Gitlint"
1345
1356
doc = "See https://docs.zephyrproject.org/latest/contribute/guidelines.html#commit-guidelines for more details"
1346
- path_hint = "<git-top>"
1347
1357
1348
1358
def run (self ):
1349
1359
# By default gitlint looks for .gitlint configuration only in
@@ -1366,7 +1376,6 @@ class PyLint(ComplianceTest):
1366
1376
"""
1367
1377
name = "Pylint"
1368
1378
doc = "See https://www.pylint.org/ for more details"
1369
- path_hint = "<git-top>"
1370
1379
1371
1380
def run (self ):
1372
1381
# Path to pylint configuration file
@@ -1441,9 +1450,6 @@ class Identity(ComplianceTest):
1441
1450
"""
1442
1451
name = "Identity"
1443
1452
doc = "See https://docs.zephyrproject.org/latest/contribute/guidelines.html#commit-guidelines for more details"
1444
- # git rev-list and git log don't depend on the current (sub)directory
1445
- # unless explicited
1446
- path_hint = "<git-top>"
1447
1453
1448
1454
def run (self ):
1449
1455
for shaidx in get_shas (COMMIT_RANGE ):
@@ -1484,7 +1490,6 @@ class BinaryFiles(ComplianceTest):
1484
1490
"""
1485
1491
name = "BinaryFiles"
1486
1492
doc = "No binary files allowed."
1487
- path_hint = "<git-top>"
1488
1493
1489
1494
def run (self ):
1490
1495
BINARY_ALLOW_PATHS = ("doc/" , "boards/" , "samples/" )
@@ -1507,7 +1512,6 @@ class ImageSize(ComplianceTest):
1507
1512
"""
1508
1513
name = "ImageSize"
1509
1514
doc = "Check the size of image files."
1510
- path_hint = "<git-top>"
1511
1515
1512
1516
def run (self ):
1513
1517
SIZE_LIMIT = 250 << 10
@@ -1537,7 +1541,6 @@ class MaintainersFormat(ComplianceTest):
1537
1541
"""
1538
1542
name = "MaintainersFormat"
1539
1543
doc = "Check that MAINTAINERS file parses correctly."
1540
- path_hint = "<git-top>"
1541
1544
1542
1545
def run (self ):
1543
1546
MAINTAINERS_FILES = ["MAINTAINERS.yml" , "MAINTAINERS.yaml" ]
@@ -1557,7 +1560,6 @@ class ModulesMaintainers(ComplianceTest):
1557
1560
"""
1558
1561
name = "ModulesMaintainers"
1559
1562
doc = "Check that all modules have a MAINTAINERS entry."
1560
- path_hint = "<git-top>"
1561
1563
1562
1564
def run (self ):
1563
1565
MAINTAINERS_FILES = ["MAINTAINERS.yml" , "MAINTAINERS.yaml" ]
@@ -1592,7 +1594,6 @@ class YAMLLint(ComplianceTest):
1592
1594
"""
1593
1595
name = "YAMLLint"
1594
1596
doc = "Check YAML files with YAMLLint."
1595
- path_hint = "<git-top>"
1596
1597
1597
1598
def run (self ):
1598
1599
config_file = ZEPHYR_BASE / ".yamllint"
@@ -1623,7 +1624,6 @@ class SphinxLint(ComplianceTest):
1623
1624
1624
1625
name = "SphinxLint"
1625
1626
doc = "Check Sphinx/reStructuredText files with sphinx-lint."
1626
- path_hint = "<git-top>"
1627
1627
1628
1628
# Checkers added/removed to sphinx-lint's default set
1629
1629
DISABLE_CHECKERS = ["horizontal-tab" , "missing-space-before-default-role" ]
@@ -1665,7 +1665,6 @@ class KeepSorted(ComplianceTest):
1665
1665
"""
1666
1666
name = "KeepSorted"
1667
1667
doc = "Check for blocks of code or config that should be kept sorted."
1668
- path_hint = "<git-top>"
1669
1668
1670
1669
MARKER = "zephyr-keep-sorted"
1671
1670
@@ -1761,7 +1760,6 @@ class Ruff(ComplianceTest):
1761
1760
"""
1762
1761
name = "Ruff"
1763
1762
doc = "Check python files with ruff."
1764
- path_hint = "<git-top>"
1765
1763
1766
1764
def run (self ):
1767
1765
for file in get_files (filter = "d" ):
@@ -1809,7 +1807,6 @@ class TextEncoding(ComplianceTest):
1809
1807
"""
1810
1808
name = "TextEncoding"
1811
1809
doc = "Check the encoding of text files."
1812
- path_hint = "<git-top>"
1813
1810
1814
1811
ALLOWED_CHARSETS = ["us-ascii" , "utf-8" ]
1815
1812
0 commit comments