[FIX] addons: browse the leftovers by integer, not by the string psql gave
Deleting the leftovers failed on « the database search does not have the
ids (('4457',)) and has extra ids ((4457,)) ». psql returns text; the ids
went into browse() as strings, Odoo compared them against integers, found
nothing and refused the whole batch.
Nothing was lost: the backup runs before the deletion, and the tool said
plainly that nothing was removed. Measured after the fact — 15 files
saved, 15 attachments still in database.
--- FR ---
[FIX] addons : parcourir les restes par entier, pas par la chaîne de psql
L'effacement échouait sur « la recherche en base n'a pas les identifiants
(('4457',)) et a des identifiants supplémentaires ((4457,)) ». psql rend
du texte ; les identifiants partaient dans browse() en chaînes, Odoo les
comparait à des entiers, ne trouvait rien et refusait tout le lot.
Rien n'a été perdu : la sauvegarde précède l'effacement, et l'outil a dit
franchement que rien n'avait été retiré. Vérifié après coup — 15 fichiers
sauvegardés, 15 pièces jointes toujours en base.
Assisted-by: Claude Opus 5
This commit is contained in:
parent
1c0635831f
commit
e75ab8b128
2 changed files with 43 additions and 1 deletions
|
|
@ -181,7 +181,11 @@ def delete_attachments(database, lst_row, config_path="./config.conf"):
|
|||
Un DELETE en SQL laisserait les fichiers orphelins et les caches
|
||||
incohérents ; unlink() fait le ménage complet, dans toutes les versions.
|
||||
"""
|
||||
lst_id = [row.split("|")[0] for row in lst_row]
|
||||
# int(), pas la chaîne du psql : browse(['4457']) fait échouer Odoo sur
|
||||
# « n'a pas les identifiants (('4457',)) et a des identifiants
|
||||
# supplémentaires ((4457,)) » — il compare des chaînes à des entiers.
|
||||
# Mesuré sur une vraie base, l'effacement n'a rien retiré.
|
||||
lst_id = [int(row.split("|")[0]) for row in lst_row]
|
||||
script = (
|
||||
f"env['ir.attachment'].browse({lst_id!r}).unlink()\n"
|
||||
"env.cr.commit()\n"
|
||||
|
|
|
|||
|
|
@ -376,6 +376,44 @@ class TestTheQuestionMustBeVisible(unittest.TestCase):
|
|||
self.assertIn("sys.stdout.isatty()", source)
|
||||
|
||||
|
||||
class TestTheIdentifiersSentToOdoo(unittest.TestCase):
|
||||
"""browse() veut des ENTIERS ; psql rend des chaînes.
|
||||
|
||||
Mesuré sur une vraie base : browse(['4457']) fait échouer Odoo sur
|
||||
« la recherche en base n'a pas les identifiants (('4457',)) et a des
|
||||
identifiants supplémentaires ((4457,)) ». Il compare des chaînes à des
|
||||
entiers, ne retrouve rien, et refuse. L'effacement n'a rien retiré —
|
||||
heureusement, la sauvegarde était déjà faite.
|
||||
"""
|
||||
|
||||
def test_the_script_browses_integers(self):
|
||||
import inspect
|
||||
|
||||
source = inspect.getsource(theme_leftover.delete_attachments)
|
||||
self.assertIn("int(row.split", source)
|
||||
|
||||
def test_the_pushed_script_carries_no_quoted_id(self):
|
||||
# Le rendu exact de ce qui part dans le shell : une seule apostrophe
|
||||
# autour d'un identifiant et Odoo refuse tout le lot.
|
||||
pushed = {}
|
||||
original = theme_leftover.subprocess.run
|
||||
theme_leftover.subprocess.run = (
|
||||
lambda *a, **kw: pushed.update(script=kw.get("input", ""))
|
||||
or type("R", (), {"returncode": 0, "stdout": "", "stderr": ""})()
|
||||
)
|
||||
self.addCleanup(setattr, theme_leftover.subprocess, "run", original)
|
||||
theme_leftover.delete_attachments(
|
||||
"db", ["4457|/theme_x/a.scss|2021-03-04", "4768|/b.css|d"]
|
||||
)
|
||||
self.assertIn("browse([4457, 4768])", pushed["script"])
|
||||
self.assertNotIn("'4457'", pushed["script"])
|
||||
|
||||
def test_a_non_numeric_row_is_not_sent_silently(self):
|
||||
# Mieux vaut échouer ici que pousser un script qu'Odoo refusera.
|
||||
with self.assertRaises(ValueError):
|
||||
theme_leftover.delete_attachments("db", ["zz|/a|d"])
|
||||
|
||||
|
||||
class TestTheMisleadingErrorCode(unittest.TestCase):
|
||||
"""« 1 » veut dire « il reste des choses », pas « ça a raté »."""
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue