diff options
-rw-r--r-- | .gitignore | 126 | ||||
-rw-r--r-- | .gitlab-ci.yml | 80 | ||||
-rw-r--r-- | .pypirc | 12 | ||||
-rw-r--r-- | LICENSE | 3 | ||||
-rw-r--r-- | Makefile | 22 | ||||
-rw-r--r-- | README.md | 79 | ||||
-rw-r--r-- | gerbonara/__init__.py | 1 | ||||
-rw-r--r-- | gerbonara/cli.py | 39 | ||||
-rw-r--r-- | setup.cfg | 2 | ||||
-rw-r--r-- | setup.py | 129 | ||||
-rw-r--r-- | test-requirements.txt | 5 |
11 files changed, 351 insertions, 147 deletions
@@ -1,51 +1,115 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ *.py[cod] +*$py.class # C extensions *.so -# Packages -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ .installed.cfg -lib -lib64 -__pycache__ +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec # Installer logs pip-log.txt +pip-delete-this-directory.txt # Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ .coverage -.tox +.coverage.* +.cache nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ # Translations *.mo +*.pot -# Mr Developer -.mr.developer.cfg -.project -.pydevproject -.idea/workspace.xml -.idea/misc.xml -.idea -.settings +# Django stuff: +*.log +local_settings.py +db.sqlite3 -# Komodo Files -*.komodoproject +# Flask stuff: +instance/ +.webassets-cache -# OS Files -.DS_Store -Thumbs.db +# Scrapy stuff: +.scrapy -# Virtual environment -venv -coverage.xml +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..d6dce87 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,80 @@ +stages: + - test + - coverage + - build + - upload + +image: python:3-alpine + +variables: + TWINE_NON_INTERACTIVE: "true" + CONFIG_FILE: ".pypirc" + +cache: + paths: + - .pipcache/ + +before_script: + - apk --no-cache add make + - pip --cache-dir .pipcache install -r test-requirements.txt + - cat /etc/alpine-release + - python -V + +.test: + stage: test + script: + - make test + +test:3.6: + extends: .test + image: python:3.6-alpine + +test:3.7: + extends: .test + image: python:3.7-alpine + +test:3.8: + extends: .test + image: python:3.8-alpine + +test:3.9: + extends: .test + image: python:3.9-alpine + +# 3.10 +test:rc: + extends: .test + allow_failure: true + image: python:rc-alpine + +testpypi: + stage: upload + script: + - pip --cache-dir .pipcache install twine + - python setup.py sdist bdist_wheel + - twine upload --skip-existing --repository testpypi dist/* + only: + - master + +pypi: + stage: upload + script: + - pip --cache-dir .pipcache install twine + - python setup.py sdist bdist_wheel + - twine upload --skip-existing --repository pypi dist/* + only: + - tags + +aur_git: + stage: upload + script: + - echo "build pygerber-git" + only: + - master + +aur: + stage: upload + script: + - echo "build pygerber" + only: + - tags @@ -0,0 +1,12 @@ +[distutils] +index-servers = + pypi + testpypi + +[pypi] +username = __token__ +password = ${env.PYPI_TOKEN} + +[testpypi] +username = __token__ +password = ${env.TESTPYPI_TOKEN} @@ -1,4 +1,4 @@ -Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -199,4 +199,3 @@ Apache License WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - @@ -2,9 +2,6 @@ PYTHON ?= python PYTEST ?= pytest -DOC_ROOT = doc -EXAMPLES = examples - .PHONY: clean clean: doc-clean find . -name '*.pyc' -delete @@ -26,16 +23,15 @@ test-coverage: install: PYTHONPATH=. $(PYTHON) setup.py install -.PHONY: doc-html -doc-html: - (cd $(DOC_ROOT); make html) +sdist: + python3 setup.py sdist + +bdist_wheel: + python3 setup.py bdist_wheel -.PHONY: doc-clean -doc-clean: - (cd $(DOC_ROOT); make clean) +upload: sdist bdist_wheel + twine upload -s -i contact@gerbonara.io --config-file ~/.pypirc --skip-existing --repository pypi dist/* -.PHONY: examples -examples: - PYTHONPATH=. $(PYTHON) examples/cairo_example.py - PYTHONPATH=. $(PYTHON) examples/pcb_example.py +testupload: sdist bdist_wheel + twine upload --config-file ~/.pypirc --skip-existing --repository testpypi dist/* @@ -1,62 +1,53 @@ -pcb-tools -============ -[![CI](https://github.com/curtacircuitos/pcb-tools/workflows/pcb-tools/badge.svg)](https://github.com/curtacircuitos/pcb-tools/actions) -[![Coverage](https://codecov.io/gh/curtacircuitos/pcb-tools/branch/master/graph/badge.svg)](https://codecov.io/gh/curtacircuitos/pcb-tools) -[![Docs](https://readthedocs.org/projects/pcb-tools/badge/?version=latest)](https://readthedocs.org/projects/pcb-tools/?badge=latest) +[![pipeline status](https://gitlab.com/gerbonara/gerbonara/badges/master/pipeline.svg)](https://gitlab.com/gerbonara/gerbonara/commits/master) +[![coverage report](https://gitlab.com/gerbonara/gerbonara/badges/master/coverage.svg)](https://gitlab.com/gerbonara/gerbonara/commits/master) +[![pypi](https://img.shields.io/pypi/v/gerbonara)](https://pypi.org/project/gerbonara/) +[![aur](https://img.shields.io/aur/version/python-gerbonara)](https://aur.archlinux.org/packages/python-gerbonara/) -Tools to handle Gerber and Excellon files in Python. +# gerbonara -Usage Example: ---------------- +Tools to handle Gerber and Excellon files in Python. -```py -import gerber -from gerber.render import GerberCairoContext +This repository is a friendly fork of [phsilva's pcb-tools](https://github.com/curtacircuitos/pcb-tools) with +[extensions from opiopan](https://github.com/opiopan/pcb-tools-extension) integrated. We decided to fork pcb-tools since +we need it as a dependency for [gerbolyze](https://gitlab.com/gerbolyze/gerbolyze) and pcb-tools was sometimes very +behind on bug fixes. -# Read gerber and Excellon files -top_copper = gerber.read('example.GTL') -nc_drill = gerber.read('example.txt') +# Installation -# Rendering context -ctx = GerberCairoContext() +Arch Linux: -# Create SVG image -top_copper.render(ctx) -nc_drill.render(ctx, 'composite.svg') +``` +yay -S python-gerbonara ``` -Rendering Examples: -------------------- -### Top Composite rendering -![Composite Top Image](examples/cairo_example.png) -![Composite Bottom Image](examples/cairo_bottom.png) - -Source code for this example can be found [here](examples/cairo_example.py). - +Python: -Install from source: ``` -$ git clone https://github.com/curtacircuitos/pcb-tools.git -$ cd pcb-tools -$ pip install -r requirements.txt -$ python setup.py install +pip install gerbonara ``` -Documentation: --------------- -[PCB Tools Documentation](http://pcb-tools.readthedocs.org/en/latest/) +# Usage + +Here's a simple example: +```python +import gerbonara +from gerbonara.render import GerberCairoContext -Development and Testing: ------------------------- +# Read gerber and Excellon files +top_copper = gerbonara.read('example.GTL') +nc_drill = gerbonara.read('example.txt') -Dependencies for developing and testing pcb-tools are listed in requirements-dev.txt. Use of a virtual environment is strongly recommended. +# Rendering context +ctx = GerberCairoContext() - $ virtualenv venv - $ source venv/bin/activate - (venv)$ pip install -r requirements-dev.txt - (venv)$ pip install -e . +# Create SVG image +top_copper.render(ctx) +nc_drill.render(ctx, 'composite.svg') +``` -We use [pytest](https://docs.pytest.org/en/latest/) to run pcb-tools's suite of unittests and doctests. +--- - (venv)$ pytest +Made with ❤️ and 🐍. +======= +pcb-tools diff --git a/gerbonara/__init__.py b/gerbonara/__init__.py new file mode 100644 index 0000000..b8023d8 --- /dev/null +++ b/gerbonara/__init__.py @@ -0,0 +1 @@ +__version__ = '0.0.1' diff --git a/gerbonara/cli.py b/gerbonara/cli.py new file mode 100644 index 0000000..5d7ef65 --- /dev/null +++ b/gerbonara/cli.py @@ -0,0 +1,39 @@ +from os import path, listdir +from glob import glob + +from . import __version__ + +import click + + +@click.group() +@click.version_option(__version__) +def cli(): + pass + + +@click.command() +@click.option('-o', '--outfile', type=click.File(mode='wb'), help='Output Filename (extension will be added automatically)') +@click.option('-t', '--theme', default='default', type=click.Choice(['default', 'OSH Park', 'Blue', 'Transparent Copper', 'Transparent Multilayer'], case_sensitive=False), help='Select render theme') +@click.option('-w', '--width', type=click.INT, help='Maximum width') +@click.option('-h', '--height', type=click.INT, help='Maximum height') +@click.option('-v', '--verbose', is_flag=True, help='Increase verbosity of the output') +@click.argument('filenames', nargs=-1, type=click.Path(exists=True)) +def render(outfile, theme, width, height, verbose, filenames): + """Render gerber files to image. If a directory is provided, it should be provided alone and should contain the gerber files for a single PCB.""" + if len(filenames) == 0: + raise click.UsageError(message='No files or folders provided') + if len(filenames) > 1: + for f in filenames: + if path.isdir(f): + raise click.UsageError(message='If a directory is provided, it should be provided alone and should contain the gerber files for a single PCB') + + # list files if folder id given + if len(filenames) == 1 and path.isdir(filenames[0]): + filenames = listdir(filenames[0]) + #filenames = [f for f in glob(f'{filenames[0]}/*.txt')] + + click.echo(f'render {filenames} with theme {theme}') + + +cli.add_command(render) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..2eb5b20 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[tool:pytest] +flake8-max-line-length = 120 @@ -1,68 +1,83 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- +#!/usr/bin/env python3 -# Copyright 2013-2014 Paulo Henrique Silva <ph.silva@gmail.com> +from os import environ +from os.path import join, abspath, dirname +from codecs import open +from setuptools import setup, find_packages +from subprocess import check_output -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 +def long_description(): + with open('README.md', 'r') as fh: + return fh.read() -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os +def version(): + with open(join(abspath(dirname(__file__)), 'gerbonara/__init__.py')) as fh: + for line in fh: + if line.startswith('__version__'): + ver = line.split("'")[1] + if environ.get('CI_COMMIT_SHA', '') != '' and environ.get('CI_COMMIT_TAG', '') == '': + # attach commit hash to non tagged test uploads from CI + commits = check_output(['/usr/bin/env', 'git', 'rev-list', '--count', 'HEAD'], text=True) + return f'{ ver }.dev{ commits.strip() }' + return ver -def read(fname): - return open(os.path.join(os.path.dirname(__file__), fname)).read() + raise RuntimeError('Unable to find version string.') -METADATA = { - 'name': 'pcb-tools', - 'version': 0.1, - 'author': 'Paulo Henrique Silva <ph.silva@gmail.com>, Hamilton Kibbe <ham@hamiltonkib.be>', - 'author_email': "ph.silva@gmail.com, ham@hamiltonkib.be", - 'description': "Utilities to handle Gerber (RS-274X) files.", - 'license': "Apache", - 'keywords': "pcb gerber tools", - 'url': "http://github.com/curtacircuitos/pcb-tools", - 'packages': ['gerber', 'gerber.render'], - 'long_description': read('README.md'), - 'classifiers': [ - "Development Status :: 3 - Alpha", - "Topic :: Utilities", - "License :: OSI Approved :: Apache Software License", - ], -} - -SETUPTOOLS_METADATA = { - 'install_requires': ['cairocffi==0.6'], - 'entry_points': { +setup( + name='gerbonara', + version=version(), + author='XenGi, Jaseg', + author_email='contact@gerbonara.io', + description='Tools to handle Gerber and Excellon files in Python', + long_description=long_description(), + long_description_content_type='text/markdown', + url='https://gitlab.com/gerbonara/gerbonara', + project_urls={ + # 'Documentation': 'https://packaging.python.org/tutorials/distributing-packages/', + # 'Funding': 'https://donate.pypi.org', + # 'Say Thanks!': 'http://saythanks.io/to/example', + 'Source': 'https://gitlab.com/gerbonara/gerbonara', + 'Tracker': 'https://gitlab.com/gerbonara/gerbonara/issues', + }, + packages=find_packages(exclude=['tests']), + install_requires=['click'], + entry_points={ 'console_scripts': [ - 'gerber-render = gerber.__main__:main', + 'gerbonara = gerbonara.cli:cli', ], }, -} - - -def install(): - """ Install using setuptools, fallback to distutils - """ - try: - from setuptools import setup - METADATA.update(SETUPTOOLS_METADATA) - setup(**METADATA) - except ImportError: - from sys import stderr - stderr.write('Could not import setuptools, using distutils') - stderr.write('NOTE: You will need to install dependencies manually') - from distutils.core import setup - setup(**METADATA) - - -if __name__ == '__main__': - install() + classifiers=[ + 'Development Status :: 1 - Planning', + #'Development Status :: 3 - Alpha', + #'Development Status :: 4 - Beta', + #'Development Status :: 5 - Production/Stable', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: Manufacturing', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3 :: Only', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Topic :: Artistic Software', + 'Topic :: Multimedia :: Graphics', + 'Topic :: Printing', + 'Topic :: Scientific/Engineering', + 'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)', + 'Topic :: Scientific/Engineering :: Image Processing', + 'Topic :: Utilities', + 'Typing :: Typed', + ], + keywords='gerber excellon pcb', + python_requires='>=3.6', +) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..86c0bfc --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,5 @@ +pytest +pytest-cov +pytest-xdist +pytest-flake8 +twine |