Merge branch 'release/0.10.7'
This commit is contained in:
@@ -28,4 +28,4 @@ deploy:
|
|||||||
secure: IxPnc95OFNQsl7kFfLlLc38KfHh/W79VXnhEkdb2x1GZznOsG167QlhpAnyXIJysCQxgMMwLMuPOOdk1WIxOpGNM1/M80hNzPAfxMYWPuwposDdwoIc8SyREPJt16BXWAY+rAH8SHxld9p1YdRbOEPSSglODe4dCmQWsCbKjV3aKv+gZxBvf6pMxUglp2fBIlCwrE77MyMYh9iW0AGzD6atC2xN9NgAm4f+2WFlKCUL/MztLhNWdvWEiibQav6Tts7p8tWrsBVzywDW2IOy3O0ihPgRdISZ7QrxhiJTjlHYPAy4eRGOnYSQXvp6Dy8ONE5a6Uv5g3Xw2UmQo85sSMUs2VxR0G7d+PQgL0A7ENBQ5i7eSAFHYs8EswiGilW2A7mM4qRXwg9URLelYSdkM+aNXvR+25dCsXakiO4NjCz/BPgNzxPeQLlBdxR5vHugeM/XYuhy6CHlZrR/uueaO0X8RyhJcqeDjBy58IrwYS3Mpj7QCfBpQ9PqsqXEWV9BKwKiBXM2+3hkhawFDWa0GW2PDbORKtSLy/ORfGLx5Y9qxQYKEGvFQA3iqkTjrLj+KeUziKtuvEAcvsdBIJVIxeoHwdl+qqxEm8A7YuRBnWVxWc3jE6wBXboeFP92gVe/ueoXmY22riK9Ja0pli3TyNga8by9WM8Qp4D2ZqkVXHwg=
|
secure: IxPnc95OFNQsl7kFfLlLc38KfHh/W79VXnhEkdb2x1GZznOsG167QlhpAnyXIJysCQxgMMwLMuPOOdk1WIxOpGNM1/M80hNzPAfxMYWPuwposDdwoIc8SyREPJt16BXWAY+rAH8SHxld9p1YdRbOEPSSglODe4dCmQWsCbKjV3aKv+gZxBvf6pMxUglp2fBIlCwrE77MyMYh9iW0AGzD6atC2xN9NgAm4f+2WFlKCUL/MztLhNWdvWEiibQav6Tts7p8tWrsBVzywDW2IOy3O0ihPgRdISZ7QrxhiJTjlHYPAy4eRGOnYSQXvp6Dy8ONE5a6Uv5g3Xw2UmQo85sSMUs2VxR0G7d+PQgL0A7ENBQ5i7eSAFHYs8EswiGilW2A7mM4qRXwg9URLelYSdkM+aNXvR+25dCsXakiO4NjCz/BPgNzxPeQLlBdxR5vHugeM/XYuhy6CHlZrR/uueaO0X8RyhJcqeDjBy58IrwYS3Mpj7QCfBpQ9PqsqXEWV9BKwKiBXM2+3hkhawFDWa0GW2PDbORKtSLy/ORfGLx5Y9qxQYKEGvFQA3iqkTjrLj+KeUziKtuvEAcvsdBIJVIxeoHwdl+qqxEm8A7YuRBnWVxWc3jE6wBXboeFP92gVe/ueoXmY22riK9Ja0pli3TyNga8by9WM8Qp4D2ZqkVXHwg=
|
||||||
on:
|
on:
|
||||||
tags: true
|
tags: true
|
||||||
all_branches: true
|
condition: $TOXENV = py27-django111-wagtail113
|
||||||
|
6
CHANGES
6
CHANGES
@@ -1,3 +1,9 @@
|
|||||||
|
0.10.7
|
||||||
|
==================
|
||||||
|
- Bug Fix: Ensure static segment members are show the survey immediately
|
||||||
|
- Records users excluded by randomisation on the segment
|
||||||
|
- Don't re-check excluded users
|
||||||
|
|
||||||
0.10.6
|
0.10.6
|
||||||
==================
|
==================
|
||||||
- Accepts and stores randomisation percentage for segment
|
- Accepts and stores randomisation percentage for segment
|
||||||
|
@@ -55,10 +55,10 @@ author = 'Lab Digital BV'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.10.6'
|
version = '0.10.7'
|
||||||
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.10.6'
|
release = '0.10.7'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 0.10.6
|
current_version = 0.10.7
|
||||||
commit = true
|
commit = true
|
||||||
tag = true
|
tag = true
|
||||||
tag_name = {new_version}
|
tag_name = {new_version}
|
||||||
|
2
setup.py
2
setup.py
@@ -32,7 +32,7 @@ with open('README.rst') as fh:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='wagtail-personalisation-molo',
|
name='wagtail-personalisation-molo',
|
||||||
version='0.10.6',
|
version='0.10.7',
|
||||||
description='A forked version of Wagtail add-on for showing personalized content',
|
description='A forked version of Wagtail add-on for showing personalized content',
|
||||||
author='Praekelt.org',
|
author='Praekelt.org',
|
||||||
author_email='dev@praekeltfoundation.org',
|
author_email='dev@praekeltfoundation.org',
|
||||||
|
@@ -177,6 +177,8 @@ class SessionSegmentsAdapter(BaseSegmentsAdapter):
|
|||||||
for segment in enabled_segments:
|
for segment in enabled_segments:
|
||||||
if segment.is_static and segment.static_users.filter(id=self.request.user.id).exists():
|
if segment.is_static and segment.static_users.filter(id=self.request.user.id).exists():
|
||||||
additional_segments.append(segment)
|
additional_segments.append(segment)
|
||||||
|
elif segment.excluded_users.filter(id=self.request.user.id).exists():
|
||||||
|
continue
|
||||||
elif not segment.is_static or not segment.is_full:
|
elif not segment.is_static or not segment.is_full:
|
||||||
segment_rules = []
|
segment_rules = []
|
||||||
for rule_model in rule_models:
|
for rule_model in rule_models:
|
||||||
@@ -184,12 +186,15 @@ class SessionSegmentsAdapter(BaseSegmentsAdapter):
|
|||||||
|
|
||||||
result = self._test_rules(segment_rules, self.request,
|
result = self._test_rules(segment_rules, self.request,
|
||||||
match_any=segment.match_any)
|
match_any=segment.match_any)
|
||||||
|
|
||||||
if result and segment.randomise_into_segment():
|
if result and segment.randomise_into_segment():
|
||||||
if segment.is_static and not segment.is_full:
|
if segment.is_static and not segment.is_full:
|
||||||
if self.request.user.is_authenticated():
|
if self.request.user.is_authenticated():
|
||||||
segment.static_users.add(self.request.user)
|
segment.static_users.add(self.request.user)
|
||||||
else:
|
|
||||||
additional_segments.append(segment)
|
additional_segments.append(segment)
|
||||||
|
elif result:
|
||||||
|
if self.request.user.is_authenticated():
|
||||||
|
segment.excluded_users.add(self.request.user)
|
||||||
|
|
||||||
self.set_segments(current_segments + additional_segments)
|
self.set_segments(current_segments + additional_segments)
|
||||||
self.update_visit_count()
|
self.update_visit_count()
|
||||||
|
@@ -107,6 +107,7 @@ class SegmentAdminForm(WagtailAdminModelForm):
|
|||||||
adapter = get_segment_adapter(request)
|
adapter = get_segment_adapter(request)
|
||||||
|
|
||||||
users_to_add = []
|
users_to_add = []
|
||||||
|
users_to_exclude = []
|
||||||
sessions = Session.objects.iterator()
|
sessions = Session.objects.iterator()
|
||||||
take_session = takewhile(
|
take_session = takewhile(
|
||||||
lambda x: instance.count == 0 or len(users_to_add) <= instance.count,
|
lambda x: instance.count == 0 or len(users_to_add) <= instance.count,
|
||||||
@@ -121,8 +122,11 @@ class SegmentAdminForm(WagtailAdminModelForm):
|
|||||||
passes = adapter._test_rules(instance.get_rules(), request, instance.match_any)
|
passes = adapter._test_rules(instance.get_rules(), request, instance.match_any)
|
||||||
if passes and instance.randomise_into_segment():
|
if passes and instance.randomise_into_segment():
|
||||||
users_to_add.append(user)
|
users_to_add.append(user)
|
||||||
|
elif passes:
|
||||||
|
users_to_exclude.append(user)
|
||||||
|
|
||||||
instance.static_users.add(*users_to_add)
|
instance.static_users.add(*users_to_add)
|
||||||
|
instance.excluded_users.add(*users_to_exclude)
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
@@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.9 on 2018-02-09 08:28
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('wagtail_personalisation', '0017_segment_randomisation_percent'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='segment',
|
||||||
|
name='excluded_users',
|
||||||
|
field=models.ManyToManyField(help_text='Users that matched the rules but were excluded from the segment for some reason e.g. randomisation', related_name='excluded_segments', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
@@ -83,6 +83,12 @@ class Segment(ClusterableModel):
|
|||||||
static_users = models.ManyToManyField(
|
static_users = models.ManyToManyField(
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
)
|
)
|
||||||
|
excluded_users = models.ManyToManyField(
|
||||||
|
settings.AUTH_USER_MODEL,
|
||||||
|
help_text=_("Users that matched the rules but were excluded from the "
|
||||||
|
"segment for some reason e.g. randomisation"),
|
||||||
|
related_name="excluded_segments"
|
||||||
|
)
|
||||||
|
|
||||||
matched_users_count = models.PositiveIntegerField(default=0, editable=False)
|
matched_users_count = models.PositiveIntegerField(default=0, editable=False)
|
||||||
matched_count_updated_at = models.DateTimeField(null=True, editable=False)
|
matched_count_updated_at = models.DateTimeField(null=True, editable=False)
|
||||||
|
@@ -282,7 +282,7 @@ def test_randomisation_percentage_max_100(site, client, mocker, django_user_mode
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_in_segment_if_random_is_below_percentage(site, client, mocker, user):
|
def test_in_static_segment_if_random_is_below_percentage(site, client, mocker, user):
|
||||||
segment = SegmentFactory.build(type=Segment.TYPE_STATIC, count=1,
|
segment = SegmentFactory.build(type=Segment.TYPE_STATIC, count=1,
|
||||||
randomisation_percent=40)
|
randomisation_percent=40)
|
||||||
rule = VisitCountRule(counted_page=site.root_page)
|
rule = VisitCountRule(counted_page=site.root_page)
|
||||||
@@ -295,11 +295,13 @@ def test_in_segment_if_random_is_below_percentage(site, client, mocker, user):
|
|||||||
client.force_login(user)
|
client.force_login(user)
|
||||||
client.get(site.root_page.url)
|
client.get(site.root_page.url)
|
||||||
|
|
||||||
|
assert instance.id == client.session['segments'][0]['id']
|
||||||
assert user in instance.static_users.all()
|
assert user in instance.static_users.all()
|
||||||
|
assert user not in instance.excluded_users.all()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_not_in_segment_if_random_is_above_percentage(site, client, mocker, user):
|
def test_not_in_static_segment_if_random_is_above_percentage(site, client, mocker, user):
|
||||||
segment = SegmentFactory.build(type=Segment.TYPE_STATIC, count=1,
|
segment = SegmentFactory.build(type=Segment.TYPE_STATIC, count=1,
|
||||||
randomisation_percent=40)
|
randomisation_percent=40)
|
||||||
rule = VisitCountRule(counted_page=site.root_page)
|
rule = VisitCountRule(counted_page=site.root_page)
|
||||||
@@ -312,7 +314,41 @@ def test_not_in_segment_if_random_is_above_percentage(site, client, mocker, user
|
|||||||
client.force_login(user)
|
client.force_login(user)
|
||||||
client.get(site.root_page.url)
|
client.get(site.root_page.url)
|
||||||
|
|
||||||
|
assert len(client.session['segments']) == 0
|
||||||
assert user not in instance.static_users.all()
|
assert user not in instance.static_users.all()
|
||||||
|
assert user in instance.excluded_users.all()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_offered_dynamic_segment_if_random_is_below_percentage(site, client, mocker):
|
||||||
|
segment = SegmentFactory.build(type=Segment.TYPE_DYNAMIC,
|
||||||
|
randomisation_percent=40)
|
||||||
|
rule = VisitCountRule(counted_page=site.root_page)
|
||||||
|
form = form_with_data(segment, rule)
|
||||||
|
instance = form.save()
|
||||||
|
|
||||||
|
mocker.patch('random.randint', return_value=39)
|
||||||
|
session = client.session
|
||||||
|
session.save()
|
||||||
|
client.get(site.root_page.url)
|
||||||
|
|
||||||
|
assert instance.id == client.session['segments'][0]['id']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_not_offered_dynamic_segment_if_random_is_above_percentage(site, client, mocker):
|
||||||
|
segment = SegmentFactory.build(type=Segment.TYPE_DYNAMIC,
|
||||||
|
randomisation_percent=40)
|
||||||
|
rule = VisitCountRule(counted_page=site.root_page)
|
||||||
|
form = form_with_data(segment, rule)
|
||||||
|
form.save()
|
||||||
|
|
||||||
|
mocker.patch('random.randint', return_value=41)
|
||||||
|
session = client.session
|
||||||
|
session.save()
|
||||||
|
client.get(site.root_page.url)
|
||||||
|
|
||||||
|
assert len(client.session['segments']) == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -328,7 +364,9 @@ def test_not_in_segment_if_percentage_is_0(site, client, mocker, user):
|
|||||||
client.force_login(user)
|
client.force_login(user)
|
||||||
client.get(site.root_page.url)
|
client.get(site.root_page.url)
|
||||||
|
|
||||||
|
assert len(client.session['segments']) == 0
|
||||||
assert user not in instance.static_users.all()
|
assert user not in instance.static_users.all()
|
||||||
|
assert user in instance.excluded_users.all()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -344,7 +382,9 @@ def test_always_in_segment_if_percentage_is_100(site, client, mocker, user):
|
|||||||
client.force_login(user)
|
client.force_login(user)
|
||||||
client.get(site.root_page.url)
|
client.get(site.root_page.url)
|
||||||
|
|
||||||
|
assert instance.id == client.session['segments'][0]['id']
|
||||||
assert user in instance.static_users.all()
|
assert user in instance.static_users.all()
|
||||||
|
assert user not in instance.excluded_users.all()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -361,6 +401,7 @@ def test_not_added_to_static_segment_at_creation_if_random_above_percent(site, c
|
|||||||
instance = form.save()
|
instance = form.save()
|
||||||
|
|
||||||
assert user not in instance.static_users.all()
|
assert user not in instance.static_users.all()
|
||||||
|
assert user in instance.excluded_users.all()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -377,6 +418,31 @@ def test_added_to_static_segment_at_creation_if_random_below_percent(site, clien
|
|||||||
instance = form.save()
|
instance = form.save()
|
||||||
|
|
||||||
assert user in instance.static_users.all()
|
assert user in instance.static_users.all()
|
||||||
|
assert user not in instance.excluded_users.all()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_rules_check_skipped_if_user_in_excluded(site, client, mocker, user):
|
||||||
|
segment = SegmentFactory.build(type=Segment.TYPE_STATIC, count=1,
|
||||||
|
randomisation_percent=100)
|
||||||
|
rule = VisitCountRule(counted_page=site.root_page)
|
||||||
|
form = form_with_data(segment, rule)
|
||||||
|
instance = form.save()
|
||||||
|
instance.excluded_users.add(user)
|
||||||
|
instance.save
|
||||||
|
|
||||||
|
mock_test_rule = mocker.patch(
|
||||||
|
'wagtail_personalisation.adapters.SessionSegmentsAdapter._test_rules')
|
||||||
|
|
||||||
|
session = client.session
|
||||||
|
session.save()
|
||||||
|
client.force_login(user)
|
||||||
|
client.get(site.root_page.url)
|
||||||
|
|
||||||
|
assert mock_test_rule.call_count == 0
|
||||||
|
assert len(client.session['segments']) == 0
|
||||||
|
assert user not in instance.static_users.all()
|
||||||
|
assert user in instance.excluded_users.all()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
|
Reference in New Issue
Block a user