Changeset - 59b088b57362
[Not reviewed]
0 2 0
Brett Smith - 4 years ago 2020-07-29 20:58:57
brettcsmith@brettcsmith.org
reports: Add BaseODS.set_properties() method.
2 files changed with 63 insertions and 0 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/reports/core.py
Show inline comments
...
 
@@ -20,35 +20,38 @@ import copy
 
import datetime
 
import enum
 
import itertools
 
import operator
 
import re
 
import urllib.parse as urlparse
 

	
 
import babel.core  # type:ignore[import]
 
import babel.numbers  # type:ignore[import]
 

	
 
import odf.config  # type:ignore[import]
 
import odf.element  # type:ignore[import]
 
import odf.meta  # type:ignore[import]
 
import odf.number  # type:ignore[import]
 
import odf.opendocument  # type:ignore[import]
 
import odf.style  # type:ignore[import]
 
import odf.table  # type:ignore[import]
 
import odf.text  # type:ignore[import]
 

	
 
from decimal import Decimal
 
from pathlib import Path
 

	
 
from beancount.core import amount as bc_amount
 
from odf.namespaces import TOOLSVERSION  # type:ignore[import]
 

	
 
from ..cliutil import VERSION
 
from .. import data
 
from .. import filters
 
from .. import rtutil
 

	
 
from typing import (
 
    cast,
 
    overload,
 
    Any,
 
    BinaryIO,
 
    Callable,
 
    Dict,
 
    Generic,
...
 
@@ -552,24 +555,25 @@ class BaseODS(BaseSpreadsheet[RT, ST], metaclass=abc.ABCMeta):
 
        re.ASCII,
 
    )
 

	
 
    def __init__(self, rt_wrapper: Optional[rtutil.RT]=None) -> None:
 
        self.rt_wrapper = rt_wrapper
 
        self.locale = babel.core.Locale.default('LC_MONETARY')
 
        self.currency_fmt_key = 'accounting'
 
        self._name_counter = itertools.count(1)
 
        self._style_cache: MutableMapping[str, odf.style.Style] = {}
 
        self.document = odf.opendocument.OpenDocumentSpreadsheet()
 
        self.init_settings()
 
        self.init_styles()
 
        self.set_properties()
 
        self.sheet = self.use_sheet("Report")
 

	
 
    ### Low-level document tree manipulation
 
    # The *intent* is that you only need to use these if you're adding new
 
    # methods to manipulate document settings or styles.
 

	
 
    def copy_element(self, elem: odf.element.Element) -> odf.element.Element:
 
        retval = odf.element.Element(
 
            qname=elem.qname,
 
            qattributes=copy.copy(elem.attributes),
 
        )
 
        try:
...
 
@@ -1037,24 +1041,39 @@ class BaseODS(BaseSpreadsheet[RT, ST], metaclass=abc.ABCMeta):
 

	
 
        self.style_starttext: odf.style.Style
 
        self.style_centertext: odf.style.Style
 
        self.style_endtext: odf.style.Style
 
        for textalign in ['start', 'center', 'end']:
 
            aligned_style = self.replace_child(
 
                styles, odf.style.Style, name=f'{textalign.title()}Text',
 
            )
 
            aligned_style.setAttribute('family', 'table-cell')
 
            aligned_style.addElement(odf.style.ParagraphProperties(textalign=textalign))
 
            setattr(self, f'style_{textalign}text', aligned_style)
 

	
 
    ### Properties
 

	
 
    def set_properties(self, *,
 
                       created: Optional[datetime.datetime]=None,
 
                       generator: str='conservancy_beancount',
 
    ) -> None:
 
        if created is None:
 
            created = datetime.datetime.now()
 
        created_elem = self.ensure_child(self.document.meta, odf.meta.CreationDate)
 
        created_elem.childNodes.clear()
 
        created_elem.addText(created.isoformat())
 
        generator_elem = self.ensure_child(self.document.meta, odf.meta.Generator)
 
        generator_elem.childNodes.clear()
 
        generator_elem.addText(f'{generator}/{VERSION} {TOOLSVERSION}')
 

	
 
    ### Rows and cells
 

	
 
    def add_row(self, *cells: odf.table.TableCell, **attrs: Any) -> odf.table.TableRow:
 
        row = odf.table.TableRow(**attrs)
 
        for cell in cells:
 
            row.addElement(cell)
 
        self.sheet.addElement(row)
 
        return row
 

	
 
    def balance_cell(self, balance: Balance, **attrs: Any) -> odf.table.TableCell:
 
        balance = balance.clean_copy() or balance
 
        balance_currency_count = len(balance)
tests/test_reports_spreadsheet.py
Show inline comments
...
 
@@ -8,30 +8,32 @@
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU Affero General Public License for more details.
 
#
 
# You should have received a copy of the GNU Affero General Public License
 
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 

	
 
import datetime
 
import io
 
import itertools
 
import re
 

	
 
import pytest
 

	
 
import babel.core
 
import babel.numbers
 
import odf.config
 
import odf.meta
 
import odf.number
 
import odf.style
 
import odf.table
 
import odf.text
 

	
 
from decimal import Decimal
 

	
 
from . import testutil
 

	
 
from conservancy_beancount import rtutil
 
from conservancy_beancount.reports import core
 

	
...
 
@@ -695,12 +697,54 @@ def test_ods_writer_copy_element(ods_writer):
 
    cell.addElement(child1)
 
    cell.addElement(child2)
 
    actual = ods_writer.copy_element(cell)
 
    assert actual is not cell
 
    assert actual.getAttribute('stylename') == 'cellsty'
 
    actual1, actual2 = actual.childNodes
 
    assert actual1 is not child1
 
    assert actual2 is not child2
 
    actual_a, = actual1.childNodes
 
    assert actual_a.getAttribute('href') == 'linkhref'
 
    assert actual_a.text == 'linktext'
 
    assert actual2.text == 'para2'
 

	
 
def test_ods_writer_default_properties(ods_writer):
 
    meta = ods_writer.document.meta
 
    yesterday = datetime.datetime.now() - datetime.timedelta(days=1)
 
    creation_date_elem = get_child(meta, odf.meta.CreationDate)
 
    creation_date = datetime.datetime.strptime(
 
        creation_date_elem.text, '%Y-%m-%dT%H:%M:%S.%f',
 
    )
 
    assert creation_date > yesterday
 
    generator = get_child(meta, odf.meta.Generator)
 
    assert re.match(r'conservancy_beancount/\d+\.\d+', generator.text)
 

	
 
def test_ods_writer_set_properties(ods_writer):
 
    ctime = datetime.datetime(2009, 9, 19, 9, 49, 59)
 
    ods_writer.set_properties(created=ctime, generator='testgen')
 
    meta = ods_writer.document.meta
 
    creation_date_elem = get_child(meta, odf.meta.CreationDate)
 
    assert creation_date_elem.text == ctime.isoformat()
 
    generator = get_child(meta, odf.meta.Generator)
 
    assert re.match(r'testgen/\d+\.\d+', generator.text)
 

	
 
@pytest.mark.parametrize('value,exptype', [
 
    (1, 'float'),
 
    (12.34, 'float'),
 
    (Decimal('5.99'), 'float'),
 
    (datetime.date(2009, 8, 17), 'date'),
 
    (datetime.datetime(2009, 8, 17, 18, 38, 58), 'date'),
 
    (True, 'boolean'),
 
    (False, 'boolean'),
 
    ('foo', None)
 
])
 
def test_ods_writer_set_custom_property(ods_writer, value, exptype):
 
    cprop = ods_writer.set_custom_property('cprop', value)
 
    assert cprop.getAttribute('name') == 'cprop'
 
    assert cprop.getAttribute('valuetype') == exptype
 
    if exptype == 'boolean':
 
        expected = str(value).lower()
 
    elif exptype == 'date':
 
        expected = value.isoformat()
 
    else:
 
        expected = str(value)
 
    assert cprop.text == expected
0 comments (0 inline, 0 general)