Projet

Général

Profil

0003-ignore-fields-with-duplicated-varname-26207.patch

Benjamin Dauvergne, 30 septembre 2019 17:53

Télécharger (9,38 ko)

Voir les différences:

Subject: [PATCH 3/3] ignore fields with duplicated varname (#26207)

 tests/conftest.py  |  5 ++-
 tests/olap.model   | 10 +++--
 tests/test_wcs.py  |  2 +-
 wcs_olap/feeder.py | 95 +++++++++++++++++++++++++++++-----------------
 4 files changed, 72 insertions(+), 40 deletions(-)
tests/conftest.py
14 14

  
15 15
import utils
16 16

  
17

  
18 17
Wcs = namedtuple('Wcs', ['url', 'appdir', 'pid'])
19 18

  
20 19

  
......
101 100
                     items=['foo', 'bar', 'baz'], varname='item'),
102 101
    fields.BoolField(id='3', label='3rd field', type='bool', varname='bool'),
103 102
    fields.ItemField(id='4', label='4rth field', type='item', varname='itemOpen'),
104
    fields.StringField(id='5', label='5th field', type='string', anonymise=False, varname='stringCaseSensitiveé'),
103
    fields.StringField(id='5', label='5th field', type='string', anonymise=False, varname='stringCaseSensitive-é'),
104
    fields.BoolField(id='6', label='6th field duplicate', type='bool', varname='duplicate'),
105
    fields.StringField(id='7', label='7th field duplicate', type='string', anonymise=False, varname='duplicate'),
105 106
]
106 107
formdef.store()
107 108

  
tests/olap.model
279 279
            {
280 280
               "filter": true,
281 281
               "label": "5th field",
282
               "name": "stringCaseSensitiveé",
282
               "name": "stringCaseSensitive-é",
283 283
               "type": "string",
284
               "value": "\"field_stringCaseSensitiveé\""
284
               "value": "\"field_stringCaseSensitive-é\""
285 285
            }
286 286
         ],
287 287
         "fact_table" : "\"formdata_demande\"",
......
395 395
               "type" : "point"
396 396
            }
397 397
         ],
398
         "name" : "formdata_demande"
398
         "name" : "formdata_demande",
399
         "warnings": [
400
            "duplicate column « 6th field duplicate » with varname « duplicate »",
401
            "duplicate column « 7th field duplicate » with varname « duplicate »"
402
         ]
399 403
      }
400 404
   ],
401 405
   "label" : "olap",
tests/test_wcs.py
60 60
        ('formdata_demande', 'field_item'),
61 61
        ('formdata_demande', 'field_bool'),
62 62
        ('formdata_demande', 'field_itemOpen'),
63
        ('formdata_demande', 'field_stringCaseSensitive\xe9'),
63
        ('formdata_demande', 'field_stringCaseSensitive-\xe9'),
64 64
        ('formdata_demande', 'function__receiver'),
65 65
        ('formdata_demande_field_item', 'id'),
66 66
        ('formdata_demande_field_item', 'label'),
wcs_olap/feeder.py
2 2

  
3 3
from __future__ import unicode_literals
4 4

  
5
from collections import OrderedDict, Counter
5 6
import datetime
6 7
import six
7 8
import copy
......
610 611
                      self.formdef.schema.name])
611 612
        self.formdef_sql_id = self.cur.fetchone()[0]
612 613

  
613
        columns = [['status_id', 'smallint REFERENCES {status_table} (id)']]
614

  
615
        comments = {}
616

  
617
        # compute list of fields
618
        fields = self.formdef.schema.fields
619
        if self.formdef.schema.workflow:
620
            fields += self.formdef.schema.workflow.fields
614
        columns = OrderedDict()
615
        columns['status_id'] = {'sql_col_name': 'status_id', 'sql_col_def': 'smallint REFERENCES {status_table} (id)'}
621 616

  
622 617
        # add item fields
623
        already_seen_varnames = set()
624
        for field in fields:
625
            if field.anonymise is True:
626
                continue
627
            if not field.varname or '-' in field.varname:
628
                continue
629
            if field.varname in already_seen_varnames:
630
                continue
631
            already_seen_varnames.add(field.varname)
618
        for field in self.good_fields.values():
632 619
            if field.type == 'item':
633 620
                comment = ('valeurs du champ « %s » du formulaire %s'
634 621
                           % (field.label, self.formdef.schema.name))
......
647 634
                field_def = 'varchar'
648 635
            else:
649 636
                continue
650
            self.fields.append(field)
651
            at = 'field_%s' % field.varname
652
            columns.append([at, field_def])
653
            comments[at] = field.label
637
            columns[field.varname] = {
638
                'field': field,
639
                'sql_col_name': 'field_%s' % field.varname,
640
                'sql_col_def': field_def,
641
                'sql_comment': field.label,
642
            }
643

  
644
        # keep loaded fields around
645
        for key in columns:
646
            if columns[key].get('field') is not None:
647
                self.fields.append(columns[key].get('field'))
654 648

  
655 649
        # add geolocation fields
656 650
        for geolocation, label in self.formdef.schema.geolocations:
657 651
            at = 'geolocation_%s' % geolocation
658
            columns.append([at, 'point'])
659
            comments[at] = label
652
            columns[at] = {
653
                'sql_col_name': at,
654
                'sql_col_def': 'point',
655
                'comment': 'géoloc « %s »' % label,
656
            }
660 657

  
661 658
        # add function fields
662 659
        for function, name in self.formdef.schema.workflow.functions.iteritems():
663 660
            at = 'function_%s' % slugify(function)
664
            columns.append([at, 'smallint REFERENCES {role_table} (id)'])
665
            comments[at] = 'fonction « %s »' % name
661
            columns[at] = {
662
                'sql_col_name': at,
663
                'sql_col_def': 'smallint REFERENCES {role_table} (id)',
664
                'comment': 'fonction « %s »' % name,
665
            }
666 666

  
667
        self.columns = ([name for name, _type in self.olap_feeder.columns] + [
668
            name for name, _type in columns])
667
        self.columns = [name for name, _type in self.olap_feeder.columns]
668
        for key in columns:
669
            self.columns.append(columns[key]['sql_col_name'])
669 670
        self.columns.remove('geolocation_base')
670 671

  
671
        self.create_table(self.table_name, columns, inherits='{generic_formdata_table}',
672
        self.create_table(self.table_name,
673
                          [(columns[key]['sql_col_name'], columns[key]['sql_col_def']) for key in columns],
674
                          inherits='{generic_formdata_table}',
672 675
                          comment='formulaire %s' % self.formdef.schema.name)
673
        for at, comment in comments.iteritems():
674
            self.ex('COMMENT ON COLUMN {formdata_table}.%s IS %%s' % quote(at), vars=(comment,))
676
        for key in columns:
677
            column = columns[key]
678
            if column.get('sql_comment'):
679
                self.ex('COMMENT ON COLUMN {formdata_table}.%s IS %%s' % quote(column['sql_col_name']),
680
                        vars=(column['sql_comment'],))
675 681

  
676 682
        # Creat index for JSON fields
677 683
        if self.has_jsonb:
678
            for field in fields:
679
                if field.varname and '-' not in field.varname:
680
                    self.create_formdata_json_index(self.table_name, field.varname)
684
            for varname in self.good_fields:
685
                self.create_formdata_json_index(self.table_name, varname)
681 686

  
682 687
        # PostgreSQL does not propagate foreign key constraints to child tables
683 688
        # so we must recreate them manually
......
900 905

  
901 906
        # create cube
902 907
        cube = self.cube = copy.deepcopy(self.base_cube)
908

  
909
        def add_warning(message):
910
            self.logger.warning('%s', message)
911
            cube.setdefault('warnings', []).append(message)
912

  
903 913
        # remove json field from formdef cubes
904 914
        cube.pop('json_field', None)
905 915
        cube.update({
......
950 960
        fields = self.formdef.schema.fields
951 961
        if self.formdef.schema.workflow:
952 962
            fields += self.formdef.schema.workflow.fields
963

  
964
        # filter duplicates
965
        duplicate_varnames = set()
966
        self.good_fields = good_fields = OrderedDict()
953 967
        for field in fields:
968
            if field.type not in ('item', 'bool', 'string'):
969
                continue
954 970
            if field.anonymise is True:
955 971
                continue
956 972
            if not field.varname:
973
                add_warning('field « %s » has no varname, ignored' % field.label)
957 974
                continue
958
            if '-' in field.varname:
975
            if field.varname in good_fields:
976
                # duplicate found
977
                duplicate_varnames.add(field.varname)
978
                add_warning('duplicate column « %s » with varname « %s »' % (
979
                    good_fields[field.varname].label, field.varname))
980
                del self.good_fields[field.varname]
981
            if field.varname in duplicate_varnames:
982
                add_warning('duplicate column « %s » with varname « %s »' % (field.label, field.varname))
959 983
                continue
984
            self.good_fields[field.varname] = field
985

  
986
        for field in good_fields.values():
960 987
            join = None
961 988

  
962 989
            if field.type == 'item':
963
-