aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/openpyxl/cell/rich_text.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/cell/rich_text.py')
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/cell/rich_text.py202
1 files changed, 202 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/cell/rich_text.py b/.venv/lib/python3.12/site-packages/openpyxl/cell/rich_text.py
new file mode 100644
index 00000000..373e263e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/cell/rich_text.py
@@ -0,0 +1,202 @@
+# Copyright (c) 2010-2024 openpyxl
+
+"""
+RichText definition
+"""
+from copy import copy
+from openpyxl.compat import NUMERIC_TYPES
+from openpyxl.cell.text import InlineFont, Text
+from openpyxl.descriptors import (
+ Strict,
+ String,
+ Typed
+)
+
+from openpyxl.xml.functions import Element, whitespace
+
+class TextBlock(Strict):
+ """ Represents text string in a specific format
+
+ This class is used as part of constructing a rich text strings.
+ """
+ font = Typed(expected_type=InlineFont)
+ text = String()
+
+ def __init__(self, font, text):
+ self.font = font
+ self.text = text
+
+
+ def __eq__(self, other):
+ return self.text == other.text and self.font == other.font
+
+
+ def __str__(self):
+ """Just retun the text"""
+ return self.text
+
+
+ def __repr__(self):
+ font = self.font != InlineFont() and self.font or "default"
+ return f"{self.__class__.__name__} text={self.text}, font={font}"
+
+
+ def to_tree(self):
+ el = Element("r")
+ el.append(self.font.to_tree(tagname="rPr"))
+ t = Element("t")
+ t.text = self.text
+ whitespace(t)
+ el.append(t)
+ return el
+
+#
+# Rich Text class.
+# This class behaves just like a list whose members are either simple strings, or TextBlock() instances.
+# In addition, it can be initialized in several ways:
+# t = CellRFichText([...]) # initialize with a list.
+# t = CellRFichText((...)) # initialize with a tuple.
+# t = CellRichText(node) # where node is an Element() from either lxml or xml.etree (has a 'tag' element)
+class CellRichText(list):
+ """Represents a rich text string.
+
+ Initialize with a list made of pure strings or :class:`TextBlock` elements
+ Can index object to access or modify individual rich text elements
+ it also supports the + and += operators between rich text strings
+ There are no user methods for this class
+
+ operations which modify the string will generally call an optimization pass afterwards,
+ that merges text blocks with identical formats, consecutive pure text strings,
+ and remove empty strings and empty text blocks
+ """
+
+ def __init__(self, *args):
+ if len(args) == 1:
+ args = args[0]
+ if isinstance(args, (list, tuple)):
+ CellRichText._check_rich_text(args)
+ else:
+ CellRichText._check_element(args)
+ args = [args]
+ else:
+ CellRichText._check_rich_text(args)
+ super().__init__(args)
+
+
+ @classmethod
+ def _check_element(cls, value):
+ if not isinstance(value, (str, TextBlock, NUMERIC_TYPES)):
+ raise TypeError(f"Illegal CellRichText element {value}")
+
+
+ @classmethod
+ def _check_rich_text(cls, rich_text):
+ for t in rich_text:
+ CellRichText._check_element(t)
+
+ @classmethod
+ def from_tree(cls, node):
+ text = Text.from_tree(node)
+ if text.t:
+ return (text.t.replace('x005F_', ''),)
+ s = []
+ for r in text.r:
+ t = ""
+ if r.t:
+ t = r.t.replace('x005F_', '')
+ if r.rPr:
+ s.append(TextBlock(r.rPr, t))
+ else:
+ s.append(t)
+ return cls(s)
+
+ # Merge TextBlocks with identical formatting
+ # remove empty elements
+ def _opt(self):
+ last_t = None
+ l = CellRichText(tuple())
+ for t in self:
+ if isinstance(t, str):
+ if not t:
+ continue
+ elif not t.text:
+ continue
+ if type(last_t) == type(t):
+ if isinstance(t, str):
+ last_t += t
+ continue
+ elif last_t.font == t.font:
+ last_t.text += t.text
+ continue
+ if last_t:
+ l.append(last_t)
+ last_t = t
+ if last_t:
+ # Add remaining TextBlock at end of rich text
+ l.append(last_t)
+ super().__setitem__(slice(None), l)
+ return self
+
+
+ def __iadd__(self, arg):
+ # copy used here to create new TextBlock() so we don't modify the right hand side in _opt()
+ CellRichText._check_rich_text(arg)
+ super().__iadd__([copy(e) for e in list(arg)])
+ return self._opt()
+
+
+ def __add__(self, arg):
+ return CellRichText([copy(e) for e in list(self) + list(arg)])._opt()
+
+
+ def __setitem__(self, indx, val):
+ CellRichText._check_element(val)
+ super().__setitem__(indx, val)
+ self._opt()
+
+
+ def append(self, arg):
+ CellRichText._check_element(arg)
+ super().append(arg)
+
+
+ def extend(self, arg):
+ CellRichText._check_rich_text(arg)
+ super().extend(arg)
+
+
+ def __repr__(self):
+ return "CellRichText([{}])".format(', '.join((repr(s) for s in self)))
+
+
+ def __str__(self):
+ return ''.join([str(s) for s in self])
+
+
+ def as_list(self):
+ """
+ Returns a list of the strings contained.
+ The main reason for this is to make editing easier.
+ """
+ return [str(s) for s in self]
+
+
+ def to_tree(self):
+ """
+ Return the full XML representation
+ """
+ container = Element("is")
+ for obj in self:
+ if isinstance(obj, TextBlock):
+ container.append(obj.to_tree())
+
+ else:
+ el = Element("r")
+ t = Element("t")
+ t.text = obj
+ whitespace(t)
+ el.append(t)
+ container.append(el)
+
+ return container
+