Merge pull request #1877 from bagerard/improve_ComplexField_validation_edge_case
Handles edge case when EmbeddedDocumentListField receives a Document and not a list
This commit is contained in:
		| @@ -314,11 +314,16 @@ class ComplexBaseField(BaseField): | |||||||
|         if hasattr(value, 'to_python'): |         if hasattr(value, 'to_python'): | ||||||
|             return value.to_python() |             return value.to_python() | ||||||
|  |  | ||||||
|  |         BaseDocument = _import_class('BaseDocument') | ||||||
|  |         if isinstance(value, BaseDocument): | ||||||
|  |             # Something is wrong, return the value as it is | ||||||
|  |             return value | ||||||
|  |  | ||||||
|         is_list = False |         is_list = False | ||||||
|         if not hasattr(value, 'items'): |         if not hasattr(value, 'items'): | ||||||
|             try: |             try: | ||||||
|                 is_list = True |                 is_list = True | ||||||
|                 value = {k: v for k, v in enumerate(value)} |                 value = {idx: v for idx, v in enumerate(value)} | ||||||
|             except TypeError:  # Not iterable return the value |             except TypeError:  # Not iterable return the value | ||||||
|                 return value |                 return value | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3743,7 +3743,7 @@ class FieldTest(MongoDBTestCase): | |||||||
|         assert isinstance(doc.field, ToEmbedChild) |         assert isinstance(doc.field, ToEmbedChild) | ||||||
|         assert doc.field == to_embed_child |         assert doc.field == to_embed_child | ||||||
|  |  | ||||||
|     def test_invalid_dict_value(self): |     def test_dict_field_invalid_dict_value(self): | ||||||
|         class DictFieldTest(Document): |         class DictFieldTest(Document): | ||||||
|             dictionary = DictField(required=True) |             dictionary = DictField(required=True) | ||||||
|  |  | ||||||
| @@ -3757,6 +3757,22 @@ class FieldTest(MongoDBTestCase): | |||||||
|         test.dictionary  # Just access to test getter |         test.dictionary  # Just access to test getter | ||||||
|         self.assertRaises(ValidationError, test.validate) |         self.assertRaises(ValidationError, test.validate) | ||||||
|  |  | ||||||
|  |     def test_dict_field_raises_validation_error_if_wrongly_assign_embedded_doc(self): | ||||||
|  |         class DictFieldTest(Document): | ||||||
|  |             dictionary = DictField(required=True) | ||||||
|  |  | ||||||
|  |         DictFieldTest.drop_collection() | ||||||
|  |  | ||||||
|  |         class Embedded(EmbeddedDocument): | ||||||
|  |             name = StringField() | ||||||
|  |  | ||||||
|  |         embed = Embedded(name='garbage') | ||||||
|  |         doc = DictFieldTest(dictionary=embed) | ||||||
|  |         with self.assertRaises(ValidationError) as ctx_err: | ||||||
|  |             doc.validate() | ||||||
|  |         self.assertIn("'dictionary'", str(ctx_err.exception)) | ||||||
|  |         self.assertIn('Only dictionaries may be used in a DictField', str(ctx_err.exception)) | ||||||
|  |  | ||||||
|     def test_cls_field(self): |     def test_cls_field(self): | ||||||
|         class Animal(Document): |         class Animal(Document): | ||||||
|             meta = {'allow_inheritance': True} |             meta = {'allow_inheritance': True} | ||||||
| @@ -3855,6 +3871,28 @@ class EmbeddedDocumentListFieldTestCase(MongoDBTestCase): | |||||||
|             self.Comments(author='user3', message='message1') |             self.Comments(author='user3', message='message1') | ||||||
|         ]).save() |         ]).save() | ||||||
|  |  | ||||||
|  |     def test_fails_upon_validate_if_provide_a_doc_instead_of_a_list_of_doc(self): | ||||||
|  |         # Relates to Issue #1464 | ||||||
|  |         comment = self.Comments(author='John') | ||||||
|  |  | ||||||
|  |         class Title(Document): | ||||||
|  |             content = StringField() | ||||||
|  |  | ||||||
|  |         # Test with an embeddedDocument instead of a list(embeddedDocument) | ||||||
|  |         # It's an edge case but it used to fail with a vague error, making it difficult to troubleshoot it | ||||||
|  |         post = self.BlogPost(comments=comment) | ||||||
|  |         with self.assertRaises(ValidationError) as ctx_err: | ||||||
|  |             post.validate() | ||||||
|  |         self.assertIn("'comments'", str(ctx_err.exception)) | ||||||
|  |         self.assertIn('Only lists and tuples may be used in a list field', str(ctx_err.exception)) | ||||||
|  |  | ||||||
|  |         # Test with a Document | ||||||
|  |         post = self.BlogPost(comments=Title(content='garbage')) | ||||||
|  |         with self.assertRaises(ValidationError) as e: | ||||||
|  |             post.validate() | ||||||
|  |         self.assertIn("'comments'", str(ctx_err.exception)) | ||||||
|  |         self.assertIn('Only lists and tuples may be used in a list field', str(ctx_err.exception)) | ||||||
|  |  | ||||||
|     def test_no_keyword_filter(self): |     def test_no_keyword_filter(self): | ||||||
|         """ |         """ | ||||||
|         Tests the filter method of a List of Embedded Documents |         Tests the filter method of a List of Embedded Documents | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user