kicad-python 0.1.0a0__tar.gz → 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. {kicad_python-0.1.0a0 → kicad_python-0.1.1}/PKG-INFO +43 -10
  2. kicad_python-0.1.1/README.md +65 -0
  3. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/board.py +205 -25
  4. kicad_python-0.1.1/build/lib/kipy/board_types.py +1800 -0
  5. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/client.py +23 -24
  6. kicad_python-0.1.1/build/lib/kipy/common_types.py +842 -0
  7. kicad_python-0.1.1/build/lib/kipy/errors.py +37 -0
  8. kicad_python-0.1.1/build/lib/kipy/geometry.py +604 -0
  9. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/kicad.py +94 -14
  10. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/project.py +31 -10
  11. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/board/board_commands_pb2.py +23 -7
  12. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/board/board_commands_pb2.pyi +159 -9
  13. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/board/board_pb2.py +4 -2
  14. kicad_python-0.1.1/build/lib/kipy/proto/board/board_types_pb2.py +150 -0
  15. kicad_python-0.1.1/build/lib/kipy/proto/board/board_types_pb2.pyi +2101 -0
  16. kicad_python-0.1.1/build/lib/kipy/proto/common/commands/base_commands_pb2.py +31 -0
  17. kicad_python-0.1.1/build/lib/kipy/proto/common/commands/base_commands_pb2.pyi +176 -0
  18. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/commands/editor_commands_pb2.py +37 -21
  19. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/commands/editor_commands_pb2.pyi +148 -19
  20. kicad_python-0.1.1/build/lib/kipy/proto/common/commands/project_commands_pb2.py +24 -0
  21. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/commands/project_commands_pb2.pyi +41 -1
  22. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/envelope_pb2.py +4 -2
  23. kicad_python-0.1.1/build/lib/kipy/proto/common/types/base_types_pb2.py +100 -0
  24. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/types/base_types_pb2.pyi +320 -24
  25. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/types/enums_pb2.py +12 -10
  26. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/types/enums_pb2.pyi +2 -10
  27. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/types/project_settings_pb2.py +4 -2
  28. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/schematic/schematic_commands_pb2.py +4 -2
  29. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/schematic/schematic_types_pb2.py +4 -2
  30. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/util/proto.py +16 -9
  31. kicad_python-0.1.1/build.py +50 -0
  32. kicad_python-0.1.1/kipy/__init__.py +20 -0
  33. kicad_python-0.1.1/kipy/board.py +467 -0
  34. kicad_python-0.1.1/kipy/board_types.py +1800 -0
  35. kicad_python-0.1.1/kipy/client.py +88 -0
  36. kicad_python-0.1.1/kipy/common_types.py +842 -0
  37. kicad_python-0.1.1/kipy/errors.py +37 -0
  38. kicad_python-0.1.1/kipy/geometry.py +604 -0
  39. kicad_python-0.1.1/kipy/kicad.py +176 -0
  40. kicad_python-0.1.1/kipy/project.py +71 -0
  41. kicad_python-0.1.0a0/build.py → kicad_python-0.1.1/kipy/project_types.py +8 -7
  42. kicad_python-0.1.1/kipy/proto/__init__.py +20 -0
  43. kicad_python-0.1.1/kipy/proto/board/__init__.py +20 -0
  44. kicad_python-0.1.1/kipy/proto/board/board_commands_pb2.py +56 -0
  45. kicad_python-0.1.1/kipy/proto/board/board_commands_pb2.pyi +491 -0
  46. kicad_python-0.1.1/kipy/proto/board/board_pb2.py +44 -0
  47. kicad_python-0.1.1/kipy/proto/board/board_pb2.pyi +294 -0
  48. kicad_python-0.1.1/kipy/proto/board/board_types_pb2.py +150 -0
  49. kicad_python-0.1.1/kipy/proto/board/board_types_pb2.pyi +2101 -0
  50. kicad_python-0.1.1/kipy/proto/common/__init__.py +23 -0
  51. kicad_python-0.1.1/kipy/proto/common/commands/__init__.py +21 -0
  52. kicad_python-0.1.1/kipy/proto/common/commands/base_commands_pb2.py +31 -0
  53. kicad_python-0.1.1/kipy/proto/common/commands/base_commands_pb2.pyi +176 -0
  54. kicad_python-0.1.1/kipy/proto/common/commands/editor_commands_pb2.py +91 -0
  55. kicad_python-0.1.1/kipy/proto/common/commands/editor_commands_pb2.pyi +814 -0
  56. kicad_python-0.1.1/kipy/proto/common/commands/project_commands_pb2.py +24 -0
  57. kicad_python-0.1.1/kipy/proto/common/commands/project_commands_pb2.pyi +97 -0
  58. kicad_python-0.1.1/kipy/proto/common/envelope_pb2.py +27 -0
  59. kicad_python-0.1.1/kipy/proto/common/envelope_pb2.pyi +188 -0
  60. kicad_python-0.1.1/kipy/proto/common/types/__init__.py +22 -0
  61. kicad_python-0.1.1/kipy/proto/common/types/base_types_pb2.py +100 -0
  62. kicad_python-0.1.1/kipy/proto/common/types/base_types_pb2.pyi +1058 -0
  63. kicad_python-0.1.1/kipy/proto/common/types/enums_pb2.py +22 -0
  64. kicad_python-0.1.1/kipy/proto/common/types/enums_pb2.pyi +189 -0
  65. kicad_python-0.1.1/kipy/proto/common/types/project_settings_pb2.py +16 -0
  66. kicad_python-0.1.1/kipy/proto/common/types/project_settings_pb2.pyi +30 -0
  67. kicad_python-0.1.1/kipy/proto/schematic/schematic_commands_pb2.py +14 -0
  68. kicad_python-0.1.1/kipy/proto/schematic/schematic_commands_pb2.pyi +23 -0
  69. kicad_python-0.1.1/kipy/proto/schematic/schematic_types_pb2.py +29 -0
  70. kicad_python-0.1.1/kipy/proto/schematic/schematic_types_pb2.pyi +214 -0
  71. kicad_python-0.1.1/kipy/util/__init__.py +21 -0
  72. kicad_python-0.1.1/kipy/util/proto.py +61 -0
  73. kicad_python-0.1.1/kipy/util/units.py +31 -0
  74. kicad_python-0.1.1/kipy/wrapper.py +35 -0
  75. {kicad_python-0.1.0a0 → kicad_python-0.1.1}/pyproject.toml +18 -16
  76. kicad_python-0.1.1/setup.py +41 -0
  77. kicad_python-0.1.0a0/README.md +0 -33
  78. kicad_python-0.1.0a0/kipy/board_types.py +0 -419
  79. kicad_python-0.1.0a0/kipy/common_types.py +0 -45
  80. kicad_python-0.1.0a0/kipy/geometry.py +0 -100
  81. kicad_python-0.1.0a0/kipy/proto/board/board_types_pb2.py +0 -90
  82. kicad_python-0.1.0a0/kipy/proto/board/board_types_pb2.pyi +0 -1232
  83. kicad_python-0.1.0a0/kipy/proto/common/commands/base_commands_pb2.py +0 -19
  84. kicad_python-0.1.0a0/kipy/proto/common/commands/base_commands_pb2.pyi +0 -67
  85. kicad_python-0.1.0a0/kipy/proto/common/commands/project_commands_pb2.py +0 -17
  86. kicad_python-0.1.0a0/kipy/proto/common/types/base_types_pb2.py +0 -76
  87. {kicad_python-0.1.0a0 → kicad_python-0.1.1}/LICENSE +0 -0
  88. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/__init__.py +0 -0
  89. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/project_types.py +0 -0
  90. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/__init__.py +0 -0
  91. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/board/__init__.py +0 -0
  92. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/board/board_pb2.pyi +0 -0
  93. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/__init__.py +0 -0
  94. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/commands/__init__.py +0 -0
  95. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/envelope_pb2.pyi +0 -0
  96. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/types/__init__.py +0 -0
  97. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/common/types/project_settings_pb2.pyi +0 -0
  98. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/schematic/schematic_commands_pb2.pyi +0 -0
  99. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/proto/schematic/schematic_types_pb2.pyi +0 -0
  100. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/util/__init__.py +0 -0
  101. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/util/units.py +0 -0
  102. {kicad_python-0.1.0a0 → kicad_python-0.1.1/build/lib}/kipy/wrapper.py +0 -0
@@ -1,24 +1,25 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kicad-python
3
- Version: 0.1.0a0
3
+ Version: 0.1.1
4
4
  Summary: KiCad API Python Bindings
5
5
  Home-page: https://kicad.org/
6
6
  License: GPL-3
7
7
  Author: The KiCad Development Team
8
- Requires-Python: >=3.8,<4.0
9
- Classifier: Development Status :: 2 - Pre-Alpha
8
+ Requires-Python: >=3.9,<3.13
9
+ Classifier: Development Status :: 3 - Alpha
10
10
  Classifier: Intended Audience :: Developers
11
11
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
12
12
  Classifier: License :: Other/Proprietary License
13
13
  Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.8
15
14
  Classifier: Programming Language :: Python :: 3.9
16
15
  Classifier: Programming Language :: Python :: 3.10
17
16
  Classifier: Programming Language :: Python :: 3.11
18
17
  Classifier: Programming Language :: Python :: 3.12
19
18
  Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
20
- Requires-Dist: protobuf (>=4.21.12,<5.0.0)
21
- Requires-Dist: pynng (>=0.7.2,<0.8.0)
19
+ Requires-Dist: furo (>=2024.8.6,<2025.0.0)
20
+ Requires-Dist: protobuf (>=5.29,<6.0)
21
+ Requires-Dist: pynng (>=0.8.0,<0.9.0)
22
+ Requires-Dist: sphinx (==7.4)
22
23
  Project-URL: Repository, https://gitlab.com/kicad/code/kicad-python
23
24
  Description-Content-Type: text/markdown
24
25
 
@@ -27,10 +28,24 @@ Description-Content-Type: text/markdown
27
28
  `kicad-python` is the official Python bindings for the [KiCad](https://kicad.org) IPC API. This
28
29
  library makes it possible to develop scripts and tools that interact with a running KiCad session.
29
30
 
31
+ The KiCad IPC API can be considered in "public beta" state with the release of KiCad 9 (currently
32
+ planned for on or around February 1, 2025). The existing SWIG-based Python bindings for KiCad's
33
+ PCB editor still exist in KiCad 9, but are in maintenance mode and will not be expanded.
34
+
30
35
  For more information about the IPC API, please see the [KiCad developer documentation](https://dev-docs.kicad.org).
31
36
 
32
- Note: Version 0.0.2 and prior of this package are an obsolete earlier effort and are unrelated to
33
- this codebase.
37
+ > Note: Version 0.0.2 and prior of this package are an obsolete earlier effort and are unrelated to
38
+ > this codebase.
39
+
40
+ ## Requirements
41
+
42
+ Using the IPC API requires a suitable version of KiCad (9.0 or higher) and requires that KiCad be
43
+ running with the API server enabled in Preferences > Plugins. This package also depends on the
44
+ `protobuf` and `pynng` packages for communication with KiCad.
45
+
46
+ > Note: Unlike the SWIG-based Python bindings, the IPC API requires communication with a running
47
+ > instance of KiCad. It is not possible to use `kicad-python` to manipulate KiCad design files
48
+ > without KiCad running.
34
49
 
35
50
  ## Contributing
36
51
 
@@ -49,10 +64,28 @@ See COMPILING.md
49
64
 
50
65
  ## API Documentation
51
66
 
52
- There is no documentation yet, sorry. We expect things to be stable enough to begin documentation
53
- for general use in late 2024.
67
+ There is no documentation separate from the code comments and examples yet, sorry! This will be
68
+ more of a priority once the KiCad 9 release is stable.
54
69
 
55
70
  ## Examples
56
71
 
57
72
  Check out the repository for some example scripts that may serve as a starting point.
58
73
 
74
+ ## Release History
75
+
76
+ ### 0.1.1 (December 24, 2024)
77
+
78
+ - Bump dependency versions to fix compilation with newer protoc
79
+
80
+ ### 0.1.0 (December 21, 2024)
81
+
82
+ *Corresponding KiCad version: 9.0.0-rc1*
83
+
84
+ First formal release of the new IPC-API version of this package. Contains support for most of the
85
+ KiCad API functionality that is currently exposed, which is focused around the PCB editor to enable
86
+ a transition path from existing SWIG-based plugins.
87
+
88
+ Caveats / Known Issues:
89
+
90
+ - Compatibility limited to Python 3.9 ~ 3.12 due to `pynng` not yet being updated for 3.13
91
+
@@ -0,0 +1,65 @@
1
+ # KiCad API Python Bindings
2
+
3
+ `kicad-python` is the official Python bindings for the [KiCad](https://kicad.org) IPC API. This
4
+ library makes it possible to develop scripts and tools that interact with a running KiCad session.
5
+
6
+ The KiCad IPC API can be considered in "public beta" state with the release of KiCad 9 (currently
7
+ planned for on or around February 1, 2025). The existing SWIG-based Python bindings for KiCad's
8
+ PCB editor still exist in KiCad 9, but are in maintenance mode and will not be expanded.
9
+
10
+ For more information about the IPC API, please see the [KiCad developer documentation](https://dev-docs.kicad.org).
11
+
12
+ > Note: Version 0.0.2 and prior of this package are an obsolete earlier effort and are unrelated to
13
+ > this codebase.
14
+
15
+ ## Requirements
16
+
17
+ Using the IPC API requires a suitable version of KiCad (9.0 or higher) and requires that KiCad be
18
+ running with the API server enabled in Preferences > Plugins. This package also depends on the
19
+ `protobuf` and `pynng` packages for communication with KiCad.
20
+
21
+ > Note: Unlike the SWIG-based Python bindings, the IPC API requires communication with a running
22
+ > instance of KiCad. It is not possible to use `kicad-python` to manipulate KiCad design files
23
+ > without KiCad running.
24
+
25
+ ## Contributing
26
+
27
+ At the moment, these bindings are being developed in parallel with the IPC API itself, and
28
+ development is being coordinated by the KiCad team (main point of contact: Jon Evans / @craftyjon).
29
+ Expect rapid change and instability during this development period, and please do not send merge
30
+ requests without discussing your idea for changes with the team ahead of time.
31
+
32
+ Once the initial stable API is released (planned for KiCad 9.0 in February 2025), this Python
33
+ library will also have its first stable release and be considered fully supported. Until that
34
+ time, please consider this a development preview.
35
+
36
+ ## Building
37
+
38
+ See COMPILING.md
39
+
40
+ ## API Documentation
41
+
42
+ There is no documentation separate from the code comments and examples yet, sorry! This will be
43
+ more of a priority once the KiCad 9 release is stable.
44
+
45
+ ## Examples
46
+
47
+ Check out the repository for some example scripts that may serve as a starting point.
48
+
49
+ ## Release History
50
+
51
+ ### 0.1.1 (December 24, 2024)
52
+
53
+ - Bump dependency versions to fix compilation with newer protoc
54
+
55
+ ### 0.1.0 (December 21, 2024)
56
+
57
+ *Corresponding KiCad version: 9.0.0-rc1*
58
+
59
+ First formal release of the new IPC-API version of this package. Contains support for most of the
60
+ KiCad API functionality that is currently exposed, which is focused around the PCB editor to enable
61
+ a transition path from existing SWIG-based plugins.
62
+
63
+ Caveats / Known Issues:
64
+
65
+ - Compatibility limited to Python 3.9 ~ 3.12 due to `pynng` not yet being updated for 3.13
@@ -16,29 +16,38 @@
16
16
  # with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  from time import sleep
19
- from typing import List, Dict, Union, Iterable, Optional, Sequence, cast
19
+ from typing import List, Dict, Union, Iterable, Optional, Sequence, cast, overload
20
20
  from google.protobuf.empty_pb2 import Empty
21
21
 
22
22
  from kipy.board_types import (
23
- Arc,
23
+ ArcTrack,
24
24
  BoardItem,
25
+ BoardText,
26
+ BoardTextBox,
27
+ Dimension,
25
28
  FootprintInstance,
26
29
  Net,
27
30
  Pad,
28
- Text,
31
+ BoardShape,
29
32
  Track,
30
33
  Via,
34
+ Zone,
35
+ to_concrete_board_shape,
36
+ to_concrete_dimension,
31
37
  unwrap
32
38
  )
33
39
  from kipy.client import ApiError, KiCadClient
34
- from kipy.common_types import Commit, TextAttributes
35
- from kipy.geometry import Box2, Vector2
40
+ from kipy.common_types import Commit, TitleBlockInfo, TextAttributes
41
+ from kipy.geometry import Box2, PolygonWithHoles, Vector2
42
+ from kipy.project import Project
43
+ from kipy.proto.board import board_types_pb2
44
+ from kipy.proto.common.commands import editor_commands_pb2, project_commands_pb2
36
45
  from kipy.proto.common.envelope_pb2 import ApiStatusCode
37
46
  from kipy.util import pack_any
38
47
  from kipy.wrapper import Item, Wrapper
39
48
 
40
49
  from kipy.proto.common.commands import Ping
41
- from kipy.proto.common.types import DocumentSpecifier, KIID, KiCadObjectType
50
+ from kipy.proto.common.types import DocumentSpecifier, KIID, KiCadObjectType, base_types_pb2
42
51
  from kipy.proto.common.commands.editor_commands_pb2 import (
43
52
  BeginCommit, BeginCommitResponse, CommitAction,
44
53
  EndCommit, EndCommitResponse,
@@ -46,7 +55,6 @@ from kipy.proto.common.commands.editor_commands_pb2 import (
46
55
  UpdateItems, UpdateItemsResponse,
47
56
  GetItems, GetItemsResponse,
48
57
  DeleteItems, DeleteItemsResponse,
49
- BoundingBoxResponse,
50
58
  HitTest, HitTestResponse, HitTestResult
51
59
  )
52
60
  from kipy.proto.board import board_pb2
@@ -54,7 +62,7 @@ from kipy.proto.board import board_commands_pb2
54
62
 
55
63
  # Re-exported protobuf enum types
56
64
  from kipy.proto.board.board_pb2 import ( # noqa
57
- BoardLayerClass
65
+ BoardLayerClass
58
66
  )
59
67
  from kipy.proto.board.board_types_pb2 import ( #noqa
60
68
  BoardLayer
@@ -64,28 +72,35 @@ class BoardLayerGraphicsDefaults(Wrapper):
64
72
  """Wraps a kiapi.board.types.BoardLayerGraphicsDefaults object"""
65
73
  def __init__(self, proto: Optional[board_pb2.BoardLayerGraphicsDefaults] = None):
66
74
  self._proto = board_pb2.BoardLayerGraphicsDefaults()
67
-
75
+
68
76
  if proto is not None:
69
77
  self._proto.CopyFrom(proto)
70
78
 
71
79
  @property
72
80
  def text(self) -> TextAttributes:
73
81
  return TextAttributes(self._proto.text)
74
-
82
+
75
83
  class Board:
76
84
  def __init__(self, kicad: KiCadClient, document: DocumentSpecifier):
77
85
  self._kicad = kicad
78
86
  self._doc = document
79
87
 
88
+ @property
89
+ def client(self) -> KiCadClient:
90
+ return self._kicad
91
+
80
92
  @property
81
93
  def document(self) -> DocumentSpecifier:
82
94
  return self._doc
83
95
 
96
+ def project(self) -> Project:
97
+ return Project(self._kicad, self._doc)
98
+
84
99
  @property
85
100
  def name(self) -> str:
86
101
  """Returns the file name of the board"""
87
102
  return self._doc.board_filename
88
-
103
+
89
104
  def save(self):
90
105
  pass
91
106
 
@@ -108,7 +123,7 @@ class Board:
108
123
  command.id.CopyFrom(commit.id)
109
124
  command.action = CommitAction.CMA_DROP
110
125
  self._kicad.send(command, EndCommitResponse)
111
-
126
+
112
127
  def create_items(self, items: Union[Wrapper, Iterable[Wrapper]]) -> List[Wrapper]:
113
128
  command = CreateItems()
114
129
  command.header.document.CopyFrom(self._doc)
@@ -137,9 +152,9 @@ class Board:
137
152
 
138
153
  return [unwrap(item) for item in self._kicad.send(command, GetItemsResponse).items]
139
154
 
140
- def get_tracks(self) -> Sequence[Union[Track, Arc]]:
155
+ def get_tracks(self) -> Sequence[Union[Track, ArcTrack]]:
141
156
  return [
142
- cast(Track, item) if isinstance(item, Track) else cast(Arc, item)
157
+ cast(Track, item) if isinstance(item, Track) else cast(ArcTrack, item)
143
158
  for item in self.get_items(
144
159
  types=[KiCadObjectType.KOT_PCB_TRACE, KiCadObjectType.KOT_PCB_ARC]
145
160
  )
@@ -147,16 +162,58 @@ class Board:
147
162
 
148
163
  def get_vias(self) -> Sequence[Via]:
149
164
  return [cast(Via, item) for item in self.get_items(types=[KiCadObjectType.KOT_PCB_VIA])]
150
-
165
+
151
166
  def get_pads(self) -> Sequence[Pad]:
152
167
  return [cast(Pad, item) for item in self.get_items(types=[KiCadObjectType.KOT_PCB_PAD])]
153
-
168
+
154
169
  def get_footprints(self) -> Sequence[FootprintInstance]:
155
170
  return [
156
171
  cast(FootprintInstance, item)
157
172
  for item in self.get_items(types=[KiCadObjectType.KOT_PCB_FOOTPRINT])
158
173
  ]
159
-
174
+
175
+ def get_shapes(self) -> Sequence[BoardShape]:
176
+ """Retrieves all graphic shapes (not including tracks or text) on the board"""
177
+ return [
178
+ item
179
+ for item in (
180
+ to_concrete_board_shape(cast(BoardShape, item))
181
+ for item in self.get_items(types=[KiCadObjectType.KOT_PCB_SHAPE])
182
+ )
183
+ if item is not None
184
+ ]
185
+
186
+ def get_dimensions(self) -> Sequence[Dimension]:
187
+ """Retrieves all dimension objects on the board"""
188
+ return [
189
+ item
190
+ for item in (
191
+ to_concrete_dimension(cast(Dimension, item))
192
+ for item in self.get_items(types=[KiCadObjectType.KOT_PCB_DIMENSION])
193
+ )
194
+ if item is not None
195
+ ]
196
+
197
+ def get_text(self) -> Sequence[Union[BoardText, BoardTextBox]]:
198
+ return [
199
+ cast(BoardText, item) if isinstance(item, BoardText) else cast(BoardTextBox, item)
200
+ for item in self.get_items(
201
+ types=[KiCadObjectType.KOT_PCB_TEXT, KiCadObjectType.KOT_PCB_TEXTBOX]
202
+ )
203
+ ]
204
+
205
+ def get_zones(self) -> Sequence[Zone]:
206
+ return [cast(Zone, item) for item in self.get_items(types=[KiCadObjectType.KOT_PCB_ZONE])]
207
+
208
+ def get_as_string(self) -> str:
209
+ command = editor_commands_pb2.SaveDocumentToString()
210
+ command.document.CopyFrom(self._doc)
211
+ return self._kicad.send(command, editor_commands_pb2.SavedDocumentResponse).contents
212
+
213
+ def get_selection_as_string(self) -> str:
214
+ command = editor_commands_pb2.SaveSelectionToString()
215
+ return self._kicad.send(command, editor_commands_pb2.SavedSelectionResponse).contents
216
+
160
217
  def update_items(self, items: Union[BoardItem, Sequence[BoardItem]]):
161
218
  command = UpdateItems()
162
219
  command.header.document.CopyFrom(self._doc)
@@ -220,7 +277,7 @@ class Board:
220
277
  command = board_commands_pb2.GetBoardStackup()
221
278
  command.board.CopyFrom(self._doc)
222
279
  return self._kicad.send(command, board_commands_pb2.BoardStackupResponse).stackup
223
-
280
+
224
281
  def get_graphics_defaults(self) -> Dict[int, BoardLayerGraphicsDefaults]:
225
282
  cmd = board_commands_pb2.GetGraphicsDefaults()
226
283
  cmd.board.CopyFrom(self._doc)
@@ -233,13 +290,112 @@ class Board:
233
290
  board_pb2.BoardLayerClass.BLC_FABRICATION: BoardLayerGraphicsDefaults(reply.defaults.layers[4]),
234
291
  board_pb2.BoardLayerClass.BLC_OTHER: BoardLayerGraphicsDefaults(reply.defaults.layers[5])
235
292
  }
236
-
237
- def get_text_extents(self, text: Text) -> Box2:
238
- cmd = board_commands_pb2.GetTextExtents()
239
- cmd.text.CopyFrom(text.proto)
240
- reply = self._kicad.send(cmd, BoundingBoxResponse)
241
- return Box2(reply.position, reply.size)
242
-
293
+
294
+ def get_title_block_info(self) -> TitleBlockInfo:
295
+ cmd = editor_commands_pb2.GetTitleBlockInfo()
296
+ cmd.document.CopyFrom(self._doc)
297
+ return TitleBlockInfo(self._kicad.send(cmd, base_types_pb2.TitleBlockInfo))
298
+
299
+ @overload
300
+ def expand_text_variables(self, text: str) -> str:
301
+ ...
302
+
303
+ @overload
304
+ def expand_text_variables(self, text: List[str]) -> List[str]:
305
+ ...
306
+
307
+ def expand_text_variables(self, text: Union[str, List[str]]) -> Union[str, List[str]]:
308
+ command = project_commands_pb2.ExpandTextVariables()
309
+ command.document.CopyFrom(self._doc)
310
+ if isinstance(text, list):
311
+ command.text.extend(text)
312
+ else:
313
+ command.text.append(text)
314
+ response = self._kicad.send(command, project_commands_pb2.ExpandTextVariablesResponse)
315
+ return (
316
+ [text for text in response.text]
317
+ if isinstance(text, list)
318
+ else response.text[0]
319
+ if len(response.text) > 0
320
+ else ""
321
+ )
322
+
323
+ @overload
324
+ def get_item_bounding_box(
325
+ self, items: BoardItem, include_text: bool = False
326
+ ) -> Optional[Box2]: ...
327
+
328
+ @overload
329
+ def get_item_bounding_box(
330
+ self, items: Sequence[BoardItem], include_text: bool = False
331
+ ) -> List[Optional[Box2]]: ...
332
+
333
+ def get_item_bounding_box(
334
+ self,
335
+ items: Union[BoardItem, Sequence[BoardItem]],
336
+ include_text: bool = False
337
+ ) -> Union[Optional[Box2], List[Optional[Box2]]]:
338
+ """Gets the KiCad-calculated bounding box for an item or items, returning None if the item
339
+ does not exist or has no bounding box"""
340
+ cmd = editor_commands_pb2.GetBoundingBox()
341
+ cmd.header.document.CopyFrom(self._doc)
342
+ cmd.mode = (
343
+ editor_commands_pb2.BoundingBoxMode.BBM_ITEM_AND_CHILD_TEXT
344
+ if include_text
345
+ else editor_commands_pb2.BoundingBoxMode.BBM_ITEM_ONLY
346
+ )
347
+
348
+ if isinstance(items, BoardItem):
349
+ cmd.items.append(items.id)
350
+ else:
351
+ cmd.items.extend([i.id for i in items])
352
+
353
+ response = self._kicad.send(cmd, editor_commands_pb2.GetBoundingBoxResponse)
354
+
355
+ if isinstance(items, BoardItem):
356
+ return Box2.from_proto(response.boxes[0]) if len(response.boxes) == 1 else None
357
+
358
+ item_to_bbox = {item: bbox for item, bbox in zip(response.items, response.boxes)}
359
+ return [
360
+ Box2.from_proto(box)
361
+ for box in (item_to_bbox.get(item.id, None) for item in items)
362
+ if box is not None
363
+ ]
364
+
365
+ @overload
366
+ def get_pad_shapes_as_polygons(
367
+ self, pads: Pad, layer: BoardLayer.ValueType = BoardLayer.BL_F_Cu
368
+ ) -> Optional[PolygonWithHoles]: ...
369
+
370
+ @overload
371
+ def get_pad_shapes_as_polygons(
372
+ self, pads: Sequence[Pad], layer: BoardLayer.ValueType = BoardLayer.BL_F_Cu
373
+ ) -> List[Optional[PolygonWithHoles]]: ...
374
+
375
+ def get_pad_shapes_as_polygons(
376
+ self, pads: Union[Pad, Sequence[Pad]], layer: BoardLayer.ValueType = BoardLayer.BL_F_Cu
377
+ ) -> Union[Optional[PolygonWithHoles], List[Optional[PolygonWithHoles]]]:
378
+ cmd = board_commands_pb2.GetPadShapeAsPolygon()
379
+ cmd.board.CopyFrom(self._doc)
380
+ cmd.layer = layer
381
+
382
+ if isinstance(pads, Pad):
383
+ cmd.pads.append(pads.id)
384
+ else:
385
+ cmd.pads.extend([pad.id for pad in pads])
386
+
387
+ response = self._kicad.send(cmd, board_commands_pb2.PadShapeAsPolygonResponse)
388
+
389
+ if isinstance(pads, Pad):
390
+ return PolygonWithHoles(response.polygons[0]) if len(response.polygons) == 1 else None
391
+
392
+ pad_to_polygon = {pad: polygon for pad, polygon in zip(response.pads, response.polygons)}
393
+ return [
394
+ PolygonWithHoles(p)
395
+ for p in (pad_to_polygon.get(pad.id, None) for pad in pads)
396
+ if p is not None
397
+ ]
398
+
243
399
  def interactive_move(self, items: Union[KIID, Iterable[KIID]]):
244
400
  cmd = board_commands_pb2.InteractiveMoveItems()
245
401
  cmd.board.CopyFrom(self._doc)
@@ -285,3 +441,27 @@ class Board:
285
441
  cmd.position.CopyFrom(position.proto)
286
442
  cmd.tolerance = tolerance
287
443
  return self._kicad.send(cmd, HitTestResponse).result == HitTestResult.HTR_HIT
444
+
445
+ def get_visible_layers(self) -> Sequence[board_types_pb2.BoardLayer.ValueType]:
446
+ cmd = board_commands_pb2.GetVisibleLayers()
447
+ cmd.board.CopyFrom(self._doc)
448
+ response = self._kicad.send(cmd, board_commands_pb2.BoardLayers)
449
+ return response.layers
450
+
451
+ def set_visible_layers(self, layers: Sequence[board_types_pb2.BoardLayer.ValueType]):
452
+ cmd = board_commands_pb2.SetVisibleLayers()
453
+ cmd.board.CopyFrom(self._doc)
454
+ cmd.layers.extend(layers)
455
+ self._kicad.send(cmd, Empty)
456
+
457
+ def get_active_layer(self) -> board_types_pb2.BoardLayer.ValueType:
458
+ cmd = board_commands_pb2.GetActiveLayer()
459
+ cmd.board.CopyFrom(self._doc)
460
+ response = self._kicad.send(cmd, board_commands_pb2.BoardLayerResponse)
461
+ return response.layer
462
+
463
+ def set_active_layer(self, layer: board_types_pb2.BoardLayer.ValueType):
464
+ cmd = board_commands_pb2.SetActiveLayer()
465
+ cmd.board.CopyFrom(self._doc)
466
+ cmd.layer = layer
467
+ self._kicad.send(cmd, Empty)