Migrate to pytest (#111)

* Migrate to pytest

All tests were update to use pytest.

Tests were alse black formatted. Eventually all code
will be black formatted but need to merge some PRs first.
This commit is contained in:
Paulo Henrique Silva 2019-11-26 00:37:41 -03:00 committed by GitHub
parent 404384cf91
commit ef589a0640
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 2349 additions and 2097 deletions

View file

@ -1,4 +0,0 @@
[report]
omit =
*/python?.?/*
*/site-packages/nose/*

View file

@ -18,9 +18,7 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
- name: Test with pytest
run: |
pip install pytest
pytest

1
.gitignore vendored
View file

@ -48,3 +48,4 @@ Thumbs.db
# Virtual environment
venv
coverage.xml

View file

@ -1,6 +1,6 @@
PYTHON ?= python
NOSETESTS ?= nosetests
PYTEST ?= pytest
DOC_ROOT = doc
EXAMPLES = examples
@ -8,17 +8,17 @@ EXAMPLES = examples
.PHONY: clean
clean: doc-clean
find . -name '*.pyc' -delete
rm -rf coverage .coverage
rm -rf *.egg-info
rm -f coverage.xml
.PHONY: test
test:
$(NOSETESTS) -s -v gerber
$(PYTEST)
.PHONY: test-coverage
test-coverage:
rm -rf coverage .coverage
$(NOSETESTS) -s -v --with-coverage --cover-package=gerber
rm -rf coverage.xml
$(PYTEST) --cov=./ --cov-report=xml
.PHONY: install
install:

View file

@ -55,6 +55,6 @@ Dependencies for developing and testing pcb-tools are listed in requirements-dev
(venv)$ pip install -r requirements-dev.txt
(venv)$ pip install -e .
We use nose to run pcb-tools's suite of unittests and doctests.
We use [pytest](https://docs.pytest.org/en/latest/) to run pcb-tools's suite of unittests and doctests.
(venv)$ nosetests
(venv)$ pytest

View file

@ -3,385 +3,393 @@
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
from .tests import *
import pytest
from ..am_statements import *
from ..am_statements import inch, metric
def test_AMPrimitive_ctor():
for exposure in ('on', 'off', 'ON', 'OFF'):
for exposure in ("on", "off", "ON", "OFF"):
for code in (0, 1, 2, 4, 5, 6, 7, 20, 21, 22):
p = AMPrimitive(code, exposure)
assert_equal(p.code, code)
assert_equal(p.exposure, exposure.lower())
assert p.code == code
assert p.exposure == exposure.lower()
def test_AMPrimitive_validation():
assert_raises(TypeError, AMPrimitive, '1', 'off')
assert_raises(ValueError, AMPrimitive, 0, 'exposed')
assert_raises(ValueError, AMPrimitive, 3, 'off')
pytest.raises(TypeError, AMPrimitive, "1", "off")
pytest.raises(ValueError, AMPrimitive, 0, "exposed")
pytest.raises(ValueError, AMPrimitive, 3, "off")
def test_AMPrimitive_conversion():
p = AMPrimitive(4, 'on')
assert_raises(NotImplementedError, p.to_inch)
assert_raises(NotImplementedError, p.to_metric)
p = AMPrimitive(4, "on")
pytest.raises(NotImplementedError, p.to_inch)
pytest.raises(NotImplementedError, p.to_metric)
def test_AMCommentPrimitive_ctor():
c = AMCommentPrimitive(0, ' This is a comment *')
assert_equal(c.code, 0)
assert_equal(c.comment, 'This is a comment')
c = AMCommentPrimitive(0, " This is a comment *")
assert c.code == 0
assert c.comment == "This is a comment"
def test_AMCommentPrimitive_validation():
assert_raises(ValueError, AMCommentPrimitive, 1, 'This is a comment')
pytest.raises(ValueError, AMCommentPrimitive, 1, "This is a comment")
def test_AMCommentPrimitive_factory():
c = AMCommentPrimitive.from_gerber('0 Rectangle with rounded corners. *')
assert_equal(c.code, 0)
assert_equal(c.comment, 'Rectangle with rounded corners.')
c = AMCommentPrimitive.from_gerber("0 Rectangle with rounded corners. *")
assert c.code == 0
assert c.comment == "Rectangle with rounded corners."
def test_AMCommentPrimitive_dump():
c = AMCommentPrimitive(0, 'Rectangle with rounded corners.')
assert_equal(c.to_gerber(), '0 Rectangle with rounded corners. *')
c = AMCommentPrimitive(0, "Rectangle with rounded corners.")
assert c.to_gerber() == "0 Rectangle with rounded corners. *"
def test_AMCommentPrimitive_conversion():
c = AMCommentPrimitive(0, 'Rectangle with rounded corners.')
c = AMCommentPrimitive(0, "Rectangle with rounded corners.")
ci = c
cm = c
ci.to_inch()
cm.to_metric()
assert_equal(c, ci)
assert_equal(c, cm)
assert c == ci
assert c == cm
def test_AMCommentPrimitive_string():
c = AMCommentPrimitive(0, 'Test Comment')
assert_equal(str(c), '<Aperture Macro Comment: Test Comment>')
c = AMCommentPrimitive(0, "Test Comment")
assert str(c) == "<Aperture Macro Comment: Test Comment>"
def test_AMCirclePrimitive_ctor():
test_cases = ((1, 'on', 0, (0, 0)),
(1, 'off', 1, (0, 1)),
(1, 'on', 2.5, (0, 2)),
(1, 'off', 5.0, (3, 3)))
test_cases = (
(1, "on", 0, (0, 0)),
(1, "off", 1, (0, 1)),
(1, "on", 2.5, (0, 2)),
(1, "off", 5.0, (3, 3)),
)
for code, exposure, diameter, position in test_cases:
c = AMCirclePrimitive(code, exposure, diameter, position)
assert_equal(c.code, code)
assert_equal(c.exposure, exposure)
assert_equal(c.diameter, diameter)
assert_equal(c.position, position)
assert c.code == code
assert c.exposure == exposure
assert c.diameter == diameter
assert c.position == position
def test_AMCirclePrimitive_validation():
assert_raises(ValueError, AMCirclePrimitive, 2, 'on', 0, (0, 0))
pytest.raises(ValueError, AMCirclePrimitive, 2, "on", 0, (0, 0))
def test_AMCirclePrimitive_factory():
c = AMCirclePrimitive.from_gerber('1,0,5,0,0*')
assert_equal(c.code, 1)
assert_equal(c.exposure, 'off')
assert_equal(c.diameter, 5)
assert_equal(c.position, (0, 0))
c = AMCirclePrimitive.from_gerber("1,0,5,0,0*")
assert c.code == 1
assert c.exposure == "off"
assert c.diameter == 5
assert c.position == (0, 0)
def test_AMCirclePrimitive_dump():
c = AMCirclePrimitive(1, 'off', 5, (0, 0))
assert_equal(c.to_gerber(), '1,0,5,0,0*')
c = AMCirclePrimitive(1, 'on', 5, (0, 0))
assert_equal(c.to_gerber(), '1,1,5,0,0*')
c = AMCirclePrimitive(1, "off", 5, (0, 0))
assert c.to_gerber() == "1,0,5,0,0*"
c = AMCirclePrimitive(1, "on", 5, (0, 0))
assert c.to_gerber() == "1,1,5,0,0*"
def test_AMCirclePrimitive_conversion():
c = AMCirclePrimitive(1, 'off', 25.4, (25.4, 0))
c = AMCirclePrimitive(1, "off", 25.4, (25.4, 0))
c.to_inch()
assert_equal(c.diameter, 1)
assert_equal(c.position, (1, 0))
assert c.diameter == 1
assert c.position == (1, 0)
c = AMCirclePrimitive(1, 'off', 1, (1, 0))
c = AMCirclePrimitive(1, "off", 1, (1, 0))
c.to_metric()
assert_equal(c.diameter, 25.4)
assert_equal(c.position, (25.4, 0))
assert c.diameter == 25.4
assert c.position == (25.4, 0)
def test_AMVectorLinePrimitive_validation():
assert_raises(ValueError, AMVectorLinePrimitive,
3, 'on', 0.1, (0, 0), (3.3, 5.4), 0)
pytest.raises(
ValueError, AMVectorLinePrimitive, 3, "on", 0.1, (0, 0), (3.3, 5.4), 0
)
def test_AMVectorLinePrimitive_factory():
l = AMVectorLinePrimitive.from_gerber('20,1,0.9,0,0.45,12,0.45,0*')
assert_equal(l.code, 20)
assert_equal(l.exposure, 'on')
assert_equal(l.width, 0.9)
assert_equal(l.start, (0, 0.45))
assert_equal(l.end, (12, 0.45))
assert_equal(l.rotation, 0)
l = AMVectorLinePrimitive.from_gerber("20,1,0.9,0,0.45,12,0.45,0*")
assert l.code == 20
assert l.exposure == "on"
assert l.width == 0.9
assert l.start == (0, 0.45)
assert l.end == (12, 0.45)
assert l.rotation == 0
def test_AMVectorLinePrimitive_dump():
l = AMVectorLinePrimitive.from_gerber('20,1,0.9,0,0.45,12,0.45,0*')
assert_equal(l.to_gerber(), '20,1,0.9,0.0,0.45,12.0,0.45,0.0*')
l = AMVectorLinePrimitive.from_gerber("20,1,0.9,0,0.45,12,0.45,0*")
assert l.to_gerber() == "20,1,0.9,0.0,0.45,12.0,0.45,0.0*"
def test_AMVectorLinePrimtive_conversion():
l = AMVectorLinePrimitive(20, 'on', 25.4, (0, 0), (25.4, 25.4), 0)
l = AMVectorLinePrimitive(20, "on", 25.4, (0, 0), (25.4, 25.4), 0)
l.to_inch()
assert_equal(l.width, 1)
assert_equal(l.start, (0, 0))
assert_equal(l.end, (1, 1))
assert l.width == 1
assert l.start == (0, 0)
assert l.end == (1, 1)
l = AMVectorLinePrimitive(20, 'on', 1, (0, 0), (1, 1), 0)
l = AMVectorLinePrimitive(20, "on", 1, (0, 0), (1, 1), 0)
l.to_metric()
assert_equal(l.width, 25.4)
assert_equal(l.start, (0, 0))
assert_equal(l.end, (25.4, 25.4))
assert l.width == 25.4
assert l.start == (0, 0)
assert l.end == (25.4, 25.4)
def test_AMOutlinePrimitive_validation():
assert_raises(ValueError, AMOutlinePrimitive, 7, 'on',
(0, 0), [(3.3, 5.4), (4.0, 5.4), (0, 0)], 0)
assert_raises(ValueError, AMOutlinePrimitive, 4, 'on',
(0, 0), [(3.3, 5.4), (4.0, 5.4), (0, 1)], 0)
pytest.raises(
ValueError,
AMOutlinePrimitive,
7,
"on",
(0, 0),
[(3.3, 5.4), (4.0, 5.4), (0, 0)],
0,
)
pytest.raises(
ValueError,
AMOutlinePrimitive,
4,
"on",
(0, 0),
[(3.3, 5.4), (4.0, 5.4), (0, 1)],
0,
)
def test_AMOutlinePrimitive_factory():
o = AMOutlinePrimitive.from_gerber('4,1,3,0,0,3,3,3,0,0,0,0*')
assert_equal(o.code, 4)
assert_equal(o.exposure, 'on')
assert_equal(o.start_point, (0, 0))
assert_equal(o.points, [(3, 3), (3, 0), (0, 0)])
assert_equal(o.rotation, 0)
o = AMOutlinePrimitive.from_gerber("4,1,3,0,0,3,3,3,0,0,0,0*")
assert o.code == 4
assert o.exposure == "on"
assert o.start_point == (0, 0)
assert o.points == [(3, 3), (3, 0), (0, 0)]
assert o.rotation == 0
def test_AMOUtlinePrimitive_dump():
o = AMOutlinePrimitive(4, 'on', (0, 0), [(3, 3), (3, 0), (0, 0)], 0)
o = AMOutlinePrimitive(4, "on", (0, 0), [(3, 3), (3, 0), (0, 0)], 0)
# New lines don't matter for Gerber, but we insert them to make it easier to remove
# For test purposes we can ignore them
assert_equal(o.to_gerber().replace('\n', ''), '4,1,3,0,0,3,3,3,0,0,0,0*')
assert o.to_gerber().replace("\n", "") == "4,1,3,0,0,3,3,3,0,0,0,0*"
def test_AMOutlinePrimitive_conversion():
o = AMOutlinePrimitive(
4, 'on', (0, 0), [(25.4, 25.4), (25.4, 0), (0, 0)], 0)
o = AMOutlinePrimitive(4, "on", (0, 0), [(25.4, 25.4), (25.4, 0), (0, 0)], 0)
o.to_inch()
assert_equal(o.start_point, (0, 0))
assert_equal(o.points, ((1., 1.), (1., 0.), (0., 0.)))
assert o.start_point == (0, 0)
assert o.points == ((1.0, 1.0), (1.0, 0.0), (0.0, 0.0))
o = AMOutlinePrimitive(4, 'on', (0, 0), [(1, 1), (1, 0), (0, 0)], 0)
o = AMOutlinePrimitive(4, "on", (0, 0), [(1, 1), (1, 0), (0, 0)], 0)
o.to_metric()
assert_equal(o.start_point, (0, 0))
assert_equal(o.points, ((25.4, 25.4), (25.4, 0), (0, 0)))
assert o.start_point == (0, 0)
assert o.points == ((25.4, 25.4), (25.4, 0), (0, 0))
def test_AMPolygonPrimitive_validation():
assert_raises(ValueError, AMPolygonPrimitive, 6, 'on', 3, (3.3, 5.4), 3, 0)
assert_raises(ValueError, AMPolygonPrimitive, 5, 'on', 2, (3.3, 5.4), 3, 0)
assert_raises(ValueError, AMPolygonPrimitive, 5, 'on', 13, (3.3, 5.4), 3, 0)
pytest.raises(ValueError, AMPolygonPrimitive, 6, "on", 3, (3.3, 5.4), 3, 0)
pytest.raises(ValueError, AMPolygonPrimitive, 5, "on", 2, (3.3, 5.4), 3, 0)
pytest.raises(ValueError, AMPolygonPrimitive, 5, "on", 13, (3.3, 5.4), 3, 0)
def test_AMPolygonPrimitive_factory():
p = AMPolygonPrimitive.from_gerber('5,1,3,3.3,5.4,3,0')
assert_equal(p.code, 5)
assert_equal(p.exposure, 'on')
assert_equal(p.vertices, 3)
assert_equal(p.position, (3.3, 5.4))
assert_equal(p.diameter, 3)
assert_equal(p.rotation, 0)
p = AMPolygonPrimitive.from_gerber("5,1,3,3.3,5.4,3,0")
assert p.code == 5
assert p.exposure == "on"
assert p.vertices == 3
assert p.position == (3.3, 5.4)
assert p.diameter == 3
assert p.rotation == 0
def test_AMPolygonPrimitive_dump():
p = AMPolygonPrimitive(5, 'on', 3, (3.3, 5.4), 3, 0)
assert_equal(p.to_gerber(), '5,1,3,3.3,5.4,3,0*')
p = AMPolygonPrimitive(5, "on", 3, (3.3, 5.4), 3, 0)
assert p.to_gerber() == "5,1,3,3.3,5.4,3,0*"
def test_AMPolygonPrimitive_conversion():
p = AMPolygonPrimitive(5, 'off', 3, (25.4, 0), 25.4, 0)
p = AMPolygonPrimitive(5, "off", 3, (25.4, 0), 25.4, 0)
p.to_inch()
assert_equal(p.diameter, 1)
assert_equal(p.position, (1, 0))
assert p.diameter == 1
assert p.position == (1, 0)
p = AMPolygonPrimitive(5, 'off', 3, (1, 0), 1, 0)
p = AMPolygonPrimitive(5, "off", 3, (1, 0), 1, 0)
p.to_metric()
assert_equal(p.diameter, 25.4)
assert_equal(p.position, (25.4, 0))
assert p.diameter == 25.4
assert p.position == (25.4, 0)
def test_AMMoirePrimitive_validation():
assert_raises(ValueError, AMMoirePrimitive, 7,
(0, 0), 5.1, 0.2, 0.4, 6, 0.1, 6.1, 0)
pytest.raises(
ValueError, AMMoirePrimitive, 7, (0, 0), 5.1, 0.2, 0.4, 6, 0.1, 6.1, 0
)
def test_AMMoirePrimitive_factory():
m = AMMoirePrimitive.from_gerber('6,0,0,5,0.5,0.5,2,0.1,6,0*')
assert_equal(m.code, 6)
assert_equal(m.position, (0, 0))
assert_equal(m.diameter, 5)
assert_equal(m.ring_thickness, 0.5)
assert_equal(m.gap, 0.5)
assert_equal(m.max_rings, 2)
assert_equal(m.crosshair_thickness, 0.1)
assert_equal(m.crosshair_length, 6)
assert_equal(m.rotation, 0)
m = AMMoirePrimitive.from_gerber("6,0,0,5,0.5,0.5,2,0.1,6,0*")
assert m.code == 6
assert m.position == (0, 0)
assert m.diameter == 5
assert m.ring_thickness == 0.5
assert m.gap == 0.5
assert m.max_rings == 2
assert m.crosshair_thickness == 0.1
assert m.crosshair_length == 6
assert m.rotation == 0
def test_AMMoirePrimitive_dump():
m = AMMoirePrimitive.from_gerber('6,0,0,5,0.5,0.5,2,0.1,6,0*')
assert_equal(m.to_gerber(), '6,0,0,5.0,0.5,0.5,2,0.1,6.0,0.0*')
m = AMMoirePrimitive.from_gerber("6,0,0,5,0.5,0.5,2,0.1,6,0*")
assert m.to_gerber() == "6,0,0,5.0,0.5,0.5,2,0.1,6.0,0.0*"
def test_AMMoirePrimitive_conversion():
m = AMMoirePrimitive(6, (25.4, 25.4), 25.4, 25.4, 25.4, 6, 25.4, 25.4, 0)
m.to_inch()
assert_equal(m.position, (1., 1.))
assert_equal(m.diameter, 1.)
assert_equal(m.ring_thickness, 1.)
assert_equal(m.gap, 1.)
assert_equal(m.crosshair_thickness, 1.)
assert_equal(m.crosshair_length, 1.)
assert m.position == (1.0, 1.0)
assert m.diameter == 1.0
assert m.ring_thickness == 1.0
assert m.gap == 1.0
assert m.crosshair_thickness == 1.0
assert m.crosshair_length == 1.0
m = AMMoirePrimitive(6, (1, 1), 1, 1, 1, 6, 1, 1, 0)
m.to_metric()
assert_equal(m.position, (25.4, 25.4))
assert_equal(m.diameter, 25.4)
assert_equal(m.ring_thickness, 25.4)
assert_equal(m.gap, 25.4)
assert_equal(m.crosshair_thickness, 25.4)
assert_equal(m.crosshair_length, 25.4)
assert m.position == (25.4, 25.4)
assert m.diameter == 25.4
assert m.ring_thickness == 25.4
assert m.gap == 25.4
assert m.crosshair_thickness == 25.4
assert m.crosshair_length == 25.4
def test_AMThermalPrimitive_validation():
assert_raises(ValueError, AMThermalPrimitive, 8, (0.0, 0.0), 7, 5, 0.2, 0.0)
assert_raises(TypeError, AMThermalPrimitive, 7, (0.0, '0'), 7, 5, 0.2, 0.0)
pytest.raises(ValueError, AMThermalPrimitive, 8, (0.0, 0.0), 7, 5, 0.2, 0.0)
pytest.raises(TypeError, AMThermalPrimitive, 7, (0.0, "0"), 7, 5, 0.2, 0.0)
def test_AMThermalPrimitive_factory():
t = AMThermalPrimitive.from_gerber('7,0,0,7,6,0.2,45*')
assert_equal(t.code, 7)
assert_equal(t.position, (0, 0))
assert_equal(t.outer_diameter, 7)
assert_equal(t.inner_diameter, 6)
assert_equal(t.gap, 0.2)
assert_equal(t.rotation, 45)
t = AMThermalPrimitive.from_gerber("7,0,0,7,6,0.2,45*")
assert t.code == 7
assert t.position == (0, 0)
assert t.outer_diameter == 7
assert t.inner_diameter == 6
assert t.gap == 0.2
assert t.rotation == 45
def test_AMThermalPrimitive_dump():
t = AMThermalPrimitive.from_gerber('7,0,0,7,6,0.2,30*')
assert_equal(t.to_gerber(), '7,0,0,7.0,6.0,0.2,30.0*')
t = AMThermalPrimitive.from_gerber("7,0,0,7,6,0.2,30*")
assert t.to_gerber() == "7,0,0,7.0,6.0,0.2,30.0*"
def test_AMThermalPrimitive_conversion():
t = AMThermalPrimitive(7, (25.4, 25.4), 25.4, 25.4, 25.4, 0.0)
t.to_inch()
assert_equal(t.position, (1., 1.))
assert_equal(t.outer_diameter, 1.)
assert_equal(t.inner_diameter, 1.)
assert_equal(t.gap, 1.)
assert t.position == (1.0, 1.0)
assert t.outer_diameter == 1.0
assert t.inner_diameter == 1.0
assert t.gap == 1.0
t = AMThermalPrimitive(7, (1, 1), 1, 1, 1, 0)
t.to_metric()
assert_equal(t.position, (25.4, 25.4))
assert_equal(t.outer_diameter, 25.4)
assert_equal(t.inner_diameter, 25.4)
assert_equal(t.gap, 25.4)
assert t.position == (25.4, 25.4)
assert t.outer_diameter == 25.4
assert t.inner_diameter == 25.4
assert t.gap == 25.4
def test_AMCenterLinePrimitive_validation():
assert_raises(ValueError, AMCenterLinePrimitive,
22, 1, 0.2, 0.5, (0, 0), 0)
pytest.raises(ValueError, AMCenterLinePrimitive, 22, 1, 0.2, 0.5, (0, 0), 0)
def test_AMCenterLinePrimtive_factory():
l = AMCenterLinePrimitive.from_gerber('21,1,6.8,1.2,3.4,0.6,0*')
assert_equal(l.code, 21)
assert_equal(l.exposure, 'on')
assert_equal(l.width, 6.8)
assert_equal(l.height, 1.2)
assert_equal(l.center, (3.4, 0.6))
assert_equal(l.rotation, 0)
l = AMCenterLinePrimitive.from_gerber("21,1,6.8,1.2,3.4,0.6,0*")
assert l.code == 21
assert l.exposure == "on"
assert l.width == 6.8
assert l.height == 1.2
assert l.center == (3.4, 0.6)
assert l.rotation == 0
def test_AMCenterLinePrimitive_dump():
l = AMCenterLinePrimitive.from_gerber('21,1,6.8,1.2,3.4,0.6,0*')
assert_equal(l.to_gerber(), '21,1,6.8,1.2,3.4,0.6,0.0*')
l = AMCenterLinePrimitive.from_gerber("21,1,6.8,1.2,3.4,0.6,0*")
assert l.to_gerber() == "21,1,6.8,1.2,3.4,0.6,0.0*"
def test_AMCenterLinePrimitive_conversion():
l = AMCenterLinePrimitive(21, 'on', 25.4, 25.4, (25.4, 25.4), 0)
l = AMCenterLinePrimitive(21, "on", 25.4, 25.4, (25.4, 25.4), 0)
l.to_inch()
assert_equal(l.width, 1.)
assert_equal(l.height, 1.)
assert_equal(l.center, (1., 1.))
assert l.width == 1.0
assert l.height == 1.0
assert l.center == (1.0, 1.0)
l = AMCenterLinePrimitive(21, 'on', 1, 1, (1, 1), 0)
l = AMCenterLinePrimitive(21, "on", 1, 1, (1, 1), 0)
l.to_metric()
assert_equal(l.width, 25.4)
assert_equal(l.height, 25.4)
assert_equal(l.center, (25.4, 25.4))
assert l.width == 25.4
assert l.height == 25.4
assert l.center == (25.4, 25.4)
def test_AMLowerLeftLinePrimitive_validation():
assert_raises(ValueError, AMLowerLeftLinePrimitive,
23, 1, 0.2, 0.5, (0, 0), 0)
pytest.raises(ValueError, AMLowerLeftLinePrimitive, 23, 1, 0.2, 0.5, (0, 0), 0)
def test_AMLowerLeftLinePrimtive_factory():
l = AMLowerLeftLinePrimitive.from_gerber('22,1,6.8,1.2,3.4,0.6,0*')
assert_equal(l.code, 22)
assert_equal(l.exposure, 'on')
assert_equal(l.width, 6.8)
assert_equal(l.height, 1.2)
assert_equal(l.lower_left, (3.4, 0.6))
assert_equal(l.rotation, 0)
l = AMLowerLeftLinePrimitive.from_gerber("22,1,6.8,1.2,3.4,0.6,0*")
assert l.code == 22
assert l.exposure == "on"
assert l.width == 6.8
assert l.height == 1.2
assert l.lower_left == (3.4, 0.6)
assert l.rotation == 0
def test_AMLowerLeftLinePrimitive_dump():
l = AMLowerLeftLinePrimitive.from_gerber('22,1,6.8,1.2,3.4,0.6,0*')
assert_equal(l.to_gerber(), '22,1,6.8,1.2,3.4,0.6,0.0*')
l = AMLowerLeftLinePrimitive.from_gerber("22,1,6.8,1.2,3.4,0.6,0*")
assert l.to_gerber() == "22,1,6.8,1.2,3.4,0.6,0.0*"
def test_AMLowerLeftLinePrimitive_conversion():
l = AMLowerLeftLinePrimitive(22, 'on', 25.4, 25.4, (25.4, 25.4), 0)
l = AMLowerLeftLinePrimitive(22, "on", 25.4, 25.4, (25.4, 25.4), 0)
l.to_inch()
assert_equal(l.width, 1.)
assert_equal(l.height, 1.)
assert_equal(l.lower_left, (1., 1.))
assert l.width == 1.0
assert l.height == 1.0
assert l.lower_left == (1.0, 1.0)
l = AMLowerLeftLinePrimitive(22, 'on', 1, 1, (1, 1), 0)
l = AMLowerLeftLinePrimitive(22, "on", 1, 1, (1, 1), 0)
l.to_metric()
assert_equal(l.width, 25.4)
assert_equal(l.height, 25.4)
assert_equal(l.lower_left, (25.4, 25.4))
assert l.width == 25.4
assert l.height == 25.4
assert l.lower_left == (25.4, 25.4)
def test_AMUnsupportPrimitive():
u = AMUnsupportPrimitive.from_gerber('Test')
assert_equal(u.primitive, 'Test')
u = AMUnsupportPrimitive('Test')
assert_equal(u.to_gerber(), 'Test')
u = AMUnsupportPrimitive.from_gerber("Test")
assert u.primitive == "Test"
u = AMUnsupportPrimitive("Test")
assert u.to_gerber() == "Test"
def test_AMUnsupportPrimitive_smoketest():
u = AMUnsupportPrimitive.from_gerber('Test')
u = AMUnsupportPrimitive.from_gerber("Test")
u.to_inch()
u.to_metric()
def test_inch():
assert_equal(inch(25.4), 1)
assert inch(25.4) == 1
def test_metric():
assert_equal(metric(1), 25.4)
assert metric(1) == 25.4

View file

@ -8,63 +8,87 @@ import tempfile
from ..render.cairo_backend import GerberCairoContext
from ..rs274x import read
from .tests import *
from nose.tools import assert_tuple_equal
def _DISABLED_test_render_two_boxes():
"""Umaco exapmle of two boxes"""
_test_render('resources/example_two_square_boxes.gbr', 'golden/example_two_square_boxes.png')
_test_render(
"resources/example_two_square_boxes.gbr", "golden/example_two_square_boxes.png"
)
def _DISABLED_test_render_single_quadrant():
"""Umaco exapmle of a single quadrant arc"""
_test_render('resources/example_single_quadrant.gbr', 'golden/example_single_quadrant.png')
_test_render(
"resources/example_single_quadrant.gbr", "golden/example_single_quadrant.png"
)
def _DISABLED_test_render_simple_contour():
def _DISABLED_test_render_simple_contour():
"""Umaco exapmle of a simple arrow-shaped contour"""
gerber = _test_render('resources/example_simple_contour.gbr', 'golden/example_simple_contour.png')
gerber = _test_render(
"resources/example_simple_contour.gbr", "golden/example_simple_contour.png"
)
# Check the resulting dimensions
assert_tuple_equal(((2.0, 11.0), (1.0, 9.0)), gerber.bounding_box)
assert ((2.0, 11.0), (1.0, 9.0)) == gerber.bounding_box
def _DISABLED_test_render_single_contour_1():
"""Umaco example of a single contour
The resulting image for this test is used by other tests because they must generate the same output."""
_test_render('resources/example_single_contour_1.gbr', 'golden/example_single_contour.png')
_test_render(
"resources/example_single_contour_1.gbr", "golden/example_single_contour.png"
)
def _DISABLED_test_render_single_contour_2():
"""Umaco exapmle of a single contour, alternate contour end order
The resulting image for this test is used by other tests because they must generate the same output."""
_test_render('resources/example_single_contour_2.gbr', 'golden/example_single_contour.png')
_test_render(
"resources/example_single_contour_2.gbr", "golden/example_single_contour.png"
)
def _DISABLED_test_render_single_contour_3():
"""Umaco exapmle of a single contour with extra line"""
_test_render('resources/example_single_contour_3.gbr', 'golden/example_single_contour_3.png')
_test_render(
"resources/example_single_contour_3.gbr", "golden/example_single_contour_3.png"
)
def _DISABLED_test_render_not_overlapping_contour():
def _DISABLED_test_render_not_overlapping_contour():
"""Umaco example of D02 staring a second contour"""
_test_render('resources/example_not_overlapping_contour.gbr', 'golden/example_not_overlapping_contour.png')
_test_render(
"resources/example_not_overlapping_contour.gbr",
"golden/example_not_overlapping_contour.png",
)
def _DISABLED_test_render_not_overlapping_touching():
def _DISABLED_test_render_not_overlapping_touching():
"""Umaco example of D02 staring a second contour"""
_test_render('resources/example_not_overlapping_touching.gbr', 'golden/example_not_overlapping_touching.png')
_test_render(
"resources/example_not_overlapping_touching.gbr",
"golden/example_not_overlapping_touching.png",
)
def test_render_overlapping_touching():
"""Umaco example of D02 staring a second contour"""
_test_render('resources/example_overlapping_touching.gbr', 'golden/example_overlapping_touching.png')
_test_render(
"resources/example_overlapping_touching.gbr",
"golden/example_overlapping_touching.png",
)
def test_render_overlapping_contour():
"""Umaco example of D02 staring a second contour"""
_test_render('resources/example_overlapping_contour.gbr', 'golden/example_overlapping_contour.png')
_test_render(
"resources/example_overlapping_contour.gbr",
"golden/example_overlapping_contour.png",
)
def _DISABLED_test_render_level_holes():
@ -72,82 +96,107 @@ def _DISABLED_test_render_level_holes():
# TODO This is clearly rendering wrong. I'm temporarily checking this in because there are more
# rendering fixes in the related repository that may resolve these.
_test_render('resources/example_level_holes.gbr', 'golden/example_overlapping_contour.png')
_test_render(
"resources/example_level_holes.gbr", "golden/example_overlapping_contour.png"
)
def _DISABLED_test_render_cutin():
"""Umaco example of using a cutin"""
# TODO This is clearly rendering wrong.
_test_render('resources/example_cutin.gbr', 'golden/example_cutin.png', '/Users/ham/Desktop/cutin.png')
_test_render(
"resources/example_cutin.gbr",
"golden/example_cutin.png",
"/Users/ham/Desktop/cutin.png",
)
def _DISABLED_test_render_fully_coincident():
def _DISABLED_test_render_fully_coincident():
"""Umaco example of coincident lines rendering two contours"""
_test_render('resources/example_fully_coincident.gbr', 'golden/example_fully_coincident.png')
_test_render(
"resources/example_fully_coincident.gbr", "golden/example_fully_coincident.png"
)
def _DISABLED_test_render_coincident_hole():
def _DISABLED_test_render_coincident_hole():
"""Umaco example of coincident lines rendering a hole in the contour"""
_test_render('resources/example_coincident_hole.gbr', 'golden/example_coincident_hole.png')
_test_render(
"resources/example_coincident_hole.gbr", "golden/example_coincident_hole.png"
)
def test_render_cutin_multiple():
"""Umaco example of a region with multiple cutins"""
_test_render('resources/example_cutin_multiple.gbr', 'golden/example_cutin_multiple.png')
_test_render(
"resources/example_cutin_multiple.gbr", "golden/example_cutin_multiple.png"
)
def _DISABLED_test_flash_circle():
"""Umaco example a simple circular flash with and without a hole"""
_test_render('resources/example_flash_circle.gbr', 'golden/example_flash_circle.png',
'/Users/ham/Desktop/flashcircle.png')
_test_render(
"resources/example_flash_circle.gbr",
"golden/example_flash_circle.png",
"/Users/ham/Desktop/flashcircle.png",
)
def _DISABLED_test_flash_rectangle():
"""Umaco example a simple rectangular flash with and without a hole"""
_test_render('resources/example_flash_rectangle.gbr', 'golden/example_flash_rectangle.png')
_test_render(
"resources/example_flash_rectangle.gbr", "golden/example_flash_rectangle.png"
)
def _DISABLED_test_flash_obround():
"""Umaco example a simple obround flash with and without a hole"""
_test_render('resources/example_flash_obround.gbr', 'golden/example_flash_obround.png')
_test_render(
"resources/example_flash_obround.gbr", "golden/example_flash_obround.png"
)
def _DISABLED_test_flash_polygon():
"""Umaco example a simple polygon flash with and without a hole"""
_test_render('resources/example_flash_polygon.gbr', 'golden/example_flash_polygon.png')
_test_render(
"resources/example_flash_polygon.gbr", "golden/example_flash_polygon.png"
)
def _DISABLED_test_holes_dont_clear():
"""Umaco example that an aperture with a hole does not clear the area"""
_test_render('resources/example_holes_dont_clear.gbr', 'golden/example_holes_dont_clear.png')
_test_render(
"resources/example_holes_dont_clear.gbr", "golden/example_holes_dont_clear.png"
)
def _DISABLED_test_render_am_exposure_modifier():
"""Umaco example that an aperture macro with a hole does not clear the area"""
_test_render('resources/example_am_exposure_modifier.gbr', 'golden/example_am_exposure_modifier.png')
_test_render(
"resources/example_am_exposure_modifier.gbr",
"golden/example_am_exposure_modifier.png",
)
def test_render_svg_simple_contour():
"""Example of rendering to an SVG file"""
_test_simple_render_svg('resources/example_simple_contour.gbr')
_test_simple_render_svg("resources/example_simple_contour.gbr")
def _resolve_path(path):
return os.path.join(os.path.dirname(__file__),
path)
return os.path.join(os.path.dirname(__file__), path)
def _test_render(gerber_path, png_expected_path, create_output_path = None):
def _test_render(gerber_path, png_expected_path, create_output_path=None):
"""Render the gerber file and compare to the expected PNG output.
Parameters
@ -176,21 +225,24 @@ def _test_render(gerber_path, png_expected_path, create_output_path = None):
# If we want to write the file bytes, do it now. This happens
if create_output_path:
with open(create_output_path, 'wb') as out_file:
with open(create_output_path, "wb") as out_file:
out_file.write(actual_bytes)
# Creating the output is dangerous - it could overwrite the expected result.
# So if we are creating the output, we make the test fail on purpose so you
# won't forget to disable this
assert_false(True, 'Test created the output %s. This needs to be disabled to make sure the test behaves correctly' % (create_output_path,))
assert not True, (
"Test created the output %s. This needs to be disabled to make sure the test behaves correctly"
% (create_output_path,)
)
# Read the expected PNG file
with open(png_expected_path, 'rb') as expected_file:
with open(png_expected_path, "rb") as expected_file:
expected_bytes = expected_file.read()
# Don't directly use assert_equal otherwise any failure pollutes the test results
equal = (expected_bytes == actual_bytes)
assert_true(equal)
equal = expected_bytes == actual_bytes
assert equal
return gerber
@ -214,14 +266,14 @@ def _test_simple_render_svg(gerber_path):
gerber.render(ctx)
temp_dir = tempfile.mkdtemp()
svg_temp_path = os.path.join(temp_dir, 'output.svg')
svg_temp_path = os.path.join(temp_dir, "output.svg")
assert_false(os.path.exists(svg_temp_path))
assert not os.path.exists(svg_temp_path)
ctx.dump(svg_temp_path)
assert_true(os.path.exists(svg_temp_path))
assert os.path.exists(svg_temp_path)
with open(svg_temp_path, 'r') as expected_file:
with open(svg_temp_path, "r") as expected_file:
expected_bytes = expected_file.read()
assert_equal(expected_bytes[:38], '<?xml version="1.0" encoding="UTF-8"?>')
assert expected_bytes[:38] == '<?xml version="1.0" encoding="UTF-8"?>'
shutil.rmtree(temp_dir)

View file

@ -3,56 +3,57 @@
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
import pytest
from ..cam import CamFile, FileSettings
from .tests import *
def test_filesettings_defaults():
""" Test FileSettings default values
"""
fs = FileSettings()
assert_equal(fs.format, (2, 5))
assert_equal(fs.notation, 'absolute')
assert_equal(fs.zero_suppression, 'trailing')
assert_equal(fs.units, 'inch')
assert fs.format == (2, 5)
assert fs.notation == "absolute"
assert fs.zero_suppression == "trailing"
assert fs.units == "inch"
def test_filesettings_dict():
""" Test FileSettings Dict
"""
fs = FileSettings()
assert_equal(fs['format'], (2, 5))
assert_equal(fs['notation'], 'absolute')
assert_equal(fs['zero_suppression'], 'trailing')
assert_equal(fs['units'], 'inch')
assert fs["format"] == (2, 5)
assert fs["notation"] == "absolute"
assert fs["zero_suppression"] == "trailing"
assert fs["units"] == "inch"
def test_filesettings_assign():
""" Test FileSettings attribute assignment
"""
fs = FileSettings()
fs.units = 'test1'
fs.notation = 'test2'
fs.zero_suppression = 'test3'
fs.format = 'test4'
assert_equal(fs.units, 'test1')
assert_equal(fs.notation, 'test2')
assert_equal(fs.zero_suppression, 'test3')
assert_equal(fs.format, 'test4')
fs.units = "test1"
fs.notation = "test2"
fs.zero_suppression = "test3"
fs.format = "test4"
assert fs.units == "test1"
assert fs.notation == "test2"
assert fs.zero_suppression == "test3"
assert fs.format == "test4"
def test_filesettings_dict_assign():
""" Test FileSettings dict-style attribute assignment
"""
fs = FileSettings()
fs['units'] = 'metric'
fs['notation'] = 'incremental'
fs['zero_suppression'] = 'leading'
fs['format'] = (1, 2)
assert_equal(fs.units, 'metric')
assert_equal(fs.notation, 'incremental')
assert_equal(fs.zero_suppression, 'leading')
assert_equal(fs.format, (1, 2))
fs["units"] = "metric"
fs["notation"] = "incremental"
fs["zero_suppression"] = "leading"
fs["format"] = (1, 2)
assert fs.units == "metric"
assert fs.notation == "incremental"
assert fs.zero_suppression == "leading"
assert fs.format == (1, 2)
def test_camfile_init():
@ -65,7 +66,7 @@ def test_camfile_settings():
""" Test CamFile Default Settings
"""
cf = CamFile()
assert_equal(cf.settings, FileSettings())
assert cf.settings == FileSettings()
def test_bounds_override_smoketest():
@ -77,73 +78,74 @@ def test_zeros():
""" Test zero/zero_suppression interaction
"""
fs = FileSettings()
assert_equal(fs.zero_suppression, 'trailing')
assert_equal(fs.zeros, 'leading')
assert fs.zero_suppression == "trailing"
assert fs.zeros == "leading"
fs['zero_suppression'] = 'leading'
assert_equal(fs.zero_suppression, 'leading')
assert_equal(fs.zeros, 'trailing')
fs["zero_suppression"] = "leading"
assert fs.zero_suppression == "leading"
assert fs.zeros == "trailing"
fs.zero_suppression = 'trailing'
assert_equal(fs.zero_suppression, 'trailing')
assert_equal(fs.zeros, 'leading')
fs.zero_suppression = "trailing"
assert fs.zero_suppression == "trailing"
assert fs.zeros == "leading"
fs['zeros'] = 'trailing'
assert_equal(fs.zeros, 'trailing')
assert_equal(fs.zero_suppression, 'leading')
fs["zeros"] = "trailing"
assert fs.zeros == "trailing"
assert fs.zero_suppression == "leading"
fs.zeros = 'leading'
assert_equal(fs.zeros, 'leading')
assert_equal(fs.zero_suppression, 'trailing')
fs.zeros = "leading"
assert fs.zeros == "leading"
assert fs.zero_suppression == "trailing"
fs = FileSettings(zeros='leading')
assert_equal(fs.zeros, 'leading')
assert_equal(fs.zero_suppression, 'trailing')
fs = FileSettings(zeros="leading")
assert fs.zeros == "leading"
assert fs.zero_suppression == "trailing"
fs = FileSettings(zero_suppression='leading')
assert_equal(fs.zeros, 'trailing')
assert_equal(fs.zero_suppression, 'leading')
fs = FileSettings(zero_suppression="leading")
assert fs.zeros == "trailing"
assert fs.zero_suppression == "leading"
fs = FileSettings(zeros='leading', zero_suppression='trailing')
assert_equal(fs.zeros, 'leading')
assert_equal(fs.zero_suppression, 'trailing')
fs = FileSettings(zeros="leading", zero_suppression="trailing")
assert fs.zeros == "leading"
assert fs.zero_suppression == "trailing"
fs = FileSettings(zeros='trailing', zero_suppression='leading')
assert_equal(fs.zeros, 'trailing')
assert_equal(fs.zero_suppression, 'leading')
fs = FileSettings(zeros="trailing", zero_suppression="leading")
assert fs.zeros == "trailing"
assert fs.zero_suppression == "leading"
def test_filesettings_validation():
""" Test FileSettings constructor argument validation
"""
# absolute-ish is not a valid notation
assert_raises(ValueError, FileSettings, 'absolute-ish',
'inch', None, (2, 5), None)
pytest.raises(ValueError, FileSettings, "absolute-ish", "inch", None, (2, 5), None)
# degrees kelvin isn't a valid unit for a CAM file
assert_raises(ValueError, FileSettings, 'absolute',
'degrees kelvin', None, (2, 5), None)
pytest.raises(
ValueError, FileSettings, "absolute", "degrees kelvin", None, (2, 5), None
)
assert_raises(ValueError, FileSettings, 'absolute',
'inch', 'leading', (2, 5), 'leading')
pytest.raises(
ValueError, FileSettings, "absolute", "inch", "leading", (2, 5), "leading"
)
# Technnically this should be an error, but Eangle files often do this incorrectly so we
# allow it
#assert_raises(ValueError, FileSettings, 'absolute',
# pytest.raises(ValueError, FileSettings, 'absolute',
# 'inch', 'following', (2, 5), None)
assert_raises(ValueError, FileSettings, 'absolute',
'inch', None, (2, 5), 'following')
assert_raises(ValueError, FileSettings, 'absolute',
'inch', None, (2, 5, 6), None)
pytest.raises(
ValueError, FileSettings, "absolute", "inch", None, (2, 5), "following"
)
pytest.raises(ValueError, FileSettings, "absolute", "inch", None, (2, 5, 6), None)
def test_key_validation():
fs = FileSettings()
assert_raises(KeyError, fs.__getitem__, 'octopus')
assert_raises(KeyError, fs.__setitem__, 'octopus', 'do not care')
assert_raises(ValueError, fs.__setitem__, 'notation', 'absolute-ish')
assert_raises(ValueError, fs.__setitem__, 'units', 'degrees kelvin')
assert_raises(ValueError, fs.__setitem__, 'zero_suppression', 'following')
assert_raises(ValueError, fs.__setitem__, 'zeros', 'following')
assert_raises(ValueError, fs.__setitem__, 'format', (2, 5, 6))
pytest.raises(KeyError, fs.__getitem__, "octopus")
pytest.raises(KeyError, fs.__setitem__, "octopus", "do not care")
pytest.raises(ValueError, fs.__setitem__, "notation", "absolute-ish")
pytest.raises(ValueError, fs.__setitem__, "units", "degrees kelvin")
pytest.raises(ValueError, fs.__setitem__, "zero_suppression", "following")
pytest.raises(ValueError, fs.__setitem__, "zeros", "following")
pytest.raises(ValueError, fs.__setitem__, "format", (2, 5, 6))

View file

@ -6,15 +6,12 @@ from ..exceptions import ParseError
from ..common import read, loads
from ..excellon import ExcellonFile
from ..rs274x import GerberFile
from .tests import *
import os
import pytest
NCDRILL_FILE = os.path.join(os.path.dirname(__file__),
'resources/ncdrill.DRD')
TOP_COPPER_FILE = os.path.join(os.path.dirname(__file__),
'resources/top_copper.GTL')
NCDRILL_FILE = os.path.join(os.path.dirname(__file__), "resources/ncdrill.DRD")
TOP_COPPER_FILE = os.path.join(os.path.dirname(__file__), "resources/top_copper.GTL")
def test_file_type_detection():
@ -22,20 +19,20 @@ def test_file_type_detection():
"""
ncdrill = read(NCDRILL_FILE)
top_copper = read(TOP_COPPER_FILE)
assert_true(isinstance(ncdrill, ExcellonFile))
assert_true(isinstance(top_copper, GerberFile))
assert isinstance(ncdrill, ExcellonFile)
assert isinstance(top_copper, GerberFile)
def test_load_from_string():
with open(NCDRILL_FILE, 'rU') as f:
with open(NCDRILL_FILE, "rU") as f:
ncdrill = loads(f.read())
with open(TOP_COPPER_FILE, 'rU') as f:
with open(TOP_COPPER_FILE, "rU") as f:
top_copper = loads(f.read())
assert_true(isinstance(ncdrill, ExcellonFile))
assert_true(isinstance(top_copper, GerberFile))
assert isinstance(ncdrill, ExcellonFile)
assert isinstance(top_copper, GerberFile)
def test_file_type_validation():
""" Test file format validation
"""
assert_raises(ParseError, read, __file__)
pytest.raises(ParseError, read, __file__)

View file

@ -3,16 +3,15 @@
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
import os
import pytest
from ..cam import FileSettings
from ..excellon import read, detect_excellon_format, ExcellonFile, ExcellonParser
from ..excellon import DrillHit, DrillSlot
from ..excellon_statements import ExcellonTool, RouteModeStmt
from .tests import *
NCDRILL_FILE = os.path.join(os.path.dirname(__file__),
'resources/ncdrill.DRD')
NCDRILL_FILE = os.path.join(os.path.dirname(__file__), "resources/ncdrill.DRD")
def test_format_detection():
@ -21,320 +20,327 @@ def test_format_detection():
with open(NCDRILL_FILE, "rU") as f:
data = f.read()
settings = detect_excellon_format(data)
assert_equal(settings['format'], (2, 4))
assert_equal(settings['zeros'], 'trailing')
assert settings["format"] == (2, 4)
assert settings["zeros"] == "trailing"
settings = detect_excellon_format(filename=NCDRILL_FILE)
assert_equal(settings['format'], (2, 4))
assert_equal(settings['zeros'], 'trailing')
assert settings["format"] == (2, 4)
assert settings["zeros"] == "trailing"
def test_read():
ncdrill = read(NCDRILL_FILE)
assert(isinstance(ncdrill, ExcellonFile))
assert isinstance(ncdrill, ExcellonFile)
def test_write():
ncdrill = read(NCDRILL_FILE)
ncdrill.write('test.ncd')
ncdrill.write("test.ncd")
with open(NCDRILL_FILE, "rU") as src:
srclines = src.readlines()
with open('test.ncd', "rU") as res:
with open("test.ncd", "rU") as res:
for idx, line in enumerate(res):
assert_equal(line.strip(), srclines[idx].strip())
os.remove('test.ncd')
assert line.strip() == srclines[idx].strip()
os.remove("test.ncd")
def test_read_settings():
ncdrill = read(NCDRILL_FILE)
assert_equal(ncdrill.settings['format'], (2, 4))
assert_equal(ncdrill.settings['zeros'], 'trailing')
assert ncdrill.settings["format"] == (2, 4)
assert ncdrill.settings["zeros"] == "trailing"
def test_bounding_box():
ncdrill = read(NCDRILL_FILE)
xbound, ybound = ncdrill.bounding_box
assert_array_almost_equal(xbound, (0.1300, 2.1430))
assert_array_almost_equal(ybound, (0.3946, 1.7164))
pytest.approx(xbound, (0.1300, 2.1430))
pytest.approx(ybound, (0.3946, 1.7164))
def test_report():
ncdrill = read(NCDRILL_FILE)
rprt = ncdrill.report()
def test_conversion():
import copy
ncdrill = read(NCDRILL_FILE)
assert_equal(ncdrill.settings.units, 'inch')
assert ncdrill.settings.units == "inch"
ncdrill_inch = copy.deepcopy(ncdrill)
ncdrill.to_metric()
assert_equal(ncdrill.settings.units, 'metric')
assert ncdrill.settings.units == "metric"
for tool in iter(ncdrill_inch.tools.values()):
tool.to_metric()
for statement in ncdrill_inch.statements:
statement.to_metric()
for m_tool, i_tool in zip(iter(ncdrill.tools.values()),
iter(ncdrill_inch.tools.values())):
assert_equal(i_tool, m_tool)
for m_tool, i_tool in zip(
iter(ncdrill.tools.values()), iter(ncdrill_inch.tools.values())
):
assert i_tool == m_tool
for m, i in zip(ncdrill.primitives, ncdrill_inch.primitives):
assert_equal(m.position, i.position, '%s not equal to %s' % (m, i))
assert_equal(m.diameter, i.diameter, '%s not equal to %s' % (m, i))
assert m.position == i.position, "%s not equal to %s" % (m, i)
assert m.diameter == i.diameter, "%s not equal to %s" % (m, i)
def test_parser_hole_count():
settings = FileSettings(**detect_excellon_format(NCDRILL_FILE))
p = ExcellonParser(settings)
p.parse(NCDRILL_FILE)
assert_equal(p.hole_count, 36)
assert p.hole_count == 36
def test_parser_hole_sizes():
settings = FileSettings(**detect_excellon_format(NCDRILL_FILE))
p = ExcellonParser(settings)
p.parse(NCDRILL_FILE)
assert_equal(p.hole_sizes, [0.0236, 0.0354, 0.04, 0.126, 0.128])
assert p.hole_sizes == [0.0236, 0.0354, 0.04, 0.126, 0.128]
def test_parse_whitespace():
p = ExcellonParser(FileSettings())
assert_equal(p._parse_line(' '), None)
assert p._parse_line(" ") == None
def test_parse_comment():
p = ExcellonParser(FileSettings())
p._parse_line(';A comment')
assert_equal(p.statements[0].comment, 'A comment')
p._parse_line(";A comment")
assert p.statements[0].comment == "A comment"
def test_parse_format_comment():
p = ExcellonParser(FileSettings())
p._parse_line('; FILE_FORMAT=9:9 ')
assert_equal(p.format, (9, 9))
p._parse_line("; FILE_FORMAT=9:9 ")
assert p.format == (9, 9)
def test_parse_header():
p = ExcellonParser(FileSettings())
p._parse_line('M48 ')
assert_equal(p.state, 'HEADER')
p._parse_line('M95 ')
assert_equal(p.state, 'DRILL')
p._parse_line("M48 ")
assert p.state == "HEADER"
p._parse_line("M95 ")
assert p.state == "DRILL"
def test_parse_rout():
p = ExcellonParser(FileSettings())
p._parse_line('G00X040944Y019842')
assert_equal(p.state, 'ROUT')
p._parse_line('G05 ')
assert_equal(p.state, 'DRILL')
p._parse_line("G00X040944Y019842")
assert p.state == "ROUT"
p._parse_line("G05 ")
assert p.state == "DRILL"
def test_parse_version():
p = ExcellonParser(FileSettings())
p._parse_line('VER,1 ')
assert_equal(p.statements[0].version, 1)
p._parse_line('VER,2 ')
assert_equal(p.statements[1].version, 2)
p._parse_line("VER,1 ")
assert p.statements[0].version == 1
p._parse_line("VER,2 ")
assert p.statements[1].version == 2
def test_parse_format():
p = ExcellonParser(FileSettings())
p._parse_line('FMAT,1 ')
assert_equal(p.statements[0].format, 1)
p._parse_line('FMAT,2 ')
assert_equal(p.statements[1].format, 2)
p._parse_line("FMAT,1 ")
assert p.statements[0].format == 1
p._parse_line("FMAT,2 ")
assert p.statements[1].format == 2
def test_parse_units():
settings = FileSettings(units='inch', zeros='trailing')
settings = FileSettings(units="inch", zeros="trailing")
p = ExcellonParser(settings)
p._parse_line(';METRIC,LZ')
assert_equal(p.units, 'inch')
assert_equal(p.zeros, 'trailing')
p._parse_line('METRIC,LZ')
assert_equal(p.units, 'metric')
assert_equal(p.zeros, 'leading')
p._parse_line(";METRIC,LZ")
assert p.units == "inch"
assert p.zeros == "trailing"
p._parse_line("METRIC,LZ")
assert p.units == "metric"
assert p.zeros == "leading"
def test_parse_incremental_mode():
settings = FileSettings(units='inch', zeros='trailing')
settings = FileSettings(units="inch", zeros="trailing")
p = ExcellonParser(settings)
assert_equal(p.notation, 'absolute')
p._parse_line('ICI,ON ')
assert_equal(p.notation, 'incremental')
p._parse_line('ICI,OFF ')
assert_equal(p.notation, 'absolute')
assert p.notation == "absolute"
p._parse_line("ICI,ON ")
assert p.notation == "incremental"
p._parse_line("ICI,OFF ")
assert p.notation == "absolute"
def test_parse_absolute_mode():
settings = FileSettings(units='inch', zeros='trailing')
settings = FileSettings(units="inch", zeros="trailing")
p = ExcellonParser(settings)
assert_equal(p.notation, 'absolute')
p._parse_line('ICI,ON ')
assert_equal(p.notation, 'incremental')
p._parse_line('G90 ')
assert_equal(p.notation, 'absolute')
assert p.notation == "absolute"
p._parse_line("ICI,ON ")
assert p.notation == "incremental"
p._parse_line("G90 ")
assert p.notation == "absolute"
def test_parse_repeat_hole():
p = ExcellonParser(FileSettings())
p.active_tool = ExcellonTool(FileSettings(), number=8)
p._parse_line('R03X1.5Y1.5')
assert_equal(p.statements[0].count, 3)
p._parse_line("R03X1.5Y1.5")
assert p.statements[0].count == 3
def test_parse_incremental_position():
p = ExcellonParser(FileSettings(notation='incremental'))
p._parse_line('X01Y01')
p._parse_line('X01Y01')
assert_equal(p.pos, [2., 2.])
p = ExcellonParser(FileSettings(notation="incremental"))
p._parse_line("X01Y01")
p._parse_line("X01Y01")
assert p.pos == [2.0, 2.0]
def test_parse_unknown():
p = ExcellonParser(FileSettings())
p._parse_line('Not A Valid Statement')
assert_equal(p.statements[0].stmt, 'Not A Valid Statement')
p._parse_line("Not A Valid Statement")
assert p.statements[0].stmt == "Not A Valid Statement"
def test_drill_hit_units_conversion():
""" Test unit conversion for drill hits
"""
# Inch hit
settings = FileSettings(units='inch')
settings = FileSettings(units="inch")
tool = ExcellonTool(settings, diameter=1.0)
hit = DrillHit(tool, (1.0, 1.0))
assert_equal(hit.tool.settings.units, 'inch')
assert_equal(hit.tool.diameter, 1.0)
assert_equal(hit.position, (1.0, 1.0))
assert hit.tool.settings.units == "inch"
assert hit.tool.diameter == 1.0
assert hit.position == (1.0, 1.0)
# No Effect
hit.to_inch()
assert_equal(hit.tool.settings.units, 'inch')
assert_equal(hit.tool.diameter, 1.0)
assert_equal(hit.position, (1.0, 1.0))
assert hit.tool.settings.units == "inch"
assert hit.tool.diameter == 1.0
assert hit.position == (1.0, 1.0)
# Should convert
hit.to_metric()
assert_equal(hit.tool.settings.units, 'metric')
assert_equal(hit.tool.diameter, 25.4)
assert_equal(hit.position, (25.4, 25.4))
assert hit.tool.settings.units == "metric"
assert hit.tool.diameter == 25.4
assert hit.position == (25.4, 25.4)
# No Effect
hit.to_metric()
assert_equal(hit.tool.settings.units, 'metric')
assert_equal(hit.tool.diameter, 25.4)
assert_equal(hit.position, (25.4, 25.4))
assert hit.tool.settings.units == "metric"
assert hit.tool.diameter == 25.4
assert hit.position == (25.4, 25.4)
# Convert back to inch
hit.to_inch()
assert_equal(hit.tool.settings.units, 'inch')
assert_equal(hit.tool.diameter, 1.0)
assert_equal(hit.position, (1.0, 1.0))
assert hit.tool.settings.units == "inch"
assert hit.tool.diameter == 1.0
assert hit.position == (1.0, 1.0)
def test_drill_hit_offset():
TEST_VECTORS = [
((0.0 ,0.0), (0.0, 1.0), (0.0, 1.0)),
((0.0, 0.0), (0.0, 1.0), (0.0, 1.0)),
((0.0, 0.0), (1.0, 1.0), (1.0, 1.0)),
((1.0, 1.0), (0.0, -1.0), (1.0, 0.0)),
((1.0, 1.0), (-1.0, -1.0), (0.0, 0.0)),
]
for position, offset, expected in TEST_VECTORS:
settings = FileSettings(units='inch')
settings = FileSettings(units="inch")
tool = ExcellonTool(settings, diameter=1.0)
hit = DrillHit(tool, position)
assert_equal(hit.position, position)
assert hit.position == position
hit.offset(offset[0], offset[1])
assert_equal(hit.position, expected)
assert hit.position == expected
def test_drill_slot_units_conversion():
""" Test unit conversion for drill hits
"""
# Inch hit
settings = FileSettings(units='inch')
settings = FileSettings(units="inch")
tool = ExcellonTool(settings, diameter=1.0)
hit = DrillSlot(tool, (1.0, 1.0), (10.0, 10.0), DrillSlot.TYPE_ROUT)
assert_equal(hit.tool.settings.units, 'inch')
assert_equal(hit.tool.diameter, 1.0)
assert_equal(hit.start, (1.0, 1.0))
assert_equal(hit.end, (10.0, 10.0))
assert hit.tool.settings.units == "inch"
assert hit.tool.diameter == 1.0
assert hit.start == (1.0, 1.0)
assert hit.end == (10.0, 10.0)
# No Effect
hit.to_inch()
assert_equal(hit.tool.settings.units, 'inch')
assert_equal(hit.tool.diameter, 1.0)
assert_equal(hit.start, (1.0, 1.0))
assert_equal(hit.end, (10.0, 10.0))
assert hit.tool.settings.units == "inch"
assert hit.tool.diameter == 1.0
assert hit.start == (1.0, 1.0)
assert hit.end == (10.0, 10.0)
# Should convert
hit.to_metric()
assert_equal(hit.tool.settings.units, 'metric')
assert_equal(hit.tool.diameter, 25.4)
assert_equal(hit.start, (25.4, 25.4))
assert_equal(hit.end, (254.0, 254.0))
assert hit.tool.settings.units == "metric"
assert hit.tool.diameter == 25.4
assert hit.start == (25.4, 25.4)
assert hit.end == (254.0, 254.0)
# No Effect
hit.to_metric()
assert_equal(hit.tool.settings.units, 'metric')
assert_equal(hit.tool.diameter, 25.4)
assert_equal(hit.start, (25.4, 25.4))
assert_equal(hit.end, (254.0, 254.0))
assert hit.tool.settings.units == "metric"
assert hit.tool.diameter == 25.4
assert hit.start == (25.4, 25.4)
assert hit.end == (254.0, 254.0)
# Convert back to inch
hit.to_inch()
assert_equal(hit.tool.settings.units, 'inch')
assert_equal(hit.tool.diameter, 1.0)
assert_equal(hit.start, (1.0, 1.0))
assert_equal(hit.end, (10.0, 10.0))
assert hit.tool.settings.units == "inch"
assert hit.tool.diameter == 1.0
assert hit.start == (1.0, 1.0)
assert hit.end == (10.0, 10.0)
def test_drill_slot_offset():
TEST_VECTORS = [
((0.0 ,0.0), (1.0, 1.0), (0.0, 0.0), (0.0, 0.0), (1.0, 1.0)),
((0.0, 0.0), (1.0, 1.0), (0.0, 0.0), (0.0, 0.0), (1.0, 1.0)),
((0.0, 0.0), (1.0, 1.0), (1.0, 0.0), (1.0, 0.0), (2.0, 1.0)),
((0.0, 0.0), (1.0, 1.0), (1.0, 1.0), (1.0, 1.0), (2.0, 2.0)),
((0.0, 0.0), (1.0, 1.0), (-1.0, 1.0), (-1.0, 1.0), (0.0, 2.0)),
]
for start, end, offset, expected_start, expected_end in TEST_VECTORS:
settings = FileSettings(units='inch')
settings = FileSettings(units="inch")
tool = ExcellonTool(settings, diameter=1.0)
slot = DrillSlot(tool, start, end, DrillSlot.TYPE_ROUT)
assert_equal(slot.start, start)
assert_equal(slot.end, end)
assert slot.start == start
assert slot.end == end
slot.offset(offset[0], offset[1])
assert_equal(slot.start, expected_start)
assert_equal(slot.end, expected_end)
assert slot.start == expected_start
assert slot.end == expected_end
def test_drill_slot_bounds():
TEST_VECTORS = [
((0.0, 0.0), (1.0, 1.0), 1.0, ((-0.5, 1.5), (-0.5, 1.5))),
((0.0, 0.0), (1.0, 1.0), 0.5, ((-0.25, 1.25), (-0.25, 1.25))),
]
for start, end, diameter, expected, in TEST_VECTORS:
settings = FileSettings(units='inch')
for start, end, diameter, expected in TEST_VECTORS:
settings = FileSettings(units="inch")
tool = ExcellonTool(settings, diameter=diameter)
slot = DrillSlot(tool, start, end, DrillSlot.TYPE_ROUT)
assert_equal(slot.bounding_box, expected)
assert slot.bounding_box == expected
def test_handling_multi_line_g00_and_g1():
"""Route Mode statements with coordinates on separate line are handled
@ -355,6 +361,6 @@ M16
"""
uut = ExcellonParser()
uut.parse_raw(test_data)
assert_equal(len([stmt for stmt in uut.statements
if isinstance(stmt, RouteModeStmt)]), 2)
assert (
len([stmt for stmt in uut.statements if isinstance(stmt, RouteModeStmt)]) == 2
)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,139 +2,147 @@
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
import pytest
from ..ipc356 import *
from ..cam import FileSettings
from .tests import *
import os
IPC_D_356_FILE = os.path.join(os.path.dirname(__file__),
'resources/ipc-d-356.ipc')
IPC_D_356_FILE = os.path.join(os.path.dirname(__file__), "resources/ipc-d-356.ipc")
def test_read():
ipcfile = read(IPC_D_356_FILE)
assert(isinstance(ipcfile, IPCNetlist))
assert isinstance(ipcfile, IPCNetlist)
def test_parser():
ipcfile = read(IPC_D_356_FILE)
assert_equal(ipcfile.settings.units, 'inch')
assert_equal(ipcfile.settings.angle_units, 'degrees')
assert_equal(len(ipcfile.comments), 3)
assert_equal(len(ipcfile.parameters), 4)
assert_equal(len(ipcfile.test_records), 105)
assert_equal(len(ipcfile.components), 21)
assert_equal(len(ipcfile.vias), 14)
assert_equal(ipcfile.test_records[-1].net_name, 'A_REALLY_LONG_NET_NAME')
assert_equal(ipcfile.outlines[0].type, 'BOARD_EDGE')
assert_equal(set(ipcfile.outlines[0].points),
{(0., 0.), (2.25, 0.), (2.25, 1.5), (0., 1.5), (0.13, 0.024)})
assert ipcfile.settings.units == "inch"
assert ipcfile.settings.angle_units == "degrees"
assert len(ipcfile.comments) == 3
assert len(ipcfile.parameters) == 4
assert len(ipcfile.test_records) == 105
assert len(ipcfile.components) == 21
assert len(ipcfile.vias) == 14
assert ipcfile.test_records[-1].net_name == "A_REALLY_LONG_NET_NAME"
assert ipcfile.outlines[0].type == "BOARD_EDGE"
assert set(ipcfile.outlines[0].points) == {
(0.0, 0.0),
(2.25, 0.0),
(2.25, 1.5),
(0.0, 1.5),
(0.13, 0.024),
}
def test_comment():
c = IPC356_Comment('Layer Stackup:')
assert_equal(c.comment, 'Layer Stackup:')
c = IPC356_Comment.from_line('C Layer Stackup: ')
assert_equal(c.comment, 'Layer Stackup:')
assert_raises(ValueError, IPC356_Comment.from_line, 'P JOB')
assert_equal(str(c), '<IPC-D-356 Comment: Layer Stackup:>')
c = IPC356_Comment("Layer Stackup:")
assert c.comment == "Layer Stackup:"
c = IPC356_Comment.from_line("C Layer Stackup: ")
assert c.comment == "Layer Stackup:"
pytest.raises(ValueError, IPC356_Comment.from_line, "P JOB")
assert str(c) == "<IPC-D-356 Comment: Layer Stackup:>"
def test_parameter():
p = IPC356_Parameter('VER', 'IPC-D-356A')
assert_equal(p.parameter, 'VER')
assert_equal(p.value, 'IPC-D-356A')
p = IPC356_Parameter.from_line('P VER IPC-D-356A ')
assert_equal(p.parameter, 'VER')
assert_equal(p.value, 'IPC-D-356A')
assert_raises(ValueError, IPC356_Parameter.from_line,
'C Layer Stackup: ')
assert_equal(str(p), '<IPC-D-356 Parameter: VER=IPC-D-356A>')
p = IPC356_Parameter("VER", "IPC-D-356A")
assert p.parameter == "VER"
assert p.value == "IPC-D-356A"
p = IPC356_Parameter.from_line("P VER IPC-D-356A ")
assert p.parameter == "VER"
assert p.value == "IPC-D-356A"
pytest.raises(ValueError, IPC356_Parameter.from_line, "C Layer Stackup: ")
assert str(p) == "<IPC-D-356 Parameter: VER=IPC-D-356A>"
def test_eof():
e = IPC356_EndOfFile()
assert_equal(e.to_netlist(), '999')
assert_equal(str(e), '<IPC-D-356 EOF>')
assert e.to_netlist() == "999"
assert str(e) == "<IPC-D-356 EOF>"
def test_outline():
type = 'BOARD_EDGE'
points = [(0.01, 0.01), (2., 2.), (4., 2.), (4., 6.)]
type = "BOARD_EDGE"
points = [(0.01, 0.01), (2.0, 2.0), (4.0, 2.0), (4.0, 6.0)]
b = IPC356_Outline(type, points)
assert_equal(b.type, type)
assert_equal(b.points, points)
b = IPC356_Outline.from_line('389BOARD_EDGE X100Y100 X20000Y20000 X40000 Y60000',
FileSettings(units='inch'))
assert_equal(b.type, 'BOARD_EDGE')
assert_equal(b.points, points)
assert b.type == type
assert b.points == points
b = IPC356_Outline.from_line(
"389BOARD_EDGE X100Y100 X20000Y20000 X40000 Y60000",
FileSettings(units="inch"),
)
assert b.type == "BOARD_EDGE"
assert b.points == points
def test_test_record():
assert_raises(ValueError, IPC356_TestRecord.from_line,
'P JOB', FileSettings())
record_string = '317+5VDC VIA - D0150PA00X 006647Y 012900X0000 S3'
r = IPC356_TestRecord.from_line(record_string, FileSettings(units='inch'))
assert_equal(r.feature_type, 'through-hole')
assert_equal(r.net_name, '+5VDC')
assert_equal(r.id, 'VIA')
assert_almost_equal(r.hole_diameter, 0.015)
assert_true(r.plated)
assert_equal(r.access, 'both')
assert_almost_equal(r.x_coord, 0.6647)
assert_almost_equal(r.y_coord, 1.29)
assert_equal(r.rect_x, 0.)
assert_equal(r.soldermask_info, 'both')
r = IPC356_TestRecord.from_line(record_string, FileSettings(units='metric'))
assert_almost_equal(r.hole_diameter, 0.15)
assert_almost_equal(r.x_coord, 6.647)
assert_almost_equal(r.y_coord, 12.9)
assert_equal(r.rect_x, 0.)
assert_equal(str(r), '<IPC-D-356 +5VDC Test Record: through-hole>')
pytest.raises(ValueError, IPC356_TestRecord.from_line, "P JOB", FileSettings())
record_string = (
"317+5VDC VIA - D0150PA00X 006647Y 012900X0000 S3"
)
r = IPC356_TestRecord.from_line(record_string, FileSettings(units="inch"))
assert r.feature_type == "through-hole"
assert r.net_name == "+5VDC"
assert r.id == "VIA"
pytest.approx(r.hole_diameter, 0.015)
assert r.plated
assert r.access == "both"
pytest.approx(r.x_coord, 0.6647)
pytest.approx(r.y_coord, 1.29)
assert r.rect_x == 0.0
assert r.soldermask_info == "both"
r = IPC356_TestRecord.from_line(record_string, FileSettings(units="metric"))
pytest.approx(r.hole_diameter, 0.15)
pytest.approx(r.x_coord, 6.647)
pytest.approx(r.y_coord, 12.9)
assert r.rect_x == 0.0
assert str(r) == "<IPC-D-356 +5VDC Test Record: through-hole>"
record_string = '327+3.3VDC R40 -1 PA01X 032100Y 007124X0236Y0315R180 S0'
r = IPC356_TestRecord.from_line(record_string, FileSettings(units='inch'))
assert_equal(r.feature_type, 'smt')
assert_equal(r.net_name, '+3.3VDC')
assert_equal(r.id, 'R40')
assert_equal(r.pin, '1')
assert_true(r.plated)
assert_equal(r.access, 'top')
assert_almost_equal(r.x_coord, 3.21)
assert_almost_equal(r.y_coord, 0.7124)
assert_almost_equal(r.rect_x, 0.0236)
assert_almost_equal(r.rect_y, 0.0315)
assert_equal(r.rect_rotation, 180)
assert_equal(r.soldermask_info, 'none')
r = IPC356_TestRecord.from_line(
record_string, FileSettings(units='metric'))
assert_almost_equal(r.x_coord, 32.1)
assert_almost_equal(r.y_coord, 7.124)
assert_almost_equal(r.rect_x, 0.236)
assert_almost_equal(r.rect_y, 0.315)
record_string = (
"327+3.3VDC R40 -1 PA01X 032100Y 007124X0236Y0315R180 S0"
)
r = IPC356_TestRecord.from_line(record_string, FileSettings(units="inch"))
assert r.feature_type == "smt"
assert r.net_name == "+3.3VDC"
assert r.id == "R40"
assert r.pin == "1"
assert r.plated
assert r.access == "top"
pytest.approx(r.x_coord, 3.21)
pytest.approx(r.y_coord, 0.7124)
pytest.approx(r.rect_x, 0.0236)
pytest.approx(r.rect_y, 0.0315)
assert r.rect_rotation == 180
assert r.soldermask_info == "none"
r = IPC356_TestRecord.from_line(record_string, FileSettings(units="metric"))
pytest.approx(r.x_coord, 32.1)
pytest.approx(r.y_coord, 7.124)
pytest.approx(r.rect_x, 0.236)
pytest.approx(r.rect_y, 0.315)
record_string = '317 J4 -M2 D0330PA00X 012447Y 008030X0000 S1'
r = IPC356_TestRecord.from_line(record_string, FileSettings(units='inch'))
assert_equal(r.feature_type, 'through-hole')
assert_equal(r.id, 'J4')
assert_equal(r.pin, 'M2')
assert_almost_equal(r.hole_diameter, 0.033)
assert_true(r.plated)
assert_equal(r.access, 'both')
assert_almost_equal(r.x_coord, 1.2447)
assert_almost_equal(r.y_coord, 0.8030)
assert_almost_equal(r.rect_x, 0.)
assert_equal(r.soldermask_info, 'primary side')
record_string = (
"317 J4 -M2 D0330PA00X 012447Y 008030X0000 S1"
)
r = IPC356_TestRecord.from_line(record_string, FileSettings(units="inch"))
assert r.feature_type == "through-hole"
assert r.id == "J4"
assert r.pin == "M2"
pytest.approx(r.hole_diameter, 0.033)
assert r.plated
assert r.access == "both"
pytest.approx(r.x_coord, 1.2447)
pytest.approx(r.y_coord, 0.8030)
pytest.approx(r.rect_x, 0.0)
assert r.soldermask_info == "primary side"
record_string = '317SCL COMMUNICATION-1 D 40PA00X 34000Y 20000X 600Y1200R270 '
r = IPC356_TestRecord.from_line(record_string, FileSettings(units='inch'))
assert_equal(r.feature_type, 'through-hole')
assert_equal(r.net_name, 'SCL')
assert_equal(r.id, 'COMMUNICATION')
assert_equal(r.pin, '1')
assert_almost_equal(r.hole_diameter, 0.004)
assert_true(r.plated)
assert_almost_equal(r.x_coord, 3.4)
assert_almost_equal(r.y_coord, 2.0)
record_string = "317SCL COMMUNICATION-1 D 40PA00X 34000Y 20000X 600Y1200R270 "
r = IPC356_TestRecord.from_line(record_string, FileSettings(units="inch"))
assert r.feature_type == "through-hole"
assert r.net_name == "SCL"
assert r.id == "COMMUNICATION"
assert r.pin == "1"
pytest.approx(r.hole_diameter, 0.004)
assert r.plated
pytest.approx(r.x_coord, 3.4)
pytest.approx(r.y_coord, 2.0)

View file

@ -18,128 +18,141 @@
import os
from .tests import *
from ..layers import *
from ..common import read
NCDRILL_FILE = os.path.join(os.path.dirname(__file__),
'resources/ncdrill.DRD')
NETLIST_FILE = os.path.join(os.path.dirname(__file__),
'resources/ipc-d-356.ipc')
COPPER_FILE = os.path.join(os.path.dirname(__file__),
'resources/top_copper.GTL')
NCDRILL_FILE = os.path.join(os.path.dirname(__file__), "resources/ncdrill.DRD")
NETLIST_FILE = os.path.join(os.path.dirname(__file__), "resources/ipc-d-356.ipc")
COPPER_FILE = os.path.join(os.path.dirname(__file__), "resources/top_copper.GTL")
def test_guess_layer_class():
""" Test layer type inferred correctly from filename
"""
# Add any specific test cases here (filename, layer_class)
test_vectors = [(None, 'unknown'), ('NCDRILL.TXT', 'unknown'),
('example_board.gtl', 'top'),
('exampmle_board.sst', 'topsilk'),
('ipc-d-356.ipc', 'ipc_netlist'), ]
test_vectors = [
(None, "unknown"),
("NCDRILL.TXT", "unknown"),
("example_board.gtl", "top"),
("exampmle_board.sst", "topsilk"),
("ipc-d-356.ipc", "ipc_netlist"),
]
for hint in hints:
for ext in hint.ext:
assert_equal(hint.layer, guess_layer_class('board.{}'.format(ext)))
assert hint.layer == guess_layer_class("board.{}".format(ext))
for name in hint.name:
assert_equal(hint.layer, guess_layer_class('{}.pho'.format(name)))
assert hint.layer == guess_layer_class("{}.pho".format(name))
for filename, layer_class in test_vectors:
assert_equal(layer_class, guess_layer_class(filename))
assert layer_class == guess_layer_class(filename)
def test_guess_layer_class_regex():
""" Test regular expressions for layer matching
"""
# Add any specific test case (filename, layer_class)
test_vectors = [('test - top copper.gbr', 'top'),
('test - copper top.gbr', 'top'), ]
test_vectors = [("test - top copper.gbr", "top"), ("test - copper top.gbr", "top")]
# Add custom regular expressions
layer_hints = [
Hint(layer='top',
ext=[],
name=[],
regex=r'(.*)(\scopper top|\stop copper).gbr',
content=[]
),
Hint(
layer="top",
ext=[],
name=[],
regex=r"(.*)(\scopper top|\stop copper).gbr",
content=[],
)
]
hints.extend(layer_hints)
for filename, layer_class in test_vectors:
assert_equal(layer_class, guess_layer_class(filename))
assert layer_class == guess_layer_class(filename)
def test_guess_layer_class_by_content():
""" Test layer class by checking content
"""
expected_layer_class = 'bottom'
filename = os.path.join(os.path.dirname(__file__),
'resources/example_guess_by_content.g0')
expected_layer_class = "bottom"
filename = os.path.join(
os.path.dirname(__file__), "resources/example_guess_by_content.g0"
)
layer_hints = [
Hint(layer='bottom',
ext=[],
name=[],
regex='',
content=['G04 Layer name: Bottom']
)
Hint(
layer="bottom",
ext=[],
name=[],
regex="",
content=["G04 Layer name: Bottom"],
)
]
hints.extend(layer_hints)
assert_equal(expected_layer_class, guess_layer_class_by_content(filename))
assert expected_layer_class == guess_layer_class_by_content(filename)
def test_sort_layers():
""" Test layer ordering
"""
layers = [
PCBLayer(layer_class='drawing'),
PCBLayer(layer_class='drill'),
PCBLayer(layer_class='bottompaste'),
PCBLayer(layer_class='bottomsilk'),
PCBLayer(layer_class='bottommask'),
PCBLayer(layer_class='bottom'),
PCBLayer(layer_class='internal'),
PCBLayer(layer_class='top'),
PCBLayer(layer_class='topmask'),
PCBLayer(layer_class='topsilk'),
PCBLayer(layer_class='toppaste'),
PCBLayer(layer_class='outline'),
PCBLayer(layer_class="drawing"),
PCBLayer(layer_class="drill"),
PCBLayer(layer_class="bottompaste"),
PCBLayer(layer_class="bottomsilk"),
PCBLayer(layer_class="bottommask"),
PCBLayer(layer_class="bottom"),
PCBLayer(layer_class="internal"),
PCBLayer(layer_class="top"),
PCBLayer(layer_class="topmask"),
PCBLayer(layer_class="topsilk"),
PCBLayer(layer_class="toppaste"),
PCBLayer(layer_class="outline"),
]
layer_order = ['outline', 'toppaste', 'topsilk', 'topmask', 'top',
'internal', 'bottom', 'bottommask', 'bottomsilk',
'bottompaste', 'drill', 'drawing']
layer_order = [
"outline",
"toppaste",
"topsilk",
"topmask",
"top",
"internal",
"bottom",
"bottommask",
"bottomsilk",
"bottompaste",
"drill",
"drawing",
]
bottom_order = list(reversed(layer_order[:10])) + layer_order[10:]
assert_equal([l.layer_class for l in sort_layers(layers)], layer_order)
assert_equal([l.layer_class for l in sort_layers(layers, from_top=False)],
bottom_order)
assert [l.layer_class for l in sort_layers(layers)] == layer_order
assert [l.layer_class for l in sort_layers(layers, from_top=False)] == bottom_order
def test_PCBLayer_from_file():
layer = PCBLayer.from_cam(read(COPPER_FILE))
assert_true(isinstance(layer, PCBLayer))
assert isinstance(layer, PCBLayer)
layer = PCBLayer.from_cam(read(NCDRILL_FILE))
assert_true(isinstance(layer, DrillLayer))
assert isinstance(layer, DrillLayer)
layer = PCBLayer.from_cam(read(NETLIST_FILE))
assert_true(isinstance(layer, PCBLayer))
assert_equal(layer.layer_class, 'ipc_netlist')
assert isinstance(layer, PCBLayer)
assert layer.layer_class == "ipc_netlist"
def test_PCBLayer_bounds():
source = read(COPPER_FILE)
layer = PCBLayer.from_cam(source)
assert_equal(source.bounds, layer.bounds)
assert source.bounds == layer.bounds
def test_DrillLayer_from_cam():
no_exceptions = True
try:
layer = DrillLayer.from_cam(read(NCDRILL_FILE))
assert_true(isinstance(layer, DrillLayer))
assert isinstance(layer, DrillLayer)
except:
no_exceptions = False
assert_true(no_exceptions)
assert no_exceptions

File diff suppressed because it is too large Load diff

View file

@ -3,53 +3,53 @@
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
import os
import pytest
from ..rs274x import read, GerberFile
from .tests import *
TOP_COPPER_FILE = os.path.join(os.path.dirname(__file__),
'resources/top_copper.GTL')
TOP_COPPER_FILE = os.path.join(os.path.dirname(__file__), "resources/top_copper.GTL")
MULTILINE_READ_FILE = os.path.join(os.path.dirname(__file__),
'resources/multiline_read.ger')
MULTILINE_READ_FILE = os.path.join(
os.path.dirname(__file__), "resources/multiline_read.ger"
)
def test_read():
top_copper = read(TOP_COPPER_FILE)
assert(isinstance(top_copper, GerberFile))
assert isinstance(top_copper, GerberFile)
def test_multiline_read():
multiline = read(MULTILINE_READ_FILE)
assert(isinstance(multiline, GerberFile))
assert_equal(10, len(multiline.statements))
assert isinstance(multiline, GerberFile)
assert 10 == len(multiline.statements)
def test_comments_parameter():
top_copper = read(TOP_COPPER_FILE)
assert_equal(top_copper.comments[0], 'This is a comment,:')
assert top_copper.comments[0] == "This is a comment,:"
def test_size_parameter():
top_copper = read(TOP_COPPER_FILE)
size = top_copper.size
assert_almost_equal(size[0], 2.256900, 6)
assert_almost_equal(size[1], 1.500000, 6)
pytest.approx(size[0], 2.256900, 6)
pytest.approx(size[1], 1.500000, 6)
def test_conversion():
top_copper = read(TOP_COPPER_FILE)
assert_equal(top_copper.units, 'inch')
assert top_copper.units == "inch"
top_copper_inch = read(TOP_COPPER_FILE)
top_copper.to_metric()
for statement in top_copper_inch.statements:
statement.to_metric()
for primitive in top_copper_inch.primitives:
primitive.to_metric()
assert_equal(top_copper.units, 'metric')
assert top_copper.units == "metric"
for i, m in zip(top_copper.statements, top_copper_inch.statements):
assert_equal(i, m)
assert i == m
for i, m in zip(top_copper.primitives, top_copper_inch.primitives):
assert_equal(i, m)
assert i == m

View file

@ -7,62 +7,86 @@ import os
from ..render.rs274x_backend import Rs274xContext
from ..rs274x import read
from .tests import *
def test_render_two_boxes():
"""Umaco exapmle of two boxes"""
_test_render('resources/example_two_square_boxes.gbr', 'golden/example_two_square_boxes.gbr')
_test_render(
"resources/example_two_square_boxes.gbr", "golden/example_two_square_boxes.gbr"
)
def _test_render_single_quadrant():
"""Umaco exapmle of a single quadrant arc"""
# TODO there is probably a bug here
_test_render('resources/example_single_quadrant.gbr', 'golden/example_single_quadrant.gbr')
_test_render(
"resources/example_single_quadrant.gbr", "golden/example_single_quadrant.gbr"
)
def _test_render_simple_contour():
"""Umaco exapmle of a simple arrow-shaped contour"""
_test_render('resources/example_simple_contour.gbr', 'golden/example_simple_contour.gbr')
_test_render(
"resources/example_simple_contour.gbr", "golden/example_simple_contour.gbr"
)
def _test_render_single_contour_1():
"""Umaco example of a single contour
The resulting image for this test is used by other tests because they must generate the same output."""
_test_render('resources/example_single_contour_1.gbr', 'golden/example_single_contour.gbr')
_test_render(
"resources/example_single_contour_1.gbr", "golden/example_single_contour.gbr"
)
def _test_render_single_contour_2():
"""Umaco exapmle of a single contour, alternate contour end order
The resulting image for this test is used by other tests because they must generate the same output."""
_test_render('resources/example_single_contour_2.gbr', 'golden/example_single_contour.gbr')
_test_render(
"resources/example_single_contour_2.gbr", "golden/example_single_contour.gbr"
)
def _test_render_single_contour_3():
"""Umaco exapmle of a single contour with extra line"""
_test_render('resources/example_single_contour_3.gbr', 'golden/example_single_contour_3.gbr')
_test_render(
"resources/example_single_contour_3.gbr", "golden/example_single_contour_3.gbr"
)
def _test_render_not_overlapping_contour():
"""Umaco example of D02 staring a second contour"""
_test_render('resources/example_not_overlapping_contour.gbr', 'golden/example_not_overlapping_contour.gbr')
_test_render(
"resources/example_not_overlapping_contour.gbr",
"golden/example_not_overlapping_contour.gbr",
)
def _test_render_not_overlapping_touching():
"""Umaco example of D02 staring a second contour"""
_test_render('resources/example_not_overlapping_touching.gbr', 'golden/example_not_overlapping_touching.gbr')
_test_render(
"resources/example_not_overlapping_touching.gbr",
"golden/example_not_overlapping_touching.gbr",
)
def _test_render_overlapping_touching():
"""Umaco example of D02 staring a second contour"""
_test_render('resources/example_overlapping_touching.gbr', 'golden/example_overlapping_touching.gbr')
_test_render(
"resources/example_overlapping_touching.gbr",
"golden/example_overlapping_touching.gbr",
)
def _test_render_overlapping_contour():
"""Umaco example of D02 staring a second contour"""
_test_render('resources/example_overlapping_contour.gbr', 'golden/example_overlapping_contour.gbr')
_test_render(
"resources/example_overlapping_contour.gbr",
"golden/example_overlapping_contour.gbr",
)
def _DISABLED_test_render_level_holes():
@ -70,76 +94,96 @@ def _DISABLED_test_render_level_holes():
# TODO This is clearly rendering wrong. I'm temporarily checking this in because there are more
# rendering fixes in the related repository that may resolve these.
_test_render('resources/example_level_holes.gbr', 'golden/example_overlapping_contour.gbr')
_test_render(
"resources/example_level_holes.gbr", "golden/example_overlapping_contour.gbr"
)
def _DISABLED_test_render_cutin():
"""Umaco example of using a cutin"""
# TODO This is clearly rendering wrong.
_test_render('resources/example_cutin.gbr', 'golden/example_cutin.gbr')
_test_render("resources/example_cutin.gbr", "golden/example_cutin.gbr")
def _test_render_fully_coincident():
"""Umaco example of coincident lines rendering two contours"""
_test_render('resources/example_fully_coincident.gbr', 'golden/example_fully_coincident.gbr')
_test_render(
"resources/example_fully_coincident.gbr", "golden/example_fully_coincident.gbr"
)
def _test_render_coincident_hole():
"""Umaco example of coincident lines rendering a hole in the contour"""
_test_render('resources/example_coincident_hole.gbr', 'golden/example_coincident_hole.gbr')
_test_render(
"resources/example_coincident_hole.gbr", "golden/example_coincident_hole.gbr"
)
def _test_render_cutin_multiple():
"""Umaco example of a region with multiple cutins"""
_test_render('resources/example_cutin_multiple.gbr', 'golden/example_cutin_multiple.gbr')
_test_render(
"resources/example_cutin_multiple.gbr", "golden/example_cutin_multiple.gbr"
)
def _test_flash_circle():
"""Umaco example a simple circular flash with and without a hole"""
_test_render('resources/example_flash_circle.gbr', 'golden/example_flash_circle.gbr')
_test_render(
"resources/example_flash_circle.gbr", "golden/example_flash_circle.gbr"
)
def _test_flash_rectangle():
"""Umaco example a simple rectangular flash with and without a hole"""
_test_render('resources/example_flash_rectangle.gbr', 'golden/example_flash_rectangle.gbr')
_test_render(
"resources/example_flash_rectangle.gbr", "golden/example_flash_rectangle.gbr"
)
def _test_flash_obround():
"""Umaco example a simple obround flash with and without a hole"""
_test_render('resources/example_flash_obround.gbr', 'golden/example_flash_obround.gbr')
_test_render(
"resources/example_flash_obround.gbr", "golden/example_flash_obround.gbr"
)
def _test_flash_polygon():
"""Umaco example a simple polygon flash with and without a hole"""
_test_render('resources/example_flash_polygon.gbr', 'golden/example_flash_polygon.gbr')
_test_render(
"resources/example_flash_polygon.gbr", "golden/example_flash_polygon.gbr"
)
def _test_holes_dont_clear():
"""Umaco example that an aperture with a hole does not clear the area"""
_test_render('resources/example_holes_dont_clear.gbr', 'golden/example_holes_dont_clear.gbr')
_test_render(
"resources/example_holes_dont_clear.gbr", "golden/example_holes_dont_clear.gbr"
)
def _test_render_am_exposure_modifier():
"""Umaco example that an aperture macro with a hole does not clear the area"""
_test_render('resources/example_am_exposure_modifier.gbr', 'golden/example_am_exposure_modifier.gbr')
_test_render(
"resources/example_am_exposure_modifier.gbr",
"golden/example_am_exposure_modifier.gbr",
)
def _resolve_path(path):
return os.path.join(os.path.dirname(__file__),
path)
return os.path.join(os.path.dirname(__file__), path)
def _test_render(gerber_path, png_expected_path, create_output_path = None):
def _test_render(gerber_path, png_expected_path, create_output_path=None):
"""Render the gerber file and compare to the expected PNG output.
Parameters
@ -168,18 +212,21 @@ def _test_render(gerber_path, png_expected_path, create_output_path = None):
# If we want to write the file bytes, do it now. This happens
if create_output_path:
with open(create_output_path, 'wb') as out_file:
with open(create_output_path, "wb") as out_file:
out_file.write(actual_contents.getvalue())
# Creating the output is dangerous - it could overwrite the expected result.
# So if we are creating the output, we make the test fail on purpose so you
# won't forget to disable this
assert_false(True, 'Test created the output %s. This needs to be disabled to make sure the test behaves correctly' % (create_output_path,))
assert not True, (
"Test created the output %s. This needs to be disabled to make sure the test behaves correctly"
% (create_output_path,)
)
# Read the expected PNG file
with open(png_expected_path, 'r') as expected_file:
with open(png_expected_path, "r") as expected_file:
expected_contents = expected_file.read()
assert_equal(expected_contents, actual_contents.getvalue())
assert expected_contents == actual_contents.getvalue()
return gerber

View file

@ -3,7 +3,7 @@
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
from .tests import assert_equal, assert_raises
import pytest
from ..utils import *
@ -14,60 +14,99 @@ def test_zero_suppression():
fmt = (2, 5)
# Test leading zero suppression
zero_suppression = 'leading'
test_cases = [('1', 0.00001), ('10', 0.0001), ('100', 0.001),
('1000', 0.01), ('10000', 0.1), ('100000', 1.0),
('1000000', 10.0), ('-1', -0.00001), ('-10', -0.0001),
('-100', -0.001), ('-1000', -0.01), ('-10000', -0.1),
('-100000', -1.0), ('-1000000', -10.0),
('0', 0.0)]
zero_suppression = "leading"
test_cases = [
("1", 0.00001),
("10", 0.0001),
("100", 0.001),
("1000", 0.01),
("10000", 0.1),
("100000", 1.0),
("1000000", 10.0),
("-1", -0.00001),
("-10", -0.0001),
("-100", -0.001),
("-1000", -0.01),
("-10000", -0.1),
("-100000", -1.0),
("-1000000", -10.0),
("0", 0.0),
]
for string, value in test_cases:
assert_equal(value, parse_gerber_value(string, fmt, zero_suppression))
assert_equal(string, write_gerber_value(value, fmt, zero_suppression))
assert value == parse_gerber_value(string, fmt, zero_suppression)
assert string == write_gerber_value(value, fmt, zero_suppression)
# Test trailing zero suppression
zero_suppression = 'trailing'
test_cases = [('1', 10.0), ('01', 1.0), ('001', 0.1), ('0001', 0.01),
('00001', 0.001), ('000001', 0.0001),
('0000001', 0.00001), ('-1', -10.0), ('-01', -1.0),
('-001', -0.1), ('-0001', -0.01), ('-00001', -0.001),
('-000001', -0.0001), ('-0000001', -0.00001),
('0', 0.0)]
zero_suppression = "trailing"
test_cases = [
("1", 10.0),
("01", 1.0),
("001", 0.1),
("0001", 0.01),
("00001", 0.001),
("000001", 0.0001),
("0000001", 0.00001),
("-1", -10.0),
("-01", -1.0),
("-001", -0.1),
("-0001", -0.01),
("-00001", -0.001),
("-000001", -0.0001),
("-0000001", -0.00001),
("0", 0.0),
]
for string, value in test_cases:
assert_equal(value, parse_gerber_value(string, fmt, zero_suppression))
assert_equal(string, write_gerber_value(value, fmt, zero_suppression))
assert value == parse_gerber_value(string, fmt, zero_suppression)
assert string == write_gerber_value(value, fmt, zero_suppression)
assert_equal(write_gerber_value(0.000000001, fmt, 'leading'), '0')
assert_equal(write_gerber_value(0.000000001, fmt, 'trailing'), '0')
assert write_gerber_value(0.000000001, fmt, "leading") == "0"
assert write_gerber_value(0.000000001, fmt, "trailing") == "0"
def test_format():
""" Test gerber value parser and writer handle format correctly
"""
zero_suppression = 'leading'
test_cases = [((2, 7), '1', 0.0000001), ((2, 6), '1', 0.000001),
((2, 5), '1', 0.00001), ((2, 4), '1', 0.0001),
((2, 3), '1', 0.001), ((2, 2), '1', 0.01),
((2, 1), '1', 0.1), ((2, 7), '-1', -0.0000001),
((2, 6), '-1', -0.000001), ((2, 5), '-1', -0.00001),
((2, 4), '-1', -0.0001), ((2, 3), '-1', -0.001),
((2, 2), '-1', -0.01), ((2, 1), '-1', -0.1),
((2, 6), '0', 0)]
zero_suppression = "leading"
test_cases = [
((2, 7), "1", 0.0000001),
((2, 6), "1", 0.000001),
((2, 5), "1", 0.00001),
((2, 4), "1", 0.0001),
((2, 3), "1", 0.001),
((2, 2), "1", 0.01),
((2, 1), "1", 0.1),
((2, 7), "-1", -0.0000001),
((2, 6), "-1", -0.000001),
((2, 5), "-1", -0.00001),
((2, 4), "-1", -0.0001),
((2, 3), "-1", -0.001),
((2, 2), "-1", -0.01),
((2, 1), "-1", -0.1),
((2, 6), "0", 0),
]
for fmt, string, value in test_cases:
assert_equal(value, parse_gerber_value(string, fmt, zero_suppression))
assert_equal(string, write_gerber_value(value, fmt, zero_suppression))
assert value == parse_gerber_value(string, fmt, zero_suppression)
assert string == write_gerber_value(value, fmt, zero_suppression)
zero_suppression = 'trailing'
test_cases = [((6, 5), '1', 100000.0), ((5, 5), '1', 10000.0),
((4, 5), '1', 1000.0), ((3, 5), '1', 100.0),
((2, 5), '1', 10.0), ((1, 5), '1', 1.0),
((6, 5), '-1', -100000.0), ((5, 5), '-1', -10000.0),
((4, 5), '-1', -1000.0), ((3, 5), '-1', -100.0),
((2, 5), '-1', -10.0), ((1, 5), '-1', -1.0),
((2, 5), '0', 0)]
zero_suppression = "trailing"
test_cases = [
((6, 5), "1", 100000.0),
((5, 5), "1", 10000.0),
((4, 5), "1", 1000.0),
((3, 5), "1", 100.0),
((2, 5), "1", 10.0),
((1, 5), "1", 1.0),
((6, 5), "-1", -100000.0),
((5, 5), "-1", -10000.0),
((4, 5), "-1", -1000.0),
((3, 5), "-1", -100.0),
((2, 5), "-1", -10.0),
((1, 5), "-1", -1.0),
((2, 5), "0", 0),
]
for fmt, string, value in test_cases:
assert_equal(value, parse_gerber_value(string, fmt, zero_suppression))
assert_equal(string, write_gerber_value(value, fmt, zero_suppression))
assert value == parse_gerber_value(string, fmt, zero_suppression)
assert string == write_gerber_value(value, fmt, zero_suppression)
def test_decimal_truncation():
@ -76,54 +115,53 @@ def test_decimal_truncation():
value = 1.123456789
for x in range(10):
result = decimal_string(value, precision=x)
calculated = '1.' + ''.join(str(y) for y in range(1, x + 1))
assert_equal(result, calculated)
calculated = "1." + "".join(str(y) for y in range(1, x + 1))
assert result == calculated
def test_decimal_padding():
""" Test decimal_string padding
"""
value = 1.123
assert_equal(decimal_string(value, precision=3, padding=True), '1.123')
assert_equal(decimal_string(value, precision=4, padding=True), '1.1230')
assert_equal(decimal_string(value, precision=5, padding=True), '1.12300')
assert_equal(decimal_string(value, precision=6, padding=True), '1.123000')
assert_equal(decimal_string(0, precision=6, padding=True), '0.000000')
assert decimal_string(value, precision=3, padding=True) == "1.123"
assert decimal_string(value, precision=4, padding=True) == "1.1230"
assert decimal_string(value, precision=5, padding=True) == "1.12300"
assert decimal_string(value, precision=6, padding=True) == "1.123000"
assert decimal_string(0, precision=6, padding=True) == "0.000000"
def test_parse_format_validation():
""" Test parse_gerber_value() format validation
"""
assert_raises(ValueError, parse_gerber_value, '00001111', (7, 5))
assert_raises(ValueError, parse_gerber_value, '00001111', (5, 8))
assert_raises(ValueError, parse_gerber_value, '00001111', (13, 1))
pytest.raises(ValueError, parse_gerber_value, "00001111", (7, 5))
pytest.raises(ValueError, parse_gerber_value, "00001111", (5, 8))
pytest.raises(ValueError, parse_gerber_value, "00001111", (13, 1))
def test_write_format_validation():
""" Test write_gerber_value() format validation
"""
assert_raises(ValueError, write_gerber_value, 69.0, (7, 5))
assert_raises(ValueError, write_gerber_value, 69.0, (5, 8))
assert_raises(ValueError, write_gerber_value, 69.0, (13, 1))
pytest.raises(ValueError, write_gerber_value, 69.0, (7, 5))
pytest.raises(ValueError, write_gerber_value, 69.0, (5, 8))
pytest.raises(ValueError, write_gerber_value, 69.0, (13, 1))
def test_detect_format_with_short_file():
""" Verify file format detection works with short files
"""
assert_equal('unknown', detect_file_format('gerber/tests/__init__.py'))
assert "unknown" == detect_file_format("gerber/tests/__init__.py")
def test_validate_coordinates():
assert_raises(TypeError, validate_coordinates, 3)
assert_raises(TypeError, validate_coordinates, 3.1)
assert_raises(TypeError, validate_coordinates, '14')
assert_raises(TypeError, validate_coordinates, (0,))
assert_raises(TypeError, validate_coordinates, (0, 1, 2))
assert_raises(TypeError, validate_coordinates, (0, 'string'))
pytest.raises(TypeError, validate_coordinates, 3)
pytest.raises(TypeError, validate_coordinates, 3.1)
pytest.raises(TypeError, validate_coordinates, "14")
pytest.raises(TypeError, validate_coordinates, (0,))
pytest.raises(TypeError, validate_coordinates, (0, 1, 2))
pytest.raises(TypeError, validate_coordinates, (0, "string"))
def test_convex_hull():
points = [(0, 0), (1, 0), (1, 1), (0.5, 0.5), (0, 1), (0, 0)]
expected = [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]
assert_equal(set(convex_hull(points)), set(expected))
assert set(convex_hull(points)) == set(expected)

View file

@ -1,25 +0,0 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
from nose.tools import assert_in
from nose.tools import assert_not_in
from nose.tools import assert_equal
from nose.tools import assert_not_equal
from nose.tools import assert_almost_equal
from nose.tools import assert_true
from nose.tools import assert_false
from nose.tools import assert_raises
from nose.tools import raises
from nose import with_setup
__all__ = ['assert_in', 'assert_not_in', 'assert_equal', 'assert_not_equal',
'assert_almost_equal', 'assert_array_almost_equal', 'assert_true',
'assert_false', 'assert_raises', 'raises', 'with_setup']
def assert_array_almost_equal(arr1, arr2, decimal=6):
assert_equal(len(arr1), len(arr2))
for i in range(len(arr1)):
assert_almost_equal(arr1[i], arr2[i], decimal)

View file

@ -1,5 +1,5 @@
# install base requirements
-r requirements.txt
coverage==4.5.4
nose==1.3.7
pytest==4.6.6
pytest-cov==2.8.1