summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore126
-rw-r--r--.gitlab-ci.yml80
-rw-r--r--.pypirc12
-rw-r--r--LICENSE3
-rw-r--r--Makefile22
-rw-r--r--README.md79
-rw-r--r--gerbonara/__init__.py1
-rw-r--r--gerbonara/cli.py39
-rw-r--r--setup.cfg2
-rw-r--r--setup.py129
-rw-r--r--test-requirements.txt5
11 files changed, 351 insertions, 147 deletions
diff --git a/.gitignore b/.gitignore
index 12fb69a..11614af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/.pypirc b/.pypirc
new file mode 100644
index 0000000..6fc43db
--- /dev/null
+++ b/.pypirc
@@ -0,0 +1,12 @@
+[distutils]
+index-servers =
+ pypi
+ testpypi
+
+[pypi]
+username = __token__
+password = ${env.PYPI_TOKEN}
+
+[testpypi]
+username = __token__
+password = ${env.TESTPYPI_TOKEN}
diff --git a/LICENSE b/LICENSE
index e06d208..8dada3e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -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.
-
diff --git a/Makefile b/Makefile
index 8ecbf86..966f2a0 100644
--- a/Makefile
+++ b/Makefile
@@ -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/*
diff --git a/README.md b/README.md
index 64d6e8d..e2af255 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/setup.py b/setup.py
index 1dee243..f26885a 100644
--- a/setup.py
+++ b/setup.py
@@ -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