-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathattrib_lint.py
114 lines (104 loc) · 3.42 KB
/
attrib_lint.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# KiCad schematic attribute linter
# checks component attributes in .sch files against contents of library
# designed for KiCad 5.1.x, i.e., EESchema Schematic File Version 4
# assumes sym-lib-table is set up to find library foo in kicad_libs/foo.lib
# those files have format EESchema-LIBRARY Version 2.4
import csv
from sys import argv
libs = {}
def process_lib(lib, verbose=False):
lf = open("kicad_libs/%s.lib" % lib)
if verbose:
print("Opened %s" % lib)
reader = csv.reader(lf, delimiter=' ')
in_def = False
lattr = {}
lib_comps = {}
for row in reader:
o = row[0]
if o == "DEF":
in_def = True
component = row[1]
lattr = {}
elif o == "ENDDEF":
in_def = False
if verbose:
print("Library %d attrs in %s:%s" % (len(lattr), lib, component))
lib_comps[component] = lattr
elif in_def:
if len(o) > 0 and o[0] == "F":
fn = int(o[1:])
if fn > 3:
val = row[1]
if False and val == " ":
val = "~~"
lattr[row[-1]] = val
if verbose:
print("%d components in %s" % (len(lib_comps), lib))
return lib_comps
def check_lib_ref(lr):
aa = lr.split(":")
if len(aa) != 2:
print("Funky Library Reference: %s" % lr)
else:
lib = aa[0]
if lib not in libs:
libs[lib] = process_lib(lib)
return libs[lib][aa[1]]
def cross_check(refid, value, lib_ref, attrs, lib_ref_attrs):
if len(attrs) == 0:
return
print("%d attrs in %s" % (len(attrs), refid))
print(" %d attrs in %s" % (len(lib_ref_attrs), lib_ref))
for k in sorted(attrs):
if k in lib_ref_attrs:
if attrs[k] == lib_ref_attrs[k]:
pass
# print("%s: OK" % k)
else:
print("%s: mismatch (%s) (%s)" % (k, attrs[k], lib_ref_attrs[k]))
else:
print("%s: not in lib (from %s)" % (k, refid))
for k in sorted(lib_ref_attrs):
if k not in attrs:
print("%s: not in component %s" % (k, refid))
if "Part Number" in attrs:
part_num = attrs["Part Number"]
if part_num != value:
print("%s: part-value mismatch %s :: %s" % (refid, part_num, value))
else:
print("%s: what?" % refid)
print(sorted(attrs.keys()))
def process_sch(f):
reader = csv.reader(f, delimiter=' ')
in_comp = False
lib_ref = None
lib_ref_attrs = None
refid = None
value = None
for row in reader:
# print(row)
if row[0] == "$Comp":
in_comp = True
attrs = {}
elif row[0] == "$EndComp":
in_comp = False
cross_check(refid, value, lib_ref, attrs, lib_ref_attrs)
refid = None
value = None
elif in_comp:
if row[0] == "L":
lib_ref = row[1]
lib_ref_attrs = check_lib_ref(lib_ref)
elif row[0] == "F" and len(row) > 2:
rnum = int(row[1])
if rnum == 0:
refid = row[2]
if rnum == 1:
value = row[2]
if rnum > 3:
attrs[row[-1]] = row[2]
for fname in argv[1:]:
print("KiCad schematic filename " + fname)
with open(fname, "r") as f:
process_sch(f)