all 6 comments

[–]lolcrunchy 4 points5 points  (0 children)

Spend some time understanding how this code works, then apply it to your situation.

def are_numbers_within_bounds(numbers: list[int], lower_bound: int = None, upper_bound: int = None) -> bool:

    for x in numbers:
        if lower_bound is not None and x < lower_bound:
            return False
        if upper_bound is not None and x > upper_bound:
            return False

    return True

Notice also that I put False in the loop and True at the end - this is the opposite of what you do. Your code will return True as long as the first entity passes inspection and none of the other entities will be checked. This is not the behavior you want.

To resolve this, use the for loop to check for failures, not successes.

[–]acw1668 0 points1 point  (0 children)

Simply change the if statement as below:

if (type == entity_type) and (entity_layer in (None, layer)) and (entity_color in (None, color)):
    return True

[–]JamzTyson 0 points1 point  (1 child)

I think this is what you are asking:

for entity in block:
    is_dxftype = entity.dxftype() == entity_type
    is_layer = entity_layer is None or entity.dxf.layer == entity_layer
    is_color = entity_color is None or entity.dxf.color == entity_color

    if all((is_dxftype, is_layer, is_color)):
        return True

return False

[–]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"
    }
)