changeset d27b905106dd in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset;node=d27b905106dd
description:
        Add validate option to trytond-admin

        It validates a percentage of the listed models or all and report the 
errors.

        issue9782
        review312751002
diffstat:

 CHANGELOG              |   1 +
 trytond/admin.py       |  39 +++++++++++++++++++++++++++++++++++++++
 trytond/commandline.py |   5 +++++
 3 files changed, 45 insertions(+), 0 deletions(-)

diffs (76 lines):

diff -r 32cd371b3e9c -r d27b905106dd CHANGELOG
--- a/CHANGELOG Wed Jan 20 00:52:07 2021 +0100
+++ b/CHANGELOG Mon Jan 25 22:56:02 2021 +0100
@@ -1,3 +1,4 @@
+* Add validate option to trytond-admin
 * Refresh pool of other processes
 * Add clear_all method to Cache
 * Support Genshi element directives in HTML editor
diff -r 32cd371b3e9c -r d27b905106dd trytond/admin.py
--- a/trytond/admin.py  Wed Jan 20 00:52:07 2021 +0100
+++ b/trytond/admin.py  Mon Jan 25 22:56:02 2021 +0100
@@ -3,6 +3,7 @@
 import sys
 import os
 import logging
+import random
 from getpass import getpass
 
 from sql import Table, Literal
@@ -119,3 +120,41 @@
             if options.hostname is not None:
                 configuration.hostname = options.hostname or None
             configuration.save()
+        with Transaction().start(db_name, 0, readonly=True):
+            if options.validate is not None:
+                validate(options.validate, options.validate_percentage)
+
+
+def validate(models, percentage=100):
+    from trytond.model import ModelStorage, ModelSingleton
+    from trytond.model.exceptions import ValidationError
+    logger = logging.getLogger('validate')
+    pool = Pool()
+    if not models:
+        models = sorted([n for n, _ in pool.iterobject()])
+    ratio = min(100, percentage) / 100
+    in_max = Transaction().database.IN_MAX
+    for name in models:
+        logger.info("validate: %s", name)
+        Model = pool.get(name)
+        if not issubclass(Model, ModelStorage):
+            continue
+        offset = 0
+        limit = in_max
+        while True:
+            records = Model.search(
+                [], order=[('id', 'ASC')], offset=offset, limit=limit)
+            if not records:
+                break
+            records = Model.browse(
+                random.sample(records, int(len(records) * ratio)))
+            for record in records:
+                try:
+                    Model._validate([record])
+                except ValidationError as exception:
+                    logger.error("%s: KO '%s'", record, exception)
+                else:
+                    logger.info("%s: OK", record)
+            if issubclass(Model, ModelSingleton):
+                break
+            offset += limit
diff -r 32cd371b3e9c -r d27b905106dd trytond/commandline.py
--- a/trytond/commandline.py    Wed Jan 20 00:52:07 2021 +0100
+++ b/trytond/commandline.py    Mon Jan 25 22:56:02 2021 +0100
@@ -90,6 +90,11 @@
         default=[], metavar='CODE', help="Load language translations")
     parser.add_argument("--hostname", dest="hostname", default=None,
         help="Limit database listing to the hostname")
+    parser.add_argument("--validate", dest="validate", nargs='*',
+        metavar='MODEL', help="validate records of models")
+    parser.add_argument("--validate-percentage", dest="validate_percentage",
+        type=float, default=100, metavar="PERCENTAGE",
+        help="percentage of records to validate (default: 100)")
 
     parser.epilog = ('The first time a database is initialized '
         'or when the password is set, the admin password is read '

Reply via email to