diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..091e39b --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +exclude = setup.py, scripts, examples, tests, build, pcbflow/hershey.py diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..150b7f7 --- /dev/null +++ b/.github/workflows/main.yml @@ -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 diff --git a/.gitignore b/.gitignore index 97a4cd5..5b75a82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# test files +skidl_test.* + # python intermediate files *.py[cod] diff --git a/README.md b/README.md index 1df6de4..21b9049 100644 --- a/README.md +++ b/README.md @@ -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) -Code style: black +Code style: black ![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) @@ -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 @@ -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, @@ -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 @@ -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 @@ -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) ``` @@ -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 @@ -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])) ``` diff --git a/environment.yml b/environment.yml index f757f33..3252130 100644 --- a/environment.yml +++ b/environment.yml @@ -3,7 +3,7 @@ channels: - conda-forge - defaults dependencies: - - python>=3.6 + - python>=3.9 - ipython - pyparsing - sphinx=3.2.1 diff --git a/examples/sample/sample.py b/examples/sample/sample.py index 0b02eed..7ec8d79 100644 --- a/examples/sample/sample.py +++ b/examples/sample/sample.py @@ -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", ) diff --git a/pcbflow/hershey.py b/pcbflow/hershey.py index 4cfdafb..e7d8dec 100644 --- a/pcbflow/hershey.py +++ b/pcbflow/hershey.py @@ -14,7 +14,7 @@ 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 = [] @@ -22,7 +22,6 @@ def hersheyparse(dat): # 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 @@ -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 @@ -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, + ] ) diff --git a/pcbflow/sexp_parser.py b/pcbflow/sexp_parser.py index 3f29dec..7146fc7 100644 --- a/pcbflow/sexp_parser.py +++ b/pcbflow/sexp_parser.py @@ -30,7 +30,7 @@ if PY3: string_types = (str,) else: - string_types = (basestring,) + string_types = (str,) logger = logging.getLogger(__name__) diff --git a/setup.py b/setup.py index adb62eb..0569c60 100644 --- a/setup.py +++ b/setup.py @@ -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__)) @@ -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