diff options
-rw-r--r-- | archaeological_files/data_importer.py | 44 | ||||
-rw-r--r-- | archaeological_operations/management/commands/ishtar_imports.py (renamed from archaeological_operations/management/commands/import_operations.py) | 6 | ||||
-rw-r--r-- | ishtar_common/data_importer.py | 85 |
3 files changed, 97 insertions, 38 deletions
diff --git a/archaeological_files/data_importer.py b/archaeological_files/data_importer.py index ae0cf340c..f60e0f5d1 100644 --- a/archaeological_files/data_importer.py +++ b/archaeological_files/data_importer.py @@ -42,6 +42,7 @@ class ImportClosingFormater(ImportFormater): obj.save() class FileImporterSraPdL(Importer): + DESC = u"Exports dossiers SRA PdL : importeur Filemaker dossiers" LINE_FORMAT = [] OBJECT_CLS = models.File DEFAULTS = {('responsible_town_planning_service', 'attached_to'):{ @@ -62,13 +63,13 @@ class FileImporterSraPdL(Importer): tf.town_dct_init() self.line_format = [ None, # A, 1 - ImportFormater(['address', 'postal_code', ['towns', 'parcels__town']], # B, 2 + ImportFormater(['address', 'postal_code', ['main_town', 'parcels__town']], # B, 2 [UnicodeFormater(500, clean=True), UnicodeFormater(5, re_filter=RE_CD_POSTAL_FILTER), tf], regexp=RE_ADD_CD_POSTAL_TOWN, regexp_formater_args=[[0], [1], [2, 1]], required=False, - comment="Dossier - adresse"), + comment=u"Dossier - adresse"), ImportFormater('general_contractor__raw_name', # C, 3 TODO - extraire nom_prenom_titre UnicodeFormater(200), comment=u"Aménageur - nom brut", @@ -83,11 +84,11 @@ class FileImporterSraPdL(Importer): town_dct=tf._town_dct)], regexp=RE_ADD_CD_POSTAL_TOWN, regexp_formater_args=[[0], [1], [2, 1]], required=False, - comment="Aménageur - adresse"), + comment=u"Aménageur - adresse"), ImportFormater("general_contractor__title", # E, 5 StrChoiceFormater(Person.TYPE, cli=True), required=False, - comment="Aménageur - titre"), + comment=u"Aménageur - titre"), None, # F, 6 None, # G, 7 None, # H, 8 @@ -96,19 +97,20 @@ class FileImporterSraPdL(Importer): required=False), ImportParcelFormater('', required=False, post_processing=True), # J, 10 None, # K, 11 - ImportFormater([['towns', 'parcels__town']], # L, 12 + ImportFormater([['main_town', 'parcels__town']], # L, 12 tf, required=False, - comment="Commune (si non définie avant)"), - ImportFormater([['towns', 'parcels__town']], # M, 13 + comment=u"Commune (si non définie avant)"), + ImportFormater([['main_town', 'parcels__town']], # M, 13 tf, required=False, - comment="Commune (si non définie avant)"), + comment=u"Commune (si non définie avant)"), ImportFormater('saisine_type', # N, 14 - StrChoiceFormater(models.SaisineType.get_types(), - model=models.SaisineType, cli=True), + StrChoiceFormater(models.SaisineType.get_types( + empty_first=False), + model=models.SaisineType, cli=True), required=False, - comment="Type de saisine"), + comment=u"Type de saisine"), None, # O, 15 ImportFormater('comment', # P, 16 UnicodeFormater(2000), @@ -127,7 +129,7 @@ class FileImporterSraPdL(Importer): town_dct=tf._town_dct)], regexp=RE_NAME_ADD_CD_POSTAL_TOWN, regexp_formater_args=[[0], [1], [2], [3, 2]], - comment="Aménageur - adresse", + comment=u"Aménageur - adresse", required=False), ImportFormater('comment', # S, 19 UnicodeFormater(2000), @@ -182,7 +184,7 @@ class FileImporterSraPdL(Importer): ImportFormater('permit_reference', # AW, 49 UnicodeFormater(300, clean=True), regexp=RE_PERMIT_REFERENCE, - comment="Réf. du permis de construire", + comment=u"Réf. du permis de construire", required=False), None, # AX, 50 None, # AY, 51 @@ -191,10 +193,10 @@ class FileImporterSraPdL(Importer): None, # BB, 54 None, # BC, 55 None, # BD, 56 - ImportFormater([['towns', 'parcels__town']], # BE, 57 + ImportFormater([['main_town', 'parcels__town']], # BE, 57 TownINSEEFormater(), required=False, - comment="Commune (si non définie avant)"), + comment=u"Commune (si non définie avant)"), ImportFormater('comment', # BF, 58 UnicodeFormater(2000), comment=u"Commentaire", @@ -216,11 +218,12 @@ class FileImporterSraPdL(Importer): 'responsible_town_planning_service__attached_to__name', # BT, 72 service instructeur UnicodeFormater(300, clean=True), regexp=RE_ORGA, - comment="Service instructeur - nom", + comment=u"Service instructeur - nom", required=False), None, # BU, 73 ImportClosingFormater('', StrToBoolean(cli=True), - post_processing=True, required=False), # BV, 74, end date + post_processing=True, required=False, + comment=u'Dossier clos'), # BV, 74, end date ImportClosingFormater('in_charge__raw_name', # BW, 75 responsable UnicodeFormater(200), comment=u"Responsable - nom brut", @@ -241,10 +244,11 @@ class FileImporterSraPdL(Importer): None, # CE, 83 None, # CF, 84 ImportFormater('permit_type', - StrChoiceFormater(models.PermitType.get_types(), - model=models.PermitType, cli=True), + StrChoiceFormater(models.PermitType.get_types( + empty_first=False), + model=models.PermitType, cli=True), required=False, - comment="Type de permis"), # CG, 85 + comment=u"Type de permis"), # CG, 85 None, # CH, 85 ] diff --git a/archaeological_operations/management/commands/import_operations.py b/archaeological_operations/management/commands/ishtar_imports.py index 09bfe23b6..23397204b 100644 --- a/archaeological_operations/management/commands/import_operations.py +++ b/archaeological_operations/management/commands/ishtar_imports.py @@ -31,6 +31,12 @@ IMPORTERS = { } try: + from archaeological_files.data_importer import * + IMPORTERS['sra-pdl-files'] = FileImporterSraPdL +except ImportError: + pass + +try: from archaeological_context_records.data_importer import * IMPORTERS['bibracte-ue'] = ContextRecordsImporterBibracte IMPORTERS['bibracte-ue-rel'] = ContextRecordsRelationImporterBibracte diff --git a/ishtar_common/data_importer.py b/ishtar_common/data_importer.py index 2963fa680..3db03d916 100644 --- a/ishtar_common/data_importer.py +++ b/ishtar_common/data_importer.py @@ -70,7 +70,7 @@ class ImportFormater(object): lst = [self.formater] for formater in lst: if formater: - formater.check(vals, output) + formater.check(vals, output, self.comment) def post_process(self, obj, context, value, owner=None): raise NotImplemented() @@ -92,9 +92,19 @@ class Formater(object): def format(self, value): return value - def check(self, values, output=None): + def check(self, values, output=None, comment=''): return +class ChoiceChecker(object): + def report_new(self, comment): + if not self.new_keys: + return + msg = u"For \"%s\" these new associations have been made:\n" % comment + sys.stderr.write(msg.encode('utf-8')) + for k in self.new_keys: + msg = u'"%s";"%s"\n' % (k, self.new_keys[k]) + sys.stderr.write(msg.encode('utf-8')) + class UnicodeFormater(Formater): def __init__(self, max_length, clean=False, re_filter=None, notnull=False, db_target=None): @@ -183,7 +193,7 @@ class IntegerFormater(Formater): raise ValueError(_(u"\"%(value)s\" is not an integer") % { 'value':value}) -class StrChoiceFormater(Formater): +class StrChoiceFormater(Formater, ChoiceChecker): def __init__(self, choices, strict=False, equiv_dict={}, model=None, cli=False, many_split='', db_target=None): self.choices = list(choices) @@ -194,6 +204,7 @@ class StrChoiceFormater(Formater): self.db_target = db_target self.create = False self.missings = set() + self.new_keys = {} self.many_split = many_split for key, value in self.choices: value = unicode(value) @@ -219,8 +230,9 @@ class StrChoiceFormater(Formater): def prepare(self, value): return unicode(value).strip() - def _get_choices(self): - msgstr = unicode(_(u"Choice for \"%s\" is not available. "\ + def _get_choices(self, comment=''): + msgstr = comment + u" - " + msgstr += unicode(_(u"Choice for \"%s\" is not available. "\ u"Which one is relevant?\n")) idx = -1 for idx, choice in enumerate(self.choices): @@ -233,7 +245,7 @@ class StrChoiceFormater(Formater): msgstr += unicode(_(u"%d. None of the above - skip")) % idx + u"\n" return msgstr, idx - def check(self, values, output=None): + def check(self, values, output=None, comment=''): if not output or output == 'silent': return if self.many_split: @@ -250,11 +262,13 @@ class StrChoiceFormater(Formater): if output != 'cli': self.missings.add(value) continue - msgstr, idx = self._get_choices() + msgstr, idx = self._get_choices(comment) res = None while res not in range(1, idx+1): - sys.stdout.write(msgstr % value) - res = raw_input(">>> ") + msg = msgstr % value + sys.stdout.write(msg.encode('utf-8')) + sys.stdout.write("\n>>> ") + res = raw_input() try: res = int(res) except ValueError: @@ -266,10 +280,12 @@ class StrChoiceFormater(Formater): v = self.model.objects.get(pk=v) self.equiv_dict[value] = v self.add_key(v, value) + self.new_keys[value] = v elif self.create and res == len(self.choices): self.equiv_dict[value] = self.new(base_value) self.choices.append((self.equiv_dict[value].pk, unicode(self.equiv_dict[value]))) + self.new_keys[value] = unicode(self.equiv_dict[value]) else: self.equiv_dict[value] = None if output == 'db' and self.db_target: @@ -283,6 +299,8 @@ class StrChoiceFormater(Formater): TargetKey.objects.create(**q) except IntegrityError: pass + if output == 'cli': + self.report_new(comment) def new(self, value): return @@ -346,7 +364,7 @@ class DateFormater(Formater): raise ValueError(_(u"\"%(value)s\" is not a valid date") % { 'value':value}) -class StrToBoolean(Formater): +class StrToBoolean(Formater, ChoiceChecker): def __init__(self, choices={}, cli=False, strict=False, db_target=None): self.dct = copy.copy(choices) self.cli = cli @@ -367,6 +385,7 @@ class StrToBoolean(Formater): else: v = None self.dct[value] = v + self.new_keys = {} def prepare(self, value): value = unicode(value).strip() @@ -374,10 +393,11 @@ class StrToBoolean(Formater): value = slugify(value) return value - def check(self, values, output=None): + def check(self, values, output=None, comment=''): if not output or output == 'silent': return - msgstr = unicode(_(u"Choice for \"%s\" is not available. "\ + msgstr = comment + u" - " + msgstr += unicode(_(u"Choice for \"%s\" is not available. "\ u"Which one is relevant?\n")) msgstr += u"1. True\n" msgstr += u"2. False\n" @@ -391,8 +411,10 @@ class StrToBoolean(Formater): continue res = None while res not in range(1, 4): - sys.stdout.write(msgstr % value) - res = raw_input(">>> ") + msg = msgstr % value + sys.stdout.write(msg.encode('utf-8')) + sys.stdout.write("\n>>> ") + res = raw_input() try: res = int(res) except ValueError: @@ -411,6 +433,9 @@ class StrToBoolean(Formater): models.TargetKey.objects.create(**q) except IntegrityError: pass + self.new_keys[value] = unicode(self.dct[value]) + if output == 'cli': + self.report_new(comment) def format(self, value): value = self.prepare(value) @@ -461,6 +486,8 @@ class Importer(object): self._defaults = self.DEFAULTS.copy() self.history_modifier = history_modifier self.output = output + self.result = [] + self.result_cols = [] if not self.history_modifier: if self.import_instance: self.history_modifier = self.import_instance.user @@ -560,16 +587,25 @@ class Importer(object): time_by_item = ellapsed/idx_line if time_by_item: left = ((total - idx_line)*time_by_item).seconds - txt = "\r* %d/%d" % (idx_line+1, total) + txt = u"\r* %d/%d" % (idx_line+1, total) if left: - txt += " (%d seconds left)" % left - sys.stdout.write(txt) + txt += u" (%d seconds left)" % left + sys.stdout.write(txt.encode('utf-8')) sys.stdout.flush() try: self._line_processing(idx_line, line) except ImporterError, msg: self.errors.append((idx_line, None, msg)) + report_name = 'report-%s.csv' % datetime.datetime.now().isoformat() + with open(report_name, 'w') as validity_file: + self.validity_file = UnicodeWriter(validity_file, + delimiter=',', quotechar='"', + quoting=csv.QUOTE_MINIMAL) + self.validity_file.writerow(self.result_cols) + for line in self.result: + self.validity_file.writerow(line) + def _line_processing(self, idx_line, line): if self.skip_lines > idx_line: self.validity.append(line) @@ -669,6 +705,19 @@ class Importer(object): for formater, val in self._post_processing: formater.post_process(obj, data, val, owner=self.history_modifier) + # writing report + self.result.append([]) + for k in data.keys(): + if k not in self.result_cols: + self.result_cols.append(k) + for k in self.result_cols: + if hasattr(obj, k): + self.result[-1].append(unicode(getattr(obj, k))) + elif k not in data or not data[k]: + self.result[-1].append('') + else: + self.result[-1].append(unicode(data[k])) + def _row_processing(self, c_row, idx_col, idx_line, val, data): if idx_col >= len(self.line_format): return @@ -827,7 +876,7 @@ class Importer(object): obj.imports.add(self.import_instance) except IntegrityError as e: raise IntegrityError(e.message) - except: + except cls.MultipleObjectsReturned: created = False obj = cls.objects.filter(**create_dict).all()[0] for attr, value in m2ms: |