Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions trytond/trytond/tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import doctest
import sys
import unittest
from unittest.mock import Mock
from io import BytesIO

import sql
Expand Down Expand Up @@ -469,6 +470,25 @@ def test_get_server_zoneinfo(self):
now = dt.datetime(2022, 5, 17, tzinfo=zi)
self.assertEqual(str(now), "2022-05-17 00:00:00+00:00")

def test_lazy_evaluation(self):
"Test that StringPartitioned doesn't evaluate its argument on __init__"
getter = Mock()
getter.side_effect = lambda s: s
ls = LazyString(getter, 'foo')

s = StringPartitioned(ls)
getter.assert_not_called()

str(s)
getter.assert_called_once()

getter.reset_mock()
s = StringPartitioned(s)
getter.assert_not_called()

str(s)
getter.assert_called_once()


class ImmutableDictTestCase(unittest.TestCase):
"Test ImmutableDict"
Expand Down
14 changes: 14 additions & 0 deletions trytond/trytond/tools/string_.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ class StringPartitioned(str):
"A string subclass that stores parts that composes itself."
__slots__ = ('_parts',)

def __new__(cls, base):
if isinstance(base, (LazyString, StringPartitioned)):
return super().__new__(cls)
return super().__new__(cls, base)

def __init__(self, base):
super().__init__()
if isinstance(base, StringPartitioned):
Expand All @@ -106,6 +111,15 @@ def __radd__(self, other):
new._parts = (other,) + self._parts
return new

def __eq__(self, other):
return str(self) == str(other)

def __bool__(self):
return bool(self._parts)

def __str__(self):
return ''.join(str(p) for p in self._parts)


class LazyString():
def __init__(self, func, *args, **kwargs):
Expand Down