[MIG] datetime_formatter: Migration to 13.0
parent
3e73fefc38
commit
8aed91993e
|
@ -6,7 +6,7 @@
|
|||
{
|
||||
"name": "Date & Time Formatter",
|
||||
"summary": "Helper functions to give correct format to date[time] fields",
|
||||
"version": "12.0.1.0.0",
|
||||
"version": "13.0.1.0.0",
|
||||
"category": "Tools",
|
||||
"website": "https://github.com/OCA/server-tools",
|
||||
"author": "Grupo ESOC Ingeniería de Servicios, "
|
||||
|
@ -14,5 +14,5 @@
|
|||
"Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"installable": True,
|
||||
"depends": ["base",],
|
||||
"depends": ["base"],
|
||||
}
|
||||
|
|
|
@ -17,14 +17,11 @@ class ResLang(models.Model):
|
|||
_inherit = "res.lang"
|
||||
|
||||
@api.model
|
||||
@api.returns("self")
|
||||
def best_match(self, lang=None, failure_safe=True):
|
||||
"""Get best match of current default lang.
|
||||
|
||||
:param str lang:
|
||||
If a language in the form of "en_US" is supplied, it will have the
|
||||
highest priority.
|
||||
|
||||
:param bool failure_safe:
|
||||
If ``False`` and the best matched language is not found installed,
|
||||
an exception will be raised. Otherwise, the first installed
|
||||
|
@ -32,26 +29,17 @@ class ResLang(models.Model):
|
|||
"""
|
||||
# Find some installed language, as fallback
|
||||
first_installed = self.search([("active", "=", True)], limit=1)
|
||||
|
||||
if not lang:
|
||||
lang = (
|
||||
# Object's language, if called like
|
||||
# ``record.lang.datetime_formatter(datetime_obj)``
|
||||
(self.ids and self[0].code)
|
||||
or
|
||||
# Context language
|
||||
self.env.context.get("lang")
|
||||
or
|
||||
# User's language
|
||||
self.env.user.lang
|
||||
or
|
||||
# First installed language found
|
||||
first_installed.code
|
||||
or self.env.context.get("lang")
|
||||
or self.env.user.lang
|
||||
or first_installed.code
|
||||
)
|
||||
|
||||
# Get DB lang record
|
||||
record = self.search([("code", "=", lang)])
|
||||
|
||||
try:
|
||||
record.ensure_one()
|
||||
except ValueError:
|
||||
|
@ -59,7 +47,6 @@ class ResLang(models.Model):
|
|||
raise UserError(_("Best matched language (%s) not found.") % lang)
|
||||
else:
|
||||
record = first_installed
|
||||
|
||||
return record
|
||||
|
||||
@api.model
|
||||
|
@ -67,30 +54,24 @@ class ResLang(models.Model):
|
|||
self, value, lang=None, template=MODE_DATETIME, separator=" ", failure_safe=True
|
||||
):
|
||||
"""Convert a datetime field to lang's default format.
|
||||
|
||||
:type value: `str`, `float` or `datetime.datetime`
|
||||
:param value:
|
||||
Datetime that will be formatted to the user's preferred format.
|
||||
|
||||
:param str lang:
|
||||
See :param:`lang` from :meth:`~.best_match`.
|
||||
|
||||
:param bool failure_safe:
|
||||
See :param:`failure_safe` from :meth:`~.best_match`.
|
||||
|
||||
:param str template:
|
||||
Will be used to format :param:`value`. If it is one of the special
|
||||
constants :const:`MODE_DATETIME`, :const:`MODE_DATE` or
|
||||
:const:`MODE_TIME`, it will use the :param:`lang`'s default
|
||||
template for that mode.
|
||||
|
||||
:param str separator:
|
||||
Only used when :param:`template` is :const:`MODE_DATETIME`, as the
|
||||
separator between the date and time parts.
|
||||
"""
|
||||
# Get the correct lang
|
||||
lang = self.best_match(lang)
|
||||
|
||||
# Get the template
|
||||
if template in {MODE_DATETIME, MODE_DATE, MODE_TIME}:
|
||||
defaults = []
|
||||
|
@ -99,7 +80,6 @@ class ResLang(models.Model):
|
|||
if "TIME" in template:
|
||||
defaults.append(lang.time_format or DEFAULT_SERVER_TIME_FORMAT)
|
||||
template = separator.join(defaults)
|
||||
|
||||
# Convert str to datetime objects
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
|
@ -107,14 +87,11 @@ class ResLang(models.Model):
|
|||
except ValueError:
|
||||
# Probably failed due to value being only time
|
||||
value = datetime.strptime(value, DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
||||
# Time-only fields are floats for Odoo
|
||||
elif isinstance(value, float):
|
||||
# Patch values >= 24 hours
|
||||
if value >= 24:
|
||||
template = template.replace("%H", "%d" % value)
|
||||
|
||||
# Convert to time
|
||||
value = (datetime.min + timedelta(hours=value)).time()
|
||||
|
||||
return value.strftime(template)
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
* Jairo Llopis
|
||||
* Vicent Cubells
|
||||
* Ernesto Tejeda
|
||||
* Víctor Martínez
|
||||
|
|
|
@ -8,42 +8,49 @@ from odoo.tests.common import TransactionCase
|
|||
class BasicCase(TransactionCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.langs = ("en_US", "es_ES", "it_IT", "pt_PT", "zh_CN")
|
||||
self.langs = (
|
||||
self.env.ref("base.lang_en"),
|
||||
self.env.ref("base.lang_es"),
|
||||
self.env.ref("base.lang_it"),
|
||||
self.env.ref("base.lang_pt"),
|
||||
self.env.ref("base.lang_zh_CN"),
|
||||
)
|
||||
self.rl = self.env["res.lang"]
|
||||
for lang in self.langs:
|
||||
if not self.rl.search([("code", "=", lang)]):
|
||||
self.rl.load_lang(lang)
|
||||
self.rl.load_lang(lang.code)
|
||||
|
||||
def test_explicit(self):
|
||||
"""When an explicit lang is used."""
|
||||
for lang in self.langs:
|
||||
self.assertEqual(self.rl.best_match(lang).code, lang)
|
||||
self.assertEqual(self.rl.best_match(lang.code).code, lang.code)
|
||||
|
||||
def test_record(self):
|
||||
"""When called from a ``res.lang`` record."""
|
||||
rl = self.rl.with_context(lang="it_IT")
|
||||
rl.env.user.lang = "pt_PT"
|
||||
|
||||
for lang in self.langs:
|
||||
self.assertEqual(rl.search([("code", "=", lang)]).best_match().code, lang)
|
||||
self.assertEqual(
|
||||
rl.search([("code", "=", lang.code)]).best_match().code, lang.code
|
||||
)
|
||||
|
||||
def test_context(self):
|
||||
"""When called with a lang in context."""
|
||||
self.env.user.lang = "pt_PT"
|
||||
|
||||
for lang in self.langs:
|
||||
self.assertEqual(self.rl.with_context(lang=lang).best_match().code, lang)
|
||||
self.assertEqual(
|
||||
self.rl.with_context(lang=lang.code).best_match().code, lang.code
|
||||
)
|
||||
|
||||
def test_user(self):
|
||||
"""When lang not specified in context."""
|
||||
for lang in self.langs:
|
||||
self.env.user.lang = lang
|
||||
|
||||
self.env.user.lang = lang.code
|
||||
# Lang is False in context
|
||||
self.assertEqual(self.rl.with_context(lang=False).best_match().code, lang)
|
||||
|
||||
self.assertEqual(
|
||||
self.rl.with_context(lang=False).best_match().code, lang.code
|
||||
)
|
||||
# Lang not found in context
|
||||
self.assertEqual(self.rl.with_context(dict()).best_match().code, lang)
|
||||
self.assertEqual(self.rl.with_context(dict()).best_match().code, lang.code)
|
||||
|
||||
def test_first_installed(self):
|
||||
"""When falling back to first installed language."""
|
||||
|
@ -56,10 +63,8 @@ class BasicCase(TransactionCase):
|
|||
self.env.user.lang = False
|
||||
self.rl = self.rl.with_context(lang=False)
|
||||
first = self.rl.search([("active", "=", True)], limit=1)
|
||||
|
||||
# Safe mode
|
||||
self.assertEqual(self.rl.best_match("fake_LANG").code, first.code)
|
||||
|
||||
# Unsafe mode
|
||||
with self.assertRaises(UserError):
|
||||
self.rl.best_match("fake_LANG", failure_safe=False)
|
||||
|
|
|
@ -27,12 +27,10 @@ class FormatterCase(TransactionCase):
|
|||
def tearDown(self):
|
||||
# This should be returned
|
||||
self.expected = self.dt.strftime(self.format)
|
||||
|
||||
# Pass a datetime object
|
||||
self.assertEqual(
|
||||
self.expected, self.rl.datetime_formatter(self.dt, **self.kwargs)
|
||||
)
|
||||
|
||||
# When the date comes as a string
|
||||
if isinstance(self.dt, datetime.datetime):
|
||||
self.dt_str = self.dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
@ -40,17 +38,14 @@ class FormatterCase(TransactionCase):
|
|||
self.dt_str = self.dt.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
elif isinstance(self.dt, datetime.time):
|
||||
self.dt_str = self.dt.strftime(DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
||||
# Pass a string
|
||||
self.assertEqual(
|
||||
self.expected, self.rl.datetime_formatter(self.dt_str, **self.kwargs)
|
||||
)
|
||||
|
||||
# Pass a unicode
|
||||
self.assertEqual(
|
||||
self.expected, self.rl.datetime_formatter(str(self.dt_str), **self.kwargs)
|
||||
)
|
||||
|
||||
super().tearDown()
|
||||
|
||||
def test_datetime(self):
|
||||
|
@ -69,14 +64,11 @@ class FormatterCase(TransactionCase):
|
|||
self.format = self.t_fmt
|
||||
self.kwargs = {"template": MODE_TIME}
|
||||
self.dt = self.dt.time()
|
||||
|
||||
# Test float times
|
||||
for n in range(50):
|
||||
n = n + random()
|
||||
|
||||
# Patch values with >= 24 hours
|
||||
fmt = self.format.replace("%H", "%02d" % n)
|
||||
|
||||
time = (datetime.datetime.min + datetime.timedelta(hours=n)).time()
|
||||
self.assertEqual(
|
||||
time.strftime(fmt), self.rl.datetime_formatter(n, **self.kwargs)
|
||||
|
|
Loading…
Reference in New Issue