def test_set_existing():
    """Setting a similarity for an existing pair just updates the score."""
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')

    sim_obj = models.ObjectSimilarity.set(obj_a, obj_b, 10)
    sim_obj_2 = models.ObjectSimilarity.set(obj_a, obj_b, 20)

    assert sim_obj.pk == sim_obj_2.pk
    assert sim_obj_2.score == 20
def test_set_existing():
    """Setting a similarity for an existing pair just updates the score."""
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')

    sim_obj = models.ObjectSimilarity.set(obj_a, obj_b, 10)
    sim_obj_2 = models.ObjectSimilarity.set(obj_a, obj_b, 20)

    assert sim_obj.pk == sim_obj_2.pk
    assert sim_obj_2.score == 20
def test_instance_list():
    """Querysets/model managers have an instance_list method."""
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foobar')
    set_score(obj_a, obj_b, 1)
    set_score(obj_a, obj_c, 2)

    instances = models.ObjectSimilarity.objects.all().order_by(
        'score').get_instances_for(obj_a)
    assert [obj_b, obj_c] == list(instances)
def test_instance_list():
    """Querysets/model managers have an instance_list method."""
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foobar')
    set_score(obj_a, obj_b, 1)
    set_score(obj_a, obj_c, 2)

    instances = models.ObjectSimilarity.objects.all().order_by(
        'score').get_instances_for(obj_a)
    assert [obj_b, obj_c] == list(instances)
def test_set_0_doesnt_create():
    """Giving a pair of new objects a score of 0 does nothing."""
    obj_a = make_quote('Hello', pk=12)
    obj_b = make_quote('World', pk=22)
    ctype = ct_models.ContentType.objects.get_for_model(obj_a)

    sim_obj = models.ObjectSimilarity.set(obj_a, obj_b, 0)

    assert sim_obj is None
    assert not models.ObjectSimilarity.objects.filter(
        object_1_content_type=ctype, object_2_content_type=ctype,
        object_1_id=obj_a.id, object_2_id=obj_b.pk).exists()
def test_similar_to():
    """similar_to is like similar_objects but returns a queryset."""
    quote_a = make_quote("foo")
    quote_b = make_quote("bar")
    quote_c = make_quote("baz")
    sim_ab = django_recommend.models.ObjectSimilarity.set(quote_a, quote_b, 10)
    sim_ac = django_recommend.models.ObjectSimilarity.set(quote_a, quote_c, 5)

    sim_quotes = django_recommend.similar_to(quote_a)
    assert list(sim_quotes) == [sim_ab, sim_ac]

    sim_quotes = sim_quotes.exclude_objects(quotes.models.Quote.objects.filter(pk=quote_b.pk))
    assert list(sim_quotes) == [sim_ac]
def test_get_instances_nopurge(settings):
    """get_instances_for propagates ObjectDoesNotExist without a handler."""
    settings.RECOMMEND_PURGE_MISSING_DATA = False
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foobar')
    set_score(obj_a, obj_b, 1)
    set_score(obj_a, obj_c, 2)
    obj_b.delete()

    with pytest.raises(quotes.models.Quote.DoesNotExist):
        models.ObjectSimilarity.objects.all().order_by(
            'score').get_instances_for(obj_a)
예제 #8
0
def test_similar_to():
    """similar_to is like similar_objects but returns a queryset."""
    quote_a = make_quote('foo')
    quote_b = make_quote('bar')
    quote_c = make_quote('baz')
    sim_ab = django_recommend.models.ObjectSimilarity.set(quote_a, quote_b, 10)
    sim_ac = django_recommend.models.ObjectSimilarity.set(quote_a, quote_c, 5)

    sim_quotes = django_recommend.similar_to(quote_a)
    assert list(sim_quotes) == [sim_ab, sim_ac]

    sim_quotes = sim_quotes.exclude_objects(
        quotes.models.Quote.objects.filter(pk=quote_b.pk))
    assert list(sim_quotes) == [sim_ac]
def test_set_0_doesnt_create():
    """Giving a pair of new objects a score of 0 does nothing."""
    obj_a = make_quote('Hello', pk=12)
    obj_b = make_quote('World', pk=22)
    ctype = ct_models.ContentType.objects.get_for_model(obj_a)

    sim_obj = models.ObjectSimilarity.set(obj_a, obj_b, 0)

    assert sim_obj is None
    assert not models.ObjectSimilarity.objects.filter(
        object_1_content_type=ctype,
        object_2_content_type=ctype,
        object_1_id=obj_a.id,
        object_2_id=obj_b.pk).exists()
def test_get_instances_nopurge(settings):
    """get_instances_for propagates ObjectDoesNotExist without a handler."""
    settings.RECOMMEND_PURGE_MISSING_DATA = False
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foobar')
    set_score(obj_a, obj_b, 1)
    set_score(obj_a, obj_c, 2)
    obj_b.delete()

    with pytest.raises(quotes.models.Quote.DoesNotExist):
        models.ObjectSimilarity.objects.all().order_by(
            'score').get_instances_for(obj_a)
def test_set_existing_to_0():
    """A score of 0 causes deletion of an existing ObjectSimilarity."""
    obj_a = make_quote('Hello', pk=12)
    obj_b = make_quote('World', pk=22)
    sim_obj = models.ObjectSimilarity.set(obj_a, obj_b, 10)
    ctype = ct_models.ContentType.objects.get_for_model(obj_a)

    models.ObjectSimilarity.set(obj_a, obj_b, 0)

    with pytest.raises(models.ObjectSimilarity.DoesNotExist):
        models.ObjectSimilarity.objects.get(pk=sim_obj.pk)

    assert not models.ObjectSimilarity.objects.filter(
        object_1_content_type=ctype, object_2_content_type=ctype,
        object_1_id=obj_a.id, object_2_id=obj_b.pk).exists()
def test_get_score_when_unset():
    """If a score is not in the DB, 0 is returned."""
    user = User.objects.create()
    quote = make_quote(content="foobar")

    assert django_recommend.models.UserScore.objects.count() == 0
    assert django_recommend.get_score(user, quote) == 0
예제 #13
0
def test_get_score_with_user():
    """The get_score function can get the user's score for an object."""
    user = User.objects.create(username='******')
    quote = make_quote(content='fizzbuzz')
    django_recommend.models.UserScore.set(user, quote, 55)

    assert django_recommend.get_score(user, quote) == 55
def test_exclude_objects_qset():
    """ObjectSimilarity qset.exclude_objects can take a queryset."""
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foo')
    obj_d = make_quote('Bar')
    sim_b = set_score(obj_a, obj_b, 1)
    set_score(obj_a, obj_c, 2)
    sim_d = set_score(obj_a, obj_d, 3)

    sims = models.ObjectSimilarity.objects.all().order_by('score')
    sims = sims.exclude_objects(
        quotes.models.Quote.objects.filter(pk=obj_c.pk))

    assert [sim_b, sim_d] == list(sims)
def test_set_bad_order():
    """ObjectSimilarity.set() always stores in the same order."""
    quote_a = make_quote(content='Hello', pk=30)
    quote_b = make_quote(content='World', pk=40)

    sim_obj = models.ObjectSimilarity.set(quote_a, quote_b, 10)

    assert sim_obj.object_1 == quote_a
    assert sim_obj.object_2 == quote_b

    # Give quotes in other order and make sure the same result happens.
    sim_obj.delete()
    sim_obj = models.ObjectSimilarity.set(quote_b, quote_a, 20)

    assert sim_obj.object_1 == quote_a
    assert sim_obj.object_2 == quote_b
예제 #16
0
def test_get_score_when_unset():
    """If a score is not in the DB, 0 is returned."""
    user = User.objects.create()
    quote = make_quote(content='foobar')

    assert django_recommend.models.UserScore.objects.count() == 0
    assert django_recommend.get_score(user, quote) == 0
def test_set_bad_order():
    """ObjectSimilarity.set() always stores in the same order."""
    quote_a = make_quote(content='Hello', pk=30)
    quote_b = make_quote(content='World', pk=40)

    sim_obj = models.ObjectSimilarity.set(quote_a, quote_b, 10)

    assert sim_obj.object_1 == quote_a
    assert sim_obj.object_2 == quote_b

    # Give quotes in other order and make sure the same result happens.
    sim_obj.delete()
    sim_obj = models.ObjectSimilarity.set(quote_b, quote_a, 20)

    assert sim_obj.object_1 == quote_a
    assert sim_obj.object_2 == quote_b
def test_exclude_objects_qset():
    """ObjectSimilarity qset.exclude_objects can take a queryset."""
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foo')
    obj_d = make_quote('Bar')
    sim_b = set_score(obj_a, obj_b, 1)
    set_score(obj_a, obj_c, 2)
    sim_d = set_score(obj_a, obj_d, 3)

    sims = models.ObjectSimilarity.objects.all().order_by('score')
    sims = sims.exclude_objects(
        quotes.models.Quote.objects.filter(pk=obj_c.pk))

    assert [sim_b, sim_d] == list(sims)
def test_get_score_with_user():
    """The get_score function can get the user's score for an object."""
    user = User.objects.create(username="******")
    quote = make_quote(content="fizzbuzz")
    django_recommend.models.UserScore.set(user, quote, 55)

    assert django_recommend.get_score(user, quote) == 55
def test_set_score_direct_user():
    """set_score() can take a user instead of a request."""
    user = User.objects.create(pk=3)
    quote = make_quote(content="fizzbuzz")

    django_recommend.set_score(user, quote, 5)

    assert django_recommend.scores_for(quote) == {"user:3": 5}
def test_get_instances_purge(settings):
    """get_instances_for deletes missing data when purge is set."""
    settings.RECOMMEND_PURGE_MISSING_DATA = True
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    django_recommend.set_score('foo', obj_a, 1)
    django_recommend.set_score('foo', obj_b, 2)
    django_recommend.tasks.update_similarity(obj_a)
    obj_b.delete()
    assert 2 == django_recommend.models.UserScore.objects.count()
    assert 1 == django_recommend.models.ObjectSimilarity.objects.count()

    models.ObjectSimilarity.objects.all().order_by('score').get_instances_for(
        obj_a)

    assert 1 == django_recommend.models.UserScore.objects.count()
    assert 0 == django_recommend.models.ObjectSimilarity.objects.count()
예제 #22
0
def test_set_score_direct_user():
    """set_score() can take a user instead of a request."""
    user = User.objects.create(pk=3)
    quote = make_quote(content='fizzbuzz')

    django_recommend.set_score(user, quote, 5)

    assert django_recommend.scores_for(quote) == {'user:3': 5}
def test_get_instances_purge(settings):
    """get_instances_for deletes missing data when purge is set."""
    settings.RECOMMEND_PURGE_MISSING_DATA = True
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    django_recommend.set_score('foo', obj_a, 1)
    django_recommend.set_score('foo', obj_b, 2)
    django_recommend.tasks.update_similarity(obj_a)
    obj_b.delete()
    assert 2 == django_recommend.models.UserScore.objects.count()
    assert 1 == django_recommend.models.ObjectSimilarity.objects.count()

    models.ObjectSimilarity.objects.all().order_by(
        'score').get_instances_for(obj_a)

    assert 1 == django_recommend.models.UserScore.objects.count()
    assert 0 == django_recommend.models.ObjectSimilarity.objects.count()
def test_set_existing_to_0():
    """A score of 0 causes deletion of an existing ObjectSimilarity."""
    obj_a = make_quote('Hello', pk=12)
    obj_b = make_quote('World', pk=22)
    sim_obj = models.ObjectSimilarity.set(obj_a, obj_b, 10)
    ctype = ct_models.ContentType.objects.get_for_model(obj_a)

    models.ObjectSimilarity.set(obj_a, obj_b, 0)

    with pytest.raises(models.ObjectSimilarity.DoesNotExist):
        models.ObjectSimilarity.objects.get(pk=sim_obj.pk)

    assert not models.ObjectSimilarity.objects.filter(
        object_1_content_type=ctype,
        object_2_content_type=ctype,
        object_1_id=obj_a.id,
        object_2_id=obj_b.pk).exists()
def sample_data():
    """Create a set of sample data."""
    quote = {
        1: make_quote('quote 1'),
        2: make_quote('quote 2'),
        3: make_quote('quote 3'),
        4: make_quote('quote 4'),
    }

    django_recommend.set_score('foo', quote[1], 3)
    django_recommend.set_score('foo', quote[2], 2)
    django_recommend.set_score('bar', quote[2], 3)
    django_recommend.set_score('bar', quote[3], 4)
    django_recommend.set_score('baz', quote[4], 5)

    # Note: quote 4/baz are not related to other users/quotes.

    return quote
예제 #26
0
def sample_data():
    """Create a set of sample data."""
    quote = {
        1: make_quote('quote 1'),
        2: make_quote('quote 2'),
        3: make_quote('quote 3'),
        4: make_quote('quote 4'),
    }

    django_recommend.set_score('foo', quote[1], 3)
    django_recommend.set_score('foo', quote[2], 2)
    django_recommend.set_score('bar', quote[2], 3)
    django_recommend.set_score('bar', quote[3], 4)
    django_recommend.set_score('baz', quote[4], 5)

    # Note: quote 4/baz are not related to other users/quotes.

    return quote
def test_filter_objects():
    """ObjectSimilarity qset.filter_objects takes a queryset."""
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foo')
    obj_d = make_quote('Bar')
    sim_ab = set_score(obj_a, obj_b, 1)
    sim_ac = set_score(obj_a, obj_c, 2)
    sim_ad = set_score(obj_a, obj_d, 3)
    set_score(obj_b, obj_c, 5)  # This data that shouldn't be included
    set_score(obj_b, obj_d, 6)

    quote_a = quotes.models.Quote.objects.filter(pk=obj_a.pk)
    sims = models.ObjectSimilarity.objects.filter_objects(quote_a)
    sims = sims.order_by('score')

    assert [sim_ab, sim_ac, sim_ad] == list(sims)
def test_filter_objects():
    """ObjectSimilarity qset.filter_objects takes a queryset."""
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foo')
    obj_d = make_quote('Bar')
    sim_ab = set_score(obj_a, obj_b, 1)
    sim_ac = set_score(obj_a, obj_c, 2)
    sim_ad = set_score(obj_a, obj_d, 3)
    set_score(obj_b, obj_c, 5)  # This data that shouldn't be included
    set_score(obj_b, obj_d, 6)

    quote_a = quotes.models.Quote.objects.filter(pk=obj_a.pk)
    sims = models.ObjectSimilarity.objects.filter_objects(quote_a)
    sims = sims.order_by('score')

    assert [sim_ab, sim_ac, sim_ad] == list(sims)
def test_get_instances_fallback():
    """get_instances_for uses a callback when an instance is missing."""
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foobar')
    ctype = ct_models.ContentType.objects.get_for_model(obj_a)
    set_score(obj_a, obj_b, 1)
    set_score(obj_a, obj_c, 2)
    obj_b_pk = obj_b.pk  # .pk gets set to None after delete()
    obj_b.delete()
    handle_missing = mock.MagicMock()

    objs = models.ObjectSimilarity.objects.all().order_by(
        'score').get_instances_for(obj_a, handle_missing)

    assert 1 == handle_missing.call_count
    assert mock.call(ctype.pk, obj_b_pk) == handle_missing.call_args
    assert [obj_c] == list(objs)
예제 #30
0
def test_set_score_request_user(client):
    """The set_score method associates a score with a user."""
    make_user(username='******', password='******', pk=30)
    assert client.login(username='******', password='******')
    req = client.get('/foo').wsgi_request
    quote = make_quote(content='hello world')

    django_recommend.set_score(req, quote, 1)

    assert django_recommend.scores_for(quote) == {'user:30': 1}

    make_user(username='******', password='******', pk=55)
    assert client.login(username='******', password='******')
    req = client.get('/bar/').wsgi_request
    quote = make_quote(content='Fizzbuzz')

    django_recommend.set_score(req, quote, 5)

    assert django_recommend.scores_for(quote) == {'user:55': 5}
def test_get_instances_fallback():
    """get_instances_for uses a callback when an instance is missing."""
    set_score = models.ObjectSimilarity.set  # Just a readability alias
    obj_a = make_quote('Hello')
    obj_b = make_quote('World')
    obj_c = make_quote('Foobar')
    ctype = ct_models.ContentType.objects.get_for_model(obj_a)
    set_score(obj_a, obj_b, 1)
    set_score(obj_a, obj_c, 2)
    obj_b_pk = obj_b.pk  # .pk gets set to None after delete()
    obj_b.delete()
    handle_missing = mock.MagicMock()

    objs = models.ObjectSimilarity.objects.all().order_by(
        'score').get_instances_for(obj_a, handle_missing)

    assert 1 == handle_missing.call_count
    assert mock.call(ctype.pk, obj_b_pk) == handle_missing.call_args
    assert [obj_c] == list(objs)
def test_setdefault_score():
    """setdefault_score only sets a score if it doesn't exist."""
    user = User.objects.create()
    quote = make_quote(content="foobar")

    assert django_recommend.get_score(user, quote) == 0
    django_recommend.setdefault_score(user, quote, 3)
    assert django_recommend.get_score(user, quote) == 3
    django_recommend.setdefault_score(user, quote, 5)
    assert django_recommend.get_score(user, quote) == 3
예제 #33
0
def test_setdefault_score():
    """setdefault_score only sets a score if it doesn't exist."""
    user = User.objects.create()
    quote = make_quote(content='foobar')

    assert django_recommend.get_score(user, quote) == 0
    django_recommend.setdefault_score(user, quote, 3)
    assert django_recommend.get_score(user, quote) == 3
    django_recommend.setdefault_score(user, quote, 5)
    assert django_recommend.get_score(user, quote) == 3
def test_set_score_request_user(client):
    """The set_score method associates a score with a user."""
    make_user(username="******", password="******", pk=30)
    assert client.login(username="******", password="******")
    req = client.get("/foo").wsgi_request
    quote = make_quote(content="hello world")

    django_recommend.set_score(req, quote, 1)

    assert django_recommend.scores_for(quote) == {"user:30": 1}

    make_user(username="******", password="******", pk=55)
    assert client.login(username="******", password="******")
    req = client.get("/bar/").wsgi_request
    quote = make_quote(content="Fizzbuzz")

    django_recommend.set_score(req, quote, 5)

    assert django_recommend.scores_for(quote) == {"user:55": 5}
예제 #35
0
def test_get_similar_objects():
    """get_similar_objects gets instances most similar to the given object."""
    quote_a = make_quote('foo')
    quote_b = make_quote('bar')
    quote_c = make_quote('baz')
    django_recommend.models.ObjectSimilarity.set(quote_a, quote_b, 10)
    django_recommend.models.ObjectSimilarity.set(quote_a, quote_c, 5)

    sim_quotes = django_recommend.similar_objects(quote_a)
    assert list(sim_quotes) == [quote_b, quote_c]

    # Change scores to ensure sorted order is given.
    django_recommend.models.ObjectSimilarity.set(quote_a, quote_b, 4)
    django_recommend.models.ObjectSimilarity.set(quote_a, quote_c, 12)

    sim_quotes = django_recommend.similar_objects(quote_a)
    assert list(sim_quotes) == [quote_c, quote_b]

    # Change which object is requested to make sure SUT isn't only filtering
    # against object_1
    sim_quotes = django_recommend.similar_objects(quote_b)
    assert list(sim_quotes) == [quote_a]
예제 #36
0
def test_forget_object():
    """forget_object() will delete all similarity data for objects."""
    make_quote = quotes.models.Quote.objects.create
    obj_a = make_quote(content='Hello')
    obj_b = make_quote(content='World')
    obj_c = make_quote(content='Foobar')
    django_recommend.set_score('foo', obj_a, 1)
    django_recommend.set_score('foo', obj_b, 1)
    django_recommend.set_score('foo', obj_c, 1)
    ctype = ct_models.ContentType.objects.get_for_model(obj_a)
    django_recommend.tasks.update_similarity((obj_a.pk, ctype.pk))
    ctype = ct_models.ContentType.objects.get_for_model(obj_b)
    obj_b_pk = obj_b.pk  # .pk gets set to None after delete()
    obj_b.delete()
    obj_b.pk = obj_b_pk

    django_recommend.forget_object(ctype.pk, obj_b_pk)

    assert 1 == django_recommend.models.ObjectSimilarity.objects.count()
    assert 2 == django_recommend.models.UserScore.objects.count()
    assert 0 == django_recommend.get_score('foo', obj_b)
    assert [obj_c] == django_recommend.similar_objects(obj_a)
def test_get_similar_objects():
    """get_similar_objects gets instances most similar to the given object."""
    quote_a = make_quote("foo")
    quote_b = make_quote("bar")
    quote_c = make_quote("baz")
    django_recommend.models.ObjectSimilarity.set(quote_a, quote_b, 10)
    django_recommend.models.ObjectSimilarity.set(quote_a, quote_c, 5)

    sim_quotes = django_recommend.similar_objects(quote_a)
    assert list(sim_quotes) == [quote_b, quote_c]

    # Change scores to ensure sorted order is given.
    django_recommend.models.ObjectSimilarity.set(quote_a, quote_b, 4)
    django_recommend.models.ObjectSimilarity.set(quote_a, quote_c, 12)

    sim_quotes = django_recommend.similar_objects(quote_a)
    assert list(sim_quotes) == [quote_c, quote_b]

    # Change which object is requested to make sure SUT isn't only filtering
    # against object_1
    sim_quotes = django_recommend.similar_objects(quote_b)
    assert list(sim_quotes) == [quote_a]
def test_forget_object():
    """forget_object() will delete all similarity data for objects."""
    make_quote = quotes.models.Quote.objects.create
    obj_a = make_quote(content="Hello")
    obj_b = make_quote(content="World")
    obj_c = make_quote(content="Foobar")
    django_recommend.set_score("foo", obj_a, 1)
    django_recommend.set_score("foo", obj_b, 1)
    django_recommend.set_score("foo", obj_c, 1)
    ctype = ct_models.ContentType.objects.get_for_model(obj_a)
    django_recommend.tasks.update_similarity((obj_a.pk, ctype.pk))
    ctype = ct_models.ContentType.objects.get_for_model(obj_b)
    obj_b_pk = obj_b.pk  # .pk gets set to None after delete()
    obj_b.delete()
    obj_b.pk = obj_b_pk

    django_recommend.forget_object(ctype.pk, obj_b_pk)

    assert 1 == django_recommend.models.ObjectSimilarity.objects.count()
    assert 2 == django_recommend.models.UserScore.objects.count()
    assert 0 == django_recommend.get_score("foo", obj_b)
    assert [obj_c] == django_recommend.similar_objects(obj_a)