From dd63b169f177389602e17bc6ced53bd0f1ba0de3 Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Sat, 10 Oct 2015 16:51:21 -0400 Subject: Allow files to be read from strings per #37 Adds a loads() method to the top level module which generates a GerberFile or ExcellonFile from a string --- gerber/excellon.py | 50 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) (limited to 'gerber/excellon.py') diff --git a/gerber/excellon.py b/gerber/excellon.py index d89b349..ba8573d 100755 --- a/gerber/excellon.py +++ b/gerber/excellon.py @@ -25,6 +25,7 @@ This module provides Excellon file classes and parsing utilities import math import operator +from cStringIO import StringIO from .excellon_statements import * from .cam import CamFile, FileSettings @@ -46,9 +47,28 @@ def read(filename): """ # File object should use settings from source file by default. - settings = FileSettings(**detect_excellon_format(filename)) + with open(filename, 'r') as f: + data = f.read() + settings = FileSettings(**detect_excellon_format(data)) return ExcellonParser(settings).parse(filename) +def loads(data): + """ Read data from string and return an ExcellonFile + Parameters + ---------- + data : string + string containing Excellon file contents + + Returns + ------- + file : :class:`gerber.excellon.ExcellonFile` + An ExcellonFile created from the specified file. + + """ + # File object should use settings from source file by default. + settings = FileSettings(**detect_excellon_format(data)) + return ExcellonParser(settings).parse_raw(data) + class DrillHit(object): def __init__(self, tool, position): @@ -302,9 +322,12 @@ class ExcellonParser(object): def parse(self, filename): with open(filename, 'r') as f: - for line in f: - self._parse(line.strip()) - + data = f.read() + return self.parse_raw(data, filename) + + def parse_raw(self, data, filename=None): + for line in StringIO(data): + self._parse(line.strip()) for stmt in self.statements: stmt.units = self.units return ExcellonFile(self.statements, self.tools, self.hits, @@ -428,14 +451,13 @@ class ExcellonParser(object): zeros=self.zeros, notation=self.notation) -def detect_excellon_format(filename): +def detect_excellon_format(data=None, filename=None): """ Detect excellon file decimal format and zero-suppression settings. Parameters ---------- - filename : string - Name of the file to parse. This does not check if the file is actually - an Excellon file, so do that before calling this. + data : string + String containing contents of Excellon file. Returns ------- @@ -449,10 +471,16 @@ def detect_excellon_format(filename): detected_format = None zeros_options = ('leading', 'trailing', ) format_options = ((2, 4), (2, 5), (3, 3),) + + if data is None and filename is None: + raise ValueError('Either data or filename arguments must be provided') + if data is None: + with open(filename, 'r') as f: + data = f.read() # Check for obvious clues: p = ExcellonParser() - p.parse(filename) + p.parse_raw(data) # Get zero_suppression from a unit statement zero_statements = [stmt.zeros for stmt in p.statements @@ -485,8 +513,8 @@ def detect_excellon_format(filename): settings = FileSettings(zeros=zeros, format=fmt) try: p = ExcellonParser(settings) - p.parse(filename) - size = tuple([t[1] - t[0] for t in p.bounds]) + p.parse_raw(data) + size = tuple([t[0] - t[1] for t in p.bounds]) hole_area = 0.0 for hit in p.hits: tool = hit.tool -- cgit