PyGerber package documentation¶
PyGerber is a Python library for 2D and 3D rendering of Gerber X3 files. It is completely written in Python, and only dependencies are limiting its portability.
Constructive Criticism¶
I would like to point out that this is the first extensive documentation I have ever written, so I would be very grateful for any constructive criticism.
Contents¶

Overview¶
PyGerber is a Python library for 2D and 3D rendering of Gerber X3 files. It is completely written in Python, and only dependencies are limiting its portability.
This package is a Free Software; it is released under MIT license. Be aware that dependencies might be using different licenses.
PyGerber offers a CLI and API for Python to allow easy rendering of Gerber files. Parser was build with GBR X3 format in mind, however, it has extensive support for older standards and deprecated features. Package is using third party libraries for low level drawing and mesh creation.
PyGerber’s parser was not mend to be used by package users, but there are no obstacles preventing you from using it. However, stability of the API is not guaranteed between minor releases (I’ll do my best to make it stable among patches).
Installation¶
PyGerber is available on PyPI and can be obtained via pip
pip install pygerber
You can also install the in-development version from github with
pip install https://github.com/Argmaster/pygerber/archive/main.zip
Blender dependency issue mentioned in previous releases was resolved by using PyR3 package which provides Blender. However, blender has to be installed independently from package by calling PyR3.install_bpy script:
python -m PyR3.install_bpy
Before You try to use 3D rendering.
Compatibility¶
PyGerber officially runs on Python 3.9.* and only on this version. However it may be possible to run 2D rendering on other Python versions that are supported by Pillow.
I’ll consider bringing Python 3.8 3D rendering support, but no sooner than after implementation of full set of 3D rendering features and macros support.
Documentation¶
Documentation of this library is available at https://pygerber.readthedocs.io/
PyGerber Installation¶
PyGerber is available on PyPI and can be obtained via pip
pip install pygerber
You can also install the in-development version from github with
pip install https://github.com/Argmaster/pygerber/archive/main.zip
Blender dependency issue mentioned in previous releases was resolved by using PyR3 package which provides Blender. However, blender has to be installed independently from package by calling PyR3.install_bpy script:
python -m PyR3.install_bpy
Before You try to use 3D rendering.
Usage¶
PyGerber project provides both CLI and API for rendering Gerber files. For rendering projects consisting of multiple files, it is necessary to use so called specfiles, which describes project structure. Specfiles has different options for 2D and different for 3D rendering.
Command Line Interface¶
First and foremost, the PyGerber command line help page can be displayed with this command:
$ python -m pygerber -h
2D rendering Example¶
To render project in 2D, specified by “tests/gerber/pillow/specfile.yaml” (from our repo) and save it as PNG named “render.png” we can use following command:
$ python -m pygerber --pillow --toml "tests/gerber/pillow/specfile.yaml" -s "render.png"
YAML specfile used defines simple 4-layer PCB project and looks like this:
dpi: 600
ignore_deprecated: yes
image_padding: 0
layers:
- file_path: ./tests/gerber/set/top_copper.grb
colors:
dark: [40, 143, 40, 255]
clear: [60, 181, 60, 255]
- file_path: ./tests/gerber/set/top_solder_mask.grb
colors: solder_mask
- file_path: ./tests/gerber/set/top_paste_mask.grb
- file_path: ./tests/gerber/set/top_silk.grb
colors: silk
On the very top level it specifies DPI of output image, 600 in our case, and sets image padding to no padding. Then layers param specifies layers from bottom-most to top-most. You have to at least specify path to gerber file in layer. For more about specfiles see Specfile for 2D rendering chapter.
3D rendering Example¶
3D rendering works identically, except that specfiles have a slightly different set of parameters. Again, see Specfile for 3D rendering chapter for more in-depth description. (DRY :D )
We also have example specfiles for 3D rendering in our repo, lets see how to use them
$ python -m pygerber --blender --toml "tests/gerber/blender/specfile.json" -s "render.glb"
That’s exactly the same 4 layer project, only this time in 3D and with specfile written in JSON instead of YAML
{
"ignore_deprecated": true,
"layers": [
{
"file_path": "./tests/gerber/set/top_copper.grb",
"structure": {
"material": {
"color": [40, 143, 40, 255]
},
"thickness": 0.78
}
},
{
"file_path": "./tests/gerber/set/top_solder_mask.grb",
"material": "solder_mask"
},
{
"file_path": "./tests/gerber/set/top_paste_mask.grb"
},
{
"file_path": "./tests/gerber/set/top_silk.grb"
}
]
}
As You can see, both top level options and layer specifications differ a bit, but remain similar. For the third time, I insist that you visit Specfile for 3D rendering. If you did, you should already be aware of the meaning of this file’s structure.
2D rendering API¶
Coming soon. (v1.0.2)
3D rendering API¶
Coming soon. (v1.0.2)
Project Specification files¶
So called specfiles contains description of project to be rendered. The parameters that can be used in them differ depending on whether you are rendering in 2D or 3D Specfiles can be written in one of three languages: JSON, YAML and TOML. You have to indicated which one of them was used by using either corresponding flag, (–yaml for YAML e.t.c) when using CLI or appropriate function (render_from_yaml() for YAML e.t.c).
Specfile for 2D rendering¶
2D spec top level parameters¶
At top level specfile contains a dictionary with following keys:
dpi
- integer, DPI of output image, optional, defaults to 600,
ignore_deprecated
- bool, if false, causes Gerber parser to halt after encountering deprecated syntax, optional, defaults to True,
layers
- list of layers, mandatory, each layer is a dictionary with following keys
file_path
, string, path to Gerber source file, mandatory,
colors
, optional, see Defining colors for layer
Defining colors for layer¶
colors
layer dictionary param can be omitted, then color will be
determined from Gerber file name. Chosen color will be one of
Predefined Colors, the first whose name will be
found in the filename.
colors
can also be set to string, which have to be one of
Predefined Colors.
Third option is to set colors manually via dictionary, then dictionary has following keys, whose values are lists of 3 or 4 integers in range 0-255 representing RGB / RGBA colors
dark
- mandatory, no default value
clear
- optional, defaults to transparent
background
optional, defaults to transparent
Predefined Colors¶
- Following predefined colors are available:
silk
white, transparent, transparentpaste_mask
gray, transparent, transparentsolder_mask
light gray, transparent, transparentcopper
green, green (lighter), transparentorange
orange, transparent, transparentgreen
green, green (darker), transparentdebug
strange, strange, transparent
Example JSON specfile¶
{
"dpi": 600,
"ignore_deprecated": true,
"image_padding": 0,
"layers": [
{
"file_path": "./tests/gerber/set/top_copper.grb",
"colors": {
"dark": [40, 143, 40, 255],
"clear": [60, 181, 60, 255]
}
},
{
"file_path": "./tests/gerber/set/top_solder_mask.grb",
"colors": "solder_mask"
},
{
"file_path": "./tests/gerber/set/top_paste_mask.grb"
},
{
"file_path": "./tests/gerber/set/top_silk.grb",
"colors": [[255, 255, 255, 255]]
}
]
}
Specfile for 3D rendering¶
3D spec top level parameters¶
- At top level specfile contains a dictionary with following keys:
ignore_deprecated
- bool, if false, causes Gerber parser to halt after encountering deprecated syntax, optional, defaults to True,scale
- float, output scale, optional, defaults to 1000, not yet modifiable.layers
- list of layers, mandatory, each layer is a dictionary with following keysfile_path
, string, path to Gerber source file, mandatory,structure
, optional, see Defining structure of a layer
Defining structure of a layer¶
structure
parameter can be omitted, then structure will be
determined from Gerber file name. Chosen structure will be one of
Predefined layer structures, the first whose name
will be found in the filename.
Otherwise it can be a string containing name of one of Predefined layer structures.
- Last possible option is to use a dictionary with following keys:
material
- dictionary with blender BSDF node parameters. Only exception from typical node parameters is that colors are lists integers in range 0-255, not floats 0.0 - 1.0thickness
- thickness of layer in millimeters as float.
Predefined layer structures¶
- Following predefined layer structure are available:
silk
0.04mm, rough, non-metalic, whitepaste_mask
0.1mm, metallic, partially rough, graysolder_mask
0.1mm, metallic, partially rough, gray (lighter)copper
0.78mm, metallic, rough, greengreen
0.78mm, default, greendebug
0.78mm, default, strangedebug2
0.78mm, default, strangedebug3
0.78mm, default, strange
Example YAML specfile¶
ignore_deprecated: yes
layers:
- file_path: ./tests/gerber/set/top_copper.grb
structure:
thickness: 0.78
material:
color: [40, 143, 40, 255]
- file_path: ./tests/gerber/set/top_solder_mask.grb
material: solder_mask
- file_path: ./tests/gerber/set/top_paste_mask.grb
- file_path: ./tests/gerber/set/top_silk.grb
pygerber¶
pygerber package¶
Subpackages¶
pygerber.parser package¶
Subpackages¶
- class pygerber.parser.pillow.apertures.circle.PillowCircle(args: <pygerber.tokens.add.ADD_Token.ARGS_dispatcher object at 0x7fc1b3825490>, renderer)[source]¶
Bases:
pygerber.parser.pillow.apertures.arc_mixin.ArcUtilMixinPillow
,pygerber.parser.pillow.apertures.flash_mixin.FlashUtilMixin
,pygerber.renderer.aperture.circular.CircularAperture
- arc(spec: pygerber.renderer.spec.ArcSpec) None [source]¶
- property diameter: float¶
- line(spec: pygerber.renderer.spec.LineSpec) None [source]¶
- property radius: float¶
- class pygerber.parser.pillow.apertures.custom.PillowCustom(args: <pygerber.tokens.add.ADD_Token.ARGS_dispatcher object at 0x7fc1b3825490>, renderer)[source]¶
Bases:
pygerber.parser.pillow.apertures.arc_mixin.ArcUtilMixinPillow
,pygerber.parser.pillow.apertures.flash_mixin.FlashUtilMixin
,pygerber.parser.pillow.apertures.flash_line_mixin.FlashLineMixin
,pygerber.renderer.aperture.custom.CustomAperture
- class pygerber.parser.pillow.apertures.flash_line_mixin.FlashLineMixin[source]¶
Bases:
object
- line(spec: pygerber.renderer.spec.LineSpec) None [source]¶
- class pygerber.parser.pillow.apertures.flash_mixin.FlashUtilMixin[source]¶
Bases:
pygerber.parser.pillow.apertures.util.PillowUtilMethdos
- property aperture_mask: PIL.Image.Image¶
- property aperture_stamp_clear: PIL.Image.Image¶
- property aperture_stamp_dark: PIL.Image.Image¶
- flash(spec: pygerber.renderer.spec.FlashSpec) None [source]¶
- flash_at_location(location: pygerber.mathclasses.Vector2D) None [source]¶
- get_aperture_hole_bbox() pygerber.mathclasses.BoundingBox [source]¶
- property hole_diameter: float¶
- property hole_radius: float¶
- property pixel_bbox¶
- class pygerber.parser.pillow.apertures.obround.PillowObround(args: <pygerber.tokens.add.ADD_Token.ARGS_dispatcher object at 0x7fc1b3825490>, renderer)[source]¶
Bases:
pygerber.parser.pillow.apertures.flash_line_mixin.FlashLineMixin
,pygerber.parser.pillow.apertures.rectangle.PillowRectangle
- class pygerber.parser.pillow.apertures.polygon.PillowPolygon(args: <pygerber.tokens.add.ADD_Token.ARGS_dispatcher object at 0x7fc1b3825490>, renderer)[source]¶
Bases:
pygerber.parser.pillow.apertures.arc_mixin.ArcUtilMixinPillow
,pygerber.parser.pillow.apertures.flash_mixin.FlashUtilMixin
,pygerber.parser.pillow.apertures.flash_line_mixin.FlashLineMixin
,pygerber.renderer.aperture.polygon.PolygonAperture
- arc(spec: pygerber.renderer.spec.ArcSpec) None [source]¶
- property radius: float¶
- class pygerber.parser.pillow.apertures.rectangle.PillowRectangle(args: <pygerber.tokens.add.ADD_Token.ARGS_dispatcher object at 0x7fc1b3825490>, renderer)[source]¶
Bases:
pygerber.parser.pillow.apertures.arc_mixin.ArcUtilMixinPillow
,pygerber.parser.pillow.apertures.flash_mixin.FlashUtilMixin
,pygerber.renderer.aperture.rectangular.RectangularAperture
- arc(spec: pygerber.renderer.spec.ArcSpec) None [source]¶
- line(spec: pygerber.renderer.spec.LineSpec) None [source]¶
- property x_half: float¶
- property y_half: float¶
- class pygerber.parser.pillow.apertures.region.PillowRegion(renderer)[source]¶
Bases:
pygerber.parser.pillow.apertures.arc_mixin.ArcUtilMixinPillow
,pygerber.renderer.aperture.region.RegionApertureManager
,pygerber.parser.pillow.apertures.util.PillowUtilMethdos
- finish(bounds: List[pygerber.renderer.spec.LineSpec]) None [source]¶
- class pygerber.parser.pillow.apertures.util.PillowUtilMethdos[source]¶
Bases:
object
- property canvas¶
- property dpmm¶
- property draw_canvas¶
- prepare_arc_spec(spec: pygerber.renderer.spec.ArcSpec) pygerber.renderer.spec.ArcSpec [source]¶
- prepare_coordinates(vector: pygerber.mathclasses.Vector2D) pygerber.mathclasses.Vector2D [source]¶
- prepare_flash_spec(spec: pygerber.renderer.spec.FlashSpec) pygerber.renderer.spec.FlashSpec [source]¶
- prepare_line_spec(spec: pygerber.renderer.spec.LineSpec) pygerber.renderer.spec.LineSpec [source]¶
- renderer: pygerber.renderer.Renderer¶
- class pygerber.parser.pillow.api.PillowLayerSpec(file_path: 'str', colors: 'ColorSet')[source]¶
Bases:
pygerber.parser.project_spec.LayerSpecBase
- file_path: str¶
- class pygerber.parser.pillow.api.PillowProjectSpec(init_spec: Dict)[source]¶
Bases:
pygerber.parser.project_spec.ProjectSpecBase
- property LayerSpecClass: pygerber.parser.pillow.api.PillowLayerSpec¶
- dpi: int = 600¶
- ignore_deprecated: bool = True¶
- image_padding: int = 0¶
- layers: List[pygerber.parser.pillow.api.PillowLayerSpec] = []¶
- class pygerber.parser.pillow.parser.ColorSet(dark: 'Color_Type', clear: 'Color_Type' = (0, 0, 0, 0), background: 'Color_Type' = (0, 0, 0, 0))[source]¶
Bases:
object
- background: Tuple[float, float, float, float] = (0, 0, 0, 0)¶
- clear: Tuple[float, float, float, float] = (0, 0, 0, 0)¶
- dark: Tuple[float, float, float, float]¶
- class pygerber.parser.pillow.parser.ParserWithPillow(*, ignore_deprecated: bool = True, dpi: int = 600, colors: pygerber.parser.pillow.parser.ColorSet = ColorSet(dark=(66, 166, 66, 255), clear=(16, 66, 36, 255), background=(0, 0, 0, 0)), image_padding: int = 0)[source]¶
Bases:
pygerber.parser.parser.AbstractParser
- apertureSet: ApertureSet = ApertureSet(circle=<class 'pygerber.parser.pillow.apertures.circle.PillowCircle'>, rectangle=<class 'pygerber.parser.pillow.apertures.rectangle.PillowRectangle'>, obround=<class 'pygerber.parser.pillow.apertures.obround.PillowObround'>, polygon=<class 'pygerber.parser.pillow.apertures.polygon.PillowPolygon'>, custom=<class 'pygerber.parser.pillow.apertures.custom.PillowCustom'>, region=<class 'pygerber.parser.pillow.apertures.region.PillowRegion'>)¶
- property canvas: PIL.Image.Image¶
- is_rendered: bool¶
- save(file_path: str, format: Optional[str] = None) None [source]¶
Saves rendered image. file_path A filename (string), pathlib.Path object or file object. format Optional format override. If omitted, the format to use is determined from the filename extension. If a file object was used instead of a filename, this parameter should always be used.
Submodules¶
pygerber.parser.parser module¶
- class pygerber.parser.parser.AbstractParser(ignore_deprecated: bool = True)[source]¶
Bases:
abc.ABC
- apertureSet: pygerber.renderer.apertureset.ApertureSet¶
- tokenizer: pygerber.tokenizer.Tokenizer¶
pygerber.parser.project_spec module¶
- class pygerber.parser.project_spec.LayerSpecBase[source]¶
Bases:
abc.ABC
- abstract static load(contents: Dict) pygerber.parser.project_spec.LayerSpecBase [source]¶
- class pygerber.parser.project_spec.ProjectSpecBase(init_spec: Dict)[source]¶
Bases:
abc.ABC
- abstract property LayerSpecClass: pygerber.parser.project_spec.LayerSpecBase¶
- classmethod from_json(file_path: str) pygerber.parser.project_spec.ProjectSpecBase [source]¶
- classmethod from_toml(file_path: str) pygerber.parser.project_spec.ProjectSpecBase [source]¶
- classmethod from_yaml(file_path: str) pygerber.parser.project_spec.ProjectSpecBase [source]¶
Module contents¶
pygerber.renderer package¶
Subpackages¶
- class pygerber.renderer.aperture.aperture.Aperture(args: ADD_Token.ARGS, renderer: Renderer)[source]¶
Bases:
abc.ABC
,pygerber.renderer.arc_util_mixin.ArcUtilMixin
- abstract arc(spec: pygerber.renderer.spec.ArcSpec) None [source]¶
- arc_bbox(spec: pygerber.renderer.spec.ArcSpec) pygerber.mathclasses.BoundingBox [source]¶
- abstract bbox() pygerber.mathclasses.BoundingBox [source]¶
- abstract flash(spec: pygerber.renderer.spec.FlashSpec) None [source]¶
- flash_bbox(spec: pygerber.renderer.spec.FlashSpec) pygerber.mathclasses.BoundingBox [source]¶
- abstract line(spec: pygerber.renderer.spec.LineSpec) None [source]¶
- line_bbox(spec: pygerber.renderer.spec.LineSpec) pygerber.mathclasses.BoundingBox [source]¶
- class pygerber.renderer.aperture.circular.CircularAperture(args: <pygerber.tokens.add.ADD_Token.ARGS_dispatcher object at 0x7fc1b3825490>, renderer)[source]¶
Bases:
pygerber.renderer.aperture.aperture.Aperture
- DIAMETER: float¶
- HOLE_DIAMETER: float¶
- class pygerber.renderer.aperture.region.RegionApertureManager(renderer)[source]¶
Bases:
abc.ABC
,pygerber.renderer.arc_util_mixin.ArcUtilMixin
- bbox(bounds: List[pygerber.renderer.spec.Spec]) pygerber.mathclasses.BoundingBox [source]¶
- abstract finish(bounds: List[pygerber.renderer.spec.Spec]) None [source]¶
- steps: List[Tuple[pygerber.renderer.aperture.aperture.Aperture, pygerber.renderer.spec.Spec]]¶
Submodules¶
pygerber.renderer.aperture_manager module¶
pygerber.renderer.apertureset module¶
- class pygerber.renderer.apertureset.ApertureSet(circle: Type[pygerber.renderer.aperture.aperture.Aperture], rectangle: Type[pygerber.renderer.aperture.aperture.Aperture], obround: Type[pygerber.renderer.aperture.aperture.Aperture], polygon: Type[pygerber.renderer.aperture.aperture.Aperture], custom: Type[pygerber.renderer.aperture.aperture.Aperture], region: Type[pygerber.renderer.aperture.region.RegionApertureManager])[source]¶
Bases:
object
- circle: Type[pygerber.renderer.aperture.aperture.Aperture]¶
- custom: Type[pygerber.renderer.aperture.aperture.Aperture]¶
- getApertureClass(name: Optional[str] = None, is_region: bool = False) pygerber.renderer.aperture.aperture.Aperture [source]¶
- obround: Type[pygerber.renderer.aperture.aperture.Aperture]¶
- polygon: Type[pygerber.renderer.aperture.aperture.Aperture]¶
- rectangle: Type[pygerber.renderer.aperture.aperture.Aperture]¶
- region: Type[pygerber.renderer.aperture.region.RegionApertureManager]¶
pygerber.renderer.arc_util_mixin module¶
- class pygerber.renderer.arc_util_mixin.ArcUtilMixin[source]¶
Bases:
object
- get_arc_points(spec: pygerber.renderer.spec.ArcSpec, is_ccw: bool) pygerber.mathclasses.Vector2D [source]¶
- get_begin_end_angles(spec: pygerber.renderer.spec.ArcSpec)[source]¶
- property isCCW¶
pygerber.renderer.spec module¶
- class pygerber.renderer.spec.ArcSpec(begin: 'Vector2D', end: 'Vector2D', center: 'Vector2D', is_region: 'bool' = False)[source]¶
Bases:
pygerber.renderer.spec.Spec
- bbox(aperture: pygerber.renderer.aperture.aperture.Aperture)[source]¶
- center: pygerber.mathclasses.Vector2D¶
- draw(aperture: pygerber.renderer.aperture.aperture.Aperture)[source]¶
- is_region: bool = False¶
- class pygerber.renderer.spec.FlashSpec(location: 'Vector2D', is_region: 'bool' = False)[source]¶
Bases:
pygerber.renderer.spec.Spec
- bbox(aperture: pygerber.renderer.aperture.aperture.Aperture)[source]¶
- draw(aperture: pygerber.renderer.aperture.aperture.Aperture)[source]¶
- is_region: bool = False¶
- location: pygerber.mathclasses.Vector2D¶
- class pygerber.renderer.spec.LineSpec(begin: 'Vector2D', end: 'Vector2D', is_region: 'bool' = False)[source]¶
Bases:
pygerber.renderer.spec.Spec
- bbox(aperture: pygerber.renderer.aperture.aperture.Aperture)[source]¶
- draw(aperture: pygerber.renderer.aperture.aperture.Aperture)[source]¶
- is_region: bool = False¶
Module contents¶
- class pygerber.renderer.Renderer(apertureSet: pygerber.renderer.apertureset.ApertureSet)[source]¶
Bases:
object
- bbox_arc(end: pygerber.mathclasses.Vector2D, offset: pygerber.mathclasses.Vector2D) None [source]¶
- bbox_flash(point: pygerber.mathclasses.Vector2D) pygerber.mathclasses.BoundingBox [source]¶
- bbox_interpolated(end: pygerber.mathclasses.Vector2D, offset: pygerber.mathclasses.Vector2D) pygerber.mathclasses.BoundingBox [source]¶
- bbox_line(end: pygerber.mathclasses.Vector2D) None [source]¶
- current_point: pygerber.mathclasses.Vector2D¶
- draw_arc(end: pygerber.mathclasses.Vector2D, offset: pygerber.mathclasses.Vector2D) None [source]¶
- draw_flash(point: pygerber.mathclasses.Vector2D) None [source]¶
- draw_interpolated(end: pygerber.mathclasses.Vector2D, offset: pygerber.mathclasses.Vector2D) None [source]¶
- draw_line(end: pygerber.mathclasses.Vector2D) None [source]¶
- finish_drawing_region() Tuple[pygerber.renderer.aperture.region.RegionApertureManager, List[pygerber.renderer.spec.Spec]] [source]¶
- move_pointer(location: pygerber.mathclasses.Vector2D) None [source]¶
- region_bounds: List[pygerber.renderer.spec.Spec]¶
- render(token_stack: Deque[pygerber.tokens.token.Token]) None [source]¶
- replace_none_with_0(vector: pygerber.mathclasses.Vector2D)[source]¶
- replace_none_with_current(vector: pygerber.mathclasses.Vector2D)[source]¶
- total_bounding_box(token_stack: Deque[pygerber.tokens.token.Token])[source]¶
pygerber.tokens package¶
Submodules¶
pygerber.tokens.add module¶
- class pygerber.tokens.add.ADD_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- class ARGS_dispatcher(pattern: str | Callable)[source]¶
Bases:
pygerber.validators.struct_validator.StructValidator
- DIAMETER = <pygerber.validators.coordinate.UnitFloat object>¶
- HOLE_DIAMETER = <pygerber.validators.coordinate.UnitFloat object>¶
- ROTATION = <pygerber.validators.basic.Float object>¶
- VERTICES = <pygerber.validators.basic.Int object>¶
- X = <pygerber.validators.coordinate.UnitFloat object>¶
- Y = <pygerber.validators.coordinate.UnitFloat object>¶
- re_match: re.Match¶
- BASIC_APERTURE = '(?P<TYPE>[CROP]),(?P<ARGS>([-+]?[0-9]*\\.?[0-9]*X?)+)'¶
- CIRCLE_PATTERN = re.compile('(?P<DIAMETER>[-+]?[0-9]*\\.?[0-9]*)(X(?P<HOLE_DIAMETER>[-+]?[0-9]*\\.?[0-9]*))?')¶
- FLOAT_PATTERN = '[-+]?[0-9]*\\.?[0-9]*'¶
- ID = <pygerber.validators.basic.Int object>¶
- NAME = <pygerber.validators.basic.String object>¶
- NAMED_APERTURE = '(?P<NAME>[a-zA-Z0-9]+)'¶
- POLYGON_PATTERN = re.compile('(?P<DIAMETER>[-+]?[0-9]*\\.?[0-9]*)X(?P<VERTICES>[-+]?[0-9]*\\.?[0-9]*)(X(?P<ROTATION>[-+]?[0-9]*\\.?[0-9]*))?(X(?P<HOLE_DIAMETER>[-+]?[0-9]*\\.?[0-9]*))?')¶
- RECTANGLE_PATTERN = re.compile('(?P<X>[-+]?[0-9]*\\.?[0-9]*)X(?P<Y>[-+]?[0-9]*\\.?[0-9]*)(X(?P<HOLE_DIAMETER>[-+]?[0-9]*\\.?[0-9]*))?')¶
- TYPE = <pygerber.validators.basic.String object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%ADD(?P<ID>[0-9]+)((?P<TYPE>[CROP]),(?P<ARGS>([-+]?[0-9]*\\.?[0-9]*X?)+)|(?P<NAME>[a-zA-Z0-9]+))\\*%')¶
pygerber.tokens.am module¶
- class pygerber.tokens.am.ApertureMacro_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- BODY = <pygerber.validators.basic.String object>¶
- NAME = <pygerber.validators.basic.String object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%AM(?P<NAME>.*?)\\*(?P<BODY>.*?)\\*%', re.DOTALL)¶
pygerber.tokens.comment module¶
- class pygerber.tokens.comment.G04_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- STRING = <pygerber.validators.basic.String object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G04(?P<STRING>.*?)\\*')¶
- class pygerber.tokens.comment.G74_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G74\\*')¶
- class pygerber.tokens.comment.G75_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G75\\*')¶
- class pygerber.tokens.comment.LoadName_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%LN.*?\\*%', re.DOTALL)¶
pygerber.tokens.control module¶
- class pygerber.tokens.control.EndOfStream_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('M0[02]\\*')¶
- class pygerber.tokens.control.ImagePolarity_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- POLARITY = <pygerber.validators.basic.String object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%IP(?P<POLARITY>((POS)|(NEG)))\\*%')¶
- class pygerber.tokens.control.Whitespace_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- keep: bool = False¶
- regex: re.Pattern = re.compile('\\s+')¶
pygerber.tokens.dispatcher_meta module¶
- class pygerber.tokens.dispatcher_meta.Dispatcher(match_object: re.Match, state: DrawingState)[source]¶
Bases:
object
Base class for all dispatcher objects. Includes tokens and some of the fields.
- class pygerber.tokens.dispatcher_meta.DispatcherMeta(name, bases, attributes)[source]¶
Bases:
abc.ABCMeta
- validators: Dict[str, pygerber.validators.validator.Validator] = {}¶
- pygerber.tokens.dispatcher_meta.getvalidators(mesh_factory: pygerber.tokens.dispatcher_meta.Dispatcher) dict [source]¶
Returns validators specified for given Dispatcher.
- Parameters
mesh_factory (Dispatcher) – Object to fetch validators from.
- Returns
dictionary of factory fields.
- Return type
dict
pygerber.tokens.dnn module¶
- class pygerber.tokens.dnn.D01_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- I = <pygerber.validators.coordinate.Coordinate object>¶
- J = <pygerber.validators.coordinate.Coordinate object>¶
- X = <pygerber.validators.coordinate.Coordinate object>¶
- Y = <pygerber.validators.coordinate.Coordinate object>¶
- property end¶
- property offset¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('(X(?P<X>[-+]?[0-9]+))?(Y(?P<Y>[-+]?[0-9]+))?(I(?P<I>[-+]?[0-9]+))?(J(?P<J>[-+]?[0-9]+))?D01\\*')¶
- class pygerber.tokens.dnn.D02_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- X = <pygerber.validators.coordinate.Coordinate object>¶
- Y = <pygerber.validators.coordinate.Coordinate object>¶
- property point¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('(X(?P<X>[-+]?[0-9]+))?(Y(?P<Y>[-+]?[0-9]+))?D02\\*')¶
- class pygerber.tokens.dnn.D03_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.dnn.D02_Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('(X(?P<X>[-+]?[0-9]+))?(Y(?P<Y>[-+]?[0-9]+))?D03\\*')¶
- class pygerber.tokens.dnn.DNN_Loader_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- ID = <pygerber.validators.basic.Int object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('D(?P<ID>[1-9][0-9]*)\\*')¶
- class pygerber.tokens.dnn.G54DNN_Loader_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.dnn.DNN_Loader_Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G54D(?P<ID>[1-9][0-9]*)\\*')¶
pygerber.tokens.fs module¶
- class pygerber.tokens.fs.FormatSpecifierToken(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- property DEC_FORMAT¶
- property INT_FORMAT¶
- X_dec = <pygerber.validators.basic.Int object>¶
- X_int = <pygerber.validators.basic.Int object>¶
- Y_dec = <pygerber.validators.conditional.CallOnCondition object>¶
- Y_int = <pygerber.validators.conditional.CallOnCondition object>¶
- property length¶
- mode = <pygerber.validators.basic.String object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%FS(?P<zeros>[LTD])(?P<mode>[AI])X(?P<X_int>[1-6])(?P<X_dec>[1-6])Y(?P<Y_int>[1-6])(?P<Y_dec>[1-6])\\*%')¶
- zeros = <pygerber.validators.basic.String object>¶
pygerber.tokens.gnn module¶
- class pygerber.tokens.gnn.G0N_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- INTERPOLATION = <pygerber.validators.basic.Int object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G0(?P<INTERPOLATION>[1-3])\\*?')¶
- class pygerber.tokens.gnn.G36_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G36\\*')¶
- class pygerber.tokens.gnn.G37_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G37\\*')¶
- class pygerber.tokens.gnn.G55_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G55.*?\\*')¶
- class pygerber.tokens.gnn.G70_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G70.*?\\*')¶
- class pygerber.tokens.gnn.G71_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G71.*?\\*')¶
- class pygerber.tokens.gnn.G90_Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- re_match: re.Match¶
- regex: re.Pattern = re.compile('G90\\*')¶
pygerber.tokens.load module¶
- class pygerber.tokens.load.LoadMirroringToken(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- MIRRORING = <pygerber.validators.basic.String object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%LM(?P<MIRRORING>((N)|(X)|(Y)|(XY)))\\*%')¶
- class pygerber.tokens.load.LoadPolarityToken(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- POLARITY = <pygerber.validators.basic.String object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%LP(?P<POLARITY>[CD])\\*%')¶
- class pygerber.tokens.load.LoadRotationToken(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- FLOAT_PATTERN = '[-+]?[0-9]*\\.?[0-9]*'¶
- ROTATION = <pygerber.validators.basic.Float object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%LR(?P<ROTATION>[-+]?[0-9]*\\.?[0-9]*)\\*%')¶
- class pygerber.tokens.load.LoadScalingToken(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.token.Token
- FLOAT_PATTERN = '[-+]?[0-9]*\\.?[0-9]*'¶
- SCALE = <pygerber.validators.basic.Float object>¶
- re_match: re.Match¶
- regex: re.Pattern = re.compile('%LS(?P<SCALE>[-+]?[0-9]*\\.?[0-9]*)\\*%')¶
pygerber.tokens.token module¶
- class pygerber.tokens.token.Token(match_object: re.Match, state: DrawingState)[source]¶
Bases:
pygerber.tokens.dispatcher_meta.Dispatcher
- keep: bool = True¶
- re_match: re.Match¶
- regex: re.Pattern¶
- render(renderer: Renderer)[source]¶
This method should be called only after token is dispatched and after alter_state().
- renderer: Renderer = None¶
Module contents¶
pygerber.validators package¶
Submodules¶
pygerber.validators.basic module¶
pygerber.validators.conditional module¶
- class pygerber.validators.conditional.CallOnCondition(validator: pygerber.validators.validator.Validator, condition: callable, onfailure: callable)[source]¶
pygerber.validators.coordinate module¶
- class pygerber.validators.coordinate.Coordinate[source]¶
Bases:
pygerber.validators.validator.Validator
- ensure_mm(state: pygerber.tokens.token.Token, value: float)[source]¶
pygerber.validators.struct_validator module¶
- class pygerber.validators.struct_validator.StructValidator(pattern: str | Callable)[source]¶
Bases:
pygerber.tokens.dispatcher_meta.Dispatcher
,pygerber.validators.validator.Validator
- re_match: re.Match¶
pygerber.validators.validator module¶
Module contents¶
Submodules¶
pygerber.API2D module¶
- pygerber.API2D.render_file(file_path: str, *, dpi: int = 600, colors: pygerber.parser.pillow.parser.ColorSet = ColorSet(dark=(66, 166, 66, 255), clear=(16, 66, 36, 255), background=(0, 0, 0, 0)), ignore_deprecated: bool = True, image_padding: int = 0) PIL.Image.Image [source]¶
Loads, parses and renders file from given path and returns its render as PIL.Image.Image.
- Parameters
file_path (str) – Path to gerber file to render.
dpi (int, optional) – Output image DPI, defaults to 600
colors (ColorSet, optional) – Color specification, defaults to DEFAULT_COLOR_SET_GREEN
ignore_deprecated (bool, optional) – If false causes parser to stop when deprecated syntax is met, defaults to True
image_padding (int, optional) – Additional image padding, defaults to 0
- Returns
Output image.
- Return type
Image.Image
- pygerber.API2D.render_file_and_save(file_path: str, save_path: str, *, dpi: int = 600, colors: pygerber.parser.pillow.parser.ColorSet = ColorSet(dark=(66, 166, 66, 255), clear=(16, 66, 36, 255), background=(0, 0, 0, 0)), ignore_deprecated: bool = True, image_padding: int = 0)[source]¶
Loads, parses, renders file from file_path and saves it in save_path.
- Parameters
file_path (str) – Path to gerber file.
save_path (str) – Path to save render.
dpi (int, optional) – DPI of output image, defaults to 600
colors (ColorSet, optional) – Color set to use, defaults to DEFAULT_COLOR_SET_GREEN
ignore_deprecated (bool, optional) – If true, causes parser to not stop when deprecated syntax is found, defaults to True
image_padding (int, optional) – Additional pixel padding for image, defaults to 0
- pygerber.API2D.render_from_json(file_path: str) PIL.Image.Image [source]¶
Render 2D image from specfile written in json.
- Parameters
file_path (str) – json specfile path.
- Returns
rendered and merged image.
- Return type
Image.Image
- pygerber.API2D.render_from_spec(spec: Dict[str, Any]) PIL.Image.Image [source]¶
Render 2D image from specfile alike dictionary.
- Parameters
spec (Dict) – specfile parameters dictionary.
- Returns
rendered and merged image.
- Return type
Image.Image
pygerber.API3D module¶
pygerber.cli module¶
pygerber.constants module¶
pygerber.coparser module¶
pygerber.drawing_state module¶
- class pygerber.drawing_state.DrawingState[source]¶
Bases:
object
- coparser: pygerber.coparser.CoParser¶
- interpolation: pygerber.constants.Interpolation¶
- is_regionmode: bool¶
- mirroring: str¶
- polarity: str¶
- rotation: float¶
- scale: float¶
- unit: pygerber.constants.Unit¶
pygerber.exceptions module¶
pygerber.mathclasses module¶
- class pygerber.mathclasses.BoundingBox(x0: 'float', y0: 'float', x1: 'float', y1: 'float') 'None' [source]¶
Bases:
object
- contains(other: pygerber.mathclasses.BoundingBox) bool [source]¶
- include_point(point: pygerber.mathclasses.Vector2D) pygerber.mathclasses.BoundingBox [source]¶
- left: float¶
- lower: float¶
- padded(delta) pygerber.mathclasses.BoundingBox [source]¶
- right: float¶
- transform(vector: pygerber.mathclasses.Vector2D) pygerber.mathclasses.BoundingBox [source]¶
- upper: float¶
- class pygerber.mathclasses.Vector2D(x: 'float', y: 'float')[source]¶
Bases:
object
- dot(other: pygerber.mathclasses.Vector2D) float [source]¶
- x: float¶
- y: float¶
- pygerber.mathclasses.angle_from_zero(vector: pygerber.mathclasses.Vector2D) float [source]¶
pygerber.tokenizer module¶
Module contents¶
Contributing¶
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
Bug reports¶
When reporting a bug please include:
Your operating system name and version.
Any details about your local setup that might be helpful in troubleshooting.
Detailed steps to reproduce the bug.
Documentation improvements¶
PyGerber could always use more documentation, whether as part of the official PyGerber docs, in docstrings, or even on the web in blog posts, articles, and such.
Feature requests and feedback¶
The best way to send feedback is to file an issue at https://github.com/Argmaster/pygerber/issues.
If you are proposing a feature:
Explain in detail how it would work.
Keep the scope as narrow as possible, to make it easier to implement.
Remember that this is a volunteer-driven project, and that code contributions are welcome :)
Development¶
To set up pygerber for local development:
Fork pygerber (look for the “Fork” button).
Clone your fork locally:
git clone git@github.com:YOURGITHUBNAME/pygerber.git
Create a branch for local development:
git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
When you’re done making changes run all the checks and docs builder with tox one command:
tox
Commit your changes and push your branch to GitHub:
git add . git commit -m "Your detailed description of your changes." git push origin name-of-your-bugfix-or-feature
Submit a pull request through the GitHub website.
Pull Request Guidelines¶
If you need some code review or feedback while you’re developing the code just make the pull request.
For merging, you should:
Include passing tests (run
tox
).Update documentation when there’s new API, functionality etc.
Add a note to
CHANGELOG.rst
about the changes.Add yourself to
AUTHORS.rst
.
Tips¶
To run a subset of tests:
tox -e envname -- pytest -k test_myfeature
To run all the test environments in parallel:
tox -p auto
Changelog¶
0.0.0 (2021-09-25)¶
First release on PyPI.
Added 2D rendering
1.0.0 (2021-10-06)¶
Added 3D rendering (not full-featured)
Added CLI and API for 3D rendering
Installing bpy is required for 3D rendering
1.0.1 (2021-10-08)¶
Added promised documentation for CLI
Added promised documentation for project specfiles
Fixed RTD python version requirement building issue
Updated devlopment pipeline