def test_get_object_hook(self): """ Test that custom logic for getting referred objects can be plugged into resource ids. """ class MyClass(): pass new_obj1 = MyClass() new_obj2 = MyClass() def _get_object_hook(arg): if str(arg) == '123': return new_obj1 elif str(arg) == '789': return new_obj2 else: return None with ResourceIdentifier._debug_class_state(): ResourceIdentifier.register_get_object_hook(_get_object_hook) rid1 = ResourceIdentifier('123') rid2 = ResourceIdentifier('456') rid3 = ResourceIdentifier('789') self.assertIs(rid1.get_referred_object(), new_obj1) self.assertIs(rid2.get_referred_object(), None) # Now clear the hook, _get_object_hook should no longer be called ResourceIdentifier.remove_get_object_hook(_get_object_hook) self.assertIs(rid3.get_referred_object(), None) # But rid1 should have been bound to new_obj1 (so it no longer # needs to call get_object_hook to find it self.assertIs(rid1.get_referred_object(), new_obj1)
def test_catalog_resource_ids(self): """ Basic tests on the catalog resource ids. """ cat1 = read_events() # The resource_id attached to the first event is self-pointing self.assertIs(cat1[0], cat1[0].resource_id.get_referred_object()) # make a copy and re-read catalog cat2 = cat1.copy() cat3 = read_events() # the resource_id on the new catalogs point to attached objects self.assertIs(cat1[0], cat1[0].resource_id.get_referred_object()) self.assertIs(cat2[0], cat2[0].resource_id.get_referred_object()) self.assertIs(cat3[0], cat3[0].resource_id.get_referred_object()) # now delete cat1 and make sure cat2 and cat3 still work del cat1 self.assertIs(cat2[0], cat2[0].resource_id.get_referred_object()) self.assertIs(cat3[0], cat3[0].resource_id.get_referred_object()) # create a resource_id with the same id as the last defined object # with the same resource id (that is still in scope) is returned new_id = cat2[0].resource_id.id rid = ResourceIdentifier(new_id) self.assertIs(rid.get_referred_object(), cat3[0]) del cat3 gc.collect() # Call gc to ensure WeakValueDict works # raises UserWarning, suppress to keep std out cleaner with WarningsCapture(): self.assertIs(rid.get_referred_object(), cat2[0]) del cat2 self.assertIs(rid.get_referred_object(), None)
def test_same_resource_id_different_referred_object(self): """ Tests the handling of the case that different ResourceIdentifier instances are created that have the same resource id but different objects. The referred objects should still return the same objects used in the ResourceIdentifier construction or set_referred_object call. However, if an object is set to a resource_id that is not equal to the last object set it should issue a warning. """ warnings.simplefilter('default') object_a = UTCDateTime(1000) object_b = UTCDateTime(1000) object_c = UTCDateTime(1001) self.assertFalse(object_a is object_b) id = 'obspy.org/tests/test_resource' res_a = ResourceIdentifier(id=id, referred_object=object_a) # Now create a new resource with the same id but a different object. # This should not raise a warning as the object a and b are equal. with WarningsCapture() as w: res_b = ResourceIdentifier(id=id, referred_object=object_b) self.assertEqual(len(w), 0) # if the set object is not equal to the last object set to the same # resource_id, however, a warning should be issued. with WarningsCapture() as w: res_c = ResourceIdentifier(id=id, referred_object=object_c) self.assertEqual(len(w), 1) expected_text = 'which is not equal to the last object bound' self.assertIn(expected_text, str(w[0])) # even though the resource_id are the same, the referred objects # should point to the original (different) objects self.assertIs(object_a, res_a.get_referred_object()) self.assertIs(object_b, res_b.get_referred_object()) self.assertIs(object_c, res_c.get_referred_object())
def test_same_resource_id_different_referred_object(self): """ Tests the handling of the case that different ResourceIdentifier instances are created that have the same resource id but different objects. The referred objects should still return the same objects used in the ResourceIdentifier construction or set_referred_object call. However, if an object is set to a resource_id that is not equal to the last object set it should issue a warning. """ warnings.simplefilter('default') object_a = UTCDateTime(1000) object_b = UTCDateTime(1000) object_c = UTCDateTime(1001) self.assertFalse(object_a is object_b) id = 'obspy.org/tests/test_resource' res_a = ResourceIdentifier(id=id, referred_object=object_a) # Now create a new resource with the same id but a different object. # This should not raise a warning as the object a and b are equal. with WarningsCapture() as w: res_b = ResourceIdentifier(id=id, referred_object=object_b) self.assertEqual(len(w), 0) # if the set object is not equal to the last object set to the same # resource_id, however, a warning should be issued. with WarningsCapture() as w: res_c = ResourceIdentifier(id=id, referred_object=object_c) self.assertEqual(len(w), 1) expected_text = 'which is not equal to the last object bound' self.assertIn(expected_text, str(w[0])) # even though the resource_id are the same, the referred objects # should point to the original (different) objects self.assertIs(object_a, res_a.get_referred_object()) self.assertIs(object_b, res_b.get_referred_object()) self.assertIs(object_c, res_c.get_referred_object())
def test_catalog_resource_ids(self): """ Basic tests on the catalog resource ids. """ cat1 = read_events() # The resource_id attached to the first event is self-pointing self.assertIs(cat1[0], cat1[0].resource_id.get_referred_object()) # make a copy and re-read catalog cat2 = cat1.copy() cat3 = read_events() # the resource_id on the new catalogs point to attached objects self.assertIs(cat1[0], cat1[0].resource_id.get_referred_object()) self.assertIs(cat2[0], cat2[0].resource_id.get_referred_object()) self.assertIs(cat3[0], cat3[0].resource_id.get_referred_object()) # now delete cat1 and make sure cat2 and cat3 still work del cat1 self.assertIs(cat2[0], cat2[0].resource_id.get_referred_object()) self.assertIs(cat3[0], cat3[0].resource_id.get_referred_object()) # create a resource_id with the same id as the last defined object # with the same resource id (that is still in scope) is returned new_id = cat2[0].resource_id.id rid = ResourceIdentifier(new_id) self.assertIs(rid.get_referred_object(), cat3[0]) del cat3 gc.collect() # Call gc to ensure WeakValueDict works # raises UserWarning, suppress to keep std out cleaner with WarningsCapture(): self.assertIs(rid.get_referred_object(), cat2[0]) del cat2 self.assertIs(rid.get_referred_object(), None)
def test_de_referencing_when_object_goes_out_of_scope(self): """ Tests that objects that have no more referrer are no longer stored in the reference dictionary. """ r_dict = self.id_order t1 = UTCDateTime(2010, 1, 1) # test object rid = 'a' # test resource id # Create object and assert the reference has been created. r1 = ResourceIdentifier(rid, referred_object=t1) self.assertEqual(r1.get_referred_object(), t1) self.assertTrue(r1._resource_key in r_dict) # Deleting the object should remove the reference. r_dict_len = len(r_dict) del r1 self.assertEqual(len(r_dict), r_dict_len - 1) # Now create two equal references. r1 = ResourceIdentifier(rid, referred_object=t1) r2 = ResourceIdentifier(rid, referred_object=t1) self.assertEqual(r1.get_referred_object(), t1) # Deleting one should not remove the reference. del r1 self.assertEqual(r2.get_referred_object(), t1) self.assertIn(r2._resource_key, r_dict) # Deleting the second one should (r_dict should now be empty) del r2 self.assertEqual(len(r_dict), 0) r3 = ResourceIdentifier(rid) self.assertNotIn(r3._resource_key, r_dict)
def test_de_referencing_when_object_goes_out_of_scope(self): """ Tests that objects that have no more referrer are no longer stored in the reference dictionary. """ r_dict = self.id_order t1 = UTCDateTime(2010, 1, 1) # test object rid = 'a' # test resource id # Create object and assert the reference has been created. r1 = ResourceIdentifier(rid, referred_object=t1) self.assertEqual(r1.get_referred_object(), t1) self.assertTrue(r1._resource_key in r_dict) # Deleting the object should remove the reference. r_dict_len = len(r_dict) del r1 self.assertEqual(len(r_dict), r_dict_len - 1) # Now create two equal references. r1 = ResourceIdentifier(rid, referred_object=t1) r2 = ResourceIdentifier(rid, referred_object=t1) self.assertEqual(r1.get_referred_object(), t1) # Deleting one should not remove the reference. del r1 self.assertEqual(r2.get_referred_object(), t1) self.assertIn(r2._resource_key, r_dict) # Deleting the second one should (r_dict should now be empty) del r2 self.assertEqual(len(r_dict), 0) r3 = ResourceIdentifier(rid) self.assertNotIn(r3._resource_key, r_dict)
def test_de_referencing_when_object_goes_out_of_scope(self, debug_state): """ Tests that objects that have no more referrer are no longer stored in the reference dictionary. """ r_dict = debug_state['id_order'] t1 = UTCDateTime(2010, 1, 1) # test object rid = 'a' # test resource id # Create object and assert the reference has been created. r1 = ResourceIdentifier(rid, referred_object=t1) assert r1.get_referred_object() == t1 assert r1._resource_key in r_dict # Deleting the object should remove the reference. r_dict_len = len(r_dict) del r1 assert len(r_dict) == r_dict_len - 1 # Now create two equal references. r1 = ResourceIdentifier(rid, referred_object=t1) r2 = ResourceIdentifier(rid, referred_object=t1) assert r1.get_referred_object() == t1 # Deleting one should not remove the reference. del r1 assert r2.get_referred_object() == t1 assert r2._resource_key in r_dict # Deleting the second one should (r_dict should now be empty) del r2 assert len(r_dict) == 0 r3 = ResourceIdentifier(rid) assert r3._resource_key not in r_dict
def test_resource_id_state_cleanup(self): """ Tests that the state in the ResourceIdentifier class gets gets cleaned up when resource_ids are garbage collected. """ obj_a = UTCDateTime() obj_b = UTCDateTime() res1 = ResourceIdentifier(referred_object=obj_a) res2 = ResourceIdentifier(referred_object=obj_b) # Now two keys should be in the global dict. self.assertEqual(len(self.id_order), 2) self.assertEqual(len(self.id_object_map), 2) del obj_a, obj_b # raises UserWarnings self.assertEqual(len(self.id_order), 2) with warnings.catch_warnings(): warnings.simplefilter("ignore", UserWarning) self.assertIs(res1.get_referred_object(), None) self.assertIs(res2.get_referred_object(), None)
def test_resource_id_state_cleanup(self, debug_state): """ Tests that the state in the ResourceIdentifier class gets gets cleaned up when resource_ids are garbage collected. """ obj_a = UTCDateTime() obj_b = UTCDateTime() res1 = ResourceIdentifier(referred_object=obj_a) res2 = ResourceIdentifier(referred_object=obj_b) # Now two keys should be in the global dict. assert len(debug_state['id_order']) == 2 assert len(debug_state['id_object_map']) == 2 del obj_a, obj_b # raises UserWarnings assert len(debug_state['id_order']) == 2 with warnings.catch_warnings(): warnings.simplefilter("ignore", UserWarning) assert res1.get_referred_object() is None assert res2.get_referred_object() is None
def test_resource_id_state_cleanup(self): """ Tests that the state in the ResourceIdentifier class gets gets cleaned up when resource_ids are garbage collected. """ obj_a = UTCDateTime() obj_b = UTCDateTime() res1 = ResourceIdentifier(referred_object=obj_a) res2 = ResourceIdentifier(referred_object=obj_b) # Now two keys should be in the global dict. self.assertEqual(len(self.id_order), 2) self.assertEqual(len(self.id_object_map), 2) del obj_a, obj_b # raises UserWarnings self.assertEqual(len(self.id_order), 2) with warnings.catch_warnings(): warnings.simplefilter("ignore", UserWarning) self.assertIs(res1.get_referred_object(), None) self.assertIs(res2.get_referred_object(), None)
def test_getting_gc_no_shared_resource_id(self): """ Test that calling get_referred_object() on a resource id whose object has been garbage collected, and whose resource_id is unique, returns None """ obj1 = UTCDateTime() rid1 = ResourceIdentifier(referred_object=obj1) # delete obj1, make sure rid1 return None del obj1 # raises UserWarning with warnings.catch_warnings(): warnings.simplefilter("ignore", UserWarning) self.assertIs(rid1.get_referred_object(), None)
def test_resource_ids_refer_to_newest_object(self): """ Tests that resource ids which are assigned multiple times but point to identical objects always point to the newest object. """ t1 = UTCDateTime(2010, 1, 1) t2 = UTCDateTime(2010, 1, 1) ResourceIdentifier("a", referred_object=t1) rid = ResourceIdentifier("a", referred_object=t2) del t1 self.assertIs(rid.get_referred_object(), t2)
def test_getting_gc_no_shared_resource_id(self): """ Test that calling get_referred_object() on a resource id whose object has been garbage collected, and whose resource_id is unique, returns None """ obj1 = UTCDateTime() rid1 = ResourceIdentifier(referred_object=obj1) # delete obj1, make sure rid1 return None del obj1 # raises UserWarning with warnings.catch_warnings(): warnings.simplefilter("ignore", UserWarning) self.assertIs(rid1.get_referred_object(), None)
def test_get_quakeml_id(self): """ Tests for returning valid quakeml ids using the get_quakeml_id method. """ obj = UTCDateTime('2017-09-17') rid1 = ResourceIdentifier('invalid_id', referred_object=obj) rid2 = rid1.get_quakeml_id(authority_id='remote') # The resource ids should not be equal but should refer to the same # object. self.assertNotEqual(rid2, rid1) self.assertIs(rid1.get_referred_object(), rid2.get_referred_object()) # A valid resource id should return a resource id that is equal. rid3 = rid2.get_quakeml_id() self.assertEqual(rid2, rid3)
def test_resource_ids_refer_to_newest_object(self): """ Tests that resource ids which are assigned multiple times but point to identical objects always point to the newest object. """ t1 = UTCDateTime(2010, 1, 1) t2 = UTCDateTime(2010, 1, 1) ResourceIdentifier("a", referred_object=t1) rid = ResourceIdentifier("a", referred_object=t2) del t1 self.assertIs(rid.get_referred_object(), t2)
def test_adding_a_referred_object_after_creation(self): """ Check that the referred objects can also be made available after the ResourceIdentifier instances have been created. """ obj = UTCDateTime() res_id = "obspy.org/time/test" ref_a = ResourceIdentifier(res_id) ref_b = ResourceIdentifier(res_id) ref_c = ResourceIdentifier(res_id) # All three will have no resource attached. self.assertEqual(ref_a.get_referred_object(), None) self.assertEqual(ref_b.get_referred_object(), None) self.assertEqual(ref_c.get_referred_object(), None) # Setting the object for one will make it available to all other # instances, provided they weren't bound to specific objects. ref_b.set_referred_object(obj) self.assertIs(ref_a.get_referred_object(), obj) self.assertIs(ref_b.get_referred_object(), obj) self.assertIs(ref_c.get_referred_object(), obj)
def test_adding_a_referred_object_after_creation(self): """ Check that the referred objects can also be made available after the ResourceIdentifier instances have been created. """ obj = UTCDateTime() res_id = "obspy.org/time/test" ref_a = ResourceIdentifier(res_id) ref_b = ResourceIdentifier(res_id) ref_c = ResourceIdentifier(res_id) # All three will have no resource attached. self.assertEqual(ref_a.get_referred_object(), None) self.assertEqual(ref_b.get_referred_object(), None) self.assertEqual(ref_c.get_referred_object(), None) # Setting the object for one will make it available to all other # instances, provided they weren't bound to specific objects. ref_b.set_referred_object(obj) self.assertIs(ref_a.get_referred_object(), obj) self.assertIs(ref_b.get_referred_object(), obj) self.assertIs(ref_c.get_referred_object(), obj)
def test_getting_gc_with_shared_resource_id(self): """ Test that calling get_referred_object on a resource id whose object has been garbage collected, but that has another object that shares the same resource_id, returns the other object with the same resource id and issues a warning """ uri = 'testuri' obj1 = UTCDateTime(1000) obj2 = UTCDateTime(1000) rid1 = ResourceIdentifier(uri, referred_object=obj1) rid2 = ResourceIdentifier(uri, referred_object=obj2) assert not (rid1.get_referred_object() is rid2.get_referred_object()) del obj1 with WarningsCapture() as w: rid1.get_referred_object() assert len(w) == 1 assert 'The object with identity' in str(w[0]) # now both rids should return the same object assert rid1.get_referred_object() is rid2.get_referred_object() # the object id should now be bound to obj2 assert rid1._object_id == rid2._object_id
def test_getting_gc_with_shared_resource_id(self): """ Test that calling get_referred_object on a resource id whose object has been garbage collected, but that has another object that shares the same resource_id, returns the other object with the same resource id and issues a warning """ uri = 'testuri' obj1 = UTCDateTime(1000) obj2 = UTCDateTime(1000) rid1 = ResourceIdentifier(uri, referred_object=obj1) rid2 = ResourceIdentifier(uri, referred_object=obj2) self.assertFalse(rid1.get_referred_object() is rid2.get_referred_object()) del obj1 with WarningsCapture() as w: rid1.get_referred_object() self.assertEqual(len(w), 1) self.assertIn('The object with identity', str(w[0])) # now both rids should return the same object self.assertIs(rid1.get_referred_object(), rid2.get_referred_object()) # the object id should now be bound to obj2 self.assertEqual(rid1._object_id, rid2._object_id)