Source code for sr.tools.bom.geda
from __future__ import print_function
import hashlib
import os
import re
import subprocess
from sr.tools.environment import get_cache_dir
[docs]def file_is_geda_pcb(f):
"""Return true if the file is a gEDA PCB file."""
f.seek(0)
# 'PCB[' will occur at the start of one of the first 20 or so lines
for i in range(20):
if re.search(r"^\s*PCB[ \t]*\[", f.readline()) is not None:
return True
return False
[docs]class GSchem(dict):
"""
Reads in gEDA file.
:param str fname: The filename of the schematic.
"""
def __init__(self, fname):
"""Create a new gEDA schematic object."""
self.fname = fname
self.__load_bom()
def __export_bom(self, ofname):
command = 'gnetlist -g partslist1 -o %s %s' % (ofname, self.fname)
subprocess.check_call(command, shell=True)
def __load_bom(self):
cache_dir = get_cache_dir('bom', 'geda', 'bom')
ab = os.path.abspath(self.fname)
# Generate cache filename
h = hashlib.sha1()
h.update(ab.encode('UTF-8'))
cfname = os.path.join(cache_dir, h.hexdigest())
cache_good = False
if os.path.exists(cfname):
# Discover if the cache is still valid
schem_t = os.path.getmtime(ab)
cache_t = os.path.getmtime(cfname)
if cache_t > schem_t:
# Cache is good
cache_good = True
if not cache_good:
self.__export_bom(cfname)
else:
print("Using cached BOM for %s." % os.path.basename(self.fname))
self.__parse_bom_fname(cfname)
def __parse_bom_fname(self, fname):
f = open(fname, "r")
# Skip the first two lines
f.readline()
f.readline()
for line in f:
if line[0] == ".":
"Ignore lines beginning with '.'"
continue
fields = line.split()
value = fields[2].strip().lower()
id = fields[0].strip().upper()
self[id] = value
f.close()
[docs]class PCB:
"""
Read in a gEDA PCB file.
:param str fname: The filename of the PCB file.
"""
def __init__(self, fname):
"""Create a new PCB object."""
self.fname = fname
def __export_image(self, res, ofname):
cmd = 'pcb -x png --as-shown --layer-stack "outline,component,silk" ' \
'--dpi {dpi} --outfile {outfile} {filename}'
p = subprocess.Popen(cmd.format(dpi=res, outfile=ofname,
filename=self.fname), shell=True)
p.communicate()
p.wait()
def __export_xy(self, ofname):
p = subprocess.Popen("""pcb -x bom --xyfile %s %s""" %
(ofname, self.fname), shell=True)
p.communicate()
p.wait()
[docs] def get_image(self, res):
"""
Get an image of the PCB.
:returns: The contents of the image.
"""
cache_dir = get_cache_dir('bom', 'geda', 'pcbimg')
ab = os.path.abspath(self.fname)
# Generate cache filename
h = hashlib.sha1()
h.update(ab + str(res))
cfname = os.path.join(cache_dir, h.hexdigest())
cache_good = False
if os.path.exists(cfname):
img_t = os.path.getmtime(ab)
cache_t = os.path.getmtime(cfname)
if cache_t > img_t:
cache_good = True
if not cache_good:
self.__export_image(res, cfname)
else:
print('Using cached PCB image for %s.' %
os.path.basename(self.fname))
with open(cfname) as file:
img = file.read()
return img
[docs] def get_xy(self):
"""
Get XY file for the PCB.
:returns: The XY file contents.
"""
cache_dir = get_cache_dir('bom', 'geda', 'pcbxy')
ab = os.path.abspath(self.fname)
# Generate cache filename
h = hashlib.sha1()
h.update(ab)
cfname = os.path.join(cache_dir, h.hexdigest())
cache_good = False
if os.path.exists(cfname):
xy_t = os.path.getmtime(ab)
cache_t = os.path.getmtime(cfname)
if cache_t > xy_t:
cache_good = True
if not cache_good:
self.__export_xy(cfname)
else:
print("Using cached PCB xy-data for %s" %
os.path.basename(self.fname))
f = open(cfname, "r")
xy = f.read()
f.close()
return xy