Known changes and backwards incompatibilities in 2024.09

Removal of StackARef

This class has been removed in this release as part of a code base cleanup.

RestrictType does not allow None

i3.RestrictType and all restrictions derived from it do not allow None as a valid value anymore.

Hence this does not work anymore:

import ipkiss3.all as i3

class ExampleRestrictType(i3.StrongPropertyInitializer):
    restricted = i3.DefinitionProperty(restriction=i3.RestrictType(int))

example = ExampleRestrictType(restricted=None)

In order to allow None, explictly pass allow_none=True to the DefinitionProperty instead.

import ipkiss3.all as i3

class ExampleRestrictType(i3.StrongPropertyInitializer):
    restricted = i3.DefinitionProperty(restriction=i3.RestrictType(int), allow_none=True)

example = ExampleRestrictType(restricted=None)

In more complex cases when you are building your own restrictions, you may need to add i3.RestrictNone(), e.g. i3.RestrictNone() | i3.RestrictType(allowed_types).

When you inherit from a class and lock a property that had allow_none=True then you’ll need to explicitly set it again. For example:

import ipkiss3.all as i3

class Super(i3.StrongPropertyInitializer):
    number_or_none = i3.NumberProperty(allow_none=True)

    def _default_number_or_none(self):
        return None

class Sub(Super)
    number_or_none = i3.NumberProperty(locked=True, allow_none=True)

Deprecated ipkiss core types

Duplication and aliased classes with ipcore.types, ipcore.properties.container_properties, and ipkiss3.core was cleaned up. As a result, several already deprecated classes were removed, some classes were combined into one, and modules have been re-organized.

Removed class

Equivalent class

In module ipcore.types.typed_dict:

  • TypedDict

  • TypedAttrDict

Use instead:

  • OrderedTypedDict

  • OrderedTypedAttrDict

In module ipcore.properties.container_properties:

  • TypedDictPreprocessor

  • TypedDictProperty

Use instead:

  • OrderedTypedDictPreprocessor

  • OrderedTypedDictProperty

Module ipkiss3.core.types.typed_list was removed:

  • TypedList

  • RestrictedList

  • RestrictedListMeta

Use classes from ipkiss3.all instead:

  • TypedList

  • RestrictedList

  • RestrictedListMeta

Module ipkiss3.core.types.typed_dict was removed:

  • TypedDict

  • OrderedTypedDict

Use classes from ipkiss3.all instead:

  • OrderedTypedDict

  • OrderedTypedDict

ipkiss3.core.types.named_typed_dict.NamedTypedDict

ipcore.types.named_typed_dict.OrderedNamedTypedDict

In module ipkiss3.core.properties.containers.named_typed_dict:

  • NamedTypedAttrDict

  • NamedTypedDictProperty

  • NamedTypedAttrDictProperty

  • RestrictNamedTypedDict

Use instead:

  • OrderedNamedTypedAttrDict

  • OrderedNamedTypedDictProperty

  • OrderedNamedTypedAttrDictProperty

  • RestrictOrderedNamedTypedDict

In module ipkiss3.core.properties.containers.atom_dict:

  • EventDict

  • ObserverDict

Use instead:

  • dict

  • dict

In module ipkiss3.core.properties.containers.autonamed_typed_dict:

  • FixedPrefixAutoNamedTypedDict

Use instead:

  • FixedPrefixOrderedAutoNamedTypedDict

Also, ipkiss3.core.moduleloader was removed.

Fixed bug in ShapeRound

A bug in fitting circular bends was fixed. Said bug was introduced in 3.10 and it was only affecting cases where there was not enough space to fit the bend with the desired radius. In those cases, rounded shapes will differ, being correct in 3.9 and 2024.09 (and incorrect in 3.10-3.12).

import ipkiss3.all as i3

pts = [(0.0, 0.0), (0.0, 30.0), (5.0, 35.0), (20.0, 20.0), (10.0, 0.0)]

shape = i3.Shape(pts)
rounded_shape = i3.ShapeRound(original_shape=shape, radius=10)

elements = i3.ElementList()
elements += i3.Boundary(
    layer=i3.Layer(1),
    shape=rounded_shape,
)
example_path = i3.LayoutCell(name="example_path").Layout(elements=elements)
example_path.visualize()
The change (bugfix) in ShapeRound.

Boolean operations (2024.09.1)

The number of shape cutting operations performed during boolean operations on elements has been reduced. Note that when exporting to GDSII, shapes of Boundaries and Paths will still be cut where necessary to adhere to the GDSII standard.

One side effect is that when i3.Path is used, closed shapes (a path with the same start and end point) will not be cut anymore before doing the boolean operation itself. As a result, such a closed shape can be cut in a different place. This is XOR equivalent and has no effect on the layout. Also, when using Luceda IPManager for regression testing of your libraries, such cutting differences will be ignored.

This is an example occurrence, going through a boolean operation function but without actually doing a real boolean operation.

import ipkiss3.all as i3

layer0 = i3.Layer(0)
layer1 = i3.Layer(1)

path_shape = i3.Shape([
        (5, 0),
        (0, 0),
        (0, 10),
        (10, 10),
        (10, 0),
        (5, 0),
    ])

path = i3.Path(
    layer=layer0,
    shape=path_shape,
    line_width=2,
)

elements = i3.ElementList([path])
boolean_elements = i3.get_elements_for_generated_layers(elements, {layer0: layer1})
layout = i3.LayoutCell().Layout(elements=boolean_elements)
layout.visualize()

In 2024.09.0 this gives:

../_images/luceda_2024091_boolean_original.png

While in 2024.09.1 this gives:

../_images/luceda_2024091_boolean_2024091.png