workaround the mysterious issue with sqlalchemy that returns instances of RegAuthorit...
Thierry Parmentelat [Fri, 5 Jun 2015 11:57:41 +0000 (13:57 +0200)]
have their __dict__ in line with the object's contents (specifically missing 'name')
a possibly other instance of that same issue was worked around in Update() using an extra print statement,
which I prefer to leave as is for now as I cannot test that thoroughly, but a similar approach would probably
be a solution in this case as well

sfa/managers/registry_manager.py
sfa/storage/model.py

index 8f65e06..1eafc10 100644 (file)
@@ -295,12 +295,11 @@ class RegistryManager:
 #                logger.debug("non recursive mode, found {} local records".format(len(records)))
             # so that sfi list can show more than plain names...
             for record in records:
-                # xxx mystery - again this useless statement is key here so that
-                # resulting records have their __dict__ field actually in line with the
-                # object's contents; was first observed with authorities' 'name' column
+                # xxx mystery - see also the bottom of model.py
+                # resulting records have been observed to not always have
+                # their __dict__ actually in line with the object's contents;
+                # was first observed with authorities' 'name' column
                 # that would be missing from result as received by client
-                # record.todict() is the place where __dict__ is used
-                print "DO NOT REMOVE ME before augment_with_sfa_builtins, record={}".format(record)
                 augment_with_sfa_builtins(record)
             record_dicts = [ record.record_to_dict(exclude_types=(InstrumentedList,)) for record in records ]
     
@@ -499,11 +498,16 @@ class RegistryManager:
                 record.email = email
         
         # update the PLC information that was specified with the record
-        # xxx mystery: oddly enough, without this useless statement, 
+        # xxx mystery -- see also the bottom of model.py,
+        # oddly enough, without this useless statement, 
         # record.__dict__ as received by the driver seems to be off
-        # anyway the driver should receive an object 
+        # anyway the driver should receive an object
         # (and then extract __dict__ itself if needed)
         print "DO NOT REMOVE ME before driver.update, record={}".format(record)
+        # as of June 2015: I suspect we could remove that print line above and replace it with
+        # augment_with_sfa_builtins(record)
+        # instead, that checks for these fields, like it is done above in List()
+        # but that would need to be confirmed by more extensive tests
         new_key_pointer = -1
         try:
            (pointer, new_key_pointer) = api.driver.update (record.__dict__, new_record.__dict__, hrn, new_key)
index b31517a..051ba87 100644 (file)
@@ -489,15 +489,35 @@ augment_map = {'authority': {'reg-pis' : 'reg_pis',},
            }
 
 
+# xxx mystery
+# the way we use sqlalchemy might be a little wrong
+# in any case what has been observed is that (Reg)Records as returned by an sqlalchemy
+# query not always have their __dict__ properly adjusted
+# typically a RegAuthority object would have its object.name set properly, but
+# object.__dict__ has no 'name' key
+# which is an issue because we rely on __dict__ for many things, in particular this
+# is what gets exposed to the drivers (this is historical and dates back before sqlalchemy)
+# so it is recommended to always run this function that will make sure
+# that such built-in fields are properly set in __dict__ too
+# 
 def augment_with_sfa_builtins(local_record):
     # don't ruin the import of that file in a client world
     from sfa.util.xrn import Xrn
     # add a 'urn' field
     setattr(local_record, 'reg-urn', Xrn(xrn=local_record.hrn, type=local_record.type).urn)
     # users have keys and this is needed to synthesize 'users' sent over to CreateSliver
+    fields_to_check = []
     if local_record.type == 'user':
         user_keys = [ key.key for key in local_record.reg_keys ]
         setattr(local_record, 'reg-keys', user_keys)
+        fields_to_check = ['email']
+    elif local_record.type == 'authority':
+        fields_to_check = ['name']
+    for field in fields_to_check:
+        if not field in local_record.__dict__:
+            logger.debug("augment_with_sfa_builtins: hotfixing missing '{}' in {}"
+                         .format(field, local_record.hrn))
+            local_record.__dict__[field] = getattr(local_record, field)
     # search in map according to record type
     type_map = augment_map.get(local_record.type, {})
     # use type-dep. map to do the job