The ActiveX Reference (CenterPlot Property, acadauto.chm, AutoCAD 2026):
"This property cannot be set to True on a layout object whose PlotType
property is set to acLayout." The shipped sequence wrote PlotType=5 and
then CenterPlot=True for the *default* call, so page_setup_apply(layout,
resolve_page_setup("ISO_A3")) could not succeed live — either COM raised
with nine writes landed and nothing put back, or the result claimed
applied.center=True over a read-back of False.
- resolve_page_setup resolves `center` to None for plot_area="layout"
(validated as a bool first; kept as the bool for "extents"), and
`center_applies(plot_type)` carries the rule for both read-backs.
- Both engines: page_setup_list reports `center: None` under acLayout
instead of a stored flag nothing honours; apply never sets the centre
bit / CenterPlot for a layout plot (ezdxf clears bit 4, the state
AutoCAD stores for acLayout; COM clears a stale CenterPlot=True *before*
PlotType moves to acLayout, and writes CenterPlot for an extents plot
only *after* PlotType=acExtents).
- COM: every write is journaled and unwound in reverse when AutoCAD
refuses one; the ValueError names the refused property and says the
layout was restored (or what could not be). The old device-only
rollback is the same mechanism now.
- tests: the fake enforces the documented CenterPlot rule (the shipped
sequence fails under it, which is the reviewer's repro), and can refuse
a named property; new cases pin the no-write, the ordering both ways,
the reverse unwind including SetCustomScale, and the None read-backs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
65 lines
2.8 KiB
Python
65 lines
2.8 KiB
Python
"""Page setup, plot styles and templates (v1.6 track E, group P).
|
|
|
|
``AutoCADBackend`` composes every contract in this package, so importing
|
|
``backends.base.AutoCADBackend`` is unchanged for callers.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
|
|
class PageSetupContract(ABC):
|
|
@abstractmethod
|
|
async def page_setup_list(self, layout: str | None = None) -> list[dict]:
|
|
"""Page setup of one paper-space layout, or of every one.
|
|
|
|
Rows: ``{layout, paper, canonical_media_name, size_mm: [w, h],
|
|
orientation, plot_style, scale, plot_area, device,
|
|
margins_mm: [top, bottom, left, right], center}``. ``paper`` is the
|
|
catalogue name when the size matches one within 0.5 mm, otherwise the
|
|
media name as stored. ``center`` is a bool for an extents plot and
|
|
``None`` for a layout plot, where centring is not applicable (AutoCAD
|
|
greys it out; ActiveX refuses ``CenterPlot = True`` under
|
|
``acLayout``). Raises ``ValueError`` for an unknown layout.
|
|
``Model`` is never listed: model space is plotted through
|
|
``drawing_export_pdf(layout=None)`` and carries no sheet.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def page_setup_apply(self, layout: str, setup: dict) -> dict:
|
|
"""Write a page setup resolved by
|
|
``engineering.standards.papers.resolve_page_setup`` to a layout.
|
|
|
|
Returns ``{ok, layout, applied: {...setup}, changed: {key: [old, new]},
|
|
plot_style_known, viewports_kept}``. ``changed`` is computed from the
|
|
read-back before and after, so re-applying the same setup reports
|
|
``{}``. Refuses ``Model``, an unknown layout, and a ``setup`` missing a
|
|
resolved key, before anything is written. A write the engine refuses
|
|
part-way through is unwound (every landed value put back) before the
|
|
``ValueError`` names the refused property. Never deletes viewports.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def plot_style_list(self) -> list[dict]:
|
|
"""``[{name, source: "catalog"|"installed", installed: bool|None}]`` —
|
|
the authored ctb catalogue plus, on a live engine, the files present
|
|
in the plot style search path. ``installed`` is ``None`` where no
|
|
installation can be scanned."""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def drawing_template_save(
|
|
self, path: str, name: str | None = None, description: str | None = None
|
|
) -> dict:
|
|
"""Save the current drawing as a template.
|
|
|
|
``.dxf`` writes on both engines; ``.dwt`` writes on the live engine
|
|
(``SaveAs(path, ac2018_Template)``) and raises
|
|
``UnsupportedCapabilityError("dwt_write")`` headlessly. Returns
|
|
``{ok, path, format: "dxf"|"dwt", backend, name, description_written}``.
|
|
"""
|
|
...
|