Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PyGerber 3 Parser implementation #256

Merged
merged 93 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
6893a86
Add new ast scaffold
Argmaster Jul 14, 2024
c9ee3af
Move math node imports
Argmaster Jul 14, 2024
f0e76e5
Add pyparsing based parser layout
Argmaster Jul 16, 2024
9877898
Add assets for testing different token types
Argmaster Jul 16, 2024
fa46cd8
Remove deprecated Parser implementation
Argmaster Jul 16, 2024
869a8e7
Add more test assets for indivitual ast node types
Argmaster Jul 22, 2024
33bd9cf
Change AST root from list to File class
Argmaster Jul 22, 2024
09e283f
Add test assets for testing primitive 1 with rotation
Argmaster Jul 23, 2024
ef6aaf8
Add macro definition parsing
Argmaster Jul 23, 2024
c1c95bc
Add fields to primitive nodes
Argmaster Jul 23, 2024
168f82d
Add test assets for macros
Argmaster Jul 23, 2024
ff92e4b
Reorder grammar definitions in grammar.py
Argmaster Jul 24, 2024
aa64afd
Add aperture block and step repeat support
Argmaster Jul 24, 2024
f56e1b2
Add parsing of AD command
Argmaster Jul 24, 2024
4e13640
Add implementation of FS node parsing
AdeRegt Jul 25, 2024
98075f1
Add MO command parsing
Argmaster Jul 26, 2024
9662f02
Skip token tests in Parser2 related suites
Argmaster Jul 26, 2024
94313c3
Add TA extended command support
Argmaster Jul 26, 2024
3021de1
Add TD extended command support
Argmaster Jul 26, 2024
e336a7a
Add file attribute parsing logic
Argmaster Jul 26, 2024
a3a1151
Add TO attribute nodes implementation
Argmaster Jul 28, 2024
6ed6c38
Redesign Coordinate representation
Argmaster Jul 28, 2024
2e641aa
Add implementation of IP node parsing
AdeRegt Jul 29, 2024
8892da4
Add test for AstVisitor base class
Argmaster Jul 31, 2024
d5fca5c
Add implementation of IR node parsing
AdeRegt Aug 3, 2024
6f3b11d
Removed standalone command end token
Argmaster Aug 12, 2024
17e087d
Remove ExtendedCommandOpen/Close
Argmaster Aug 13, 2024
ffa88a5
Replace direct use of self._asterisk with calls to self._command()
Argmaster Aug 13, 2024
6bd6021
Add implementation of LN node parsing
AdeRegt Aug 13, 2024
3240b62
Add OF command
Argmaster Aug 13, 2024
543949d
Fix OF when A or B is not supplied
Argmaster Aug 13, 2024
95831fc
Add AS node parsing
Argmaster Aug 13, 2024
eb564b2
Add MI command parsing
Argmaster Aug 13, 2024
6c547d9
Add IN command parsing
Argmaster Aug 13, 2024
3a2895c
Add SF command parsing
Argmaster Aug 13, 2024
ffe4457
Add support for formatting G codes
Argmaster Aug 14, 2024
bf359f3
Add macro formatting
Argmaster Aug 14, 2024
d6f95fd
Add properties formatting
Argmaster Aug 14, 2024
8420bb4
Add aperture nodes formatting
Argmaster Aug 14, 2024
d2881b7
Add TA & TD formatting
Argmaster Aug 15, 2024
11e4255
Add TF formatting
Argmaster Aug 15, 2024
55d450b
Add TO formatting
Argmaster Aug 15, 2024
bf14e2c
Fix G04 formatting
Argmaster Aug 15, 2024
f4cba79
Add macro related formatting options
Argmaster Aug 17, 2024
471a173
Add intendtation options implementation
Argmaster Aug 17, 2024
1a1b0cf
Add typing-extensions package to dependencies
Argmaster Aug 17, 2024
5bbd452
Replace test logging handler with RotatingFileHandler
Argmaster Aug 17, 2024
125d9ca
Add load commands parsing
Argmaster Aug 17, 2024
9f28a3e
Add support for non-standalone G codes
Argmaster Aug 17, 2024
a13d27d
Merge branch 'feature/pygerber-3-parser' into feature/pygerber-3-form…
Argmaster Aug 17, 2024
762979f
Add PyGerber 3 formatter #1 (#272)
Argmaster Aug 17, 2024
8b8910a
Add formatter options for non standalone codes
Argmaster Aug 17, 2024
e88239e
Fix assert in formatter test
Argmaster Aug 17, 2024
9c9401c
Add load commands formatting
Argmaster Aug 18, 2024
5593607
Fix parsing and formatting of SR block
Argmaster Aug 18, 2024
c278f58
Add empty_line_before_polarity_switch implementation
Argmaster Aug 19, 2024
24f86a1
Add test_step_and_repeat_body_indent()
Argmaster Aug 19, 2024
8c0bef6
Add formatter presets
Argmaster Aug 19, 2024
bbe7be9
Improve Shape docstring
Argmaster Aug 19, 2024
7c31175
Extract enums used by nodes into separate module
Argmaster Aug 19, 2024
7ce8da4
Add common base class for all AD command variants
Argmaster Aug 19, 2024
99b3c2a
Add AB class for wrapping whole AB blocks
Argmaster Aug 19, 2024
4f63df0
Add AM class for aperture macro wrapping
Argmaster Aug 19, 2024
3939c6f
Fix nested AB parsing
Argmaster Aug 19, 2024
e8168fc
Add SR class for wrapping whole SR blocks
Argmaster Aug 19, 2024
7866d07
Add aperture creating commands to StateTrackingVisitor
Argmaster Aug 19, 2024
18cde8d
Add attribute tracking logic to StateTrackingVisitor
Argmaster Aug 19, 2024
c4de2f9
Add D01 handling to StateTrackingVisitor
Argmaster Aug 21, 2024
2b77f5e
Fix poe calls + add pytest_mock
Argmaster Aug 22, 2024
362048e
Add tests for aperture callbacks
Argmaster Aug 22, 2024
eb9f067
Replace aperture_identifier with aperture_id for consistency
Argmaster Aug 22, 2024
e513fe3
Improve abstraction in expression definition in grammar
Argmaster Aug 22, 2024
4401024
Improve abstraction in expression definition in grammar
Argmaster Aug 23, 2024
93c834d
Add separate draw handlers for region mode
Argmaster Aug 23, 2024
6363d27
Remove location and source parameters from hand crafted Node instances
Argmaster Aug 23, 2024
569c1f2
Remove location and source parameters from hand crafted Node instances
Argmaster Aug 23, 2024
e50d6d3
Fix expression handling & add tests for explicit_parenthesis in Forma…
Argmaster Aug 24, 2024
9cf28c3
Add support for arc interpolation swapping
Argmaster Aug 24, 2024
3a6e73e
Fix error message for D01 with no aperture selected
Argmaster Aug 24, 2024
bb5b335
Add StateTrackingVisitor support for G90 & G91
Argmaster Aug 24, 2024
2ca3572
Add StateTrackingVisitor support for load commands
Argmaster Aug 24, 2024
c209d47
Add StateTrackingVisitor support for M00 & M02
Argmaster Aug 24, 2024
738890c
Fix MD5 checking
Argmaster Aug 24, 2024
70e42f1
Rename visitor.py module to ast_visitor.py for consistency
Argmaster Aug 24, 2024
b5c153f
Add StateTrackingVisitor support for property commands
Argmaster Aug 24, 2024
6ca4a98
Fix state_tracking_visitor.py docstring
Argmaster Aug 25, 2024
16e3d86
Add ExpressionEvalVisitor for evaluating math expressions
Argmaster Aug 25, 2024
4a4a05e
Extend ExpressionEvalVisitor test suite
Argmaster Aug 25, 2024
eeaabf8
Ignore failures in legacy code
Argmaster Aug 25, 2024
30a272e
Replace list with List in type hints for backwards compatibility
Argmaster Aug 25, 2024
3fc3629
Make staticmethods in Formatter a free functions
Argmaster Aug 25, 2024
e912b5d
Add test for coordinate format selection
Argmaster Aug 25, 2024
4d16851
Replace dict with Dict in type hints for backwards compatibility
Argmaster Aug 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 18 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ numpy = [
pygls = { version = "^1.0.2", optional = true }
lsprotocol = { version = "^2023.0.0a3", optional = true }
drawsvg = { version = "^2.3.0", optional = true }
typing-extensions = "^4.12.2"

[tool.poetry.group.dev.dependencies]
mypy = "^1.6.1"
Expand All @@ -80,6 +81,7 @@ pytest-cov = ">=4.1,<6.0"
pytest-lsp = "^0.4.2"
pytest-asyncio = "^0.23.7"

pytest-mock = "^3.14.0"
[tool.poetry.group.docs]
optional = true

Expand Down Expand Up @@ -112,23 +114,22 @@ pygerber_language_server = "pygerber.gerberx3.language_server.__main__:main"
# -------------------------------------------------------------------------------------
# git hooks
install-hooks = [
{ cmd = "poetry install --sync --with=docs --extras=language-server --extras=svg --no-ansi" },
{ cmd = "poetry install --sync --with=docs --extras=all --no-ansi" },
{ cmd = "poetry run python -m scripts.install_hooks" },
{ cmd = "poetry run pre-commit install --install-hooks --overwrite" },
]
# -------------
# hook triggers
run-code-quality-checks = [
{ cmd = "poetry install --sync --with=docs --extras=language-server --extras=svg --no-ansi" },
{ cmd = "poetry install --sync --with=docs --extras=all --no-ansi" },
{ cmd = "poetry run pre-commit run --all-files -v" },
]
# -------------------------------------------------------------------------------------
run-unit-tests = [
{ cmd = "poetry install --sync --with=docs --extras=language-server --extras=svg --no-ansi" },
{ cmd = "poetry install --sync --with=docs --extras=all --no-ansi" },
{ cmd = "poetry run pytest --log-level=DEBUG -s -n logical --cov=pygerber --cov-report=term-missing:skip-covered" },
]
run-type-checks = [
{ cmd = "poetry install --sync --with=docs --extras=language-server --extras=svg --no-ansi" },
{ cmd = "poetry run mypy --config-file=pyproject.toml src/pygerber/ test/" },
]

Expand All @@ -150,6 +151,7 @@ lint.ignore = [
"ISC001", # Checks for the absence of trailing commas. Conflicts with ruff format.
"COM812", # Checks for implicitly concatenated strings on a single line. Conflicts with ruff format.
"S101", # Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
"EXE002", # Breaks on file systems which do not support executable permissions.
]
show-fixes = true
target-version = "py38"
Expand Down
92 changes: 1 addition & 91 deletions src/pygerber/console/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,11 @@

from __future__ import annotations

from pathlib import Path
from typing import Generator, Optional, TextIO
from typing import Generator

import click

import pygerber
from pygerber.console.raster_2d_style import (
STYLE_TO_COLOR_SCHEME,
get_color_scheme_from_style,
)
from pygerber.gerberx3.api import Rasterized2DLayer, Rasterized2DLayerParams
from pygerber.gerberx3.api.v2 import (
DEFAULT_ALPHA_COLOR_MAP,
DEFAULT_COLOR_MAP,
Expand All @@ -32,90 +26,6 @@ def main() -> None:
"""


@main.command("raster-2d")
@click.argument("source", type=click.File())
@click.option(
"-s",
"--style",
default="copper",
type=click.Choice(list(STYLE_TO_COLOR_SCHEME.keys()), case_sensitive=False),
help="Color style of the rendered image. When style is 'custom' then option "
"`--custom` must also be provided. Default is 'copper'.",
)
@click.option(
"-o",
"--output",
type=Path,
default="output.png",
help="Path to output file. File format will be inferred from extension, unless "
"`--format` is given. Default is 'output.png'",
)
@click.option(
"-f",
"--format",
"format_",
type=str,
default=None,
help="Output image format. Can be omitted, then format will be inferred from file"
"extension or be one of formats supported by Pillow.",
)
@click.option(
"-c",
"--custom",
type=str,
default=None,
help="String representing custom set of colors for rendering.\n"
"Custom color should be a single string consisting of 5 or 7 valid hexadecimal "
"colors separated with commas. Any color which can be parsed by RGBA type is "
"accepted.\n"
"Colors are assigned in order:"
"\n\n"
"- background_color\n\n"
"- clear_color\n\n"
"- solid_color\n\n"
"- clear_region_color\n\n"
"- solid_region_color\n\n"
"- debug_1_color (optional, by default #ABABAB)\n\n"
"- debug_2_color (optional, by default #7D7D7D)\n\n"
"\n\n"
'eg. `"000000,000000,FFFFFF,000000,FFFFFF"`',
)
@click.option(
"-d",
"--dpi",
type=int,
default=1000,
help="DPI of output image, by default 1000.",
)
def raster_2d(
source: TextIO,
style: str,
output: Path,
format_: Optional[str],
custom: Optional[str],
dpi: int,
) -> None:
"""Render rasterized 2D image from Gerber X3/X2 SOURCE file.

SOURCE - A path to the Gerber file to render.

List of file formats supported by Pillow:
https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html

\x08
RGBA type documentation:
https://argmaster.github.io/pygerber/latest/reference/pygerber/gerberx3/api/__init__.html#pygerber.common.rgba.RGBA.from_hex
""" # noqa: D301
gerber_code = source.read()
Rasterized2DLayer(
options=Rasterized2DLayerParams(
source_code=gerber_code,
colors=get_color_scheme_from_style(style, custom),
dpi=dpi,
),
).render().save(output, format=format_)


@main.command("is-language-server-available")
def _is_language_server_available() -> None:
from pygerber.gerberx3.language_server import IS_LANGUAGE_SERVER_FEATURE_AVAILABLE
Expand Down
42 changes: 0 additions & 42 deletions src/pygerber/gerberx3/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,53 +11,11 @@
MutuallyExclusiveViolationError,
RenderingResultNotReadyError,
)
from pygerber.gerberx3.api._layers import (
Layer,
LayerParams,
LayerProperties,
Rasterized2DLayer,
Rasterized2DLayerParams,
RenderingResult,
)
from pygerber.gerberx3.parser.errors import (
ApertureNotDefinedError,
ApertureNotSelectedError,
CoordinateFormatNotSetError,
ExitParsingProcessInterrupt,
IncrementalCoordinatesNotSupportedError,
InvalidCoordinateLengthError,
OnUpdateDrawingStateError,
ParserError,
ParserFatalError,
UnitNotSetError,
UnsupportedCoordinateTypeError,
ZeroOmissionNotSupportedError,
)
from pygerber.gerberx3.parser.parser import ParserOnErrorAction

__all__ = [
"RGBA",
"ColorScheme",
"Layer",
"LayerParams",
"Rasterized2DLayer",
"Rasterized2DLayerParams",
"LayerProperties",
"RenderingResult",
"ParserOnErrorAction",
"GerberX3APIError",
"RenderingResultNotReadyError",
"MutuallyExclusiveViolationError",
"ParserError",
"ZeroOmissionNotSupportedError",
"IncrementalCoordinatesNotSupportedError",
"UnsupportedCoordinateTypeError",
"InvalidCoordinateLengthError",
"ParserFatalError",
"OnUpdateDrawingStateError",
"UnitNotSetError",
"ApertureNotDefinedError",
"CoordinateFormatNotSetError",
"ApertureNotSelectedError",
"ExitParsingProcessInterrupt",
]
Loading
Loading