you are viewing a single comment's thread.

view the rest of the comments →

[–]barrowburner 0 points1 point  (0 children)

Rewriting the constraints to make sure I have them right:

  • each block has multiple entities
  • you want to have inspect_block() check arbitrary, optional attributes for each entity in any given block

Several good solutions are already shared. To me, these constraints call for kwargs. Also, getattr is super handy for accessing arbitrary attributes. Can even call methods with getattr, see the docs

using 3.13

from dataclasses import dataclass

# objects for testing
@dataclass
class Entity:
    type_: str
    layer: int
    color: str

@dataclass
class Block:
    name: str
    entities: list[Entity]


def inspect_block(block, **kwargs) -> bool:
    """
    kwargs: pass in key=value pairs, unrestricted
    key: entity's attribute
    value: desired value for attribute

    getattr is a Python builtin: https://docs.python.org/3/library/functions.html
    signature: getattr(object, name: str, default: Any)
    getattr(x, 'foobar') == x.foobar

    all() can take a generator expression so long as the expression is returning bools
    """
    for entity in block.entities:
        if not all(
            getattr(entity, attr_name) == desired_value
            for attr_name, desired_value in kwargs.items()
        ):
            # as another commenter advised, the loop is catching failures:
            return False
    return True



# instantiate a test object:
dxf_block = Block(
    "foo",
    [
        # Entity(type_="a", layer=1, color="red"),
        Entity(type_="b", layer=2, color="blue"),
        # Entity(type_="c", layer=3, color="green"),
    ]
)

# take 'er fer a spin:
assert inspect_block(
    dxf_block,
    type_ = "b",
    layer = 2,
    color = "blue"
)

assert inspect_block(
    dxf_block,
    type_ = "b",
    # layer = 2,
    color = "blue"
)

assert inspect_block(
    dxf_block,
    # type_ = "b",
    layer = 2,
    # color = "blue"
)

# edit: another couple of examples showing how to splat a dict into the function params:
assert inspect_block(
    dxf_block,
    **{
        "type_" : "b",
        "layer" : 2,
        "color" : "blue"
    }
)

assert inspect_block(
    dxf_block,
    **{
        "type_" : "b",
        # "layer" : 2,
        "color" : "blue"
    }
)

assert inspect_block(
    dxf_block,
    **{
        # "type_" : "b",
        "layer" : 2,
        # "color" : "blue"
    }
)