Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
exclude = setup.py, scripts, examples, tests, build, pcbflow/hershey.py
77 changes: 77 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: pcbflow

on:
push:
pull_request:
branches: [ "main" ]

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 10
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest skidl setuptools
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
python setup.py install
- name: Test with pytest
run: |
pytest
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 flake8-black
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8 / flake8-black
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
run: |
python setup.py install
- name: Run basic blank
run: |
python examples/basic/blank.py
- name: Run basic holes
run: |
python examples/basic/holes.py
# - name: Run sample
# run: |
# python examples/sample/sample.py
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# test files
skidl_test.*

# python intermediate files
*.py[cod]

Expand Down
25 changes: 12 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# pcbflow - Python PCB layout and design (based on CuFlow)

![python version](https://img.shields.io/static/v1?label=python&message=3.9%2B&color=blue&style=flat&logo=python)
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>

![https://travis-ci.org/michaelgale/pcbflow](https://travis-ci.com/michaelgale/pcbflow.svg?branch=main)
[![codecov](https://codecov.io/gh/michaelgale/pcbflow/branch/main/graph/badge.svg)](https://codecov.io/gh/michaelgale/pcbflow)
Expand All @@ -29,14 +29,13 @@ This implementation is alpha and not fully documented.

## Requirements

Since the initial release of `pcbflow`, some changes have been made to adapt with newer versions of python and library dependancies. In particular:
Since the initial release of `pcbflow`, some changes have been made to adapt with newer versions of python and library dependancies. In particular:

- Python 3.9+
- the initial versions of `pcbflow` used `shapely` v.1.6+. However `shapely` has changed the way geometries are iterated in v.2.0.1+; therefore `pcbflow` has been changed to support `shapley` versions 2.0.1+

>
> `pcbflow` has been changed to support `shapley` versions 2.0.1+ ONLY.
> Check your version with `pip list` and verify `shapley` is v.2.0.1+
>
> [!IMPORTANT]
> `pcbflow` has been changed to support `shapley` versions 2.0.1+ ONLY. Check your version with `pip list` and verify `shapley` is v.2.0.1+. If it's not, you can fix by running `pip install --upgrade shapely`

## Installation

Expand Down Expand Up @@ -177,7 +176,7 @@ The `side` argument can be specified as either `top` or `bottom`. This will mir
Arbitrary bitmap logos/annotations can be applied to the PCB as follows:

```python
brd.add_bitmap((x, y), "logo.png",
brd.add_bitmap((x, y), "logo.png",
scale=None,
side="top",
layer=None,
Expand All @@ -189,7 +188,7 @@ The bitmap should be a monochrome bitmap image with transparent background. It

## Named Polygons

Arbitary polygon regions can be added to a copper layer with a name corresponding to its net name. For example, this can be used to apply different voltage "patches" under a part requiring several voltages, or to make a split plane of several voltages or GND references.
Arbitary polygon regions can be added to a copper layer with a name corresponding to its net name. For example, this can be used to apply different voltage "patches" under a part requiring several voltages, or to make a split plane of several voltages or GND references.

```python
# add a polygon with a coordinate list
Expand Down Expand Up @@ -252,7 +251,7 @@ print(usb_con)
# 5: VUSB (17.00, 8.12)

# alternatively, we can reference the pad by name to do the same thing
usb_con.pad("D-").turtle("r 90 f 5 l 90 f 10").wire(width=0.25)
usb_con.pad("D-").turtle("r 90 f 5 l 90 f 10").wire(width=0.25)
```

## Saving Asset Files
Expand All @@ -269,7 +268,7 @@ usb_con.pad("D-").turtle("r 90 f 5 l 90 f 10").wire(width=0.25)
Outfiles can be created in the same folder as the script file or in a subfolder under the script (generated automatically). To generate asset files:

```python
brd.save(basename, in_subdir=True,
brd.save(basename, in_subdir=True,
gerber=True, pdf=True, bom=True, centroids=True, povray=False)
```

Expand Down Expand Up @@ -360,7 +359,7 @@ if __name__ == "__main__":

# Create a pcbflow Board instance
brd = Board((55, 30))

# add two inner copper layers (named GP2, GP3)
brd.add_inner_copper_layer(2)
# Place 2 mm mounting holes in the corners
Expand Down Expand Up @@ -394,14 +393,14 @@ if __name__ == "__main__":
sp.fanout(["GND"], relative_to="inside")

print(brd.parts_str())

# finish the PCB with an outline and poured copper layers
brd.add_outline()
brd.fill_layer("GTL", "GND")
brd.fill_layer("GBL", "GND")
brd.fill_layer("GP3", "GND")

# Save the rendered PCB to asset files
# Save the rendered PCB to asset files
brd.save("%s" % (os.path.basename(__file__)[:-3]))
```

Expand Down
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ channels:
- conda-forge
- defaults
dependencies:
- python>=3.6
- python>=3.9
- ipython
- pyparsing
- sphinx=3.2.1
Expand Down
2 changes: 1 addition & 1 deletion examples/sample/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
brd.add_part((35, 5), SOIC8, side="bottom")
usb_con = EaglePart(
brd.DC((50, 15)).right(180),
libraryfile="sparkfun.lbr",
libraryfile="scripts/sparkfun.lbr",
partname="USB-B-SMT",
side="top",
)
Expand Down
32 changes: 26 additions & 6 deletions pcbflow/hershey.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ def char2val(c): # data is stored as signed bytes relative to ASCII R


def hersheyparse(dat):
""" reads a line of Hershey font text """
"""reads a line of Hershey font text"""

lines = []

# individual lines are stored separated by <space>+R
# starting at col 11

for s in dat[10:].split(" R"):

# each line is a list of pairs of coordinates
# NB: origin is at centre(ish) of character
# Y coordinates **increase** downwards
Expand All @@ -46,7 +45,7 @@ def hersheyparse(dat):

def plline(l):
(ucode, h, _) = [int(i, 0) for i in l[:-1].split(",")]
return (unichr(ucode), h)
return (chr(ucode), h)


# From http://paulbourke.net/dataformats/hershey/romans.hmp
Expand All @@ -71,11 +70,32 @@ def plline(l):
720,
]
+ list(range(700, 710))
+ [712, 713, 2241, 726, 2242, 715, 2273,]
+ [
712,
713,
2241,
726,
2242,
715,
2273,
]
+ list(range(501, 527))
+ [2223, 804, 2224, 2262, 999, 730,]
+ [
2223,
804,
2224,
2262,
999,
730,
]
+ list(range(601, 627))
+ [2225, 723, 2226, 2246, 718,]
+ [
2225,
723,
2226,
2246,
718,
]
)


Expand Down
2 changes: 1 addition & 1 deletion pcbflow/sexp_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
if PY3:
string_types = (str,)
else:
string_types = (basestring,)
string_types = (str,)

logger = logging.getLogger(__name__)

Expand Down
21 changes: 10 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import setuptools

PACKAGE_NAME = "pcbflow"
MINIMUM_PYTHON_VERSION = "3.6"
MINIMUM_PYTHON_VERSION = "3.9"

loc = os.path.abspath(os.path.dirname(__file__))

Expand Down Expand Up @@ -38,19 +38,18 @@

def check_python_version():
"""Exit when the Python version is too low."""

# get the version number, remove any trailing text, split into numerical values.
# then compare these sequences of numbers to one another
version = [int(v) for v in sys.version.split(' ')[0].split(".")]
min_version = [int(v) for v in MINIMUM_PYTHON_VERSION.split(' ')[0].split(".")]
for a,b in zip(version, min_version):
if a>b:
version = [int(v) for v in sys.version.split(" ")[0].split(".")]
min_version = [int(v) for v in MINIMUM_PYTHON_VERSION.split(" ")[0].split(".")]
for a, b in zip(version, min_version):
if a > b:
break
if a<b:
sys.exit("Python {0}+ is required.".format(MINIMUM_PYTHON_VERSION))


#if sys.version < MINIMUM_PYTHON_VERSION:
if a < b:
sys.exit("Python {0}+ is required.".format(MINIMUM_PYTHON_VERSION))

# if sys.version < MINIMUM_PYTHON_VERSION:


def read_package_variable(key, filename="__init__.py"):
Expand Down