aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/xlsxwriter/chart_pie.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/xlsxwriter/chart_pie.py')
-rw-r--r--.venv/lib/python3.12/site-packages/xlsxwriter/chart_pie.py263
1 files changed, 263 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/xlsxwriter/chart_pie.py b/.venv/lib/python3.12/site-packages/xlsxwriter/chart_pie.py
new file mode 100644
index 00000000..2b55ba76
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/xlsxwriter/chart_pie.py
@@ -0,0 +1,263 @@
+###############################################################################
+#
+# ChartPie - A class for writing the Excel XLSX Pie charts.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org
+#
+
+from warnings import warn
+
+from . import chart
+
+
+class ChartPie(chart.Chart):
+ """
+ A class for writing the Excel XLSX Pie charts.
+
+
+ """
+
+ ###########################################################################
+ #
+ # Public API.
+ #
+ ###########################################################################
+
+ def __init__(self):
+ """
+ Constructor.
+
+ """
+ super().__init__()
+
+ self.vary_data_color = 1
+ self.rotation = 0
+
+ # Set the available data label positions for this chart type.
+ self.label_position_default = "best_fit"
+ self.label_positions = {
+ "center": "ctr",
+ "inside_end": "inEnd",
+ "outside_end": "outEnd",
+ "best_fit": "bestFit",
+ }
+
+ def set_rotation(self, rotation):
+ """
+ Set the Pie/Doughnut chart rotation: the angle of the first slice.
+
+ Args:
+ rotation: First segment angle: 0 <= rotation <= 360.
+
+ Returns:
+ Nothing.
+
+ """
+ if rotation is None:
+ return
+
+ # Ensure the rotation is in Excel's range.
+ if rotation < 0 or rotation > 360:
+ warn(
+ f"Chart rotation '{rotation}' outside Excel range: 0 <= rotation <= 360"
+ )
+ return
+
+ self.rotation = int(rotation)
+
+ ###########################################################################
+ #
+ # Private API.
+ #
+ ###########################################################################
+
+ def _write_chart_type(self, args):
+ # Override the virtual superclass method with a chart specific method.
+ # Write the c:pieChart element.
+ self._write_pie_chart()
+
+ ###########################################################################
+ #
+ # XML methods.
+ #
+ ###########################################################################
+
+ def _write_pie_chart(self):
+ # Write the <c:pieChart> element. Over-ridden method to remove
+ # axis_id code since Pie charts don't require val and cat axes.
+ self._xml_start_tag("c:pieChart")
+
+ # Write the c:varyColors element.
+ self._write_vary_colors()
+
+ # Write the series elements.
+ for data in self.series:
+ self._write_ser(data)
+
+ # Write the c:firstSliceAng element.
+ self._write_first_slice_ang()
+
+ self._xml_end_tag("c:pieChart")
+
+ def _write_plot_area(self):
+ # Over-ridden method to remove the cat_axis() and val_axis() code
+ # since Pie charts don't require those axes.
+ #
+ # Write the <c:plotArea> element.
+
+ self._xml_start_tag("c:plotArea")
+
+ # Write the c:layout element.
+ self._write_layout(self.plotarea.get("layout"), "plot")
+
+ # Write the subclass chart type element.
+ self._write_chart_type(None)
+ # Configure a combined chart if present.
+ second_chart = self.combined
+
+ if second_chart:
+ # Secondary axis has unique id otherwise use same as primary.
+ if second_chart.is_secondary:
+ second_chart.id = 1000 + self.id
+ else:
+ second_chart.id = self.id
+
+ # Share the same filehandle for writing.
+ second_chart.fh = self.fh
+
+ # Share series index with primary chart.
+ second_chart.series_index = self.series_index
+
+ # Write the subclass chart type elements for combined chart.
+ # pylint: disable-next=protected-access
+ second_chart._write_chart_type(None)
+
+ # Write the c:spPr element for the plotarea formatting.
+ self._write_sp_pr(self.plotarea)
+
+ self._xml_end_tag("c:plotArea")
+
+ def _write_legend(self):
+ # Over-ridden method to add <c:txPr> to legend.
+ # Write the <c:legend> element.
+ legend = self.legend
+ position = legend.get("position", "right")
+ font = legend.get("font")
+ delete_series = []
+ overlay = 0
+
+ if legend.get("delete_series") and isinstance(legend["delete_series"], list):
+ delete_series = legend["delete_series"]
+
+ if position.startswith("overlay_"):
+ position = position.replace("overlay_", "")
+ overlay = 1
+
+ allowed = {
+ "right": "r",
+ "left": "l",
+ "top": "t",
+ "bottom": "b",
+ "top_right": "tr",
+ }
+
+ if position == "none":
+ return
+
+ if position not in allowed:
+ return
+
+ position = allowed[position]
+
+ self._xml_start_tag("c:legend")
+
+ # Write the c:legendPos element.
+ self._write_legend_pos(position)
+
+ # Remove series labels from the legend.
+ for index in delete_series:
+ # Write the c:legendEntry element.
+ self._write_legend_entry(index)
+
+ # Write the c:layout element.
+ self._write_layout(legend.get("layout"), "legend")
+
+ # Write the c:overlay element.
+ if overlay:
+ self._write_overlay()
+
+ # Write the c:spPr element.
+ self._write_sp_pr(legend)
+
+ # Write the c:txPr element. Over-ridden.
+ self._write_tx_pr_legend(None, font)
+
+ self._xml_end_tag("c:legend")
+
+ def _write_tx_pr_legend(self, horiz, font):
+ # Write the <c:txPr> element for legends.
+
+ if font and font.get("rotation"):
+ rotation = font["rotation"]
+ else:
+ rotation = None
+
+ self._xml_start_tag("c:txPr")
+
+ # Write the a:bodyPr element.
+ self._write_a_body_pr(rotation, horiz)
+
+ # Write the a:lstStyle element.
+ self._write_a_lst_style()
+
+ # Write the a:p element.
+ self._write_a_p_legend(font)
+
+ self._xml_end_tag("c:txPr")
+
+ def _write_a_p_legend(self, font):
+ # Write the <a:p> element for legends.
+
+ self._xml_start_tag("a:p")
+
+ # Write the a:pPr element.
+ self._write_a_p_pr_legend(font)
+
+ # Write the a:endParaRPr element.
+ self._write_a_end_para_rpr()
+
+ self._xml_end_tag("a:p")
+
+ def _write_a_p_pr_legend(self, font):
+ # Write the <a:pPr> element for legends.
+ attributes = [("rtl", 0)]
+
+ self._xml_start_tag("a:pPr", attributes)
+
+ # Write the a:defRPr element.
+ self._write_a_def_rpr(font)
+
+ self._xml_end_tag("a:pPr")
+
+ def _write_vary_colors(self):
+ # Write the <c:varyColors> element.
+ attributes = [("val", 1)]
+
+ self._xml_empty_tag("c:varyColors", attributes)
+
+ def _write_first_slice_ang(self):
+ # Write the <c:firstSliceAng> element.
+ attributes = [("val", self.rotation)]
+
+ self._xml_empty_tag("c:firstSliceAng", attributes)
+
+ def _write_show_leader_lines(self):
+ # Write the <c:showLeaderLines> element.
+ #
+ # This is for Pie/Doughnut charts. Other chart types only supported
+ # leader lines after Excel 2015 via an extension element.
+ attributes = [("val", 1)]
+
+ self._xml_empty_tag("c:showLeaderLines", attributes)