Skip to content

Commit

Permalink
Add general layout of Parser2 implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Argmaster committed Dec 28, 2023
1 parent db43696 commit d74842a
Show file tree
Hide file tree
Showing 29 changed files with 1,813 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/pygerber/common/general_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Class based on pydantic BaseModel with common set of features."""
from __future__ import annotations

from pydantic import BaseModel, ConfigDict


class GeneralModel(BaseModel):
"""Model with common set of general purpose features."""

model_config = ConfigDict(
extra="forbid",
frozen=False,
arbitrary_types_allowed=True,
)
59 changes: 59 additions & 0 deletions src/pygerber/common/immutable_map_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""Module contains model class wrapping immutable mapping."""
from __future__ import annotations

from types import MappingProxyType
from typing import TYPE_CHECKING, Generic, Mapping, Optional, TypeVar

from pydantic import Field, field_validator

from pygerber.common.frozen_general_model import FrozenGeneralModel

if TYPE_CHECKING:
from typing_extensions import Self

KeyT = TypeVar("KeyT")
ValueT = TypeVar("ValueT")


class ImmutableMapping(FrozenGeneralModel, Generic[KeyT, ValueT]):
"""Model class wrapping immutable dictionary."""

mapping: Mapping[KeyT, ValueT] = Field(
default_factory=lambda: MappingProxyType({}),
)

@field_validator("mapping")
@classmethod
def _validate_mapping(cls, v: Mapping[str, str]) -> Mapping[str, str]:
if isinstance(v, MappingProxyType):
return v
if isinstance(v, dict):
return MappingProxyType(v)
raise TypeError(type(v))

def update(self, __key: KeyT, __value: ValueT) -> Self:
"""Update underlying mapping."""
return self.model_copy(
update={
"mapping": MappingProxyType(
{
**self.mapping,
__key: __value,
},
),
},
)

def get(self, __key: KeyT, __default: Optional[ValueT] = None) -> Optional[ValueT]:
"""Get item if exists or add it to mapping with __default value and return."""
return self.mapping.get(__key, __default)

def delete(self, __key: KeyT) -> Self:
"""Remove entry from mapping."""
return self.model_copy(
update={
"mapping": MappingProxyType(
{k: v for k, v in self.mapping.items() if (k != __key)},
),
},
)
1 change: 1 addition & 0 deletions src/pygerber/gerberx3/parser2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Gerber AST parser, version 2."""
1 change: 1 addition & 0 deletions src/pygerber/gerberx3/parser2/apertures2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Parser level abstraction of aperture info for Gerber AST parser, version 2."""
25 changes: 25 additions & 0 deletions src/pygerber/gerberx3/parser2/apertures2/aperture2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Parser level abstraction of aperture info for Gerber AST parser, version 2."""
from __future__ import annotations

from pydantic import Field

from pygerber.common.frozen_general_model import FrozenGeneralModel
from pygerber.common.immutable_map_model import ImmutableMapping


class Aperture2(FrozenGeneralModel):
"""Parser level abstraction of aperture info."""

attributes: ImmutableMapping[str, str] = Field(default_factory=ImmutableMapping)

def set_attribute(self, key: str, value: str) -> Aperture2:
"""Set aperture attribute."""
return self.model_copy(
update={
"attributes": self.attributes.update(key, value),
},
)

def get_attribute(self, key: str) -> str | None:
"""Get aperture attribute."""
return self.attributes.get(key)
1 change: 1 addition & 0 deletions src/pygerber/gerberx3/parser2/apertures2/circle2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Parser level abstraction of circle aperture info for Gerber AST parser, version 2."""
1 change: 1 addition & 0 deletions src/pygerber/gerberx3/parser2/apertures2/macro2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Parser level abstraction of macro aperture info for Gerber AST parser, version 2."""
3 changes: 3 additions & 0 deletions src/pygerber/gerberx3/parser2/apertures2/obround2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Parser level abstraction of obround aperture info for Gerber AST parser,
version 2.
"""
3 changes: 3 additions & 0 deletions src/pygerber/gerberx3/parser2/apertures2/polygon2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Parser level abstraction of polygon aperture info for Gerber AST parser,
version 2.
"""
3 changes: 3 additions & 0 deletions src/pygerber/gerberx3/parser2/apertures2/rectangle2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Parser level abstraction of rectangle aperture info for Gerber AST parser,
version 2.
"""
22 changes: 22 additions & 0 deletions src/pygerber/gerberx3/parser2/command_buffer2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Module contains definition of class for buffering draw commands."""
from __future__ import annotations

from typing import Iterator, List

from pydantic import Field

from pygerber.common.general_model import GeneralModel
from pygerber.gerberx3.parser2.draws2.draw2 import Draw2


class CommandBuffer2(GeneralModel):
"""Container for buffering draw commands."""

commands: List[Draw2] = Field(default_factory=list)

def add_command(self, __command: Draw2) -> None:
"""Add draw command to command buffer."""
self.commands.append(__command)

def __iter__(self) -> Iterator[Draw2]:
yield from self.commands
Loading

0 comments on commit d74842a

Please sign in to comment.