fix(com): a DXF type filter finds what ActiveX names differently
block_find_references asks entity_list(type_filter="INSERT"), and ActiveX calls a block reference AcDbBlockReference, so on a live seat the filter matched nothing and every block reported zero references. Measured on AutoCAD 2026 (25.1s): AcDbBlockReference, AcDbPolyline, and one class per dimension kind (AcDbRotatedDimension, AcDbAlignedDimension, AcDbDiametricDimension, AcDbRadialDimension, AcDb2LineAngularDimension, AcDbOrdinateDimension). entity_list and entity_count now let the DXF name find them: INSERT matches BLOCKREFERENCE/MINSERTBLOCK, LWPOLYLINE matches POLYLINE, and DIMENSION every *DIMENSION class. The reported type stays the ActiveX spelling, so a caller already filtering by it is unaffected. Verified live in a scratch document: two inserts, one dimension and one line are found by INSERT, DIMENSION and LINE (the INSERT filter found 0 before). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
898e775f93
commit
e6f685643d
@@ -27,7 +27,7 @@ Live through COM on Windows, or headless through ezdxf anywhere — one typed co
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
> **v1.5 release snapshot:** 229 tools · 8 resources · 5 prompt templates · 3990 collected tests.
|
> **v1.5 release snapshot:** 229 tools · 8 resources · 5 prompt templates · 3995 collected tests.
|
||||||
> 229 is the **registered** count; a default install advertises 224 over `tools/list`,
|
> 229 is the **registered** count; a default install advertises 224 over `tools/list`,
|
||||||
> because `ENABLE_3D` is unset. `system_about` is the runtime authority.
|
> because `ENABLE_3D` is unset. `system_about` is the runtime authority.
|
||||||
|
|
||||||
|
|||||||
+23
-4
@@ -1245,6 +1245,26 @@ def _com_geometry_bbox(entity) -> dict | None:
|
|||||||
_COM_LWPOLYLINE_NAMES = ("AcDbPolyline", "AcDbLWPolyline")
|
_COM_LWPOLYLINE_NAMES = ("AcDbPolyline", "AcDbLWPolyline")
|
||||||
|
|
||||||
|
|
||||||
|
# A tool filters by the DXF entity name; ActiveX names three of them differently
|
||||||
|
# (measured on AutoCAD 2026: AcDbBlockReference, AcDbPolyline and one class per
|
||||||
|
# dimension kind). The reported type stays the ActiveX spelling, so a caller
|
||||||
|
# already filtering by it is unaffected; the DXF name simply finds them too.
|
||||||
|
_DXF_TYPE_ALIASES: dict[str, frozenset[str]] = {
|
||||||
|
"INSERT": frozenset({"BLOCKREFERENCE", "MINSERTBLOCK"}),
|
||||||
|
"LWPOLYLINE": frozenset({"POLYLINE"}),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _type_filter_matches(type_filter: str, ent_type: str) -> bool:
|
||||||
|
"""True when an entity whose ActiveX type is ``ent_type`` answers ``type_filter``."""
|
||||||
|
wanted = type_filter.upper()
|
||||||
|
if ent_type == wanted or ent_type in _DXF_TYPE_ALIASES.get(wanted, ()):
|
||||||
|
return True
|
||||||
|
# DXF has one DIMENSION entity; ActiveX has AcDbRotatedDimension,
|
||||||
|
# AcDbAlignedDimension, AcDbDiametricDimension, AcDb2LineAngularDimension, …
|
||||||
|
return wanted == "DIMENSION" and ent_type.endswith("DIMENSION")
|
||||||
|
|
||||||
|
|
||||||
def _entity_info(entity) -> EntityInfo:
|
def _entity_info(entity) -> EntityInfo:
|
||||||
"""Convert a COM entity object to EntityInfo dataclass."""
|
"""Convert a COM entity object to EntityInfo dataclass."""
|
||||||
try:
|
try:
|
||||||
@@ -5275,7 +5295,7 @@ class ComBackend(AutoCADBackend):
|
|||||||
ent_type = ent.ObjectName.replace("AcDb", "").upper()
|
ent_type = ent.ObjectName.replace("AcDb", "").upper()
|
||||||
ent_layer = ent.Layer
|
ent_layer = ent.Layer
|
||||||
|
|
||||||
if type_filter and type_filter.upper() != ent_type:
|
if type_filter and not _type_filter_matches(type_filter, ent_type):
|
||||||
continue
|
continue
|
||||||
if layer_filter and layer_filter.lower() != ent_layer.lower():
|
if layer_filter and layer_filter.lower() != ent_layer.lower():
|
||||||
continue
|
continue
|
||||||
@@ -5307,9 +5327,8 @@ class ComBackend(AutoCADBackend):
|
|||||||
for i in range(mspace.Count):
|
for i in range(mspace.Count):
|
||||||
try:
|
try:
|
||||||
ent = mspace.Item(i)
|
ent = mspace.Item(i)
|
||||||
if (
|
if type_filter and not _type_filter_matches(
|
||||||
type_filter
|
type_filter, ent.ObjectName.replace("AcDb", "").upper()
|
||||||
and type_filter.upper() != ent.ObjectName.replace("AcDb", "").upper()
|
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
if layer_filter and layer_filter.lower() != ent.Layer.lower():
|
if layer_filter and layer_filter.lower() != ent.Layer.lower():
|
||||||
|
|||||||
@@ -1089,3 +1089,82 @@ async def test_drawing_audit_restores_auditctl_when_the_command_raises(sysvar_se
|
|||||||
await backend.drawing_audit()
|
await backend.drawing_audit()
|
||||||
assert doc.variables["AUDITCTL"] == 0
|
assert doc.variables["AUDITCTL"] == 0
|
||||||
assert doc.calls[-1] == ("SetVariable", "AUDITCTL", 0)
|
assert doc.calls[-1] == ("SetVariable", "AUDITCTL", 0)
|
||||||
|
|
||||||
|
|
||||||
|
# ── type filters speak the DXF names on the live engine too ─────────────────
|
||||||
|
|
||||||
|
|
||||||
|
def _typed_modelspace(monkeypatch, object_names):
|
||||||
|
"""A ComBackend whose model space holds one entity per ActiveX ObjectName."""
|
||||||
|
import backends.com_backend as cb
|
||||||
|
|
||||||
|
members = [
|
||||||
|
_Entity(
|
||||||
|
name,
|
||||||
|
Handle=f"{i + 1:X}",
|
||||||
|
Layer="0",
|
||||||
|
color=256,
|
||||||
|
Linetype="ByLayer",
|
||||||
|
Visible=True,
|
||||||
|
GetBoundingBox=lambda: ((0.0, 0.0, 0.0), (1.0, 1.0, 0.0)),
|
||||||
|
)
|
||||||
|
for i, name in enumerate(object_names)
|
||||||
|
]
|
||||||
|
space = SimpleNamespace(Count=len(members), Item=lambda i: members[i])
|
||||||
|
monkeypatch.setattr(cb, "_msp", lambda: space)
|
||||||
|
backend = ComBackend()
|
||||||
|
|
||||||
|
async def _run_inline(func, *args, **kwargs):
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
monkeypatch.setattr(backend, "_run", _run_inline)
|
||||||
|
return backend
|
||||||
|
|
||||||
|
|
||||||
|
# The ObjectNames measured on AutoCAD 2026 (25.1s) for each kind of entity a
|
||||||
|
# tool filters by its DXF name: a block reference, a lightweight polyline and
|
||||||
|
# every dimension subclass ActiveX creates.
|
||||||
|
_LIVE_NAMES = [
|
||||||
|
"AcDbBlockReference",
|
||||||
|
"AcDbPolyline",
|
||||||
|
"AcDbRotatedDimension",
|
||||||
|
"AcDbAlignedDimension",
|
||||||
|
"AcDbDiametricDimension",
|
||||||
|
"AcDbRadialDimension",
|
||||||
|
"AcDb2LineAngularDimension",
|
||||||
|
"AcDbOrdinateDimension",
|
||||||
|
"AcDbLine",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("dxf_name", "expected"),
|
||||||
|
[
|
||||||
|
("INSERT", 1),
|
||||||
|
("LWPOLYLINE", 1),
|
||||||
|
("DIMENSION", 6),
|
||||||
|
("LINE", 1),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_a_dxf_type_filter_finds_what_activex_names_differently(
|
||||||
|
monkeypatch, dxf_name, expected
|
||||||
|
):
|
||||||
|
"""block_find_references asks entity_list for INSERTs; ActiveX calls the
|
||||||
|
same entity AcDbBlockReference, so on the live seat the filter matched
|
||||||
|
nothing and every block reported zero references. The DXF name a tool
|
||||||
|
passes must find the entity on both engines."""
|
||||||
|
backend = _typed_modelspace(monkeypatch, _LIVE_NAMES)
|
||||||
|
listed = await backend.entity_list(type_filter=dxf_name, limit=100)
|
||||||
|
assert len(listed) == expected
|
||||||
|
assert await backend.entity_count(type_filter=dxf_name) == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_the_activex_type_names_still_filter_as_before(monkeypatch):
|
||||||
|
"""The reported type names do not change, so a caller already filtering by
|
||||||
|
the ActiveX spelling keeps getting exactly what it got."""
|
||||||
|
backend = _typed_modelspace(monkeypatch, _LIVE_NAMES)
|
||||||
|
assert len(await backend.entity_list(type_filter="BLOCKREFERENCE")) == 1
|
||||||
|
assert len(await backend.entity_list(type_filter="POLYLINE")) == 1
|
||||||
|
assert len(await backend.entity_list(type_filter="ROTATEDDIMENSION")) == 1
|
||||||
|
|||||||
Reference in New Issue
Block a user