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

Commit

Permalink
Error checking in sch.Component.addField (#267)
Browse files Browse the repository at this point in the history
* Add error checking to Component.addField. Change interface.

The function prototype is changed to a more pythonic one - keyword
based, making sure both 'ref' and 'name' are always passed. Invalid
items in the additional 'field_data' are discarded silently. 'ref' and
'name' are automatically doubled-quoted if that's not already the
case.

* Fix add_part_number script for new Component.addField interface

* Make coding style PEP8 compliant
  • Loading branch information
airwoodix authored Mar 7, 2020
1 parent d362bbb commit 24bd891
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 34 deletions.
3 changes: 2 additions & 1 deletion sch/add_part_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
if field['name'].replace('"', '') == args.pn_field_name:
break
else:
field = component.addField({'name': '"%s"' % args.pn_field_name, 'ref': '"~"'})
field = component.addField(name="{}".format(args.pn_field_name),
ref="{}".format("~"))

# component reference
comp_ref = component.fields[0]['ref'].replace('"', '')
Expand Down
97 changes: 64 additions & 33 deletions sch/sch.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
# -*- coding: utf-8 -*-

import sys, shlex
import sys
import shlex
import re


def ensure_quoted(s):
"""
Returns a quoted version of string 's' if that's not already the case
"""
rx = r"^\"(.+)\"$"

if re.match(rx, s) is not None:
return s
else:
return "\"{}\"".format(s)


class Description(object):
"""
Expand All @@ -10,6 +25,7 @@ class Description(object):
def __init__(self, data):
self.raw_data = data


class Component(object):
"""
A class to parse components of Schematic Files Format of the KiCad
Expand All @@ -18,9 +34,12 @@ class Component(object):
_U_KEYS = ['unit', 'convert', 'time_stamp']
_P_KEYS = ['posx', 'posy']
_AR_KEYS = ['path', 'ref', 'part']
_F_KEYS = ['id', 'ref', 'orient', 'posx', 'posy', 'size', 'attributs', 'hjust', 'props', 'name']
_F_KEYS = ['id', 'ref', 'orient', 'posx', 'posy', 'size', 'attributs',
'hjust', 'props', 'name']

_KEYS = {'L': _L_KEYS, 'U': _U_KEYS, 'P': _P_KEYS,
'AR': _AR_KEYS, 'F': _F_KEYS}

_KEYS = {'L':_L_KEYS, 'U':_U_KEYS, 'P':_P_KEYS, 'AR':_AR_KEYS, 'F':_F_KEYS}
def __init__(self, data):
self.labels = {}
self.unit = {}
Expand All @@ -44,45 +63,52 @@ def __init__(self, data):
# select the keys list and default values array
if line[0] in self._KEYS:
key_list = self._KEYS[line[0]]
values = line[1:] + ['' for n in range(len(key_list) - len(line[1:]))]
values = line[1:] + ['']*(len(key_list) - len(line[1:]))

if line[0] == 'L':
self.labels = dict(zip(key_list,values))
self.labels = dict(zip(key_list, values))
elif line[0] == 'U':
self.unit = dict(zip(key_list,values))
self.unit = dict(zip(key_list, values))
elif line[0] == 'P':
self.position = dict(zip(key_list,values))
self.position = dict(zip(key_list, values))
elif line[0] == 'AR':
self.references.append(dict(zip(key_list,values)))
self.references.append(dict(zip(key_list, values)))
elif line[0] == 'F':
self.fields.append(dict(zip(key_list,values)))
self.fields.append(dict(zip(key_list, values)))

# TODO: error checking
# * check if field_data is a dictionary
# * check if at least 'ref' and 'name' were passed
# * ignore invalid items of field_data on merging
# TODO: enhancements
# * 'value' could be used instead of 'ref'
def addField(self, field_data):
def_field = {'id':None, 'ref':None, 'orient':'H', 'posx':'0', 'posy':'0', 'size':'50',
'attributs':'0001', 'hjust':'C', 'props':'CNN', 'name':'~'}
def addField(self, *, ref, name, **field_data):
field = {'id': None, 'ref': None, 'orient': 'H', 'posx': '0',
'posy': '0', 'size': '50', 'attributs': '0001',
'hjust': 'C', 'props': 'CNN', 'name': '~'}

# 'ref' and 'name' must be quoted
ref = ensure_quoted(ref)
name = ensure_quoted(name)

# ignore invalid items in field_data
field_data = {key: val for (key, val) in field_data.items()
if key in self._F_KEYS}

# merge dictionaries and set the id value
field = dict(list(def_field.items()) + list(field_data.items()))
field.update(field_data, ref=ref, name=name)
field['id'] = str(len(self.fields))

self.fields.append(field)
return field


class Sheet(object):
"""
A class to parse sheets of Schematic Files Format of the KiCad
"""
_S_KEYS = ['topLeftPosx', 'topLeftPosy','botRightPosx', 'botRightPosy']
_S_KEYS = ['topLeftPosx', 'topLeftPosy', 'botRightPosx', 'botRightPosy']
_U_KEYS = ['uniqID']
_F_KEYS = ['id', 'value', 'IOState', 'side', 'posx', 'posy', 'size']

_KEYS = {'S':_S_KEYS, 'U':_U_KEYS, 'F':_F_KEYS}
_KEYS = {'S': _S_KEYS, 'U': _U_KEYS, 'F': _F_KEYS}

def __init__(self, data):
self.shape = {}
self.unit = {}
Expand All @@ -97,15 +123,16 @@ def __init__(self, data):
# select the keys list and default values array
if line[0] in self._KEYS:
key_list = self._KEYS[line[0]]
values = line[1:] + ['' for n in range(len(key_list) - len(line[1:]))]
values = line[1:] + ['']*(len(key_list) - len(line[1:]))
if line[0] == 'S':
self.shape = dict(zip(key_list,values))
self.shape = dict(zip(key_list, values))
elif line[0] == 'U':
self.unit = dict(zip(key_list,values))
self.unit = dict(zip(key_list, values))
elif line[0][0] == 'F':
key_list = self._F_KEYS
values = line + ['' for n in range(len(key_list) - len(line))]
self.fields.append(dict(zip(key_list,values)))
self.fields.append(dict(zip(key_list, values)))


class Bitmap(object):
"""
Expand All @@ -115,6 +142,7 @@ class Bitmap(object):
def __init__(self, data):
self.raw_data = data


class Schematic(object):
"""
A class to parse Schematic Files Format of the KiCad
Expand All @@ -135,7 +163,7 @@ def __init__(self, filename):
self.conns = []
self.noconns = []

if not 'EESchema Schematic File' in self.header:
if 'EESchema Schematic File' not in self.header:
self.header = None
sys.stderr.write('The file is not a KiCad Schematic File\n')
return
Expand All @@ -144,7 +172,8 @@ def __init__(self, filename):

while True:
line = f.readline()
if not line: break
if not line:
break

if line.startswith('LIBS:'):
self.libs.append(line)
Expand All @@ -160,19 +189,19 @@ def __init__(self, filename):
block_data = []
block_data.append(line)
elif line.startswith('Text'):
data = {'desc':line, 'data':f.readline()}
data = {'desc': line, 'data': f.readline()}
self.texts.append(data)
elif line.startswith('Wire'):
data = {'desc':line, 'data':f.readline()}
data = {'desc': line, 'data': f.readline()}
self.wires.append(data)
elif line.startswith('Entry'):
data = {'desc':line, 'data':f.readline()}
data = {'desc': line, 'data': f.readline()}
self.entries.append(data)
elif line.startswith('Connection'):
data = {'desc':line}
data = {'desc': line}
self.conns.append(data)
elif line.startswith('NoConn'):
data = {'desc':line}
data = {'desc': line}
self.noconns.append(data)

elif building_block:
Expand All @@ -191,9 +220,11 @@ def __init__(self, filename):

def save(self, filename=None):
# check whether it has header, what means that sch file was loaded fine
if not self.header: return
if not self.header:
return

if not filename: filename = self.filename
if not filename:
filename = self.filename

# insert the header
to_write = []
Expand All @@ -214,7 +245,7 @@ def save(self, filename=None):
if sheet.shape:
line = 'S '
for key in sheet._S_KEYS:
line+= sheet.shape[key] + ' '
line += sheet.shape[key] + ' '
to_write += [line.rstrip() + '\n']
if sheet.unit:
line = 'U '
Expand Down

0 comments on commit 24bd891

Please sign in to comment.