An auto-shape's outline width, set via shape.line.width = Emu(value), emits <a:ln w="EMU"/> inside the shape's <p:spPr>. This manifest is a parameterised family over 6 widths (hairline, thin, medium, thick, extrathick, heavy): one manifest file expands into 6 cases, each backed by a distinct fixture pptx/shape-line-width--<id>.pptx generated from the same gen_shape_line_width.py script parameterised by --emu.
Library verdicts: python-pptx: — pptxjs: —
| Feature id | pptx/shape-line-width--hairline |
|---|---|
| Format | pptx |
| Category | shapes |
| Family | pptx/shape-line-width |
| Axis values | width=hairline |
| Spec | ecma-376-5-part-1 § 20.1.8.60 a:ln |
| ID / part | Predicate | XPath | python-pptx | pptxjs |
|---|---|---|---|---|
shape-line-width-hairlineppt/slides/slide1.xml | equal = 3175The rectangle shape's <p:spPr> must declare <a:ln w="3175"/>. | //p:sp[p:spPr/a:prstGeom[@prst='rect']]/p:spPr/a:ln/@w | — | — |
No render assertions declared.
scripts/gen_shape_line_width.py
#!/usr/bin/env python3
"""Generate a single ``fixtures/pptx/shape-line-width--<id>.pptx`` fixture.
Parameterised generator for the ``pptx/shape-line-width`` manifest
family. The conformance runner invokes this script once per case with
``--emu <WIDTH_EMU> --out <path>``.
Each invocation produces a single-slide presentation containing one
rectangle auto-shape whose outline width is set via ``shape.line.width
= Emu(width)``. The underlying XML is ``<p:sp>/<p:spPr>/<a:ln w="..."/>``;
the manifest asserts the ``@w`` attribute equals the axis ``val`` field.
"""
from __future__ import annotations
import argparse
import datetime as _dt
from pathlib import Path
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE
from pptx.util import Emu, Inches
_REPO_ROOT = Path(__file__).resolve().parent.parent
_REPRODUCIBLE_DT = _dt.datetime(2000, 1, 1, 0, 0, 0)
def _write(width_emu: int, out: Path) -> None:
prs = Presentation()
# "Title Only" layout — an empty title placeholder plus our shape.
slide = prs.slides.add_slide(prs.slide_layouts[5])
shape = slide.shapes.add_shape(
MSO_SHAPE.RECTANGLE, Inches(1), Inches(1), Inches(3), Inches(2)
)
shape.line.width = Emu(width_emu)
out.parent.mkdir(parents=True, exist_ok=True)
prs.save(out, zip_date_time=_REPRODUCIBLE_DT)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"--emu",
required=True,
type=int,
help="Line width in EMU (914400 EMU/inch, 12700 EMU/pt).",
)
parser.add_argument(
"--out",
required=True,
help="Output fixture path (absolute or repo-relative).",
)
args = parser.parse_args()
out_path = Path(args.out)
if not out_path.is_absolute():
out_path = _REPO_ROOT / out_path
_write(args.emu, out_path)
print(out_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())
{
"$schema": "../manifest.schema.json",
"id": "pptx/shape-line-width--hairline",
"kind": "literal",
"title": "Shape outline line width",
"format": "pptx",
"category": "shapes",
"summary": "An auto-shape's outline width, set via shape.line.width = Emu(value), emits <a:ln w=\"EMU\"/> inside the shape's <p:spPr>. This manifest is a parameterised family over 6 widths (hairline, thin, medium, thick, extrathick, heavy): one manifest file expands into 6 cases, each backed by a distinct fixture pptx/shape-line-width--<id>.pptx generated from the same gen_shape_line_width.py script parameterised by --emu.",
"spec": {
"source": "ecma-376-5-part-1",
"clause": "20.1.8.60",
"element": "a:ln",
"rnc_reference": "spec/ecma-376-5/part-1/rnc/DrawingML.rnc",
"xsd_reference": "spec/ecma-376-5/part-1/xsd/dml-lineProperties.xsd",
"notes": "DrawingML <a:ln> declares line (outline) properties on a shape. Its @w attribute is a ST_LineWidth (ST_PositiveCoordinate32) value in EMU — 914400 EMU = 1 inch, 12700 EMU = 1 point. python-pptx's ``shape.line.width = Emu(v)`` writes the @w attribute directly. The assertion targets the <p:sp> whose <a:prstGeom prst=\"rect\"/> identifies it as the test rectangle, avoiding false matches against placeholder shapes."
},
"fixtures": {
"machine": "pptx/shape-line-width--hairline"
},
"generator": {
"python": "scripts/gen_shape_line_width.py",
"arg_template": "--emu {width.val} --out fixtures/pptx/shape-line-width--{width.id}.pptx"
},
"_expansion": {
"parent_id": "pptx/shape-line-width",
"bindings": {
"width": "hairline"
}
},
"assertions": [
{
"id": "shape-line-width-hairline",
"part": "ppt/slides/slide1.xml",
"namespaces": {
"p": "http://schemas.openxmlformats.org/presentationml/2006/main",
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//p:sp[p:spPr/a:prstGeom[@prst='rect']]/p:spPr/a:ln/@w",
"must": "equal",
"value": "3175",
"description": "The rectangle shape's <p:spPr> must declare <a:ln w=\"3175\"/>."
}
]
}
