Example #1
0
 def __init__(self, pools, representation=None):
     self._pool = pools
     if representation:
         self._representation = representation
     else:
         self._id_factory = SaltedTimeIDFactory()
         self._representation = IonSerializerDictionaryRepresentation(id_factory=self._id_factory)
Example #2
0
class RepresentationTest(IonIntegrationTestCase):

    def setUp(self):
        self.subject = IonSerializerDictionaryRepresentation(id_factory=SaltedTimeIDFactory())

    def test_encode_decode(self):
        obj = IonObject(RT.InstrumentDevice, name='SBE37IMDevice', description="SBE37IMDevice", serial_number="12345" )
        d = self.subject.encode(obj)
        print 'keys: ' + repr(d)
        self.assertFalse('_id' in d.keys())
        new_obj = self.subject.decode(d)
        self.assertEqual(obj, new_obj)
        d2 = self.subject.encode(new_obj, add_id=True)
        self.assertTrue('_id' in d2.keys(), msg=repr(d2.keys()))

        # retains key once added
        d3 = self.subject.encode(self.subject.decode(d2))
        self.assertTrue('_id' in d3.keys())

    def test_fails(self):
        d = {}
        try:
            self.subject.decode(d)
            self.fail('should not have worked')
        except:
            pass

        obj = IonObject(RT.InstrumentDevice, name='SBE37IMDevice', description="SBE37IMDevice", serial_number="12345" )
        d2 = self.subject.encode(obj)
        d2['more']='stuff'
        try:
            self.subject.decode(d2)
            self.fail('should not be able to decode')
        except:
            pass
Example #3
0
class Repository(object):

    def __init__(self, pools, representation=None):
        self._pool = pools
        if representation:
            self._representation = representation
        else:
            self._id_factory = SaltedTimeIDFactory()
            self._representation = IonSerializerDictionaryRepresentation(id_factory=self._id_factory)

    def close(self):
        for pool in self._pool.values():
            pool.close(op=self._close_connection)

    def _close_connection(self, connection):
        connection.close()

    #############################

    def _validate_object(self, arg):
        ''' check that arg is IonObject or list of IonObjects '''
        if isinstance(arg, IonObjectBase):
            return
        if isinstance(arg, list) and len(arg) and all([isinstance(o, IonObjectBase) for o in arg]):
            return
        raise BadRequest('invalid repository entry type ' + arg.__class__.__name__ + ': ' + repr(arg))

    def _validate_object_or_id(self, arg):
        ''' collection of IDs is valid, otherwise check for valid IonObject(s) '''
        if isinstance(arg, str):
            return
        if isinstance(arg, list) and len(arg) and all([isinstance(id, str) for id in arg]):
            return
        self._validate_object(arg)

    def _is_id(self, arg):
        return isinstance(arg, str) or (isinstance(arg, list) and isinstance(arg[0], str))

    #############################
    #
    # CRUD operations delegate to datastore
    # all use _perform for consistency:
    # - check argument for allowed types argect, id, list of objects or list of ids
    # - get pooled datastore instance
    # - perform operation, notify of any non-application exceptions
    # - return connection to pool

    def insert(self, store, arg, _connection=None, **kw):
        """ insert one or more IonObjects into the DB
            return value is one/list of triples (success, id, exception)
                   indicating success or failure per insert
        """
        if not _connection:
            self._validate_object(arg)
            encoded = self._encode(arg, add_id=True)
            return self._perform(self.insert, store, encoded)
        return _connection.insert(arg, **kw)

    def update(self, store, arg, _connection=None, **kw):
        """ update one or more IonObjects
            return value is one/list of triples (success, id, exception)
                   indicating success or failure per insert
        """
        if not _connection:
            self._validate_object(arg)
            return self._perform(self.update, store, self._encode(arg))
        return _connection.update(arg, **kw)

    def read(self, store, arg, _connection=None, **kw):
        """ read one or more IonObjects from the DB
            arg may be IonObject(s) (which will be updated)
                or if type is provided, id(s)
            returns one/list of tuples (success, id, IonObject or exception)
        """
        if not _connection:
            self._validate_object_or_id(arg)
            return self._perform(self.read, store, self._encode_or_id(arg))
        return self._decode(_connection.read(arg, **kw))

    def delete(self, store, arg, _connection=None, **kw):
        """ delete one or more objects from the DB
            arg may be IonObject(s), or if type is provided, id(s)
            return value is one/list of triples (success, id, exception)
                   indicating success or failure per insert
        """
        if not _connection:
            self._validate_object_or_id(arg)
            return self._perform(self.delete, store, self._encode_or_id(arg))
        return _connection.delete(arg, **kw)

    def _encode_or_id(self, arg):
        if self._is_id(arg):
            return arg
        else:
            return self._encode(arg)

    def _encode(self, arg, add_id=False):
        if isinstance(arg, list):
            return [ self._encode(o, add_id=add_id) for o in arg ]
        return self._representation.encode(arg, add_id=add_id)

    def _decode(self, arg):
        if isinstance(arg, list):
            return [ self._decode(d) for d in arg ]
        if isinstance(arg, tuple):
            return arg[0], arg[1], self._decode(arg[2])
        if isinstance(arg, Exception):
            return arg
        return self._representation.decode(arg)

    def _perform(self, op, store, *args, **kwargs):
        """ re-invoke the calling operation with a pooled DB connection """
        pool = self._pool[store]
        connection = pool.check_out()
        if not connection:
            raise ServerError('failed to get a connection for store: ' + store)
        try:
            return op(store, *args, _connection=connection, **kwargs)
        except IonException:
            raise
        except:
            # should have been rethrown as application exception by store, find and fix these occurrences...
            log.error('unexpected exception from datastore', exc_info=True)
            raise
        finally:
            pool.check_in(connection)

    #############################
    #
    # NOT YET IMPLEMENTED
    def create_association(self, subject=None, predicate=None, arg=None, assoc_type=AT.H2H):
        pass

    def delete_association(self, association=''):
        pass

    def find_objects(self, subject, predicate="", object_type="", id_only=False):
        pass

    def find_subjects(self, subject_type="", predicate="", obj="", id_only=False):
        pass

    def find_associations(self, subject="", predicate="", obj="", assoc_type=AT.H2H, id_only=True):
        pass

    def find_resources(self, restype="", lcstate="", name="", id_only=True):
        pass
Example #4
0
 def setUp(self):
     self.subject = IonSerializerDictionaryRepresentation(id_factory=SaltedTimeIDFactory())