Merge branch 'master' into dev
This commit is contained in:
		| @@ -508,6 +508,17 @@ class BaseDocument(object): | |||||||
|                 return True |                 return True | ||||||
|         return False |         return False | ||||||
|  |  | ||||||
|  |     def __ne__(self, other): | ||||||
|  |         return not self.__eq__(other) | ||||||
|  |  | ||||||
|  |     def __hash__(self): | ||||||
|  |         """ For list, dic key  """ | ||||||
|  |         if self.pk is None: | ||||||
|  |             # For new object | ||||||
|  |             return super(BaseDocument,self).__hash__() | ||||||
|  |         else: | ||||||
|  |             return hash(self.pk) | ||||||
|  |  | ||||||
| if sys.version_info < (2, 5): | if sys.version_info < (2, 5): | ||||||
|     # Prior to Python 2.5, Exception was an old-style class |     # Prior to Python 2.5, Exception was an old-style class | ||||||
|     import types |     import types | ||||||
|   | |||||||
| @@ -538,7 +538,7 @@ class QuerySet(object): | |||||||
|         """ |         """ | ||||||
|         operators = ['ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod', |         operators = ['ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod', | ||||||
|                      'all', 'size', 'exists', 'not'] |                      'all', 'size', 'exists', 'not'] | ||||||
|         geo_operators = ['within_distance', 'within_box', 'near'] |         geo_operators = ['within_distance', 'within_spherical_distance', 'within_box', 'near', 'near_sphere'] | ||||||
|         match_operators = ['contains', 'icontains', 'startswith',  |         match_operators = ['contains', 'icontains', 'startswith',  | ||||||
|                            'istartswith', 'endswith', 'iendswith',  |                            'istartswith', 'endswith', 'iendswith',  | ||||||
|                            'exact', 'iexact'] |                            'exact', 'iexact'] | ||||||
| @@ -582,8 +582,12 @@ class QuerySet(object): | |||||||
|                 if op in geo_operators: |                 if op in geo_operators: | ||||||
|                     if op == "within_distance": |                     if op == "within_distance": | ||||||
|                         value = {'$within': {'$center': value}} |                         value = {'$within': {'$center': value}} | ||||||
|  |                     elif op == "within_spherical_distance": | ||||||
|  |                         value = {'$within': {'$centerSphere': value}} | ||||||
|                     elif op == "near": |                     elif op == "near": | ||||||
|                         value = {'$near': value} |                         value = {'$near': value} | ||||||
|  |                     elif op == "near_sphere": | ||||||
|  |                         value = {'$nearSphere': value} | ||||||
|                     elif op == 'within_box': |                     elif op == 'within_box': | ||||||
|                         value = {'$within': {'$box': value}} |                         value = {'$within': {'$box': value}} | ||||||
|                     else: |                     else: | ||||||
|   | |||||||
| @@ -729,6 +729,54 @@ class DocumentTest(unittest.TestCase): | |||||||
|     def tearDown(self): |     def tearDown(self): | ||||||
|         self.Person.drop_collection() |         self.Person.drop_collection() | ||||||
|  |  | ||||||
|  |     def test_document_hash(self): | ||||||
|  |         """Test document in list, dict, set | ||||||
|  |         """ | ||||||
|  |         class User(Document): | ||||||
|  |             pass | ||||||
|  |  | ||||||
|  |         class BlogPost(Document): | ||||||
|  |             pass | ||||||
|  |          | ||||||
|  |         # Clear old datas | ||||||
|  |         User.drop_collection() | ||||||
|  |         BlogPost.drop_collection() | ||||||
|  |  | ||||||
|  |         u1 = User.objects.create() | ||||||
|  |         u2 = User.objects.create() | ||||||
|  |         u3 = User.objects.create() | ||||||
|  |         u4 = User() # New object | ||||||
|  |  | ||||||
|  |         b1 = BlogPost.objects.create() | ||||||
|  |         b2 = BlogPost.objects.create() | ||||||
|  |  | ||||||
|  |         # in List | ||||||
|  |         all_user_list = list(User.objects.all()) | ||||||
|  |  | ||||||
|  |         self.assertTrue(u1 in all_user_list) | ||||||
|  |         self.assertTrue(u2 in all_user_list) | ||||||
|  |         self.assertTrue(u3 in all_user_list) | ||||||
|  |         self.assertFalse(u4 in all_user_list) # New object | ||||||
|  |         self.assertFalse(b1 in all_user_list) # Other object | ||||||
|  |         self.assertFalse(b2 in all_user_list) # Other object | ||||||
|  |  | ||||||
|  |         # in Dict | ||||||
|  |         all_user_dic = {} | ||||||
|  |         for u in User.objects.all(): | ||||||
|  |             all_user_dic[u] = "OK" | ||||||
|  |  | ||||||
|  |         self.assertEqual(all_user_dic.get(u1, False), "OK" ) | ||||||
|  |         self.assertEqual(all_user_dic.get(u2, False), "OK" ) | ||||||
|  |         self.assertEqual(all_user_dic.get(u3, False), "OK" ) | ||||||
|  |         self.assertEqual(all_user_dic.get(u4, False), False ) # New object | ||||||
|  |         self.assertEqual(all_user_dic.get(b1, False), False ) # Other object | ||||||
|  |         self.assertEqual(all_user_dic.get(b2, False), False ) # Other object | ||||||
|  |  | ||||||
|  |         # in Set | ||||||
|  |         all_user_set = set(User.objects.all()) | ||||||
|  |          | ||||||
|  |         self.assertTrue(u1 in all_user_set ) | ||||||
|  |          | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|   | |||||||
| @@ -1544,7 +1544,7 @@ class QuerySetTest(unittest.TestCase): | |||||||
|         self.assertEqual(events.count(), 3) |         self.assertEqual(events.count(), 3) | ||||||
|         self.assertEqual(list(events), [event1, event3, event2]) |         self.assertEqual(list(events), [event1, event3, event2]) | ||||||
|  |  | ||||||
|         # find events within 5 miles of pitchfork office, chicago |         # find events within 5 degrees of pitchfork office, chicago | ||||||
|         point_and_distance = [[41.9120459, -87.67892], 5] |         point_and_distance = [[41.9120459, -87.67892], 5] | ||||||
|         events = Event.objects(location__within_distance=point_and_distance) |         events = Event.objects(location__within_distance=point_and_distance) | ||||||
|         self.assertEqual(events.count(), 2) |         self.assertEqual(events.count(), 2) | ||||||
| @@ -1559,13 +1559,13 @@ class QuerySetTest(unittest.TestCase): | |||||||
|         self.assertEqual(events.count(), 3) |         self.assertEqual(events.count(), 3) | ||||||
|         self.assertEqual(list(events), [event3, event1, event2]) |         self.assertEqual(list(events), [event3, event1, event2]) | ||||||
|          |          | ||||||
|         # find events around san francisco |         # find events within 10 degrees of san francisco | ||||||
|         point_and_distance = [[37.7566023, -122.415579], 10] |         point_and_distance = [[37.7566023, -122.415579], 10] | ||||||
|         events = Event.objects(location__within_distance=point_and_distance) |         events = Event.objects(location__within_distance=point_and_distance) | ||||||
|         self.assertEqual(events.count(), 1) |         self.assertEqual(events.count(), 1) | ||||||
|         self.assertEqual(events[0], event2) |         self.assertEqual(events[0], event2) | ||||||
|          |          | ||||||
|         # find events within 1 mile of greenpoint, broolyn, nyc, ny |         # find events within 1 degree of greenpoint, broolyn, nyc, ny | ||||||
|         point_and_distance = [[40.7237134, -73.9509714], 1] |         point_and_distance = [[40.7237134, -73.9509714], 1] | ||||||
|         events = Event.objects(location__within_distance=point_and_distance) |         events = Event.objects(location__within_distance=point_and_distance) | ||||||
|         self.assertEqual(events.count(), 0) |         self.assertEqual(events.count(), 0) | ||||||
| @@ -1585,6 +1585,58 @@ class QuerySetTest(unittest.TestCase): | |||||||
|          |          | ||||||
|         Event.drop_collection() |         Event.drop_collection() | ||||||
|  |  | ||||||
|  |     def test_spherical_geospatial_operators(self): | ||||||
|  |         """Ensure that spherical geospatial queries are working | ||||||
|  |         """ | ||||||
|  |         class Point(Document): | ||||||
|  |             location = GeoPointField() | ||||||
|  |  | ||||||
|  |         Point.drop_collection() | ||||||
|  |  | ||||||
|  |         # These points are one degree apart, which (according to Google Maps) | ||||||
|  |         # is about 110 km apart at this place on the Earth. | ||||||
|  |         north_point = Point(location=[-122, 38]) # Near Concord, CA | ||||||
|  |         south_point = Point(location=[-122, 37]) # Near Santa Cruz, CA | ||||||
|  |         north_point.save() | ||||||
|  |         south_point.save() | ||||||
|  |  | ||||||
|  |         earth_radius = 6378.009; # in km (needs to be a float for dividing by) | ||||||
|  |  | ||||||
|  |         # Finds both points because they are within 60 km of the reference | ||||||
|  |         # point equidistant between them. | ||||||
|  |         points = Point.objects(location__near_sphere=[-122, 37.5]) | ||||||
|  |         self.assertEqual(points.count(), 2) | ||||||
|  |  | ||||||
|  |         # Same behavior for _within_spherical_distance | ||||||
|  |         points = Point.objects( | ||||||
|  |             location__within_spherical_distance=[[-122, 37.5], 60/earth_radius] | ||||||
|  |         ); | ||||||
|  |         self.assertEqual(points.count(), 2) | ||||||
|  |  | ||||||
|  |         # Finds both points, but orders the north point first because it's | ||||||
|  |         # closer to the reference point to the north. | ||||||
|  |         points = Point.objects(location__near_sphere=[-122, 38.5]) | ||||||
|  |         self.assertEqual(points.count(), 2) | ||||||
|  |         self.assertEqual(points[0].id, north_point.id) | ||||||
|  |         self.assertEqual(points[1].id, south_point.id) | ||||||
|  |  | ||||||
|  |         # Finds both points, but orders the south point first because it's | ||||||
|  |         # closer to the reference point to the south. | ||||||
|  |         points = Point.objects(location__near_sphere=[-122, 36.5]) | ||||||
|  |         self.assertEqual(points.count(), 2) | ||||||
|  |         self.assertEqual(points[0].id, south_point.id) | ||||||
|  |         self.assertEqual(points[1].id, north_point.id) | ||||||
|  |  | ||||||
|  |         # Finds only one point because only the first point is within 60km of | ||||||
|  |         # the reference point to the south. | ||||||
|  |         points = Point.objects( | ||||||
|  |             location__within_spherical_distance=[[-122, 36.5], 60/earth_radius] | ||||||
|  |         ); | ||||||
|  |         self.assertEqual(points.count(), 1) | ||||||
|  |         self.assertEqual(points[0].id, south_point.id) | ||||||
|  |  | ||||||
|  |         Point.drop_collection() | ||||||
|  |  | ||||||
|     def test_custom_querysets(self): |     def test_custom_querysets(self): | ||||||
|         """Ensure that custom QuerySet classes may be used. |         """Ensure that custom QuerySet classes may be used. | ||||||
|         """ |         """ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user