[ccplugin] Add proper option handling à la CWCTL. Add CSV uuid read option
authorVladimir Popescu <vladimir.popescu@logilab.fr>
Fri, 05 Jul 2013 11:40:52 +0200
changeset 190 aac836fcd93d
parent 189 36b1978f95bc
child 191 9ed3f8fa6af7
[ccplugin] Add proper option handling à la CWCTL. Add CSV uuid read option
ccplugin.py
test/unittest_remake-uuid.py
--- a/ccplugin.py	Wed Jul 03 19:26:09 2013 +0200
+++ b/ccplugin.py	Fri Jul 05 11:40:52 2013 +0200
@@ -4,14 +4,14 @@
 from os import path as osp
 import shutil
 import logging
-
+import csv 
 from cubicweb import AuthenticationError
 from cubicweb import cwconfig
 from cubicweb.utils import make_uid
 from cubicweb.server.utils import manager_userpasswd
 from cubicweb.dbapi import in_memory_repo_cnx
 from cubicweb.toolsutils import Command
-from cubicweb.cwctl import CWCTL
+from cubicweb.cwctl import CWCTL, check_options_consistency
 
 
 def copy_file(old_fpath, new_fpath, logger=None):
@@ -59,6 +59,20 @@
         session.execute('SET X filepath %(i)s WHERE X eid %(e)s', {'i': new_filepath, 'e': concerned_eid})
 
 
+def get_ids_uids_from_csv(csv_filename, logger=None):
+    try:
+        csvf = open(csv_filename, 'r')
+    except IOError:
+        if logger:
+            logger.error('get_ids_uids_from_csv: External UUID CSV file not found: %s\n' % csv_filename)
+        raise
+    with csvf:
+        dialect = csv.Sniffer().sniff(csvf.readline())
+        csvf.seek(0)
+        return dict((row for row in csv.reader(csvf, dialect)))
+
+
+
 class BrainomicsRemakeUidCommand(Command):
     """ Change subjects uids for anonymization.
 
@@ -67,7 +81,20 @@
 
     """
     name = 'remake-uid'
-    arguments = '<instance> [log] [delete]'
+    arguments = '<instance>'
+    min_args = 1
+    options = (
+        ('log',
+         {'short': 'l', 'action': 'store_true', 'default': False,
+          'help': 'logging mode: logs all command operations'}),
+        ('delete',
+         {'short': 'd', 'action': 'store_true', 'default': False,
+          'help': ('delete files at the old path, '
+                   'after creating the files at the new path')}),
+        ('external-uids',
+         {'short': 'u', 'type': 'string',
+          'help': 'specify external UID file'}),
+        )
 
     def _init_cw_connection(self, appid):
         logger = logging.getLogger('brainomics')
@@ -94,17 +121,30 @@
         logger = logging.getLogger('brainomics')
         if len(args) > 0:
             appid = args.pop(0)
-            import ipdb; ipdb.set_trace()
             cw_cnx, session = self._init_cw_connection(appid)
             session.set_cnxset()
-            log = True if args and args.pop(0) == 'log' else False
-            delete = True if args and args.pop(0) == 'delete' else False
+            log = self.config.log
+            delete = self.config.delete
+            if self.config.external_uids:
+                csv_filename = self.config.external_uids[0]
+                ids_uids = get_ids_uids_from_csv(csv_filename, logger)
             if log:
                 log_file = logging.FileHandler(appid + '.log')
                 logger.addHandler(log_file)
-            for subject_eid in session.execute('Any X WHERE X is Subject', build_descr=False):
-                subject_eid = subject_eid[0]
-                uuid = unicode(make_uid())
+            rset = session.execute('Any X, I WHERE X is Subject, X identifier I', build_descr=False)
+            for subject_eid, subject_identifier in rset:
+                if not self.config.external_uids:
+                    uuid = unicode(make_uid())
+                else:
+                    try:
+                        uuid = ids_uids[subject_identifier]
+                    except KeyError:
+                        if logger:
+                            logger.error('remake-uid: New identifier not found in %s '
+                                         'for identifier %s; keeping the old one \n'
+                                         % (csv_filename, subject_identifier))
+                        session.rollback()
+                        raise
                 update_ident_fpath(session, subject_eid, uuid, delete, logger)
             session.commit()
         else:
--- a/test/unittest_remake-uuid.py	Wed Jul 03 19:26:09 2013 +0200
+++ b/test/unittest_remake-uuid.py	Fri Jul 05 11:40:52 2013 +0200
@@ -2,9 +2,10 @@
 import os.path as osp
 import tempfile
 import logging
+import csv
 from cubicweb.utils import make_uid
 from cubicweb.devtools.testlib import CubicWebTC
-from cubes.brainomics.ccplugin import copy_file, update_ident_fpath
+from cubes.brainomics.ccplugin import copy_file, update_ident_fpath, get_ids_uids_from_csv
 
 
 
@@ -64,6 +65,29 @@
 
         self.assertNotEqual(old_fpaths, new_fpaths)
 
+    def test_get_uid_from_csv(self):
+        old_new_uuids = {}
+        identifiers_rset = self.rql('Any I WHERE X is Subject, X identifier I', 
+                                    build_descr=False)
+        # Generate test CSV
+        test_csv_fname = 'test_external_uuids.csv'
+        with open(test_csv_fname, 'wb') as csvf:
+            csvw = csv.writer(csvf, delimiter='\t')
+            for old_identifier in identifiers_rset: 
+                old_new_uuids[old_identifier[0]] = u'test_' + unicode(make_uid())
+                csvw.writerow([old_identifier[0], old_new_uuids[old_identifier[0]]])
+        # Verify that the new UUIDs are correctly retrieved from the CSV
+        ids_uids = get_ids_uids_from_csv(test_csv_fname, logger=self.log)
+        for old_identifier in identifiers_rset:
+            self.assertEqual(old_new_uuids[old_identifier[0]], 
+                             ids_uids[old_identifier[0]])
+
+
+
+
+
+
+
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
     unittest_main()