[FIX] base: avoid KeyError in res_partner._display_address

In some case, users use custom `address_format` with keys that do not
exists. This lead to errors in odoo and upgrade process. Avoid
`KeyError` by using defaultdict with `str` value.

upg-361146
upg-361241

```
Traceback (most recent call last):
  File "/home/odoo/src/odoo/14.0/odoo/service/server.py", line 1201, in preload_registries
    registry = Registry.new(dbname, update_module=update_module)
  File "/home/odoo/src/odoo/14.0/odoo/modules/registry.py", line 89, in new
    odoo.modules.load_modules(registry._db, force_demo, status, update_module)
  File "/home/odoo/src/odoo/14.0/odoo/modules/loading.py", line 457, in load_modules
    force, status, report, loaded_modules, update_module, models_to_check)
  File "/home/odoo/src/odoo/14.0/odoo/modules/loading.py", line 349, in load_marked_modules
    perform_checks=perform_checks, models_to_check=models_to_check
  File "/home/odoo/src/odoo/14.0/odoo/modules/loading.py", line 227, in load_module_graph
    migrations.migrate_module(package, 'post')
  File "/home/odoo/src/odoo/14.0/odoo/modules/migration.py", line 180, in migrate_module
    migrate(self.cr, installed_version)
  File "/tmp/tmp1bew9m7l/migrations/website/14.0.1.0/post-adapt-footer-data.py", line 69, in migrate
    address = html_escape(partner._display_address(without_company=True))
  File "/home/odoo/src/odoo/14.0/odoo/addons/base/models/res_partner.py", line 950, in _display_address
    return address_format % args
KeyError: 'town_name'
```

closes odoo/odoo#96703

X-original-commit: 81bf1d2101202a4a6cb832004500129905c2d3be
Signed-off-by: Christophe Simonis <chs@odoo.com>
This commit is contained in:
arg-odoo
2022-07-27 14:04:40 +02:00
committed by Christophe Simonis
parent 170aa05182
commit ef5a9612f7
2 changed files with 22 additions and 2 deletions
+3 -2
View File
@@ -10,6 +10,7 @@ import threading
import re
import requests
from collections import defaultdict
from lxml import etree
from random import randint
from werkzeug import urls
@@ -967,13 +968,13 @@ class Partner(models.Model):
# get the information that will be injected into the display format
# get the address format
address_format = self._get_address_format()
args = {
args = defaultdict(str, {
'state_code': self.state_id.code or '',
'state_name': self.state_id.name or '',
'country_code': self.country_id.code or '',
'country_name': self._get_country_name(),
'company_name': self.commercial_company_name or '',
}
})
for field in self._formatting_address_fields():
args[field] = getattr(self, field) or ''
if without_company:
@@ -182,3 +182,22 @@ class TestPartner(TransactionCase):
partner_form.company_type = 'person'
partner_form.name = 'Philip'
self.assertEqual(partner_form.user_id, test_parent_partner.user_id)
def test_display_address_missing_key(self):
""" Check _display_address when some keys are missing. As a defaultdict is used, missing keys should be
filled with empty strings. """
country = self.env["res.country"].create({"name": "TestCountry", "address_format": "%(city)s %(zip)s"})
partner = self.env["res.partner"].create({
"name": "TestPartner",
"country_id": country.id,
"city": "TestCity",
"zip": "12345",
})
before = partner._display_address()
# Manually update the country address_format because placeholders are checked by create
self.env.cr.execute(
"UPDATE res_country SET address_format ='%%(city)s %%(zip)s %%(nothing)s' WHERE id=%s",
[country.id]
)
self.env["res.country"].invalidate_model()
self.assertEqual(before, partner._display_address().strip())