def test_many_to_many_fields_not_supported(self, migration_apps):
        """
        Test that if an item in the yaml includes a many-to-many field,
        the function raises NotImplementedError as this is not supported yet.
        """
        yaml_content = """
- model: datahub.core.test.support.book
  pk: 1
  fields:
    name: name
    authors:
        - 1
        - 2
    published_on: '2010-01-01'
"""
        mocked_read = mock.mock_open(read_data=yaml_content)

        PersonFactory.create_batch(2, pk=factory.Iterator([1, 2]))

        with pytest.raises(NotImplementedError) as excinfo:
            with mock.patch('datahub.core.migration_utils.open',
                            mocked_read,
                            create=True):
                load_yaml_data_in_migration(migration_apps,
                                            'path-to-file.yaml')
        assert str(excinfo.value) == 'Many-to-many fields not supported'
    def test_with_default_outer_field(self, expression):
        """
        Test that a Person query set can annotated with the name of the most
        recently published book.

        This considers a single many-to-one relationship between Book and Person.
        """
        person = PersonFactory()
        book_data = [
            {'name': 'oldest', 'published_on': date(2010, 1, 1)},
            {'name': 'in the middle', 'published_on': date(2013, 1, 1)},
            {'name': 'newest', 'published_on': date(2015, 1, 1)},
        ]
        shuffle(book_data)

        for item_data in book_data:
            BookFactory(
                proofreader=person,
                authors=[],
                **item_data,
            )

        queryset = Person.objects.annotate(
            name_of_latest_book=get_top_related_expression_subquery(
                Book.proofreader.field, expression, ('-published_on',),
            ),
        )
        assert queryset.first().name_of_latest_book == 'newest'
 def test_ignores_blank_first_name(self):
     """Tests that a blank first_name is ignored."""
     person = PersonFactory(first_name='')
     queryset = Person.objects.annotate(
         name=get_full_name_expression(),
     )
     assert queryset.first().name == person.last_name
 def test_aggregates_as_array(self, names, distinct):
     """
     Test that the first names of all authors for each book can be aggregated into an array
     for various cases, and with distinct on and off.
     """
     authors = PersonFactory.create_batch(
         len(names),
         first_name=factory.Iterator(
             sample(names, len(names)),
         ),
     )
     BookFactory(authors=authors)
     queryset = Book.objects.annotate(
         author_names=get_array_agg_subquery(
             Book.authors.through,
             'book',
             'person__first_name',
             distinct=distinct,
         ),
     )
     actual_author_names = queryset.first().author_names
     if distinct:
         assert Counter(actual_author_names) == Counter(set(names))
     else:
         assert Counter(actual_author_names) == Counter(names)
Пример #5
0
 def test_as_annotation(self):
     """Test that the function can be used as an annotation."""
     person = PersonFactory()
     queryset = Person.objects.annotate(data=JSONBBuildObject(
         first_name='first_name', last_name='last_name'), )
     assert queryset.first().data == {
         'first_name': person.first_name,
         'last_name': person.last_name,
     }
def test_get_empty_string_if_null_expression(value, expected):
    """Tests if None can be replaced with an empty string."""
    PersonFactory()
    query = Person.objects.annotate(
        possibly_null_value=Value(value, output_field=CharField(null=True)),
        some_property=get_empty_string_if_null_expression('possibly_null_value'),
    ).values('some_property')
    person = query.first()
    assert person['some_property'] == expected
Пример #7
0
    def test_full_name_annotation(self, include_country, country):
        """Tests that a Person query set can be annotated with full names."""
        person = PersonFactory(country=country)
        bracketed_field_name = 'country' if include_country else None
        queryset = Person.objects.annotate(name=get_full_name_expression(
            bracketed_field_name=bracketed_field_name), )
        expected_name = f'{person.first_name} {person.last_name}'
        if country and include_country:
            expected_name += f' ({person.country})'

        assert queryset.first().name == expected_name
def test_get_string_agg_subquery(num_authors):
    """
    Test that get_string_agg_subquery() can be used to concatenate the first names of
    all authors for each book into one field.
    """
    authors = PersonFactory.create_batch(num_authors)
    BookFactory(authors=authors)
    queryset = Book.objects.annotate(author_names=get_string_agg_subquery(
        Book, 'authors__first_name'), )
    author_names_str = queryset.first().author_names
    actual_author_names = sorted(
        author_names_str.split(', ')) if author_names_str else []
    expected_author_names = sorted(author.first_name for author in authors)
    assert actual_author_names == expected_author_names
 def test_with_max_aggregate_expression(self, num_books):
     """
     Test that Max() can be used to calculate the maximum published-on date for the books a
     person has proofread.
     """
     proofreader = PersonFactory()
     books = BookFactory.create_batch(num_books, proofreader=proofreader)
     queryset = Person.objects.annotate(
         max_published=get_aggregate_subquery(Person, Max('proofread_books__published_on')),
     ).filter(
         pk=proofreader.pk,
     )
     actual_max_published = queryset.first().max_published
     expected_max_published = max(book.published_on for book in books) if num_books else None
     assert actual_max_published == expected_max_published
 def test_can_annotate_queryset(self, names, distinct, expected_result):
     """
     Test that the first names of all authors for each book can be concatenated into
     one field as a query set annotation for various cases.
     """
     authors = PersonFactory.create_batch(
         len(names),
         first_name=factory.Iterator(
             sample(names, len(names)),
         ),
     )
     BookFactory(authors=authors)
     queryset = Book.objects.annotate(
         author_names=get_string_agg_subquery(Book, 'authors__first_name', distinct=distinct),
     )
     actual_author_names = queryset.first().author_names
     assert actual_author_names == expected_result
Пример #11
0
 def test_orders_results_when_ordering_specified(self, ordering,
                                                 expected_names):
     """Test that the values are ordered corrected when an ordering is specified."""
     names = ['Barbara', 'Claire', 'Samantha']
     authors = PersonFactory.create_batch(
         len(names),
         first_name=factory.Iterator(sample(names, len(names)), ),
     )
     BookFactory(authors=authors)
     queryset = Book.objects.annotate(author_names=get_array_agg_subquery(
         Book.authors.through,
         'book',
         'person__first_name',
         ordering=ordering,
     ), )
     actual_author_names = queryset.first().author_names
     assert actual_author_names == expected_names
Пример #12
0
 def test_aggregates_as_filtered_array(self, names, desired_names):
     """
     Test that the desired first names of authors for each book can be aggregated into an array
     for various cases.
     """
     authors = PersonFactory.create_batch(
         len(names),
         first_name=factory.Iterator(sample(names, len(names)), ),
     )
     BookFactory(authors=authors)
     queryset = Book.objects.annotate(author_names=get_array_agg_subquery(
         Book.authors.through,
         'book',
         'person__first_name',
         filter=Q(person__first_name__in=desired_names),
     ), )
     actual_author_names = queryset.first()
     assert set(actual_author_names.author_names) == set(desired_names)
Пример #13
0
    def test_with_no_related_objects(self):
        """
        Test that, if a Person query set is annotated with the name of the most
        recently published proofread books, and there are no such books, the annotation
        value is None.

        This considers a single many-to-one relationship between Book and Person.
        """
        created_person = PersonFactory()

        queryset = Person.objects.annotate(
            name_of_latest_book=get_top_related_expression_subquery(
                Book.proofreader.field,
                'name',
                ('-published_on', ),
            ), )
        returned_person = queryset.first()
        assert returned_person == created_person
        assert returned_person.name_of_latest_book is None
 def test_annotation(
     self,
     first_name,
     last_name,
     country,
     fields,
     bracketed_field,
     expected_value,
 ):
     """
     Tests that a Person query set can be annotated using get_bracketed_concat_expression().
     """
     PersonFactory(first_name=first_name, last_name=last_name, country=country)
     queryset = Person.objects.annotate(
         name=get_bracketed_concat_expression(
             *fields,
             expression_to_bracket=bracketed_field,
         ),
     )
     assert queryset.first().name == expected_value
def test_get_top_related_expression_subquery(expression):
    """
    Test that get_top_related_expression_subquery() can be used to get the name of the most
    recently published book.
    """
    person = PersonFactory()
    book_data = [
        {
            'name': 'oldest',
            'published_on': date(2010, 1, 1)
        },
        {
            'name': 'in the middle',
            'published_on': date(2013, 1, 1)
        },
        {
            'name': 'newest',
            'published_on': date(2015, 1, 1)
        },
    ]
    shuffle(book_data)

    for item_data in book_data:
        BookFactory(
            proofreader=person,
            authors=[],
            **item_data,
        )

    queryset = Person.objects.annotate(
        name_of_latest_book=get_top_related_expression_subquery(
            Book.proofreader.field,
            expression,
            ('-published_on', ),
        ), )
    assert queryset.first().name_of_latest_book == 'newest'
Пример #16
0
 def test_full_name_annotation(self):
     """Tests that a Person query set can be annotated with full names."""
     person = PersonFactory()
     queryset = Person.objects.annotate(name=get_full_name_expression(), )
     expected_name = f'{person.first_name} {person.last_name}'
     assert queryset.first().name == expected_name
Пример #17
0
 def test_only_excludes_referenced_objects(self):
     """Test that only referenced objects are excluded."""
     unreferenced_person = PersonFactory()
     BookFactory()
     queryset = get_unreferenced_objects_query(Person)
     assert list(queryset) == [unreferenced_person]
    def test_loading(self, migration_apps):
        """
        Test that loading a yaml file updates the existing data.
        """
        yaml_content = """
# person with pk=1, last_name should change
- model: datahub.core.test.support.person
  pk: 1
  fields:
    first_name: Existing
    last_name: Person with changed surname

# person with pk=3, first_name should change, last_name shouldn't change
- model: datahub.core.test.support.person
  pk: 3
  fields:
    first_name: Another existing

# person with pk=10, a new record should be created
- model: datahub.core.test.support.person
  pk: 10
  fields:
    first_name: New
    last_name: Person

# book with pk=1, fk to person (proofreader) should change
- model: datahub.core.test.support.book
  pk: 1
  fields:
    name: Book name
    proofreader: 3
    published_on: '2010-01-01'
"""
        mocked_read = mock.mock_open(read_data=yaml_content)

        people = PersonFactory.create_batch(
            3,
            pk=factory.Iterator([1, 2, 3]),
            first_name='Existing',
            last_name='Person',
        )
        BookFactory(
            pk=1,
            name='Previous book name',
            proofreader=people[0],
            published_on=datetime.date(2010, 1, 1),
            authors=[],
        )

        with mock.patch('datahub.core.migration_utils.open', mocked_read, create=True):
            load_yaml_data_in_migration(migration_apps, 'path-to-file.yaml')

        qs = Person.objects.order_by('id').values('id', 'first_name', 'last_name')
        assert list(qs) == [
            {'id': 1, 'first_name': 'Existing', 'last_name': 'Person with changed surname'},
            {'id': 2, 'first_name': 'Existing', 'last_name': 'Person'},
            {'id': 3, 'first_name': 'Another existing', 'last_name': 'Person'},
            {'id': 10, 'first_name': 'New', 'last_name': 'Person'},
        ]

        qs = Book.objects.order_by('id').values('id', 'name', 'proofreader', 'published_on')
        assert list(qs) == [
            {
                'id': 1,
                'name': 'Book name',
                'proofreader': 3,
                'published_on': datetime.date(2010, 1, 1),
            },
        ]