Source code for fastpyxl.chart.pie_chart

# Autogenerated schema
from __future__ import annotations

from fastpyxl.typed_serialisable.base import Serialisable
from fastpyxl.typed_serialisable.errors import FieldValidationError
from fastpyxl.typed_serialisable.fields import AliasField, Field

from fastpyxl.descriptors.excel import ExtensionList

from ._chart import ChartBase
from .axis import ChartLines
from .descriptors import NestedGapAmount
from .series import Series
from .label import DataLabelList


def _bounded_int(value, lo: int, hi: int, name: str):
    if value is None:
        return None
    try:
        n = int(value)
    except (TypeError, ValueError) as exc:
        raise FieldValidationError(f"{name} rejected value {value!r}") from exc
    if n < lo or n > hi:
        raise FieldValidationError(f"{name} rejected value {value!r}")
    return n


def _of_pie_type(v):
    if v is None:
        return None
    if v not in ("pie", "bar"):
        raise FieldValidationError(f"ofPieType rejected value {v!r}")
    return v


def _split_type(v):
    if v is None or v == "none":
        return None
    allowed = frozenset({"auto", "cust", "percent", "pos", "val"})
    if v not in allowed:
        raise FieldValidationError(f"splitType rejected value {v!r}")
    return v


class _PieChartBase(ChartBase):
    varyColors: bool | None = Field.nested_bool(allow_none=True, default=None)
    ser: list[Series] | None = Field.sequence(expected_type=Series, allow_none=True, default=list)
    dLbls: DataLabelList | None = Field.element(
        expected_type=DataLabelList, allow_none=True, default=None
    )
    dataLabels = AliasField("dLbls", default=None)

    _series_type = "pie"

    xml_order = ("varyColors", "ser", "dLbls")

    def __init__(self, varyColors=True, ser=(), dLbls=None, **kw):
        self.varyColors = varyColors
        self.ser = list(ser) if ser is not None else []
        self.dLbls = dLbls
        super().__init__(**kw)


[docs] class PieChart(_PieChartBase): tagname = "pieChart" firstSliceAng: int | None = Field.nested_value( expected_type=int, allow_none=True, converter=lambda v: _bounded_int(v, 0, 360, "firstSliceAng"), default=None, ) extLst: ExtensionList | None = Field.element( expected_type=ExtensionList, allow_none=True, serialize=False, default=None ) xml_order = _PieChartBase.xml_order + ("firstSliceAng",) def __init__(self, firstSliceAng=0, extLst=None, **kw): self.firstSliceAng = firstSliceAng self.extLst = extLst super().__init__(**kw)
[docs] class PieChart3D(_PieChartBase): tagname = "pie3DChart" extLst: ExtensionList | None = Field.element( expected_type=ExtensionList, allow_none=True, serialize=False, default=None ) xml_order = _PieChartBase.xml_order def __init__(self, extLst=None, **kw): self.extLst = extLst super().__init__(**kw)
[docs] class DoughnutChart(_PieChartBase): tagname = "doughnutChart" firstSliceAng: int | None = Field.nested_value( expected_type=int, allow_none=True, converter=lambda v: _bounded_int(v, 0, 360, "firstSliceAng"), default=None, ) holeSize: int | None = Field.nested_value( expected_type=int, allow_none=True, converter=lambda v: _bounded_int(v, 1, 90, "holeSize"), default=None, ) extLst: ExtensionList | None = Field.element( expected_type=ExtensionList, allow_none=True, serialize=False, default=None ) xml_order = _PieChartBase.xml_order + ("firstSliceAng", "holeSize") def __init__(self, firstSliceAng=0, holeSize=10, extLst=None, **kw): self.firstSliceAng = firstSliceAng self.holeSize = holeSize self.extLst = extLst super().__init__(**kw)
[docs] class CustomSplit(Serialisable): tagname = "custSplit" secondPiePt: list[int] | None = Field.sequence( expected_type=int, allow_none=True, primitive_attribute="val", default=list, ) xml_order = ("secondPiePt",) def __init__(self, secondPiePt=()): self.secondPiePt = list(secondPiePt) if secondPiePt is not None else []
[docs] class ProjectedPieChart(_PieChartBase): """ From the spec 21.2.2.126 This element contains the pie of pie or bar of pie series on this chart. Only the first series shall be displayed. The splitType element shall determine whether the splitPos and custSplit elements apply. """ tagname = "ofPieChart" ofPieType: str | None = Field.nested_value( expected_type=str, allow_none=True, converter=_of_pie_type, default=None, ) type = AliasField("ofPieType", default=None) gapWidth = NestedGapAmount splitType: str | None = Field.nested_value( expected_type=str, allow_none=True, converter=_split_type, default=None, ) splitPos: float | None = Field.nested_value(expected_type=float, allow_none=True, default=None) custSplit: CustomSplit | None = Field.element(expected_type=CustomSplit, allow_none=True, default=None) secondPieSize: int | None = Field.nested_value( expected_type=int, allow_none=True, converter=lambda v: _bounded_int(v, 5, 200, "secondPieSize"), default=None, ) serLines: ChartLines | None = Field.element(expected_type=ChartLines, allow_none=True, default=None) join_lines = AliasField("serLines", default=None) extLst: ExtensionList | None = Field.element( expected_type=ExtensionList, allow_none=True, serialize=False, default=None ) xml_order = _PieChartBase.xml_order + ( "ofPieType", "gapWidth", "splitType", "splitPos", "custSplit", "secondPieSize", "serLines", ) def __init__( self, ofPieType="pie", gapWidth=None, splitType="auto", splitPos=None, custSplit=None, secondPieSize=75, serLines=None, extLst=None, **kw, ): self.ofPieType = ofPieType self.gapWidth = gapWidth self.splitType = splitType self.splitPos = splitPos self.custSplit = custSplit self.secondPieSize = secondPieSize if serLines is None: serLines = ChartLines() self.serLines = serLines self.extLst = extLst super().__init__(**kw)