Skip to content

exceptions

AsymmetricCoreMismatchError

Bases: ValueError

Raised when the core offsets of two asymmetric ports differ.

Raised with allow_cross_section_mismatch, which only requires the cores of asymmetric cross sections to match.

Source code in kfactory/exceptions.py
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
class AsymmetricCoreMismatchError(ValueError):
    """Raised when the core offsets of two asymmetric ports differ.

    Raised with `allow_cross_section_mismatch`, which only requires the cores of
    asymmetric cross sections to match.
    """

    def __init__(
        self,
        p1: ProtoPort[Any],
        p2: ProtoPort[Any],
        *args: Any,
    ) -> None:
        xs1 = p1.base.asymmetric_cross_section
        xs2 = p2.base.asymmetric_cross_section
        assert xs1 is not None
        assert xs2 is not None
        super().__init__(
            f"Core offset mismatch between the asymmetric ports {p1.name!r}"
            f" ({xs1.section_min}, {xs1.section_max}) and {p2.name!r}"
            f" ({xs2.section_min}, {xs2.section_max}).",
            *args,
        )

AsymmetricMirrorRequiredError

Bases: ValueError

Raised when connecting two asymmetric ports without mirror=True.

Two ports carrying an AsymmetricalCrossSection can only be connected via an M90 (mirror) transformation, since R180 would flip the left/right halves of the profile. Pass mirror=True to connect.

Source code in kfactory/exceptions.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
class AsymmetricMirrorRequiredError(ValueError):
    """Raised when connecting two asymmetric ports without `mirror=True`.

    Two ports carrying an `AsymmetricalCrossSection` can only be connected via
    an M90 (mirror) transformation, since R180 would flip the left/right halves
    of the profile. Pass `mirror=True` to `connect`.
    """

    def __init__(
        self,
        p1: ProtoPort[Any],
        p2: ProtoPort[Any],
        *args: Any,
    ) -> None:
        super().__init__(
            f"Cannot connect ports {p1.name!r} and {p2.name!r} carrying"
            " asymmetric cross sections without `mirror=True`. Asymmetric profiles"
            " require an M90 transformation (mirror) — R180 would flip the"
            " left/right halves. Pass `mirror=True` to `connect`.",
            *args,
        )

CellNameError

Bases: ValueError

Raised if a KCell is created and the automatic assigned name is taken.

Source code in kfactory/exceptions.py
262
263
class CellNameError(ValueError):
    """Raised if a KCell is created and the automatic assigned name is taken."""

CrossSectionMismatchError

Bases: ValueError

Raised when connecting asymmetric ports with different cross sections.

The ports have the same width and main layer, but their cross sections differ. Pass allow_cross_section_mismatch=True to connect to only require matching core offsets.

Source code in kfactory/exceptions.py
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
class CrossSectionMismatchError(ValueError):
    """Raised when connecting asymmetric ports with different cross sections.

    The ports have the same width and main layer, but their cross sections
    differ. Pass `allow_cross_section_mismatch=True` to `connect` to only
    require matching core offsets.
    """

    def __init__(
        self,
        p1: ProtoPort[Any],
        p2: ProtoPort[Any],
        *args: Any,
    ) -> None:
        super().__init__(
            f"Cross section mismatch between the ports {p1.name!r}"
            f" ({p1.base.any_cross_section.name!r}) and {p2.name!r}"
            f" ({p2.base.any_cross_section.name!r}).",
            *args,
        )

CrossSectionNamingConflictError

Bases: ValueError

Raised when a second name is registered for an existing structural signature.

Cross sections and enclosures are canonicalized by their name-independent structural signature. A given signature may have at most one named canonical entry; attempting to register a second, differently-named entry for the same signature (or to reuse a name for a different signature) raises this error.

Source code in kfactory/exceptions.py
52
53
54
55
56
57
58
59
class CrossSectionNamingConflictError(ValueError):
    """Raised when a second name is registered for an existing structural signature.

    Cross sections and enclosures are canonicalized by their name-independent
    structural signature. A given signature may have at most one *named* canonical
    entry; attempting to register a second, differently-named entry for the same
    signature (or to reuse a name for a different signature) raises this error.
    """

CrossSectionSymmetryMismatchError

Bases: ValueError

Raised when connecting ports whose cross sections differ in symmetry.

A symmetric and an asymmetric cross section with the same width and layer cannot be connected, since they are structurally different objects. Use allow_cross_section_mismatch to connect them anyway.

Source code in kfactory/exceptions.py
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
class CrossSectionSymmetryMismatchError(ValueError):
    """Raised when connecting ports whose cross sections differ in symmetry.

    A symmetric and an asymmetric cross section with the same width and layer
    cannot be connected, since they are structurally different objects. Use
    `allow_cross_section_mismatch` to connect them anyway.
    """

    def __init__(
        self,
        p1: ProtoPort[Any],
        p2: ProtoPort[Any],
        *args: Any,
    ) -> None:
        kind1 = "symmetric" if p1.base.is_symmetric() else "asymmetric"
        kind2 = "symmetric" if p2.base.is_symmetric() else "asymmetric"
        super().__init__(
            f"Cross section symmetry mismatch between ports {p1.name!r} ({kind1})"
            f" and {p2.name!r} ({kind2}). Symmetric and asymmetric cross sections"
            " cannot be connected.",
            *args,
        )

DuplicateCellNameError

Bases: RuntimeError

Raised when writing a layout with multiple cells sharing the same name.

GDS/OASIS formats require unique cell names. This error provides details about which names are duplicated and which cells are involved.

Source code in kfactory/exceptions.py
266
267
268
269
270
271
class DuplicateCellNameError(RuntimeError):
    """Raised when writing a layout with multiple cells sharing the same name.

    GDS/OASIS formats require unique cell names. This error provides details
    about which names are duplicated and which cells are involved.
    """

ExtrudeConfigConflictError

Bases: ValueError

Raised when a cross section already has a different extrude config.

Extrude configs are keyed by the cross section's structural signature, so cross sections with the same geometry share one config.

Source code in kfactory/exceptions.py
62
63
64
65
66
67
class ExtrudeConfigConflictError(ValueError):
    """Raised when a cross section already has a different extrude config.

    Extrude configs are keyed by the cross section's structural signature, so
    cross sections with the same geometry share one config.
    """

FactoriesLockedError

Bases: RuntimeError

Raised when trying to add a factory to a locked Factories collection.

Source code in kfactory/exceptions.py
44
45
class FactoriesLockedError(RuntimeError):
    """Raised when trying to add a factory to a locked Factories collection."""

InvalidLayerError

Bases: ValueError

Raised when a layer is not valid.

Source code in kfactory/exceptions.py
274
275
class InvalidLayerError(ValueError):
    """Raised when a layer is not valid."""

LockedError

Bases: AttributeError

Raised when a locked cell is being modified.

Source code in kfactory/exceptions.py
31
32
33
34
35
36
37
38
39
40
41
class LockedError(AttributeError):
    """Raised when a locked cell is being modified."""

    def __init__(self, kcell: AnyKCell | BaseKCell) -> None:
        """Throw _locked error."""
        super().__init__(
            f"{kcell.name!r} is locked and likely stored in cache. Modifications are "
            "disabled as its associated function is decorated with `cell`. To modify, "
            "update the code in the function or create a copy of "
            f"the {kcell.__class__.__name__}."
        )

__init__

__init__(kcell: AnyKCell | BaseKCell) -> None

Throw _locked error.

Source code in kfactory/exceptions.py
34
35
36
37
38
39
40
41
def __init__(self, kcell: AnyKCell | BaseKCell) -> None:
    """Throw _locked error."""
    super().__init__(
        f"{kcell.name!r} is locked and likely stored in cache. Modifications are "
        "disabled as its associated function is decorated with `cell`. To modify, "
        "update the code in the function or create a copy of "
        f"the {kcell.__class__.__name__}."
    )

MergeError

Bases: ValueError

Raised if two layout's have conflicting cell definitions.

Source code in kfactory/exceptions.py
48
49
class MergeError(ValueError):
    """Raised if two layout's have conflicting cell definitions."""

PortLayerMismatchError

Bases: ValueError

Error thrown when two ports don't have a matching layer.

Source code in kfactory/exceptions.py
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
class PortLayerMismatchError(ValueError):
    """Error thrown when two ports don't have a matching `layer`."""

    def __init__(
        self,
        kcl: KCLayout,
        inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any],
        other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any],
        p1: ProtoPort[Any],
        p2: ProtoPort[Any],
        *args: Any,
    ) -> None:
        """Throw error for the two ports `p1`/`p1`."""
        from .instance import ProtoInstance
        from .layer import LayerEnum

        l1 = (
            f"{p1.layer.name}({p1.layer.__int__()})"
            if isinstance(p1.layer, LayerEnum)
            else str(kcl.layout.get_info(p1.layer))
        )
        l2 = (
            f"{p2.layer.name}({p2.layer.__int__()})"
            if isinstance(p2.layer, LayerEnum)
            else str(kcl.layout.get_info(p2.layer))
        )
        if isinstance(other_inst, ProtoInstance):
            super().__init__(
                f'Layer mismatch between the ports {inst.name}["{p1.name}"]'
                f' and {other_inst.name}["{p2.name}"] ("{l1}"/"{l2}")',
                *args,
            )
        else:
            super().__init__(
                f'Layer mismatch between the ports {inst.name}["{p1.name}"]'
                f' and Port "{p2.name}" ("{l1}"/"{l2}")',
                *args,
            )

__init__

__init__(kcl: KCLayout, inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any], other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any], p1: ProtoPort[Any], p2: ProtoPort[Any], *args: Any) -> None

Throw error for the two ports p1/p1.

Source code in kfactory/exceptions.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
def __init__(
    self,
    kcl: KCLayout,
    inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any],
    other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any],
    p1: ProtoPort[Any],
    p2: ProtoPort[Any],
    *args: Any,
) -> None:
    """Throw error for the two ports `p1`/`p1`."""
    from .instance import ProtoInstance
    from .layer import LayerEnum

    l1 = (
        f"{p1.layer.name}({p1.layer.__int__()})"
        if isinstance(p1.layer, LayerEnum)
        else str(kcl.layout.get_info(p1.layer))
    )
    l2 = (
        f"{p2.layer.name}({p2.layer.__int__()})"
        if isinstance(p2.layer, LayerEnum)
        else str(kcl.layout.get_info(p2.layer))
    )
    if isinstance(other_inst, ProtoInstance):
        super().__init__(
            f'Layer mismatch between the ports {inst.name}["{p1.name}"]'
            f' and {other_inst.name}["{p2.name}"] ("{l1}"/"{l2}")',
            *args,
        )
    else:
        super().__init__(
            f'Layer mismatch between the ports {inst.name}["{p1.name}"]'
            f' and Port "{p2.name}" ("{l1}"/"{l2}")',
            *args,
        )

PortTypeMismatchError

Bases: ValueError

Error thrown when two ports don't have a matching port_type.

Source code in kfactory/exceptions.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
class PortTypeMismatchError(ValueError):
    """Error thrown when two ports don't have a matching `port_type`."""

    def __init__(
        self,
        inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any],
        other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any],
        p1: ProtoPort[Any],
        p2: ProtoPort[Any],
        *args: Any,
    ) -> None:
        """Throw error for the two ports `p1`/`p1`."""
        from .instance import ProtoInstance

        if isinstance(other_inst, ProtoInstance):
            super().__init__(
                f'Type mismatch between the ports {inst.name}["{p1.name}"]'
                f' and {other_inst.name}["{p2.name}"]'
                f" ({p1.port_type}/{p2.port_type})",
                *args,
            )
        else:
            super().__init__(
                f'Type mismatch between the ports {inst.name}["{p1.name}"]'
                f' and Port "{p2.name}" ({p1.port_type}/{p2.port_type})',
                *args,
            )

__init__

__init__(inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any], other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any], p1: ProtoPort[Any], p2: ProtoPort[Any], *args: Any) -> None

Throw error for the two ports p1/p1.

Source code in kfactory/exceptions.py
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
def __init__(
    self,
    inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any],
    other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any],
    p1: ProtoPort[Any],
    p2: ProtoPort[Any],
    *args: Any,
) -> None:
    """Throw error for the two ports `p1`/`p1`."""
    from .instance import ProtoInstance

    if isinstance(other_inst, ProtoInstance):
        super().__init__(
            f'Type mismatch between the ports {inst.name}["{p1.name}"]'
            f' and {other_inst.name}["{p2.name}"]'
            f" ({p1.port_type}/{p2.port_type})",
            *args,
        )
    else:
        super().__init__(
            f'Type mismatch between the ports {inst.name}["{p1.name}"]'
            f' and Port "{p2.name}" ({p1.port_type}/{p2.port_type})',
            *args,
        )

PortWidthMismatchError

Bases: ValueError

Error thrown when two ports don't have a matching width.

Source code in kfactory/exceptions.py
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class PortWidthMismatchError(ValueError):
    """Error thrown when two ports don't have a matching `width`."""

    def __init__(
        self,
        inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any],
        other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any],
        p1: ProtoPort[Any],
        p2: ProtoPort[Any],
        *args: Any,
    ) -> None:
        """Throw error for the two ports `p1`/`p1`."""
        from .instance import ProtoInstance

        if isinstance(other_inst, ProtoInstance):
            super().__init__(
                f'Width mismatch between the ports {inst.name}["{p1.name}"] '
                f'and {other_inst.name}["{p2.name}"]'
                f'("{p1.width}"/"{p2.width}")',
                *args,
            )
        else:
            super().__init__(
                f'Width mismatch between the ports {inst.name}["{p1.name}"] '
                f'and Port "{p2.name}" ("{p1.width}"/"{p2.width}")',
                *args,
            )

__init__

__init__(inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any], other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any], p1: ProtoPort[Any], p2: ProtoPort[Any], *args: Any) -> None

Throw error for the two ports p1/p1.

Source code in kfactory/exceptions.py
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def __init__(
    self,
    inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any],
    other_inst: ProtoInstance[Any] | ProtoInstanceGroup[Any, Any] | ProtoPort[Any],
    p1: ProtoPort[Any],
    p2: ProtoPort[Any],
    *args: Any,
) -> None:
    """Throw error for the two ports `p1`/`p1`."""
    from .instance import ProtoInstance

    if isinstance(other_inst, ProtoInstance):
        super().__init__(
            f'Width mismatch between the ports {inst.name}["{p1.name}"] '
            f'and {other_inst.name}["{p2.name}"]'
            f'("{p1.width}"/"{p2.width}")',
            *args,
        )
    else:
        super().__init__(
            f'Width mismatch between the ports {inst.name}["{p1.name}"] '
            f'and Port "{p2.name}" ("{p1.width}"/"{p2.width}")',
            *args,
        )