Best Python code snippet using lisa_python
test_user.py
Source:test_user.py  
1from unittest.mock import Mock, patch2import pytest3from django.core.exceptions import ObjectDoesNotExist4from django.urls import reverse5from django.utils import timezone6from rest_framework import status7from rest_framework.response import Response8from rest_framework.test import APIClient9from apps.base.constants import ADMIN_PERMISSIONS, EDITOR_PERMISSIONS10from apps.base.models import UserNotificationPolicy11from apps.user_management.models.user import default_working_hours12from common.constants.role import Role13@pytest.mark.django_db14def test_update_user(15    make_organization,16    make_team,17    make_user_for_organization,18    make_token_for_organization,19    make_user_auth_headers,20):21    organization = make_organization()22    admin = make_user_for_organization(organization)23    team = make_team(organization)24    team.users.add(admin)25    _, token = make_token_for_organization(organization)26    client = APIClient()27    url = reverse("api-internal:user-detail", kwargs={"pk": admin.public_primary_key})28    data = {29        "unverified_phone_number": "+79123456789",30        "current_team": team.public_primary_key,31    }32    response = client.put(url, data, format="json", **make_user_auth_headers(admin, token))33    assert response.status_code == status.HTTP_200_OK34    assert response.json()["unverified_phone_number"] == data["unverified_phone_number"]35    assert response.json()["current_team"] == data["current_team"]36@pytest.mark.django_db37def test_update_user_cant_change_email_and_username(38    make_organization,39    make_user_for_organization,40    make_token_for_organization,41    make_user_auth_headers,42):43    organization = make_organization()44    admin = make_user_for_organization(organization)45    _, token = make_token_for_organization(organization)46    client = APIClient()47    url = reverse("api-internal:user-detail", kwargs={"pk": admin.public_primary_key})48    phone_number = "+79123456789"49    data = {50        "unverified_phone_number": phone_number,51        "email": "test@amixr.io",52        "username": "bob",53    }54    expected_response = {55        "pk": admin.public_primary_key,56        "organization": {"pk": organization.public_primary_key, "name": organization.org_title},57        "current_team": None,58        "email": admin.email,59        "hide_phone_number": False,60        "username": admin.username,61        "role": admin.role,62        "timezone": None,63        "working_hours": default_working_hours(),64        "unverified_phone_number": phone_number,65        "verified_phone_number": None,66        "telegram_configuration": None,67        "messaging_backends": {68            "TESTONLY": {69                "user": admin.username,70            }71        },72        "cloud_connection_status": 0,73        "permissions": ADMIN_PERMISSIONS,74        "notification_chain_verbal": {"default": "", "important": ""},75        "slack_user_identity": None,76        "avatar": admin.avatar_url,77    }78    response = client.put(url, data, format="json", **make_user_auth_headers(admin, token))79    assert response.status_code == status.HTTP_200_OK80    assert response.json() == expected_response81@pytest.mark.django_db82def test_list_users(83    make_organization,84    make_user_for_organization,85    make_token_for_organization,86    make_user_auth_headers,87):88    organization = make_organization()89    admin = make_user_for_organization(organization)90    editor = make_user_for_organization(organization, role=Role.EDITOR)91    _, token = make_token_for_organization(organization)92    client = APIClient()93    url = reverse("api-internal:user-list")94    expected_payload = {95        "count": 2,96        "next": None,97        "previous": None,98        "results": [99            {100                "pk": admin.public_primary_key,101                "organization": {"pk": organization.public_primary_key, "name": organization.org_title},102                "current_team": None,103                "email": admin.email,104                "hide_phone_number": False,105                "username": admin.username,106                "role": admin.role,107                "timezone": None,108                "working_hours": default_working_hours(),109                "unverified_phone_number": None,110                "verified_phone_number": None,111                "telegram_configuration": None,112                "messaging_backends": {113                    "TESTONLY": {114                        "user": admin.username,115                    }116                },117                "permissions": ADMIN_PERMISSIONS,118                "notification_chain_verbal": {"default": "", "important": ""},119                "slack_user_identity": None,120                "avatar": admin.avatar_url,121                "cloud_connection_status": 0,122            },123            {124                "pk": editor.public_primary_key,125                "organization": {"pk": organization.public_primary_key, "name": organization.org_title},126                "current_team": None,127                "email": editor.email,128                "hide_phone_number": False,129                "username": editor.username,130                "role": editor.role,131                "timezone": None,132                "working_hours": default_working_hours(),133                "unverified_phone_number": None,134                "verified_phone_number": None,135                "telegram_configuration": None,136                "messaging_backends": {137                    "TESTONLY": {138                        "user": editor.username,139                    }140                },141                "permissions": EDITOR_PERMISSIONS,142                "notification_chain_verbal": {"default": "", "important": ""},143                "slack_user_identity": None,144                "avatar": editor.avatar_url,145                "cloud_connection_status": 0,146            },147        ],148    }149    response = client.get(url, format="json", **make_user_auth_headers(admin, token))150    assert response.status_code == status.HTTP_200_OK151    assert response.json() == expected_payload152@pytest.mark.django_db153def test_notification_chain_verbal(154    make_organization,155    make_user_for_organization,156    make_token_for_organization,157    make_user_auth_headers,158    make_user_notification_policy,159):160    organization = make_organization()161    admin = make_user_for_organization(organization)162    _, token = make_token_for_organization(organization)163    data_for_creation = [164        {"step": UserNotificationPolicy.Step.NOTIFY, "notify_by": UserNotificationPolicy.NotificationChannel.SLACK},165        {"step": UserNotificationPolicy.Step.WAIT, "wait_delay": timezone.timedelta(minutes=5)},166        {167            "step": UserNotificationPolicy.Step.NOTIFY,168            "notify_by": UserNotificationPolicy.NotificationChannel.PHONE_CALL,169        },170        {"step": UserNotificationPolicy.Step.WAIT, "wait_delay": None},171        {"step": UserNotificationPolicy.Step.NOTIFY, "notify_by": UserNotificationPolicy.NotificationChannel.TELEGRAM},172        {"step": None},173        {174            "step": UserNotificationPolicy.Step.NOTIFY,175            "notify_by": UserNotificationPolicy.NotificationChannel.SLACK,176            "important": True,177        },178        {"step": UserNotificationPolicy.Step.WAIT, "wait_delay": timezone.timedelta(minutes=5), "important": True},179        {180            "step": UserNotificationPolicy.Step.NOTIFY,181            "notify_by": UserNotificationPolicy.NotificationChannel.PHONE_CALL,182            "important": True,183        },184        {"step": UserNotificationPolicy.Step.WAIT, "wait_delay": None, "important": True},185        {186            "step": UserNotificationPolicy.Step.NOTIFY,187            "notify_by": UserNotificationPolicy.NotificationChannel.TELEGRAM,188            "important": True,189        },190    ]191    for data in data_for_creation:192        make_user_notification_policy(admin, **data)193    client = APIClient()194    url = reverse("api-internal:user-detail", kwargs={"pk": admin.public_primary_key})195    expected_notification_chain = {196        "default": "Slack - 5 min - \U0000260E - Telegram",197        "important": "Slack - 5 min - \U0000260E - Telegram",198    }199    response = client.get(url, format="json", **make_user_auth_headers(admin, token))200    assert response.status_code == status.HTTP_200_OK201    assert response.json()["notification_chain_verbal"] == expected_notification_chain202@pytest.mark.django_db203@pytest.mark.parametrize(204    "role,expected_status",205    [206        (Role.ADMIN, status.HTTP_200_OK),207        (Role.EDITOR, status.HTTP_200_OK),208        (Role.VIEWER, status.HTTP_403_FORBIDDEN),209    ],210)211def test_user_update_self_permissions(212    make_organization,213    make_user_for_organization,214    make_token_for_organization,215    make_user_auth_headers,216    role,217    expected_status,218):219    organization = make_organization()220    tester = make_user_for_organization(organization, role=role)221    _, token = make_token_for_organization(organization)222    client = APIClient()223    url = reverse("api-internal:user-detail", kwargs={"pk": tester.public_primary_key})224    with patch(225        "apps.api.views.user.UserView.update",226        return_value=Response(227            status=status.HTTP_200_OK,228        ),229    ):230        response = client.put(url, format="json", **make_user_auth_headers(tester, token))231    assert response.status_code == expected_status232@pytest.mark.django_db233@pytest.mark.parametrize(234    "role,expected_status",235    [236        (Role.ADMIN, status.HTTP_200_OK),237        (Role.EDITOR, status.HTTP_403_FORBIDDEN),238        (Role.VIEWER, status.HTTP_403_FORBIDDEN),239    ],240)241def test_user_update_other_permissions(242    make_organization,243    make_user_for_organization,244    make_token_for_organization,245    make_user_auth_headers,246    role,247    expected_status,248):249    organization = make_organization()250    admin = make_user_for_organization(organization)251    tester = make_user_for_organization(organization, role=role)252    _, token = make_token_for_organization(organization)253    client = APIClient()254    url = reverse("api-internal:user-detail", kwargs={"pk": admin.public_primary_key})255    data = {"unverified_phone_number": "+79123456789"}256    response = client.put(url, data, format="json", **make_user_auth_headers(tester, token))257    assert response.status_code == expected_status258@pytest.mark.django_db259@pytest.mark.parametrize(260    "role,expected_status",261    [262        (Role.ADMIN, status.HTTP_200_OK),263        (Role.EDITOR, status.HTTP_200_OK),264        (Role.VIEWER, status.HTTP_403_FORBIDDEN),265    ],266)267def test_user_list_permissions(268    make_organization,269    make_user_for_organization,270    make_token_for_organization,271    make_user_auth_headers,272    role,273    expected_status,274):275    organization = make_organization()276    tester = make_user_for_organization(organization, role=role)277    _, token = make_token_for_organization(organization)278    client = APIClient()279    url = reverse("api-internal:user-list")280    with patch(281        "apps.api.views.user.UserView.list",282        return_value=Response(283            status=status.HTTP_200_OK,284        ),285    ):286        response = client.get(url, format="json", **make_user_auth_headers(tester, token))287    assert response.status_code == expected_status288@pytest.mark.django_db289@pytest.mark.parametrize(290    "role,expected_status",291    [292        (Role.ADMIN, status.HTTP_200_OK),293        (Role.EDITOR, status.HTTP_200_OK),294        (Role.VIEWER, status.HTTP_200_OK),295    ],296)297def test_user_detail_self_permissions(298    make_organization,299    make_user_for_organization,300    make_token_for_organization,301    make_user_auth_headers,302    role,303    expected_status,304):305    organization = make_organization()306    tester = make_user_for_organization(organization, role=role)307    _, token = make_token_for_organization(organization)308    client = APIClient()309    url = reverse("api-internal:user-detail", kwargs={"pk": tester.public_primary_key})310    with patch(311        "apps.api.views.user.UserView.list",312        return_value=Response(313            status=status.HTTP_200_OK,314        ),315    ):316        response = client.get(url, format="json", **make_user_auth_headers(tester, token))317    assert response.status_code == expected_status318@pytest.mark.django_db319@pytest.mark.parametrize(320    "role,expected_status",321    [322        (Role.ADMIN, status.HTTP_200_OK),323        (Role.EDITOR, status.HTTP_403_FORBIDDEN),324        (Role.VIEWER, status.HTTP_403_FORBIDDEN),325    ],326)327def test_user_detail_other_permissions(328    make_organization,329    make_user_for_organization,330    make_token_for_organization,331    make_user_auth_headers,332    role,333    expected_status,334):335    organization = make_organization()336    admin = make_user_for_organization(organization)337    tester = make_user_for_organization(organization, role=role)338    _, token = make_token_for_organization(organization)339    client = APIClient()340    url = reverse("api-internal:user-detail", kwargs={"pk": admin.public_primary_key})341    response = client.get(url, format="json", **make_user_auth_headers(tester, token))342    assert response.status_code == expected_status343@pytest.mark.django_db344@pytest.mark.parametrize(345    "role,expected_status",346    [347        (Role.ADMIN, status.HTTP_200_OK),348        (Role.EDITOR, status.HTTP_200_OK),349        (Role.VIEWER, status.HTTP_403_FORBIDDEN),350    ],351)352def test_user_get_own_verification_code(353    make_organization,354    make_user_for_organization,355    make_token_for_organization,356    make_user_auth_headers,357    role,358    expected_status,359):360    organization = make_organization()361    tester = make_user_for_organization(organization, role=role)362    _, token = make_token_for_organization(organization)363    client = APIClient()364    url = reverse("api-internal:user-get-verification-code", kwargs={"pk": tester.public_primary_key})365    with patch(366        "apps.api.views.user.UserView.get_verification_code",367        return_value=Response(368            status=status.HTTP_200_OK,369        ),370    ):371        response = client.get(url, format="json", **make_user_auth_headers(tester, token))372    assert response.status_code == expected_status373@pytest.mark.django_db374@pytest.mark.parametrize(375    "role,expected_status",376    [377        (Role.ADMIN, status.HTTP_200_OK),378        (Role.EDITOR, status.HTTP_403_FORBIDDEN),379        (Role.VIEWER, status.HTTP_403_FORBIDDEN),380    ],381)382def test_user_get_other_verification_code(383    make_organization,384    make_user_for_organization,385    make_token_for_organization,386    make_user_auth_headers,387    role,388    expected_status,389):390    organization = make_organization()391    admin = make_user_for_organization(organization)392    tester = make_user_for_organization(organization, role=role)393    _, token = make_token_for_organization(organization)394    client = APIClient()395    url = reverse("api-internal:user-get-verification-code", kwargs={"pk": admin.public_primary_key})396    with patch("apps.twilioapp.phone_manager.PhoneManager.send_verification_code", return_value=Mock()):397        response = client.get(url, format="json", **make_user_auth_headers(tester, token))398    assert response.status_code == expected_status399@pytest.mark.django_db400@pytest.mark.parametrize(401    "role,expected_status",402    [403        (Role.ADMIN, status.HTTP_200_OK),404        (Role.EDITOR, status.HTTP_200_OK),405        (Role.VIEWER, status.HTTP_403_FORBIDDEN),406    ],407)408def test_user_verify_own_phone(409    make_organization,410    make_user_for_organization,411    make_token_for_organization,412    make_user_auth_headers,413    role,414    expected_status,415):416    organization = make_organization()417    tester = make_user_for_organization(organization, role=role)418    _, token = make_token_for_organization(organization)419    client = APIClient()420    url = reverse("api-internal:user-verify-number", kwargs={"pk": tester.public_primary_key})421    with patch(422        "apps.api.views.user.UserView.verify_number",423        return_value=Response(424            status=status.HTTP_200_OK,425        ),426    ):427        response = client.put(url, format="json", **make_user_auth_headers(tester, token))428    assert response.status_code == expected_status429"""430Tests below are outdated431"""432@pytest.mark.django_db433@pytest.mark.parametrize(434    "role,expected_status",435    [436        (Role.ADMIN, status.HTTP_200_OK),437        (Role.EDITOR, status.HTTP_403_FORBIDDEN),438        (Role.VIEWER, status.HTTP_403_FORBIDDEN),439    ],440)441def test_user_verify_another_phone(442    make_organization,443    make_user_for_organization,444    make_token_for_organization,445    make_user_auth_headers,446    role,447    expected_status,448):449    organization = make_organization()450    tester = make_user_for_organization(organization, role=role)451    other_user = make_user_for_organization(organization, role=Role.EDITOR)452    _, token = make_token_for_organization(organization)453    client = APIClient()454    url = reverse("api-internal:user-verify-number", kwargs={"pk": other_user.public_primary_key})455    with patch("apps.twilioapp.phone_manager.PhoneManager.verify_phone_number", return_value=(True, None)):456        response = client.put(f"{url}?token=12345", format="json", **make_user_auth_headers(tester, token))457    assert response.status_code == expected_status458@pytest.mark.django_db459@pytest.mark.parametrize(460    "role,expected_status",461    [462        (Role.ADMIN, status.HTTP_200_OK),463        (Role.EDITOR, status.HTTP_200_OK),464        (Role.VIEWER, status.HTTP_403_FORBIDDEN),465    ],466)467def test_user_get_own_telegram_verification_code(468    make_organization,469    make_user_for_organization,470    make_token_for_organization,471    make_user_auth_headers,472    role,473    expected_status,474):475    organization = make_organization()476    tester = make_user_for_organization(organization, role=role)477    _, token = make_token_for_organization(organization)478    client = APIClient()479    url = reverse("api-internal:user-get-telegram-verification-code", kwargs={"pk": tester.public_primary_key})480    response = client.get(url, format="json", **make_user_auth_headers(tester, token))481    assert response.status_code == expected_status482@pytest.mark.django_db483@pytest.mark.parametrize(484    "role,expected_status",485    [486        (Role.ADMIN, status.HTTP_200_OK),487        (Role.EDITOR, status.HTTP_403_FORBIDDEN),488        (Role.VIEWER, status.HTTP_403_FORBIDDEN),489    ],490)491def test_user_get_another_telegram_verification_code(492    make_organization,493    make_user_for_organization,494    make_token_for_organization,495    make_user_auth_headers,496    role,497    expected_status,498):499    organization = make_organization()500    tester = make_user_for_organization(organization, role=role)501    other_user = make_user_for_organization(organization, role=Role.EDITOR)502    _, token = make_token_for_organization(organization)503    client = APIClient()504    url = reverse("api-internal:user-get-telegram-verification-code", kwargs={"pk": other_user.public_primary_key})505    response = client.get(url, format="json", **make_user_auth_headers(tester, token))506    assert response.status_code == expected_status507@pytest.mark.django_db508def test_admin_can_update_user(509    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers510):511    organization = make_organization()512    tester = make_user_for_organization(organization, role=Role.ADMIN)513    other_user = make_user_for_organization(organization, role=Role.EDITOR)514    _, token = make_token_for_organization(organization)515    client = APIClient()516    data = {517        "email": "test@amixr.io",518        "role": Role.ADMIN,519        "username": "updated_test_username",520        "unverified_phone_number": "+1234567890",521        "slack_login": "",522    }523    url = reverse("api-internal:user-detail", kwargs={"pk": other_user.public_primary_key})524    response = client.put(url, format="json", data=data, **make_user_auth_headers(tester, token))525    assert response.status_code == status.HTTP_200_OK526@pytest.mark.django_db527def test_admin_can_update_himself(528    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers529):530    organization = make_organization()531    admin = make_user_for_organization(organization, role=Role.ADMIN)532    _, token = make_token_for_organization(organization)533    client = APIClient()534    data = {535        "email": "test@amixr.io",536        "role": Role.ADMIN,537        "username": "updated_test_username",538        "unverified_phone_number": "+1234567890",539        "slack_login": "",540    }541    url = reverse("api-internal:user-detail", kwargs={"pk": admin.public_primary_key})542    response = client.put(url, format="json", data=data, **make_user_auth_headers(admin, token))543    assert response.status_code == status.HTTP_200_OK544@pytest.mark.django_db545def test_admin_can_list_users(546    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers547):548    organization = make_organization()549    admin = make_user_for_organization(organization, role=Role.ADMIN)550    _, token = make_token_for_organization(organization)551    client = APIClient()552    url = reverse("api-internal:user-list")553    response = client.get(url, format="json", **make_user_auth_headers(admin, token))554    assert response.status_code == status.HTTP_200_OK555@pytest.mark.django_db556def test_admin_can_detail_users(557    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers558):559    organization = make_organization()560    admin = make_user_for_organization(organization, role=Role.ADMIN)561    editor = make_user_for_organization(organization, role=Role.EDITOR)562    _, token = make_token_for_organization(organization)563    client = APIClient()564    url = reverse("api-internal:user-detail", kwargs={"pk": editor.public_primary_key})565    response = client.get(url, format="json", **make_user_auth_headers(admin, token))566    assert response.status_code == status.HTTP_200_OK567@patch("apps.twilioapp.phone_manager.PhoneManager.send_verification_code", return_value=Mock())568@pytest.mark.django_db569def test_admin_can_get_own_verification_code(570    mock_verification_start,571    make_organization,572    make_user_for_organization,573    make_token_for_organization,574    make_user_auth_headers,575):576    organization = make_organization()577    admin = make_user_for_organization(organization, role=Role.ADMIN)578    _, token = make_token_for_organization(organization)579    client = APIClient()580    url = reverse("api-internal:user-get-verification-code", kwargs={"pk": admin.public_primary_key})581    response = client.get(url, format="json", **make_user_auth_headers(admin, token))582    assert response.status_code == status.HTTP_200_OK583@patch("apps.twilioapp.phone_manager.PhoneManager.send_verification_code", return_value=Mock())584@pytest.mark.django_db585def test_admin_can_get_another_user_verification_code(586    mock_verification_start,587    make_organization,588    make_user_for_organization,589    make_token_for_organization,590    make_user_auth_headers,591):592    organization = make_organization()593    admin = make_user_for_organization(organization, role=Role.ADMIN)594    editor = make_user_for_organization(organization, role=Role.EDITOR)595    _, token = make_token_for_organization(organization)596    client = APIClient()597    url = reverse("api-internal:user-get-verification-code", kwargs={"pk": editor.public_primary_key})598    response = client.get(url, format="json", **make_user_auth_headers(admin, token))599    assert response.status_code == status.HTTP_200_OK600@patch("apps.twilioapp.phone_manager.PhoneManager.verify_phone_number", return_value=(True, None))601@pytest.mark.django_db602def test_admin_can_verify_own_phone(603    mocked_verification_check,604    make_organization,605    make_user_for_organization,606    make_token_for_organization,607    make_user_auth_headers,608):609    organization = make_organization()610    admin = make_user_for_organization(organization, role=Role.ADMIN)611    _, token = make_token_for_organization(organization)612    client = APIClient()613    url = reverse("api-internal:user-verify-number", kwargs={"pk": admin.public_primary_key})614    response = client.put(f"{url}?token=12345", format="json", **make_user_auth_headers(admin, token))615    assert response.status_code == status.HTTP_200_OK616@patch("apps.twilioapp.phone_manager.PhoneManager.verify_phone_number", return_value=(True, None))617@pytest.mark.django_db618def test_admin_can_verify_another_user_phone(619    mocked_verification_check,620    make_organization,621    make_user_for_organization,622    make_token_for_organization,623    make_user_auth_headers,624):625    organization = make_organization()626    admin = make_user_for_organization(organization, role=Role.ADMIN)627    editor = make_user_for_organization(organization, role=Role.EDITOR)628    _, token = make_token_for_organization(organization)629    client = APIClient()630    url = reverse("api-internal:user-verify-number", kwargs={"pk": editor.public_primary_key})631    response = client.put(f"{url}?token=12345", format="json", **make_user_auth_headers(admin, token))632    assert response.status_code == status.HTTP_200_OK633@pytest.mark.django_db634def test_admin_can_get_own_telegram_verification_code(635    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers636):637    organization = make_organization()638    admin = make_user_for_organization(organization, role=Role.ADMIN)639    _, token = make_token_for_organization(organization)640    client = APIClient()641    url = reverse("api-internal:user-get-telegram-verification-code", kwargs={"pk": admin.public_primary_key})642    response = client.get(url, format="json", **make_user_auth_headers(admin, token))643    assert response.status_code == status.HTTP_200_OK644@pytest.mark.django_db645def test_admin_can_get_another_user_telegram_verification_code(646    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers647):648    organization = make_organization()649    admin = make_user_for_organization(organization, role=Role.ADMIN)650    editor = make_user_for_organization(organization, role=Role.EDITOR)651    _, token = make_token_for_organization(organization)652    client = APIClient()653    url = reverse("api-internal:user-get-telegram-verification-code", kwargs={"pk": editor.public_primary_key})654    response = client.get(url, format="json", **make_user_auth_headers(admin, token))655    assert response.status_code == status.HTTP_200_OK656@pytest.mark.django_db657def test_admin_can_get_another_user_backend_verification_code(658    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers659):660    organization = make_organization()661    admin = make_user_for_organization(organization, role=Role.ADMIN)662    editor = make_user_for_organization(organization, role=Role.EDITOR)663    _, token = make_token_for_organization(organization)664    client = APIClient()665    url = (666        reverse("api-internal:user-get-backend-verification-code", kwargs={"pk": editor.public_primary_key})667        + "?backend=TESTONLY"668    )669    response = client.get(url, format="json", **make_user_auth_headers(admin, token))670    assert response.status_code == status.HTTP_200_OK671@pytest.mark.django_db672def test_admin_can_unlink_another_user_backend_account(673    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers674):675    organization = make_organization()676    admin = make_user_for_organization(organization, role=Role.ADMIN)677    editor = make_user_for_organization(organization, role=Role.EDITOR)678    _, token = make_token_for_organization(organization)679    client = APIClient()680    url = reverse("api-internal:user-unlink-backend", kwargs={"pk": editor.public_primary_key}) + "?backend=TESTONLY"681    response = client.post(url, format="json", **make_user_auth_headers(admin, token))682    assert response.status_code == status.HTTP_200_OK683@pytest.mark.django_db684def test_admin_can_unlink_another_user_slack_account(685    make_organization_with_slack_team_identity,686    make_user_for_organization,687    make_user_with_slack_user_identity,688    make_token_for_organization,689    make_user_auth_headers,690):691    organization, slack_team_identity = make_organization_with_slack_team_identity()692    admin = make_user_for_organization(organization, role=Role.ADMIN)693    editor, slack_user_identity_1 = make_user_with_slack_user_identity(694        slack_team_identity, organization, slack_id="user_1", role=Role.EDITOR695    )696    _, token = make_token_for_organization(organization)697    client = APIClient()698    url = reverse("api-internal:user-unlink-slack", kwargs={"pk": editor.public_primary_key})699    response = client.post(url, format="json", **make_user_auth_headers(admin, token))700    assert response.status_code == status.HTTP_200_OK701    editor.refresh_from_db()702    assert editor.slack_user_identity is None703"""Test user permissions"""704@pytest.mark.django_db705def test_user_cant_update_user(706    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers707):708    organization = make_organization()709    first_user = make_user_for_organization(organization, role=Role.EDITOR)710    second_user = make_user_for_organization(organization, role=Role.EDITOR)711    _, token = make_token_for_organization(organization)712    client = APIClient()713    data = {714        "email": "test@amixr.io",715        "role": Role.ADMIN,716        "username": "updated_test_username",717        "unverified_phone_number": "+1234567890",718        "slack_login": "",719    }720    url = reverse("api-internal:user-detail", kwargs={"pk": first_user.public_primary_key})721    response = client.put(url, format="json", data=data, **make_user_auth_headers(second_user, token))722    assert response.status_code == status.HTTP_403_FORBIDDEN723@pytest.mark.django_db724def test_user_can_update_themself(725    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers726):727    organization = make_organization()728    user = make_user_for_organization(organization, role=Role.EDITOR)729    _, token = make_token_for_organization(organization)730    client = APIClient()731    data = {732        "email": "test@amixr.io",733        "role": Role.EDITOR,734        "username": "updated_test_username",735        "unverified_phone_number": "+1234567890",736        "slack_login": "",737    }738    url = reverse("api-internal:user-detail", kwargs={"pk": user.public_primary_key})739    response = client.put(url, format="json", data=data, **make_user_auth_headers(user, token))740    assert response.status_code == status.HTTP_200_OK741@pytest.mark.django_db742def test_user_can_list_users(743    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers744):745    organization = make_organization()746    editor = make_user_for_organization(organization, role=Role.EDITOR)747    _, token = make_token_for_organization(organization)748    client = APIClient()749    url = reverse("api-internal:user-list")750    response = client.get(url, format="json", **make_user_auth_headers(editor, token))751    assert response.status_code == status.HTTP_200_OK752@pytest.mark.django_db753def test_user_can_detail_users(754    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers755):756    organization = make_organization()757    admin = make_user_for_organization(organization, role=Role.ADMIN)758    editor = make_user_for_organization(organization, role=Role.EDITOR)759    _, token = make_token_for_organization(organization)760    client = APIClient()761    url = reverse("api-internal:user-detail", kwargs={"pk": admin.public_primary_key})762    response = client.get(url, format="json", **make_user_auth_headers(editor, token))763    assert response.status_code == status.HTTP_403_FORBIDDEN764@patch("apps.twilioapp.phone_manager.PhoneManager.send_verification_code", return_value=Mock())765@pytest.mark.django_db766def test_user_can_get_own_verification_code(767    mock_verification_start,768    make_organization,769    make_user_for_organization,770    make_token_for_organization,771    make_user_auth_headers,772):773    organization = make_organization()774    user = make_user_for_organization(organization, role=Role.EDITOR)775    _, token = make_token_for_organization(organization)776    client = APIClient()777    url = reverse("api-internal:user-get-verification-code", kwargs={"pk": user.public_primary_key})778    response = client.get(f"{url}", format="json", **make_user_auth_headers(user, token))779    assert response.status_code == status.HTTP_200_OK780@patch("apps.twilioapp.phone_manager.PhoneManager.send_verification_code", return_value=Mock())781@pytest.mark.django_db782def test_user_cant_get_another_user_verification_code(783    mock_verification_start,784    make_organization,785    make_user_for_organization,786    make_token_for_organization,787    make_user_auth_headers,788):789    organization = make_organization()790    first_user = make_user_for_organization(organization, role=Role.EDITOR)791    second_user = make_user_for_organization(organization, role=Role.EDITOR)792    _, token = make_token_for_organization(organization)793    client = APIClient()794    url = reverse("api-internal:user-get-verification-code", kwargs={"pk": first_user.public_primary_key})795    response = client.get(f"{url}", format="json", **make_user_auth_headers(second_user, token))796    assert response.status_code == status.HTTP_403_FORBIDDEN797@patch("apps.twilioapp.phone_manager.PhoneManager.verify_phone_number", return_value=(True, None))798@pytest.mark.django_db799def test_user_can_verify_own_phone(800    mocked_verification_check,801    make_organization,802    make_user_for_organization,803    make_token_for_organization,804    make_user_auth_headers,805):806    organization = make_organization()807    user = make_user_for_organization(organization, role=Role.EDITOR)808    _, token = make_token_for_organization(organization)809    client = APIClient()810    url = reverse("api-internal:user-verify-number", kwargs={"pk": user.public_primary_key})811    response = client.put(f"{url}?token=12345", format="json", **make_user_auth_headers(user, token))812    assert response.status_code == status.HTTP_200_OK813@patch("apps.twilioapp.phone_manager.PhoneManager.verify_phone_number", return_value=(True, None))814@pytest.mark.django_db815def test_user_cant_verify_another_user_phone(816    mocked_verification_check,817    make_organization,818    make_user_for_organization,819    make_token_for_organization,820    make_user_auth_headers,821):822    organization = make_organization()823    first_user = make_user_for_organization(organization, role=Role.EDITOR)824    second_user = make_user_for_organization(organization, role=Role.EDITOR)825    _, token = make_token_for_organization(organization)826    client = APIClient()827    url = reverse("api-internal:user-verify-number", kwargs={"pk": first_user.public_primary_key})828    response = client.put(f"{url}?token=12345", format="json", **make_user_auth_headers(second_user, token))829    assert response.status_code == status.HTTP_403_FORBIDDEN830@pytest.mark.django_db831def test_user_can_get_own_telegram_verification_code(832    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers833):834    organization = make_organization()835    user = make_user_for_organization(organization, role=Role.EDITOR)836    _, token = make_token_for_organization(organization)837    client = APIClient()838    url = reverse("api-internal:user-get-telegram-verification-code", kwargs={"pk": user.public_primary_key})839    response = client.get(f"{url}", format="json", **make_user_auth_headers(user, token))840    assert response.status_code == status.HTTP_200_OK841@pytest.mark.django_db842def test_user_cant_get_another_user_telegram_verification_code(843    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers844):845    organization = make_organization()846    first_user = make_user_for_organization(organization, role=Role.EDITOR)847    second_user = make_user_for_organization(organization, role=Role.EDITOR)848    _, token = make_token_for_organization(organization)849    client = APIClient()850    url = reverse("api-internal:user-get-telegram-verification-code", kwargs={"pk": first_user.public_primary_key})851    response = client.get(f"{url}", format="json", **make_user_auth_headers(second_user, token))852    assert response.status_code == status.HTTP_403_FORBIDDEN853@pytest.mark.django_db854def test_user_can_get_own_backend_verification_code(855    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers856):857    organization = make_organization()858    user = make_user_for_organization(organization, role=Role.EDITOR)859    _, token = make_token_for_organization(organization)860    client = APIClient()861    url = (862        reverse("api-internal:user-get-backend-verification-code", kwargs={"pk": user.public_primary_key})863        + "?backend=TESTONLY"864    )865    with patch(866        "apps.base.tests.messaging_backend.TestOnlyBackend.generate_user_verification_code",867        return_value="the-code",868    ) as mock_generate_code:869        response = client.get(f"{url}", format="json", **make_user_auth_headers(user, token))870    assert response.status_code == status.HTTP_200_OK871    assert response.json() == "the-code"872    mock_generate_code.assert_called_once_with(user)873@pytest.mark.django_db874def test_user_cant_get_another_user_backend_verification_code(875    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers876):877    organization = make_organization()878    first_user = make_user_for_organization(organization, role=Role.EDITOR)879    second_user = make_user_for_organization(organization, role=Role.EDITOR)880    _, token = make_token_for_organization(organization)881    client = APIClient()882    url = (883        reverse("api-internal:user-get-backend-verification-code", kwargs={"pk": first_user.public_primary_key})884        + "?backend=TESTONLY"885    )886    response = client.get(f"{url}", format="json", **make_user_auth_headers(second_user, token))887    assert response.status_code == status.HTTP_403_FORBIDDEN888@pytest.mark.django_db889def test_user_can_unlink_own_slack_account(890    make_organization_with_slack_team_identity,891    make_user_with_slack_user_identity,892    make_token_for_organization,893    make_user_auth_headers,894):895    organization, slack_team_identity = make_organization_with_slack_team_identity()896    user, slack_user_identity_1 = make_user_with_slack_user_identity(897        slack_team_identity, organization, slack_id="user_1", role=Role.EDITOR898    )899    _, token = make_token_for_organization(organization)900    client = APIClient()901    url = reverse("api-internal:user-unlink-slack", kwargs={"pk": user.public_primary_key})902    response = client.post(url, format="json", **make_user_auth_headers(user, token))903    assert response.status_code == status.HTTP_200_OK904    user.refresh_from_db()905    assert user.slack_user_identity is None906@pytest.mark.django_db907def test_user_can_unlink_backend_own_account(908    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers909):910    organization = make_organization()911    user = make_user_for_organization(organization, role=Role.EDITOR)912    _, token = make_token_for_organization(organization)913    client = APIClient()914    url = reverse("api-internal:user-unlink-backend", kwargs={"pk": user.public_primary_key}) + "?backend=TESTONLY"915    response = client.post(f"{url}", format="json", **make_user_auth_headers(user, token))916    assert response.status_code == status.HTTP_200_OK917@pytest.mark.django_db918def test_user_unlink_backend_invalid_backend_id(919    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers920):921    organization = make_organization()922    user = make_user_for_organization(organization, role=Role.EDITOR)923    _, token = make_token_for_organization(organization)924    client = APIClient()925    url = reverse("api-internal:user-unlink-backend", kwargs={"pk": user.public_primary_key}) + "?backend=INVALID"926    response = client.post(f"{url}", format="json", **make_user_auth_headers(user, token))927    assert response.status_code == status.HTTP_400_BAD_REQUEST928@pytest.mark.django_db929def test_user_unlink_backend_backend_account_not_found(930    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers931):932    organization = make_organization()933    user = make_user_for_organization(organization, role=Role.EDITOR)934    _, token = make_token_for_organization(organization)935    client = APIClient()936    url = reverse("api-internal:user-unlink-backend", kwargs={"pk": user.public_primary_key}) + "?backend=TESTONLY"937    with patch("apps.base.tests.messaging_backend.TestOnlyBackend.unlink_user", side_effect=ObjectDoesNotExist):938        response = client.post(f"{url}", format="json", **make_user_auth_headers(user, token))939    assert response.status_code == status.HTTP_400_BAD_REQUEST940@pytest.mark.django_db941def test_user_cant_unlink_slack_another_user(942    make_organization_with_slack_team_identity,943    make_user_with_slack_user_identity,944    make_token_for_organization,945    make_user_auth_headers,946):947    organization, slack_team_identity = make_organization_with_slack_team_identity()948    first_user, slack_user_identity_1 = make_user_with_slack_user_identity(949        slack_team_identity, organization, slack_id="user_1", role=Role.EDITOR950    )951    second_user, slack_user_identity_2 = make_user_with_slack_user_identity(952        slack_team_identity, organization, slack_id="user_2", role=Role.EDITOR953    )954    _, token = make_token_for_organization(organization)955    client = APIClient()956    url = reverse("api-internal:user-unlink-slack", kwargs={"pk": first_user.public_primary_key})957    response = client.post(url, format="json", **make_user_auth_headers(second_user, token))958    assert response.status_code == status.HTTP_403_FORBIDDEN959    first_user.refresh_from_db()960    assert first_user.slack_user_identity is not None961@pytest.mark.django_db962def test_user_cant_unlink_backend__another_user(963    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers964):965    organization = make_organization()966    first_user = make_user_for_organization(organization, role=Role.EDITOR)967    second_user = make_user_for_organization(organization, role=Role.EDITOR)968    _, token = make_token_for_organization(organization)969    client = APIClient()970    url = (971        reverse("api-internal:user-unlink-backend", kwargs={"pk": first_user.public_primary_key}) + "?backend=TESTONLY"972    )973    response = client.post(f"{url}", format="json", **make_user_auth_headers(second_user, token))974    assert response.status_code == status.HTTP_403_FORBIDDEN975"""Test stakeholder permissions"""976@pytest.mark.django_db977def test_viewer_cant_create_user(978    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers979):980    organization = make_organization()981    user = make_user_for_organization(organization, role=Role.VIEWER)982    _, token = make_token_for_organization(organization)983    client = APIClient()984    url = reverse("api-internal:user-list")985    data = {986        "email": "test@amixr.io",987        "role": Role.ADMIN,988        "username": "test_username",989        "unverified_phone_number": None,990        "slack_login": "",991    }992    response = client.post(url, format="json", data=data, **make_user_auth_headers(user, token))993    assert response.status_code == status.HTTP_403_FORBIDDEN994@pytest.mark.django_db995def test_viewer_cant_update_user(996    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers997):998    organization = make_organization()999    first_user = make_user_for_organization(organization, role=Role.EDITOR)1000    second_user = make_user_for_organization(organization, role=Role.VIEWER)1001    _, token = make_token_for_organization(organization)1002    data = {1003        "email": "test@amixr.io",1004        "role": Role.EDITOR,1005        "username": "updated_test_username",1006        "unverified_phone_number": "+1234567890",1007        "slack_login": "",1008    }1009    client = APIClient()1010    url = reverse("api-internal:user-detail", kwargs={"pk": first_user.public_primary_key})1011    response = client.put(url, format="json", data=data, **make_user_auth_headers(second_user, token))1012    assert response.status_code == status.HTTP_403_FORBIDDEN1013@pytest.mark.django_db1014def test_viewer_cant_update_himself(1015    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1016):1017    organization = make_organization()1018    user = make_user_for_organization(organization, role=Role.VIEWER)1019    _, token = make_token_for_organization(organization)1020    data = {1021        "email": "test@amixr.io",1022        "role": Role.VIEWER,1023        "username": "updated_test_username",1024        "unverified_phone_number": "+1234567890",1025        "slack_login": "",1026    }1027    client = APIClient()1028    url = reverse("api-internal:user-detail", kwargs={"pk": user.public_primary_key})1029    response = client.put(url, format="json", data=data, **make_user_auth_headers(user, token))1030    assert response.status_code == status.HTTP_403_FORBIDDEN1031@pytest.mark.django_db1032def test_viewer_cant_list_users(1033    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1034):1035    organization = make_organization()1036    user = make_user_for_organization(organization, role=Role.VIEWER)1037    _, token = make_token_for_organization(organization)1038    client = APIClient()1039    url = reverse("api-internal:user-list")1040    response = client.get(url, format="json", **make_user_auth_headers(user, token))1041    assert response.status_code == status.HTTP_403_FORBIDDEN1042@pytest.mark.django_db1043def test_viewer_cant_detail_users(1044    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1045):1046    organization = make_organization()1047    first_user = make_user_for_organization(organization, role=Role.EDITOR)1048    second_user = make_user_for_organization(organization, role=Role.VIEWER)1049    _, token = make_token_for_organization(organization)1050    client = APIClient()1051    url = reverse("api-internal:user-detail", kwargs={"pk": first_user.public_primary_key})1052    response = client.get(url, format="json", **make_user_auth_headers(second_user, token))1053    assert response.status_code == status.HTTP_403_FORBIDDEN1054@patch("apps.twilioapp.phone_manager.PhoneManager.send_verification_code", return_value=Mock())1055@pytest.mark.django_db1056def test_viewer_cant_get_own_verification_code(1057    mock_verification_start,1058    make_organization,1059    make_user_for_organization,1060    make_token_for_organization,1061    make_user_auth_headers,1062):1063    organization = make_organization()1064    user = make_user_for_organization(organization, role=Role.VIEWER)1065    _, token = make_token_for_organization(organization)1066    client = APIClient()1067    url = reverse("api-internal:user-get-verification-code", kwargs={"pk": user.public_primary_key})1068    response = client.get(url, format="json", **make_user_auth_headers(user, token))1069    assert response.status_code == status.HTTP_403_FORBIDDEN1070@patch("apps.twilioapp.phone_manager.PhoneManager.send_verification_code", return_value=Mock())1071@pytest.mark.django_db1072def test_viewer_cant_get_another_user_verification_code(1073    mock_verification_start,1074    make_organization,1075    make_user_for_organization,1076    make_token_for_organization,1077    make_user_auth_headers,1078):1079    organization = make_organization()1080    first_user = make_user_for_organization(organization, role=Role.EDITOR)1081    second_user = make_user_for_organization(organization, role=Role.VIEWER)1082    _, token = make_token_for_organization(organization)1083    client = APIClient()1084    url = reverse("api-internal:user-get-verification-code", kwargs={"pk": first_user.public_primary_key})1085    response = client.get(url, format="json", **make_user_auth_headers(second_user, token))1086    assert response.status_code == status.HTTP_403_FORBIDDEN1087@patch("apps.twilioapp.phone_manager.PhoneManager.verify_phone_number", return_value=(True, None))1088@pytest.mark.django_db1089def test_viewer_cant_verify_own_phone(1090    mocked_verification_check,1091    make_organization,1092    make_user_for_organization,1093    make_token_for_organization,1094    make_user_auth_headers,1095):1096    organization = make_organization()1097    user = make_user_for_organization(organization, role=Role.VIEWER)1098    _, token = make_token_for_organization(organization)1099    client = APIClient()1100    url = reverse("api-internal:user-verify-number", kwargs={"pk": user.public_primary_key})1101    response = client.put(f"{url}?token=12345", format="json", **make_user_auth_headers(user, token))1102    assert response.status_code == status.HTTP_403_FORBIDDEN1103@patch("apps.twilioapp.phone_manager.PhoneManager.verify_phone_number", return_value=(True, None))1104@pytest.mark.django_db1105def test_viewer_cant_verify_another_user_phone(1106    mocked_verification_check,1107    make_organization,1108    make_user_for_organization,1109    make_token_for_organization,1110    make_user_auth_headers,1111):1112    organization = make_organization()1113    first_user = make_user_for_organization(organization, role=Role.EDITOR)1114    second_user = make_user_for_organization(organization, role=Role.VIEWER)1115    _, token = make_token_for_organization(organization)1116    client = APIClient()1117    url = reverse("api-internal:user-verify-number", kwargs={"pk": first_user.public_primary_key})1118    response = client.put(f"{url}?token=12345", format="json", **make_user_auth_headers(second_user, token))1119    assert response.status_code == status.HTTP_403_FORBIDDEN1120@pytest.mark.django_db1121def test_viewer_cant_get_own_telegram_verification_code(1122    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1123):1124    organization = make_organization()1125    user = make_user_for_organization(organization, role=Role.VIEWER)1126    _, token = make_token_for_organization(organization)1127    client = APIClient()1128    url = reverse("api-internal:user-get-telegram-verification-code", kwargs={"pk": user.public_primary_key})1129    response = client.get(f"{url}", format="json", **make_user_auth_headers(user, token))1130    assert response.status_code == status.HTTP_403_FORBIDDEN1131@pytest.mark.django_db1132def test_viewer_cant_get_another_user_telegram_verification_code(1133    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1134):1135    organization = make_organization()1136    first_user = make_user_for_organization(organization, role=Role.EDITOR)1137    second_user = make_user_for_organization(organization, role=Role.VIEWER)1138    _, token = make_token_for_organization(organization)1139    client = APIClient()1140    url = reverse("api-internal:user-get-telegram-verification-code", kwargs={"pk": first_user.public_primary_key})1141    response = client.get(url, format="json", **make_user_auth_headers(second_user, token))1142    assert response.status_code == status.HTTP_403_FORBIDDEN1143@pytest.mark.django_db1144@pytest.mark.parametrize(1145    "role,expected_status,initial_unverified_number,initial_verified_number",1146    [1147        (Role.ADMIN, status.HTTP_200_OK, "+1234567890", None),1148        (Role.EDITOR, status.HTTP_200_OK, "+1234567890", None),1149        (Role.VIEWER, status.HTTP_403_FORBIDDEN, "+1234567890", None),1150        (Role.ADMIN, status.HTTP_200_OK, None, "+1234567890"),1151        (Role.EDITOR, status.HTTP_200_OK, None, "+1234567890"),1152        (Role.VIEWER, status.HTTP_403_FORBIDDEN, None, "+1234567890"),1153    ],1154)1155def test_forget_own_number(1156    make_organization,1157    make_team,1158    make_user_for_organization,1159    make_token_for_organization,1160    make_user_auth_headers,1161    role,1162    expected_status,1163    initial_unverified_number,1164    initial_verified_number,1165):1166    organization = make_organization()1167    admin = make_user_for_organization(organization, role=Role.ADMIN)1168    user = make_user_for_organization(1169        organization,1170        role=role,1171        unverified_phone_number=initial_unverified_number,1172        _verified_phone_number=initial_verified_number,1173    )1174    _, token = make_token_for_organization(organization)1175    client = APIClient()1176    url = reverse("api-internal:user-forget-number", kwargs={"pk": user.public_primary_key})1177    with patch(1178        "apps.twilioapp.phone_manager.PhoneManager.notify_about_changed_verified_phone_number", return_value=None1179    ):1180        response = client.put(url, None, format="json", **make_user_auth_headers(user, token))1181        assert response.status_code == expected_status1182    user_detail_url = reverse("api-internal:user-detail", kwargs={"pk": user.public_primary_key})1183    response = client.get(user_detail_url, None, format="json", **make_user_auth_headers(admin, token))1184    assert response.status_code == status.HTTP_200_OK1185    if expected_status == status.HTTP_200_OK:1186        assert not response.json()["unverified_phone_number"]1187        assert not response.json()["verified_phone_number"]1188    else:1189        assert response.json()["unverified_phone_number"] == initial_unverified_number1190        assert response.json()["verified_phone_number"] == initial_verified_number1191@pytest.mark.django_db1192@pytest.mark.parametrize(1193    "role,expected_status,initial_unverified_number,initial_verified_number",1194    [1195        (Role.ADMIN, status.HTTP_200_OK, "+1234567890", None),1196        (Role.EDITOR, status.HTTP_403_FORBIDDEN, "+1234567890", None),1197        (Role.VIEWER, status.HTTP_403_FORBIDDEN, "+1234567890", None),1198        (Role.ADMIN, status.HTTP_200_OK, None, "+1234567890"),1199        (Role.EDITOR, status.HTTP_403_FORBIDDEN, None, "+1234567890"),1200        (Role.VIEWER, status.HTTP_403_FORBIDDEN, None, "+1234567890"),1201    ],1202)1203def test_forget_other_number(1204    make_organization,1205    make_team,1206    make_user_for_organization,1207    make_token_for_organization,1208    make_user_auth_headers,1209    role,1210    expected_status,1211    initial_unverified_number,1212    initial_verified_number,1213):1214    organization = make_organization()1215    user = make_user_for_organization(1216        organization,1217        role=Role.ADMIN,1218        unverified_phone_number=initial_unverified_number,1219        _verified_phone_number=initial_verified_number,1220    )1221    other_user = make_user_for_organization(organization, role=role)1222    _, token = make_token_for_organization(organization)1223    client = APIClient()1224    url = reverse("api-internal:user-forget-number", kwargs={"pk": user.public_primary_key})1225    with patch(1226        "apps.twilioapp.phone_manager.PhoneManager.notify_about_changed_verified_phone_number", return_value=None1227    ):1228        response = client.put(url, None, format="json", **make_user_auth_headers(other_user, token))1229        assert response.status_code == expected_status1230    user_detail_url = reverse("api-internal:user-detail", kwargs={"pk": user.public_primary_key})1231    response = client.get(user_detail_url, None, format="json", **make_user_auth_headers(user, token))1232    assert response.status_code == status.HTTP_200_OK1233    if expected_status == status.HTTP_200_OK:1234        assert not response.json()["unverified_phone_number"]1235        assert not response.json()["verified_phone_number"]1236    else:1237        assert response.json()["unverified_phone_number"] == initial_unverified_number1238        assert response.json()["verified_phone_number"] == initial_verified_number1239@pytest.mark.django_db1240def test_viewer_cant_get_own_backend_verification_code(1241    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1242):1243    organization = make_organization()1244    user = make_user_for_organization(organization, role=Role.VIEWER)1245    _, token = make_token_for_organization(organization)1246    client = APIClient()1247    url = (1248        reverse("api-internal:user-get-backend-verification-code", kwargs={"pk": user.public_primary_key})1249        + "?backend=TESTONLY"1250    )1251    response = client.get(f"{url}", format="json", **make_user_auth_headers(user, token))1252    assert response.status_code == status.HTTP_403_FORBIDDEN1253@pytest.mark.django_db1254def test_viewer_cant_get_another_user_backend_verification_code(1255    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1256):1257    organization = make_organization()1258    first_user = make_user_for_organization(organization, role=Role.EDITOR)1259    second_user = make_user_for_organization(organization, role=Role.VIEWER)1260    _, token = make_token_for_organization(organization)1261    client = APIClient()1262    url = (1263        reverse("api-internal:user-get-backend-verification-code", kwargs={"pk": first_user.public_primary_key})1264        + "?backend=TESTONLY"1265    )1266    response = client.get(url, format="json", **make_user_auth_headers(second_user, token))1267    assert response.status_code == status.HTTP_403_FORBIDDEN1268@pytest.mark.django_db1269def test_viewer_cant_unlink_backend_own_user(1270    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1271):1272    organization = make_organization()1273    user = make_user_for_organization(organization, role=Role.VIEWER)1274    _, token = make_token_for_organization(organization)1275    client = APIClient()1276    url = reverse("api-internal:user-unlink-backend", kwargs={"pk": user.public_primary_key}) + "?backend=TESTONLY"1277    response = client.post(f"{url}", format="json", **make_user_auth_headers(user, token))1278    assert response.status_code == status.HTTP_403_FORBIDDEN1279@pytest.mark.django_db1280def test_viewer_cant_unlink_backend_another_user(1281    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1282):1283    organization = make_organization()1284    first_user = make_user_for_organization(organization, role=Role.EDITOR)1285    second_user = make_user_for_organization(organization, role=Role.VIEWER)1286    _, token = make_token_for_organization(organization)1287    client = APIClient()1288    url = (1289        reverse("api-internal:user-unlink-backend", kwargs={"pk": first_user.public_primary_key}) + "?backend=TESTONLY"1290    )1291    response = client.post(url, format="json", **make_user_auth_headers(second_user, token))1292    assert response.status_code == status.HTTP_403_FORBIDDEN1293@pytest.mark.django_db1294def test_change_timezone(1295    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1296):1297    organization = make_organization()1298    user = make_user_for_organization(organization, role=Role.EDITOR)1299    _, token = make_token_for_organization(organization)1300    client = APIClient()1301    url = reverse("api-internal:user-detail", kwargs={"pk": user.public_primary_key})1302    data = {"timezone": "Europe/London"}1303    response = client.put(f"{url}", data, format="json", **make_user_auth_headers(user, token))1304    assert response.status_code == status.HTTP_200_OK1305    assert "timezone" in response.json()1306    assert response.json()["timezone"] == "Europe/London"1307@pytest.mark.django_db1308@pytest.mark.parametrize("timezone", ["", 1, "NotATimezone"])1309def test_invalid_timezone(1310    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers, timezone1311):1312    organization = make_organization()1313    user = make_user_for_organization(organization, role=Role.EDITOR)1314    _, token = make_token_for_organization(organization)1315    client = APIClient()1316    url = reverse("api-internal:user-detail", kwargs={"pk": user.public_primary_key})1317    data = {"timezone": timezone}1318    response = client.put(f"{url}", data, format="json", **make_user_auth_headers(user, token))1319    assert response.status_code == status.HTTP_400_BAD_REQUEST1320@pytest.mark.django_db1321def test_change_working_hours(1322    make_organization, make_user_for_organization, make_token_for_organization, make_user_auth_headers1323):1324    organization = make_organization()1325    user = make_user_for_organization(organization, role=Role.EDITOR)1326    _, token = make_token_for_organization(organization)1327    client = APIClient()1328    url = reverse("api-internal:user-detail", kwargs={"pk": user.public_primary_key})1329    periods = [{"start": "05:00:00", "end": "23:00:00"}]1330    working_hours = {1331        day: periods for day in ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]1332    }1333    data = {"working_hours": working_hours}1334    response = client.put(f"{url}", data, format="json", **make_user_auth_headers(user, token))1335    assert response.status_code == status.HTTP_200_OK1336    assert "working_hours" in response.json()1337    assert response.json()["working_hours"] == working_hours1338@pytest.mark.django_db1339@pytest.mark.parametrize(1340    "working_hours_extra",1341    [1342        {},1343        {"sunday": 1},1344        {"sunday": ""},1345        {"sunday": {"start": "18:00:00"}},1346        {"sunday": {"start": "", "end": ""}},1347        {"sunday": {"start": "18:00:00", "end": None}},1348        {"sunday": {"start": "18:00:00", "end": "18:00:00"}},1349        {"sunday": {"start": "18:00:00", "end": "9:00:00"}},1350        {"sunday": {"start": "18:00:00", "end": "9:00:00", "extra": 1}},1351    ],1352)1353def test_invalid_working_hours(1354    make_organization,1355    make_user_for_organization,1356    make_token_for_organization,1357    make_user_auth_headers,1358    working_hours_extra,1359):1360    organization = make_organization()1361    user = make_user_for_organization(organization, role=Role.EDITOR)1362    _, token = make_token_for_organization(organization)1363    client = APIClient()1364    url = reverse("api-internal:user-detail", kwargs={"pk": user.public_primary_key})1365    periods = [{"start": "05:00:00", "end": "23:00:00"}]1366    working_hours = {day: periods for day in ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]}1367    working_hours.update(working_hours_extra)1368    data = {"working_hours": working_hours}1369    response = client.put(f"{url}", data, format="json", **make_user_auth_headers(user, token))...make_einstein.py
Source:make_einstein.py  
1from enum import Enum2class Nationality(Enum):3    brit = 04    swede = 15    dane = 26    norwegian = 37    german = 48    def __int__(self):9        return self.value10class Color(Enum):11    red = 012    green = 113    yellow = 214    blue = 315    white = 416    def __int__(self):17        return self.value18class Beverage(Enum):19    tea = 020    coffee = 121    milk = 222    beer = 323    water = 424    def __int__(self):25        return self.value26class Cigar(Enum):27    pallmall = 028    dunhill = 129    blends = 230    bluemasters = 331    prince = 432    def __int__(self):33        return self.value34class Pet(Enum):35    dogs = 036    birds = 137    cats = 238    horse = 339    fish = 440    def __int__(self):41        return self.value42class Clause:43    def __init__(self):44        self.s = set([])45    def __str__(self):46        ret_str = ""47        for p in self.s:48            ret_str += str(p)49            ret_str += " "50        ret_str += "0"51        return ret_str52    53    def __repr__(self):54        ret_str = ""55        for p in self.s:56            ret_str += str(p)57            ret_str += " "58        ret_str += "0"59        return ret_str60    def add_literal(self, l):61        self.s.add(l)62def make_literal(prop, negated=False):63    if negated:64        return -(prop + 1)65    else:66        return prop + 167        68def make_einstein_prop(n=None, c=None, b=None, s=None, p=None, h=None):69    assert(isinstance(n, Nationality) or n is None)70    assert(isinstance(c, Color) or c is None)71    assert(isinstance(b, Beverage) or b is None)72    assert(isinstance(s, Cigar) or s is None)73    assert(isinstance(p, Pet) or p is None)74    assert(isinstance(h, int) or h is None)75    num_not_none = sum([x is not None for x in [n, c, b, s, p, h]])76    assert(num_not_none==2)77    prop_num = 078    # Nationality79    if n is not None:80        if c is not None:81            # NC82            prop_num = prop_num + (int(n)*5) + int(c)83            return prop_num84        elif b is not None:85            # NB86            prop_num = 2587            prop_num = prop_num + (int(n)*5) + int(b)88            return prop_num89        elif s is not None:90            # NS91            prop_num = 5092            prop_num = prop_num + (int(n)*5) + int(s)93            return prop_num94        elif p is not None:95            # NP96            prop_num = 7597            prop_num = prop_num + (int(n)*5) + int(p)98            return prop_num99        else:100            # NH101            prop_num = 100102            prop_num = prop_num + (int(n)*5) + int(h)103            return prop_num104    # Color105    elif c is not None:106        prop_num = 125107        if b is not None:108            # CB109            prop_num = prop_num + (int(c)*5) + int(b)110            return prop_num111        elif s is not None:112            # CS113            prop_num = prop_num + 25114            prop_num = prop_num + (int(c)*5) + int(s)115            return prop_num116        elif p is not None:117            # CP118            prop_num = prop_num + 50119            prop_num = prop_num + (int(c)*5) + int(p)120            return prop_num121        else:122            # CH123            prop_num = prop_num + 75124            prop_num = prop_num + (int(c)*5) + int(h)125            return prop_num126    # Beverage127    elif b is not None:128        prop_num = 225129        if s is not None:130            # BS131            prop_num = prop_num + (int(b)*5) + int(s)132            return prop_num133        elif p is not None:134            # BP135            prop_num = prop_num + 25136            prop_num = prop_num + (int(b)*5) + int(p)137            return prop_num138        else:139            # BH140            prop_num = prop_num + 50141            prop_num = prop_num + (int(b)*5) + int(h)142            return prop_num143    # Smoking144    elif s is not None:145        prop_num = 300146        if p is not None:147            # SP148            prop_num = prop_num + (int(s)*5) + int(p)149            return prop_num150        else:151            # SH152            prop_num = prop_num + 25153            prop_num = prop_num + (int(s)*5) + int(h)154            return prop_num155    # Pet156    else:157        # PH158        prop_num = 350159        prop_num = prop_num + (int(p)*5) + int(h)160        return prop_num161def make_exclusion_axioms(ns=None, cs=None, bs=None, ss=None, ps=None, hs=None):162    num_not_none = sum([x is not None for x in [ns, cs, bs, ss, ps, hs]])163    assert(num_not_none==2)164    axioms = []165    # Nationality166    if ns is not None:167        if cs is not None:168            # NC169            for c in cs:170                disjunctive_c = Clause()171                for i in range(len(ns)):172                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], c=c)))173                    for j in range(i+1, len(ns)):174                        exclusive_c = Clause()175                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], c=c), negated=True))176                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[j], c=c), negated=True))177                        axioms.append(exclusive_c)178                axioms.append(disjunctive_c)179            for n in ns:180                disjunctive_c = Clause()181                for i in range(len(cs)):182                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=n, c=cs[i])))183                    for j in range(i+1, len(cs)):184                        exclusive_c = Clause()185                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, c=cs[i]), negated=True))186                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, c=cs[j]), negated=True))187                        axioms.append(exclusive_c)188                axioms.append(disjunctive_c)189        elif bs is not None:190            # NB191            for b in bs:192                disjunctive_c = Clause()193                for i in range(len(ns)):194                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], b=b)))195                    for j in range(i+1, len(ns)):196                        exclusive_c = Clause()197                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], b=b), negated=True))198                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[j], b=b), negated=True))199                        axioms.append(exclusive_c)200                axioms.append(disjunctive_c)201            for n in ns:202                disjunctive_c = Clause()203                for i in range(len(bs)):204                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=n, b=bs[i])))205                    for j in range(i+1, len(bs)):206                        exclusive_c = Clause()207                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, b=bs[i]), negated=True))208                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, b=bs[j]), negated=True))209                        axioms.append(exclusive_c)210                axioms.append(disjunctive_c)211        elif ss is not None:212            # NS213            for s in ss:214                disjunctive_c = Clause()215                for i in range(len(ns)):216                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], s=s)))217                    for j in range(i+1, len(ns)):218                        exclusive_c = Clause()219                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], s=s), negated=True))220                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[j], s=s), negated=True))221                        axioms.append(exclusive_c)222                axioms.append(disjunctive_c)223            for n in ns:224                disjunctive_c = Clause()225                for i in range(len(ss)):226                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=n, s=ss[i])))227                    for j in range(i+1, len(ss)):228                        exclusive_c = Clause()229                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, s=ss[i]), negated=True))230                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, s=ss[j]), negated=True))231                        axioms.append(exclusive_c)232                axioms.append(disjunctive_c)233        elif ps is not None:234            # NP235            for p in ps:236                disjunctive_c = Clause()237                for i in range(len(ns)):238                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], p=p)))239                    for j in range(i+1, len(ns)):240                        exclusive_c = Clause()241                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], p=p), negated=True))242                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[j], p=p), negated=True))243                        axioms.append(exclusive_c)244                axioms.append(disjunctive_c)245            for n in ns:246                disjunctive_c = Clause()247                for i in range(len(ps)):248                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=n, p=ps[i])))249                    for j in range(i+1, len(ps)):250                        exclusive_c = Clause()251                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, p=ps[i]), negated=True))252                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, p=ps[j]), negated=True))253                        axioms.append(exclusive_c)254                axioms.append(disjunctive_c)255        else:256            # NH257            for h in hs:258                disjunctive_c = Clause()259                for i in range(len(ns)):260                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], h=h)))261                    for j in range(i+1, len(ns)):262                        exclusive_c = Clause()263                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[i], h=h), negated=True))264                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=ns[j], h=h), negated=True))265                        axioms.append(exclusive_c)266                axioms.append(disjunctive_c)267            for n in ns:268                disjunctive_c = Clause()269                for i in range(len(hs)):270                    disjunctive_c.add_literal(make_literal(make_einstein_prop(n=n, h=hs[i])))271                    for j in range(i+1, len(hs)):272                        exclusive_c = Clause()273                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, h=hs[i]), negated=True))274                        exclusive_c.add_literal(make_literal(make_einstein_prop(n=n, h=hs[j]), negated=True))275                        axioms.append(exclusive_c)276                axioms.append(disjunctive_c)277    # Color278    elif cs is not None:279        if bs is not None:280            # CB281            for b in bs:282                disjunctive_c = Clause()283                for i in range(len(cs)):284                    disjunctive_c.add_literal(make_literal(make_einstein_prop(c=cs[i], b=b)))285                    for j in range(i+1, len(cs)):286                        exclusive_c = Clause()287                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=cs[i], b=b), negated=True))288                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=cs[j], b=b), negated=True))289                        axioms.append(exclusive_c)290                axioms.append(disjunctive_c)291            for c in cs:292                disjunctive_c = Clause()293                for i in range(len(bs)):294                    disjunctive_c.add_literal(make_literal(make_einstein_prop(c=c, b=bs[i])))295                    for j in range(i+1, len(bs)):296                        exclusive_c = Clause()297                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=c, b=bs[i]), negated=True))298                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=c, b=bs[j]), negated=True))299                        axioms.append(exclusive_c)300                axioms.append(disjunctive_c)301        elif ss is not None:302            # CS303            for s in ss:304                disjunctive_c = Clause()305                for i in range(len(cs)):306                    disjunctive_c.add_literal(make_literal(make_einstein_prop(c=cs[i], s=s)))307                    for j in range(i+1, len(cs)):308                        exclusive_c = Clause()309                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=cs[i], s=s), negated=True))310                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=cs[j], s=s), negated=True))311                        axioms.append(exclusive_c)312                axioms.append(disjunctive_c)313            for c in cs:314                disjunctive_c = Clause()315                for i in range(len(ss)):316                    disjunctive_c.add_literal(make_literal(make_einstein_prop(c=c, s=ss[i])))317                    for j in range(i+1, len(ss)):318                        exclusive_c = Clause()319                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=c, s=ss[i]), negated=True))320                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=c, s=ss[j]), negated=True))321                        axioms.append(exclusive_c)322                axioms.append(disjunctive_c)323        elif ps is not None:324            # CP325            for p in ps:326                disjunctive_c = Clause()327                for i in range(len(cs)):328                    disjunctive_c.add_literal(make_literal(make_einstein_prop(c=cs[i], p=p)))329                    for j in range(i+1, len(cs)):330                        exclusive_c = Clause()331                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=cs[i], p=p), negated=True))332                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=cs[j], p=p), negated=True))333                        axioms.append(exclusive_c)334                axioms.append(disjunctive_c)335            for c in cs:336                disjunctive_c = Clause()337                for i in range(len(ps)):338                    disjunctive_c.add_literal(make_literal(make_einstein_prop(c=c, p=ps[i])))339                    for j in range(i+1, len(ps)):340                        exclusive_c = Clause()341                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=c, p=ps[i]), negated=True))342                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=c, p=ps[j]), negated=True))343                        axioms.append(exclusive_c)344                axioms.append(disjunctive_c)345        else:346            # CH347            for h in hs:348                disjunctive_c = Clause()349                for i in range(len(cs)):350                    disjunctive_c.add_literal(make_literal(make_einstein_prop(c=cs[i], h=h)))351                    for j in range(i+1, len(cs)):352                        exclusive_c = Clause()353                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=cs[i], h=h), negated=True))354                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=cs[j], h=h), negated=True))355                        axioms.append(exclusive_c)356                axioms.append(disjunctive_c)357            for c in cs:358                disjunctive_c = Clause()359                for i in range(len(hs)):360                    disjunctive_c.add_literal(make_literal(make_einstein_prop(c=c, h=hs[i])))361                    for j in range(i+1, len(hs)):362                        exclusive_c = Clause()363                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=c, h=hs[i]), negated=True))364                        exclusive_c.add_literal(make_literal(make_einstein_prop(c=c, h=hs[j]), negated=True))365                        axioms.append(exclusive_c)366                axioms.append(disjunctive_c)367    # Beverage368    elif bs is not None:369        if ss is not None:370            # BS371            for s in ss:372                disjunctive_c = Clause()373                for i in range(len(bs)):374                    disjunctive_c.add_literal(make_literal(make_einstein_prop(b=bs[i], s=s)))375                    for j in range(i+1, len(bs)):376                        exclusive_c = Clause()377                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=bs[i], s=s), negated=True))378                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=bs[j], s=s), negated=True))379                        axioms.append(exclusive_c)380                axioms.append(disjunctive_c)381            for b in bs:382                disjunctive_c = Clause()383                for i in range(len(ss)):384                    disjunctive_c.add_literal(make_literal(make_einstein_prop(b=b, s=ss[i])))385                    for j in range(i+1, len(ss)):386                        exclusive_c = Clause()387                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=b, s=ss[i]), negated=True))388                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=b, s=ss[j]), negated=True))389                        axioms.append(exclusive_c)390                axioms.append(disjunctive_c)391        elif ps is not None:392            # BP393            for p in ps:394                disjunctive_c = Clause()395                for i in range(len(bs)):396                    disjunctive_c.add_literal(make_literal(make_einstein_prop(b=bs[i], p=p)))397                    for j in range(i+1, len(bs)):398                        exclusive_c = Clause()399                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=bs[i], p=p), negated=True))400                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=bs[j], p=p), negated=True))401                        axioms.append(exclusive_c)402                axioms.append(disjunctive_c)403            for b in bs:404                disjunctive_c = Clause()405                for i in range(len(ps)):406                    disjunctive_c.add_literal(make_literal(make_einstein_prop(b=b, p=ps[i])))407                    for j in range(i+1, len(ps)):408                        exclusive_c = Clause()409                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=b, p=ps[i]), negated=True))410                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=b, p=ps[j]), negated=True))411                        axioms.append(exclusive_c)412                axioms.append(disjunctive_c)413        else:414            # BH415            for h in hs:416                disjunctive_c = Clause()417                for i in range(len(bs)):418                    disjunctive_c.add_literal(make_literal(make_einstein_prop(b=bs[i], h=h)))419                    for j in range(i+1, len(bs)):420                        exclusive_c = Clause()421                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=bs[i], h=h), negated=True))422                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=bs[j], h=h), negated=True))423                        axioms.append(exclusive_c)424                axioms.append(disjunctive_c)425            for b in bs:426                disjunctive_c = Clause()427                for i in range(len(hs)):428                    disjunctive_c.add_literal(make_literal(make_einstein_prop(b=b, h=hs[i])))429                    for j in range(i+1, len(hs)):430                        exclusive_c = Clause()431                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=b, h=hs[i]), negated=True))432                        exclusive_c.add_literal(make_literal(make_einstein_prop(b=b, h=hs[j]), negated=True))433                        axioms.append(exclusive_c)434                axioms.append(disjunctive_c)435    # Smoking436    elif ss is not None:437        if ps is not None:438            # SP439            for p in ps:440                disjunctive_c = Clause()441                for i in range(len(ss)):442                    disjunctive_c.add_literal(make_literal(make_einstein_prop(s=ss[i], p=p)))443                    for j in range(i+1, len(ss)):444                        exclusive_c = Clause()445                        exclusive_c.add_literal(make_literal(make_einstein_prop(s=ss[i], p=p), negated=True))446                        exclusive_c.add_literal(make_literal(make_einstein_prop(s=ss[j], p=p), negated=True))447                        axioms.append(exclusive_c)448                axioms.append(disjunctive_c)449            for s in ss:450                disjunctive_c = Clause()451                for i in range(len(ps)):452                    disjunctive_c.add_literal(make_literal(make_einstein_prop(s=s, p=ps[i])))453                    for j in range(i+1, len(ps)):454                        exclusive_c = Clause()455                        exclusive_c.add_literal(make_literal(make_einstein_prop(s=s, p=ps[i]), negated=True))456                        exclusive_c.add_literal(make_literal(make_einstein_prop(s=s, p=ps[j]), negated=True))457                        axioms.append(exclusive_c)458                axioms.append(disjunctive_c)459        else:460            # SH461            for h in hs:462                disjunctive_c = Clause()463                for i in range(len(ss)):464                    disjunctive_c.add_literal(make_literal(make_einstein_prop(s=ss[i], h=h)))465                    for j in range(i+1, len(ss)):466                        exclusive_c = Clause()467                        exclusive_c.add_literal(make_literal(make_einstein_prop(s=ss[i], h=h), negated=True))468                        exclusive_c.add_literal(make_literal(make_einstein_prop(s=ss[j], h=h), negated=True))469                        axioms.append(exclusive_c)470                axioms.append(disjunctive_c)471            for s in ss:472                disjunctive_c = Clause()473                for i in range(len(hs)):474                    disjunctive_c.add_literal(make_literal(make_einstein_prop(s=s, h=hs[i])))475                    for j in range(i+1, len(hs)):476                        exclusive_c = Clause()477                        exclusive_c.add_literal(make_literal(make_einstein_prop(s=s, h=hs[i]), negated=True))478                        exclusive_c.add_literal(make_literal(make_einstein_prop(s=s, h=hs[j]), negated=True))479                        axioms.append(exclusive_c)480                axioms.append(disjunctive_c)481    # Pet482    else:483        # PH484        for h in hs:485            disjunctive_c = Clause()486            for i in range(len(ps)):487                disjunctive_c.add_literal(make_literal(make_einstein_prop(p=ps[i], h=h)))488                for j in range(i+1, len(ps)):489                    exclusive_c = Clause()490                    exclusive_c.add_literal(make_literal(make_einstein_prop(p=ps[i], h=h), negated=True))491                    exclusive_c.add_literal(make_literal(make_einstein_prop(p=ps[j], h=h), negated=True))492                    axioms.append(exclusive_c)493            axioms.append(disjunctive_c)494        for p in ps:495            disjunctive_c = Clause()496            for i in range(len(hs)):497                disjunctive_c.add_literal(make_literal(make_einstein_prop(p=p, h=hs[i])))498                for j in range(i+1, len(hs)):499                    exclusive_c = Clause()500                    exclusive_c.add_literal(make_literal(make_einstein_prop(p=p, h=hs[i]), negated=True))501                    exclusive_c.add_literal(make_literal(make_einstein_prop(p=p, h=hs[j]), negated=True))502                    axioms.append(exclusive_c)503            axioms.append(disjunctive_c)504    return axioms505# TODO Implement consistency axioms, which should say that (p_{n,c} and p_{n, p}) \implies p_{c, p}) 506# I.e. (\neg p_{n, c} \vee \neg p_{n, p} \vee p_{c, p}) for all combinations of pairs507def make_consistency_axioms():508    axioms = []509    for i in range(5):510        for j in range(5):511            for k in range(5):512                # NC513                c = Clause()514                c.add_literal(make_literal(make_einstein_prop(n=Nationality(j), h=i), negated=True))515                c.add_literal(make_literal(make_einstein_prop(c=Color(k), h=i), negated=True))516                c.add_literal(make_literal(make_einstein_prop(n=Nationality(j), c=Color(k))))517                axioms.append(c)518                # NB519                c = Clause()520                c.add_literal(make_literal(make_einstein_prop(n=Nationality(j), h=i), negated=True))521                c.add_literal(make_literal(make_einstein_prop(b=Beverage(k), h=i), negated=True))522                c.add_literal(make_literal(make_einstein_prop(n=Nationality(j), b=Beverage(k))))523                axioms.append(c)524                525                # NS526                c = Clause()527                c.add_literal(make_literal(make_einstein_prop(n=Nationality(j), h=i), negated=True))528                c.add_literal(make_literal(make_einstein_prop(s=Cigar(k), h=i), negated=True))529                c.add_literal(make_literal(make_einstein_prop(n=Nationality(j), s=Cigar(k))))530                axioms.append(c)531                # NP532                c = Clause()533                c.add_literal(make_literal(make_einstein_prop(n=Nationality(j), h=i), negated=True))534                c.add_literal(make_literal(make_einstein_prop(p=Pet(k), h=i), negated=True))535                c.add_literal(make_literal(make_einstein_prop(n=Nationality(j), p=Pet(k))))536                axioms.append(c)537                # CB538                c = Clause()539                c.add_literal(make_literal(make_einstein_prop(c=Color(j), h=i), negated=True))540                c.add_literal(make_literal(make_einstein_prop(b=Beverage(k), h=i), negated=True))541                c.add_literal(make_literal(make_einstein_prop(c=Color(j), b=Beverage(k))))542                axioms.append(c)543                # CS544                c = Clause()545                c.add_literal(make_literal(make_einstein_prop(c=Color(j), h=i), negated=True))546                c.add_literal(make_literal(make_einstein_prop(s=Cigar(k), h=i), negated=True))547                c.add_literal(make_literal(make_einstein_prop(c=Color(j), s=Cigar(k))))548                axioms.append(c)549                # CP550                c = Clause()551                c.add_literal(make_literal(make_einstein_prop(c=Color(j), h=i), negated=True))552                c.add_literal(make_literal(make_einstein_prop(p=Pet(k), h=i), negated=True))553                c.add_literal(make_literal(make_einstein_prop(c=Color(j), p=Pet(k))))554                axioms.append(c)555                # BS556                c = Clause()557                c.add_literal(make_literal(make_einstein_prop(b=Beverage(j), h=i), negated=True))558                c.add_literal(make_literal(make_einstein_prop(s=Cigar(k), h=i), negated=True))559                c.add_literal(make_literal(make_einstein_prop(b=Beverage(j), s=Cigar(k))))560                axioms.append(c)561                # BP562                c = Clause()563                c.add_literal(make_literal(make_einstein_prop(b=Beverage(j), h=i), negated=True))564                c.add_literal(make_literal(make_einstein_prop(p=Pet(k), h=i), negated=True))565                c.add_literal(make_literal(make_einstein_prop(b=Beverage(j), p=Pet(k))))566                axioms.append(c)567                # SP568                c = Clause()569                c.add_literal(make_literal(make_einstein_prop(s=Cigar(j), h=i), negated=True))570                c.add_literal(make_literal(make_einstein_prop(p=Pet(k), h=i), negated=True))571                c.add_literal(make_literal(make_einstein_prop(s=Cigar(j), p=Pet(k))))572                axioms.append(c)573    return axioms574def make_einstein_axioms():575    axioms = []576    ## Basic exclusion axioms577    ns = [Nationality.brit, Nationality.swede, Nationality.dane, Nationality.norwegian,  Nationality.german]578    cs = [Color.red, Color.green, Color.yellow, Color.blue, Color.white]579    bs = [Beverage.tea, Beverage.coffee, Beverage.milk, Beverage.beer, Beverage.water]580    ss = [Cigar.pallmall, Cigar.dunhill, Cigar.blends, Cigar.bluemasters, Cigar.prince]581    ps = [Pet.dogs, Pet.birds, Pet.cats, Pet.horse, Pet.fish]582    hs = [0, 1, 2, 3, 4]583    axioms = axioms + make_exclusion_axioms(ns=ns, cs=cs)584    axioms = axioms + make_exclusion_axioms(ns=ns, bs=bs)585    axioms = axioms + make_exclusion_axioms(ns=ns, ss=ss)586    axioms = axioms + make_exclusion_axioms(ns=ns, ps=ps)587    axioms = axioms + make_exclusion_axioms(ns=ns, hs=hs)588    axioms = axioms + make_exclusion_axioms(cs=cs, bs=bs)589    axioms = axioms + make_exclusion_axioms(cs=cs, ss=ss)590    axioms = axioms + make_exclusion_axioms(cs=cs, ps=ps)591    axioms = axioms + make_exclusion_axioms(cs=cs, hs=hs)592    axioms = axioms + make_exclusion_axioms(bs=bs, ss=ss)593    axioms = axioms + make_exclusion_axioms(bs=bs, ps=ps)594    axioms = axioms + make_exclusion_axioms(bs=bs, hs=hs)595    axioms = axioms + make_exclusion_axioms(ss=ss, ps=ps)596    axioms = axioms + make_exclusion_axioms(ss=ss, hs=hs)597    axioms = axioms + make_exclusion_axioms(ps=ps, hs=hs)598    599    # Consistency axioms600    axioms = axioms + make_consistency_axioms()601    ## Fifteen facts602    # Brit lives in red house603    c1 = Clause()604    c1.add_literal(make_literal(make_einstein_prop(n=Nationality.brit, c=Color.red)))605    axioms.append(c1)606    # Swede keeps dogs607    c2 = Clause()608    c2.add_literal(make_literal(make_einstein_prop(n=Nationality.swede, p=Pet.dogs)))609    axioms.append(c2)610    # Dane drinks tea611    c3 = Clause()612    c3.add_literal(make_literal(make_einstein_prop(n=Nationality.dane, b=Beverage.tea)))613    axioms.append(c3)614    # Green house on the left of white house615    c4 = Clause()616    c4.add_literal(make_literal(make_einstein_prop(c=Color.white, h=1), negated=True))617    axioms.append(c4)618    c4 = Clause()619    c4.add_literal(make_literal(make_einstein_prop(c=Color.white, h=2), negated=True))620    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=1)))621    axioms.append(c4)622    c4 = Clause()623    c4.add_literal(make_literal(make_einstein_prop(c=Color.white, h=3), negated=True))624    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=2)))625    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=1)))626    axioms.append(c4)627    c4 = Clause()628    c4.add_literal(make_literal(make_einstein_prop(c=Color.white, h=4), negated=True))629    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=3)))630    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=2)))631    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=1)))632    axioms.append(c4)633    c4 = Clause()634    c4.add_literal(make_literal(make_einstein_prop(c=Color.white, h=5), negated=True))635    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=4)))636    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=3)))637    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=2)))638    c4.add_literal(make_literal(make_einstein_prop(c=Color.green, h=1)))639    axioms.append(c4)640    # Green house's owner drinks coffee641    c5 = Clause()642    c5.add_literal(make_literal(make_einstein_prop(c=Color.green, b=Beverage.coffee)))643    axioms.append(c5)644    645    # Person who smokes Pall Mall drinks coffee646    c6 = Clause()647    c6.add_literal(make_literal(make_einstein_prop(s=Cigar.pallmall, p=Pet.birds)))648    axioms.append(c6)649    # The owner of the yellow house smokes Dunhill650    c7 = Clause()651    c7.add_literal(make_literal(make_einstein_prop(c=Color.yellow, s=Cigar.dunhill)))652    axioms.append(c7)653    # The man living in the center house drinks milk654    c8 = Clause()655    c8.add_literal(make_literal(make_einstein_prop(b=Beverage.milk, h=2)))656    axioms.append(c8)657    # The Norwegian lives in the first house658    c9 = Clause()659    c9.add_literal(make_literal(make_einstein_prop(n=Nationality.norwegian, h=0)))660    axioms.append(c9)661    # The man who smokes Blends lives next to the one who keeps cats662    c10 = Clause()663    c10.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=0), negated=True))664    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=1)))665    axioms.append(c10)666    c10 = Clause()667    c10.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=1)))668    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=0), negated=True))669    axioms.append(c10)670    c10 = Clause()671    c10.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=4), negated=True))672    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=3)))673    axioms.append(c10)674    c10 = Clause()675    c10.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=3)))676    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=4), negated=True))677    axioms.append(c10)678    c10 = Clause()679    c10.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=1), negated=True))680    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=0)))681    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=2)))682    axioms.append(c10)683    c10 = Clause()684    c10.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=2), negated=True))685    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=1)))686    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=3)))687    axioms.append(c10)688    c10 = Clause()689    c10.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=3), negated=True))690    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=2)))691    c10.add_literal(make_literal(make_einstein_prop(p=Pet.cats, h=4)))692    axioms.append(c10)693    # The man who keeps the horse lives next to the man who smokes Dunhill694    c11 = Clause()695    c11.add_literal(make_literal(make_einstein_prop(p=Pet.horse, h=0), negated=True))696    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=1)))697    axioms.append(c11)698    c11 = Clause()699    c11.add_literal(make_literal(make_einstein_prop(p=Pet.horse, h=1)))700    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=0), negated=True))701    axioms.append(c11)702    c11 = Clause()703    c11.add_literal(make_literal(make_einstein_prop(p=Pet.horse, h=4), negated=True))704    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=3)))705    axioms.append(c11)706    c11 = Clause()707    c11.add_literal(make_literal(make_einstein_prop(p=Pet.horse, h=3)))708    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=4), negated=True))709    axioms.append(c11)710    c11 = Clause()711    c11.add_literal(make_literal(make_einstein_prop(p=Pet.horse, h=1), negated=True))712    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=0)))713    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=2)))714    axioms.append(c11)715    c11 = Clause()716    c11.add_literal(make_literal(make_einstein_prop(p=Pet.horse, h=2), negated=True))717    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=1)))718    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=3)))719    axioms.append(c11)720    c11 = Clause()721    c11.add_literal(make_literal(make_einstein_prop(p=Pet.horse, h=3), negated=True))722    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=2)))723    c11.add_literal(make_literal(make_einstein_prop(s=Cigar.dunhill, h=4)))724    axioms.append(c11)725    # The owner who smokes Bluemasters drinks beer726    c12 = Clause()727    c12.add_literal(make_literal(make_einstein_prop(b=Beverage.beer, s=Cigar.bluemasters)))728    axioms.append(c12)729    # The German smokes Prince730    c13 = Clause()731    c13.add_literal(make_literal(make_einstein_prop(n=Nationality.german, s=Cigar.prince)))732    axioms.append(c13)733    # The Norwegian lives next to the blue house734    c14 = Clause()735    c14.add_literal(make_literal(make_einstein_prop(n=Nationality.norwegian, h=0), negated=True))736    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=1)))737    axioms.append(c14)738    c14 = Clause()739    c14.add_literal(make_literal(make_einstein_prop(n=Nationality.norwegian, h=1)))740    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=0), negated=True))741    axioms.append(c14)742    c14 = Clause()743    c14.add_literal(make_literal(make_einstein_prop(n=Nationality.norwegian, h=4), negated=True))744    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=3)))745    axioms.append(c14)746    c14 = Clause()747    c14.add_literal(make_literal(make_einstein_prop(n=Nationality.norwegian, h=3)))748    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=4), negated=True))749    axioms.append(c14)750    c14 = Clause()751    c14.add_literal(make_literal(make_einstein_prop(n=Nationality.norwegian, h=1), negated=True))752    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=0)))753    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=2)))754    axioms.append(c14)755    c14 = Clause()756    c14.add_literal(make_literal(make_einstein_prop(n=Nationality.norwegian, h=2), negated=True))757    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=1)))758    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=3)))759    axioms.append(c14)760    c14 = Clause()761    c14.add_literal(make_literal(make_einstein_prop(n=Nationality.norwegian, h=3), negated=True))762    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=2)))763    c14.add_literal(make_literal(make_einstein_prop(c=Color.blue, h=4)))764    axioms.append(c14)765    # The man who smokes Blends has a neighbor who drinks water766    c15 = Clause()767    c15.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=0), negated=True))768    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=1)))769    axioms.append(c15)770    c15 = Clause()771    c15.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=1)))772    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=0), negated=True))773    axioms.append(c15)774    c15 = Clause()775    c15.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=4), negated=True))776    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=3)))777    axioms.append(c15)778    c15 = Clause()779    c15.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=3)))780    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=4), negated=True))781    axioms.append(c15)782    c15 = Clause()783    c15.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=1), negated=True))784    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=0)))785    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=2)))786    axioms.append(c15)787    c15 = Clause()788    c15.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=2), negated=True))789    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=1)))790    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=3)))791    axioms.append(c15)792    c15 = Clause()793    c15.add_literal(make_literal(make_einstein_prop(s=Cigar.blends, h=3), negated=True))794    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=2)))795    c15.add_literal(make_literal(make_einstein_prop(b=Beverage.water, h=4)))796    axioms.append(c15)797    return axioms798def run():799    assert(make_einstein_prop(n=Nationality.brit, c=Color.red) == 0)800    assert(make_einstein_prop(c=Color.red, b=Beverage.tea) == 125)801    assert(make_einstein_prop(b=Beverage.tea, s=Cigar.pallmall) == 225)802    assert(make_einstein_prop(s=Cigar.pallmall, p=Pet.dogs) == 300)803    assert(make_einstein_prop(p=Pet.dogs, h=0) == 350)804    assert(make_einstein_prop(p=Pet.fish, h=4) == 374)805    axioms = make_einstein_axioms()806    print("p cnf 375 {}".format(len(axioms)))807    for a in axioms:808        print(a)809if __name__ == "__main__":...08.py
Source:08.py  
1test = {2  'name': 'Problem 8',3  'points': 2,4  'suites': [5    {6      'cases': [7        {8          'answer': 'a list of restaurants reviewed by the user',9          'choices': [10            'a list of restaurants reviewed by the user',11            'a list of all possible restaurants',12            'a list of ratings for restaurants reviewed by the user'13          ],14          'hidden': False,15          'locked': False,16          'question': r"""17          In the starter code for best_predictor, what does the18          variable reviewed represent?19          """20        },21        {22          'answer': 'a predictor function and its r_squared value',23          'choices': [24            'a predictor function and its r_squared value',25            'a predictor function',26            'an r_squared value',27            'a restaurant'28          ],29          'hidden': False,30          'locked': False,31          'question': r"""32          Given a user, a list of restaurants, and a feature function, what33          does find_predictor from Problem 7 return?34          """35        },36        {37          'answer': 'the predictor with the highest r_squared value',38          'choices': [39            'the predictor with the highest r_squared value',40            'the predictor with the lowest r_squared value',41            'the first predictor in the list',42            'an arbitrary predictor'43          ],44          'hidden': False,45          'locked': False,46          'question': r"""47          After computing a list of [predictor, r_squared] pairs,48          which predictor should we select?49          """50        }51      ],52      'scored': False,53      'type': 'concept'54    },55    {56      'cases': [57        {58          'code': r"""59          >>> user = make_user('Cheapskate', [60          ...     make_review('A', 2),61          ...     make_review('B', 5),62          ...     make_review('C', 2),63          ...     make_review('D', 5),64          ... ])65          >>> cluster = [66          ...     make_restaurant('A', [5, 2], [], 4, [67          ...         make_review('A', 5)68          ...     ]),69          ...     make_restaurant('B', [3, 2], [], 2, [70          ...         make_review('B', 5)71          ...     ]),72          ...     make_restaurant('C', [-2, 6], [], 4, [73          ...         make_review('C', 4)74          ...     ]),75          ...     make_restaurant('D', [4, 2], [], 2, [76          ...         make_review('D', 3),77          ...         make_review('D', 4)78          ...     ]),79          ... ]80          >>> fns = [restaurant_price, lambda r: mean(restaurant_ratings(r))]81          >>> pred = best_predictor(user, cluster, fns)82          >>> [round(pred(r), 5) for r in cluster] # should be a list of decimals83          [2.0, 5.0, 2.0, 5.0]84          """,85          'hidden': False,86          'locked': False87        },88        {89          'code': r"""90          >>> user = make_user('Cheapskate', [91          ...     make_review('A', 2),92          ...     make_review('B', 5),93          ...     make_review('C', 2),94          ...     make_review('D', 5),95          ... ])96          >>> cluster = [97          ...     make_restaurant('A', [5, 2], [], 4, [98          ...         make_review('A', 5)99          ...     ]),100          ...     make_restaurant('B', [3, 2], [], 2, [101          ...         make_review('B', 5)102          ...     ]),103          ...     make_restaurant('C', [-2, 6], [], 4, [104          ...         make_review('C', 4)105          ...     ]),106          ... ]107          >>> fns = [restaurant_price, lambda r: mean(restaurant_ratings(r))]108          >>> pred = best_predictor(user, cluster, fns)109          >>> [round(pred(r), 5) for r in cluster]110          [2.0, 5.0, 2.0]111          """,112          'hidden': False,113          'locked': False114        },115        {116          'code': r"""117          >>> user = make_user('Cheapskate', [118          ...     make_review('A', 2),119          ...     make_review('B', 5),120          ...     make_review('C', 2),121          ...     make_review('D', 5),122          ... ])123          >>> cluster = [124          ...     make_restaurant('A', [5, 2], [], 4, [125          ...         make_review('A', 5)126          ...     ]),127          ...     make_restaurant('B', [3, 2], [], 2, [128          ...         make_review('B', 5)129          ...     ]),130          ...     make_restaurant('C', [-2, 6], [], 4, [131          ...         make_review('C', 4)132          ...     ]),133          ... ]134          >>> fns = [lambda r: mean(restaurant_ratings(r)), restaurant_price]135          >>> pred = best_predictor(user, cluster, fns)136          >>> [round(pred(r), 5) for r in cluster] # Make sure you're iterating through feature_fns!137          [2.0, 5.0, 2.0]138          """,139          'hidden': False,140          'locked': False141        },142        {143          'code': r"""144          >>> user = make_user('Cheapskate', [145          ...     make_review('A', 2),146          ...     make_review('B', 5),147          ...     make_review('C', 2),148          ...     make_review('D', 5),149          ... ])150          >>> cluster = [151          ...     make_restaurant('A', [5, 2], [], 4, [152          ...         make_review('A', 5)153          ...     ]),154          ...     make_restaurant('B', [3, 2], [], 2, [155          ...         make_review('B', 5)156          ...     ]),157          ...     make_restaurant('C', [-2, 6], [], 4, [158          ...         make_review('C', 4)159          ...     ]),160          ...     make_restaurant('E', [1, 2], [], 4, [161          ...         make_review('E', 4)162          ...     ]),163          ... ]164          >>> fns = [lambda r: mean(restaurant_ratings(r)), restaurant_price]165          >>> pred = best_predictor(user, cluster, fns) # Make sure you're only using user-reviewed restaurants!166          >>> [round(pred(r), 5) for r in cluster]167          [2.0, 5.0, 2.0, 2.0]168          """,169          'hidden': False,170          'locked': False171        }172      ],173      'scored': True,174      'setup': r"""175      >>> import tests.test_functions as test176      >>> from recommend import *177      """,178      'teardown': '',179      'type': 'doctest'180    },181    {182      'cases': [183        {184          'code': r"""185          >>> user = make_user('Cheapskate', [186          ...     make_review('A', 2),187          ...     make_review('B', 5),188          ...     make_review('C', 2),189          ...     make_review('D', 5),190          ... ])191          >>> cluster = [192          ...     make_restaurant('A', [5, 2], [], 4, [193          ...         make_review('A', 5)194          ...     ]),195          ...     make_restaurant('B', [3, 2], [], 2, [196          ...         make_review('B', 5)197          ...     ]),198          ...     make_restaurant('C', [-2, 6], [], 4, [199          ...         make_review('C', 4)200          ...     ]),201          ...     make_restaurant('D', [4, 2], [], 2, [202          ...         make_review('D', 3),203          ...         make_review('D', 4)204          ...     ]),205          ... ]206          >>> fns = [restaurant_price, lambda r: mean(restaurant_ratings(r))]207          >>> pred = best_predictor(user, cluster, fns)208          >>> # Hint: Price is a perfect predictor of this user's ratings,209          >>> #       so the predicted ratings should equal the user's ratings210          >>> [round(pred(r), 5) for r in cluster] # should be a list of decimals211          [2.0, 5.0, 2.0, 5.0]212          """,213          'hidden': False,214          'locked': False215        },216        {217          'code': r"""218          >>> user = make_user('Cheapskate', [219          ...     make_review('A', 2),220          ...     make_review('B', 5),221          ...     make_review('C', 2),222          ...     make_review('D', 5),223          ... ])224          >>> cluster = [225          ...     make_restaurant('A', [5, 2], [], 4, [226          ...         make_review('A', 5)227          ...     ]),228          ...     make_restaurant('B', [3, 2], [], 2, [229          ...         make_review('B', 5)230          ...     ]),231          ...     make_restaurant('C', [-2, 6], [], 4, [232          ...         make_review('C', 4)233          ...     ]),234          ... ]235          >>> fns = [restaurant_price, lambda r: mean(restaurant_ratings(r))]236          >>> pred = best_predictor(user, cluster, fns)237          >>> [round(pred(r), 5) for r in cluster]238          [2.0, 5.0, 2.0]239          """,240          'hidden': False,241          'locked': False242        },243        {244          'code': r"""245          >>> user = make_user('Cheapskate', [246          ...     make_review('A', 2),247          ...     make_review('B', 5),248          ...     make_review('C', 2),249          ...     make_review('D', 5),250          ... ])251          >>> cluster = [252          ...     make_restaurant('A', [5, 2], [], 4, [253          ...         make_review('A', 5)254          ...     ]),255          ...     make_restaurant('B', [3, 2], [], 2, [256          ...         make_review('B', 5)257          ...     ]),258          ...     make_restaurant('C', [-2, 6], [], 4, [259          ...         make_review('C', 4)260          ...     ]),261          ... ]262          >>> fns = [lambda r: mean(restaurant_ratings(r)), restaurant_price]263          >>> pred = best_predictor(user, cluster, fns)264          >>> [round(pred(r), 5) for r in cluster] # Make sure you're iterating through feature_fns!265          [2.0, 5.0, 2.0]266          """,267          'hidden': False,268          'locked': False269        },270        {271          'code': r"""272          >>> user = make_user('Cheapskate', [273          ...     make_review('A', 2),274          ...     make_review('B', 5),275          ...     make_review('C', 2),276          ...     make_review('D', 5),277          ... ])278          >>> cluster = [279          ...     make_restaurant('A', [5, 2], [], 4, [280          ...         make_review('A', 5)281          ...     ]),282          ...     make_restaurant('B', [3, 2], [], 2, [283          ...         make_review('B', 5)284          ...     ]),285          ...     make_restaurant('C', [-2, 6], [], 4, [286          ...         make_review('C', 4)287          ...     ]),288          ...     make_restaurant('E', [1, 2], [], 4, [289          ...         make_review('E', 4)290          ...     ]),291          ... ]292          >>> fns = [lambda r: mean(restaurant_ratings(r)), restaurant_price]293          >>> pred = best_predictor(user, cluster, fns) # Make sure you're only using user-reviewed restaurants!294          >>> [round(pred(r), 5) for r in cluster]295          [2.0, 5.0, 2.0, 2.0]296          """,297          'hidden': False,298          'locked': False299        }300      ],301      'scored': True,302      'setup': r"""303      >>> import tests.test_functions as test304      >>> import recommend305      >>> test.swap_implementations(recommend)306      >>> from recommend import *307      """,308      'teardown': r"""309      >>> test.restore_implementations(recommend)310      """,311      'type': 'doctest'312    }313  ]...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
