Source code for xlsxwriter_celldsl.formats
from collections import defaultdict
from typing import Any, Dict
from attr import Factory, attrs
from xlsxwriter import Workbook as XlsxWriterWorkbook
from xlsxwriter.format import Format
[docs]class FormatDict(Dict[str, Any]):
"""A special variant of vanilla dictionary that implement __or__ and __hash__. Used to create and merge formats.
Examples:
>>> F = FormatDict
>>> F1 = F({'font_name': 'Arial'})
>>> F2 = F({'font_size': 12})
>>> F3 = F({'font_name': 'Arial', 'font_size': 12})
>>> F1 | F2 == F3
True
>>> F2 | F1 == F3
True
>>> hash(F1 | F2) == hash(F3)
True
"""
def __or__(self, other):
return FormatDict({
**self,
**other
})
__ror__ = __or__
def __hash__(self):
return hash((*sorted(self.items()),))
[docs]@attrs(auto_attribs=True)
class FormatHandler(object):
"""This object is used to handle adding new formats when necessary. Only one should be used per Workbook."""
target: XlsxWriterWorkbook
_memoized: Dict[int, Format] = Factory(dict)
def verify_format(self, format_: FormatDict):
hashed = hash(format_)
if hashed not in self._memoized:
self._memoized[hashed] = self.target.add_format(format_)
return self._memoized[hashed]
[docs]def ensure_format_uniqueness(class_):
"""A class decorator used to verify that all formats in the decorated class are unique and use FormatDict."""
from xlsxwriter_celldsl.errors import CellDSLError
hashes = defaultdict(list)
for attr in dir(class_):
if not attr.startswith('_'):
attr_value = getattr(class_, attr)
if not isinstance(attr_value, FormatDict):
raise CellDSLError(f'Format {attr_value} must be a FormatDict')
hashes[hash(attr_value)].append(attr)
for formats in hashes.values():
if len(formats) > 1:
raise CellDSLError(f'{formats} are the same')
return class_
[docs]@ensure_format_uniqueness
class FormatsNamespace(object):
base = FormatDict({})
default_font_name = base | {'font_name': 'Liberation Sans'}
default_font_size = base | {'font_size': 10}
default_header_size = base | {'font_size': 18}
percent = base | {'num_format': '0.0%'}
regular_float = base | {'num_format': '0.00'}
float_with_red = regular_float | {'num_format': '0.00;[RED]-0.00'}
percent_with_red = percent | {'num_format': '0.0%;[RED]-0.0%'}
left = base | {'align': 'left'}
center = base | {'align': 'center', 'valign': 'vcenter'}
right = base | {'align': 'right'}
fill = base | {'align': 'fill'}
justify = base | {'align': 'justify'}
center_across = base | {'align': 'center_across'}
distributed = base | {'align': 'distributed'}
vbottom = base | {'valign': 'bottom'}
vtop = base | {'valign': 'top'}
vcenter = base | {'valign': 'vcenter'}
vjustify = base | {'valign': 'vjustify'}
vdistributed = base | {'valign': 'vdistributed'}
rotated_0 = base | {'rotation': 0}
rotated_90 = base | {'rotation': 90}
rotated_180 = base | {'rotation': 270}
rotated_270 = base | {'rotation': -90}
wrapped = base | {'text_wrap': True}
bold = base | {'bold': True}
italic = base | {'italic': True}
underline = base | {'underline': True}
strikeout = base | {'font_strikeout': True}
superscript = base | {'font_script': 1}
subscript = base | {'font_script': 2}
default_font = default_font_name | default_font_size | left
default_font_bold = default_font | bold
default_header = default_font_bold | default_header_size
default_percent = default_font | percent | center
default_percent_bold = default_percent | bold
default_font_centered = default_font | center
default_font_bold_centered = default_font_bold | center
default_table_row_font = default_font_bold_centered | wrapped
default_table_column_font = default_font_bold_centered | rotated_90 | vbottom
left_border = base | {'left': 1}
top_border = base | {'top': 1}
right_border = base | {'right': 1}
bottom_border = base | {'bottom': 1}
highlight_border = left_border | top_border | right_border | bottom_border