Skip to content
This repository has been archived by the owner on Oct 2, 2020. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into SolderPaste_EP
Browse files Browse the repository at this point in the history
  • Loading branch information
JacobEFO committed Feb 25, 2020
2 parents eca004f + efba12a commit cfea135
Show file tree
Hide file tree
Showing 20 changed files with 408 additions and 137 deletions.
116 changes: 39 additions & 77 deletions check_lib_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,100 +14,62 @@
from __future__ import print_function

import argparse
import re
import os
import sys

parser = argparse.ArgumentParser(description='Compare a sym_lib_table file against a list of .lib library files')
from lib_table import LibTable

parser = argparse.ArgumentParser(description='Compare a sym-lib-table file against a list of .lib library files')
parser.add_argument('libs', nargs='+', help='.lib files')
parser.add_argument('-t', '--table', help='sym_lib_table file', action='store')
parser.add_argument('-t', '--table', help='sym-lib-table file', action='store')

args = parser.parse_args()

class LibTable:

def __init__(self, filename):

RE_NAME = r'\(name "?([^\)"]*)"?\)'
RE_TYPE = r'\(type "?([^\)"]*)"?\)'
RE_URI = r'\(uri "?([^\)"]*)"?\)'
RE_OPT = r'\(options "?([^\)"]*)"?\)'
RE_DESC = r'\(descr "?([^\)"]*)"?'

self.entries = []
self.errors = []

with open(filename, 'r') as lib_table_file:

for line in lib_table_file:

# Skip lines that do not define a library
if not '(lib ' in line:
continue

re_name = re.search(RE_NAME, line)
re_type = re.search(RE_TYPE, line)
re_uri = re.search(RE_URI, line)
re_opt = re.search(RE_OPT, line)
re_desc = re.search(RE_DESC, line)

if re_name and re_type and re_uri and re_opt and re_desc:
entry = {}
entry['name'] = re_name.groups()[0]
entry['type'] = re_type.groups()[0]
entry['uri'] = re_uri.groups()[0]
entry['opt'] = re_opt.groups()[0]
entry['desc'] = re_desc.groups()[0]

self.entries.append(entry)
def check_entries(lib_table, lib_names):

else:
self.errors.append(line)
errors = 0

def check_entries(self, lib_names):
# Check for entries that are incorrectly formatted
for entry in lib_table.entries:
nickname = entry['name']
uri = entry['uri']

errors = 0

# Check for entries that are incorrectly formatted
for entry in self.entries:
nickname = entry['name']
uri = entry['uri']

if '\\' in uri:
print("Found '\\' character in entry '{nick}' - Path separators must be '/'".format(nick=nickname))
errors += 1

uri_last = '.'.join(uri.split('/')[-1].split('.')[:-1])
if '\\' in uri:
print("Found '\\' character in entry '{nick}' - Path separators must be '/'".format(nick=nickname))
errors += 1

if not uri_last == nickname:
print("Nickname '{n}' does not match path '{p}'".format(n=nickname, p=uri))
errors += 1
uri_last = '.'.join(uri.split('/')[-1].split('.')[:-1])

lib_table_names = [entry['name'] for entry in self.entries]
if not uri_last == nickname:
print("Nickname '{n}' does not match path '{p}'".format(n=nickname, p=uri))
errors += 1

# Check for libraries that are in the lib_table but should not be
for name in lib_table_names:
if not name in lib_names:
errors += 1
print("- Extra library '{l}' found in library table".format(l=name))
lib_table_names = [entry['name'] for entry in lib_table.entries]

if lib_table_names.count(name) > 1:
errors += 1
print("- Library '{l}' is duplicated in table".format(l=name))
# Check for libraries that are in the lib_table but should not be
for name in lib_table_names:
if not name in lib_names:
errors += 1
print("- Extra library '{l}' found in library table".format(l=name))

# Check for libraries that are not in the lib_table but should be
for name in lib_names:
if not name in lib_table_names:
errors += 1
print("- Library '{l}' missing from library table".format(l=name))
if lib_table_names.count(name) > 1:
errors += 1
print("- Library '{l}' is duplicated in table".format(l=name))

# Incorrect lines in the library table
for error in self.errors:
# Check for libraries that are not in the lib_table but should be
for name in lib_names:
if not name in lib_table_names:
errors += 1
print("- Incorrect line found in library table:")
print(" - '{line}'".format(line=error))
print("- Library '{l}' missing from library table".format(l=name))

# Incorrect lines in the library table
for error in lib_table.errors:
errors += 1
print("- Incorrect line found in library table:")
print(" - '{line}'".format(line=error))

return errors
return errors


lib_names = []
Expand All @@ -122,6 +84,6 @@ def check_entries(self, lib_names):

table = LibTable(args.table)

errors = table.check_entries(lib_names)
errors = check_entries(table, lib_names)

sys.exit(errors)
sys.exit(errors)
19 changes: 18 additions & 1 deletion common/rulebase.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

import inspect, os
import inspect, os, sys
import json

def logError(log_file, rule_name, lib_name, item_name, warning=False):
Expand Down Expand Up @@ -66,6 +66,23 @@ def isValidName(name, checkForGraphicSymbol=False, checkForPowerSymbol=False):

return True

def checkLineEndings(filename):
"""
Check for proper (Unix) line endings
"""
filecontentsraw = open(filename, 'rb').readline()

LE1 = ord(chr(filecontentsraw[-2]))
LE2 = ord(chr(filecontentsraw[-1]))

# 0x0D0A = Windows (CRLF)
# 0x__0D = Mac OS 9 (CR)
# 0x__0A = Unix (LF)
if (LE1 == 0x0D and LE2 == 0x0A) or (LE2 == 0x0D):
return False

return True

class Verbosity:
NONE=0
NORMAL=1
Expand Down
43 changes: 43 additions & 0 deletions lib_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import re

class LibTable:

def __init__(self, filename):

RE_NAME = r'\(name "?([^\)"]*)"?\)'
RE_TYPE = r'\(type "?([^\)"]*)"?\)'
RE_URI = r'\(uri "?([^\)"]*)"?\)'
RE_OPT = r'\(options "?([^\)"]*)"?\)'
RE_DESC = r'\(descr "?([^\)"]*)"?'

self.entries = []
self.errors = []

with open(filename, 'r') as lib_table_file:

for line in lib_table_file:

# Skip lines that do not define a library
if not '(lib ' in line:
continue

re_name = re.search(RE_NAME, line)
re_type = re.search(RE_TYPE, line)
re_uri = re.search(RE_URI, line)
re_opt = re.search(RE_OPT, line)
re_desc = re.search(RE_DESC, line)

if re_name and re_type and re_uri and re_opt and re_desc:
entry = {}
entry['name'] = re_name.groups()[0]
entry['type'] = re_type.groups()[0]
entry['uri'] = re_uri.groups()[0]
entry['opt'] = re_opt.groups()[0]
entry['desc'] = re_desc.groups()[0]

self.entries.append(entry)

else:
self.errors.append(line)


2 changes: 1 addition & 1 deletion pcb/check_kicad_mod.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3

from __future__ import print_function

Expand Down
20 changes: 1 addition & 19 deletions pcb/kicad_mod.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,6 @@ class KicadMod(object):
def __init__(self, filename):
self.filename = filename

# check file line-endings
self.unix_line_endings=True
filecontentsraw=open(filename,"rb").readline()

LE1 = filecontentsraw[-2]
LE2 = filecontentsraw[-1]

# Ord is different for python3
if sys.version_info.major >= 3:
LE1 = chr(LE1)
LE2 = chr(LE2)

LE1 = ord(LE1)
LE2 = ord(LE2)

if (LE1 == 0x0D and LE2 == 0x0A) or (LE2 == 0x0D):
self.unix_line_endings=False

# read the s-expression data
f = open(filename)
sexpr_data = ''.join(f.readlines())
Expand Down Expand Up @@ -1097,7 +1079,7 @@ def save(self, filename=None):

se.endGroup(True)

with open(filename, 'w') as f:
with open(filename, 'w', newline='\n') as f:
f.write(se.output)
f.write('\n')

Expand Down
60 changes: 59 additions & 1 deletion pcb/rules/F5_3.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,51 @@ def defaultCourtyard(self):
else:
return None


def isClosed(self, layer):
def isSame(p1, p2, tolerance):
s = abs(p1['x'] - p2['x']) <= tolerance and abs(p1['y'] - p2['y']) <= tolerance
return s

# no line is considered as closed
if len(layer) == 0:
return []

# clone the lines, so we can remove them from the list
lines = layer[0:]
curr_line = lines.pop()
curr_point = getStartPoint(curr_line)
end_point = getEndPoint(curr_line)
tolerance = 0

while len(lines) > 0:
tolerance = 0
match = False
for line in lines:
if 'angle' in line or 'angle' in curr_line:
tolerance = 0.01
if isSame(curr_point, getStartPoint(line), tolerance):
curr_line = line
curr_point = getEndPoint(line)
lines.remove(line)
match = True
break
if isSame(curr_point, getEndPoint(line), tolerance):
curr_line = line
curr_point = getStartPoint(line)
lines.remove(line)
match = True
break
# we should hit a continue
# if now, that means no line connects
if not match:
return [curr_line]
# now check the if the last points match
if isSame(curr_point, end_point, tolerance):
return []
else:
return [curr_line]

def check(self):
"""
Proceeds the checking of the rule.
Expand All @@ -118,6 +163,7 @@ def check(self):

self.bad_grid = []
self.bad_width = []
self.unconnected = []

self.fCourtyard = module.filterGraphs('F.CrtYd')
self.bCourtyard = module.filterGraphs('B.CrtYd')
Expand All @@ -133,6 +179,10 @@ def check(self):

GRID = int(KLC_CRTYD_GRID * 1E6)

# Check for intersecting lines
self.unconnected.extend(self.isClosed(self.fCourtyard))
self.unconnected.extend(self.isClosed(self.bCourtyard))

for graph in self.courtyard:
if graph['width'] != KLC_CRTYD_WIDTH:
self.bad_width.append(graph)
Expand Down Expand Up @@ -174,9 +224,17 @@ def check(self):
for bad in self.bad_grid:
self.errorExtra(graphItemString(bad, layer=True, width=False))

# Check that courtyard is closed
if len(self.unconnected) > 0:
self.error("Courtyard must be closed.")
self.errorExtra("The following lines have unconnected endpoints")
for bad in self.unconnected:
self.errorExtra(graphItemString(bad, layer=True, width=False))

return any([
len(self.bad_width) > 0,
len(self.bad_grid) > 0
len(self.bad_grid) > 0,
len(self.unconnected) > 0
])

def fix(self):
Expand Down
Loading

0 comments on commit cfea135

Please sign in to comment.