# coding: utf-8
"""
This test file tests the lib.policy.py

The lib.policy.py only depends on the database model.
"""
import dateutil
import mock

from .base import MyTestCase, FakeFlaskG, FakeAudit

from privacyidea.lib.auth import ROLE
from privacyidea.lib.policy import (set_policy, delete_policy,
                                    import_policies, export_policies,
                                    get_static_policy_definitions,
                                    PolicyClass, SCOPE, enable_policy,
                                    PolicyError, ACTION, MAIN_MENU,
                                    delete_all_policies,
                                    get_action_values_from_options, Match, MatchingError,
                                    get_allowed_custom_attributes)
from privacyidea.lib.realm import (set_realm, delete_realm, get_realms)
from privacyidea.lib.resolver import (save_resolver, get_resolver_list,
                                      delete_resolver)
from privacyidea.lib.error import ParameterError
from privacyidea.lib.user import User
from .base import PWFILE as FILE_PASSWORDS
from .base import PWFILE2 as FILE_PASSWD

def _check_policy_name(polname, policies):
    """
    Checks if the polname is contained in the policies list.
    """
    contained = False
    for pol in policies:
        if pol.get("name") == polname:
            contained = True
            break
    return contained

class PolicyTestCase(MyTestCase):
    """
    Test the policies on a database level
    """

    def test_01_create_simple_policy(self):
        p = set_policy(name="pol1",
                       action="read",
                       scope="system")
        self.assertTrue(p > 0)

        p = set_policy(name="pol2",
                       action="tokentype=HOTP",
                       scope=SCOPE.AUTHZ)
        self.assertTrue(p > 0)

        p = set_policy(name="pol3",
                       action="serial=OATH",
                       scope=SCOPE.AUTHZ)
        self.assertTrue(p > 0)

        p = set_policy(name="pol4",
                       action="enroll, init, disable , enable",
                       scope="admin")
        self.assertTrue(p > 0)

        P = PolicyClass()
        policies = P.match_policies(name="pol3")
        # only one policy found
        self.assertTrue(len(policies) == 1, len(policies))

        policies = P.match_policies(scope=SCOPE.AUTHZ)
        self.assertTrue(len(policies) == 2, len(policies))

        policies = P.match_policies(scope=SCOPE.AUTHZ,
                                    action="tokentype")
        self.assertTrue(len(policies) == 1, len(policies))

        policies = P.match_policies(scope="admin",
                                    action="disable")
        self.assertTrue(len(policies) == 1, len(policies))
        self.assertTrue(policies[0].get("name") == "pol4")

    def test_02_update_policies(self):
        p = set_policy(name="pol1",
                       action="read",
                       scope="system",
                       realm="*",
                       resolver="*",
                       user="*",
                       client="0.0.0.0/0",
                       active=False)
        self.assertTrue(p > 0)

        p = set_policy(name="pol2",
                       action="tokentype=HOTP",
                       scope=SCOPE.AUTHZ,
                       realm="*")
        self.assertTrue(p > 0)

        p = set_policy(name="pol2a",
                       action="tokentype=TOTP",
                       scope=SCOPE.AUTHZ,
                       realm="realm2")
        self.assertTrue(p > 0)

        p = set_policy(name="pol3",
                       action="serial=OATH",
                       scope=SCOPE.AUTHZ,
                       realm="realm1",
                       resolver="resolver1")
        self.assertTrue(p > 0)

        p = set_policy(name="pol4",
                       action="enroll, init, disable , enable",
                       scope="admin",
                       realm="realm2",
                       adminuser=["admin", "superroot"])
        self.assertTrue(p > 0)

        # enable and disable policies
        policies = PolicyClass().match_policies(active=False)
        num_old = len(policies)
        p = enable_policy("pol4", False)
        policies = PolicyClass().match_policies(active=False)
        self.assertTrue(num_old + 1 == len(policies), (num_old, len(policies)))
        p = enable_policy("pol4", True)
        policies = PolicyClass().match_policies(active=False)
        self.assertTrue(num_old == len(policies), len(policies))

        # find inactive policies
        P = PolicyClass()
        policies = P.match_policies(active=False)
        self.assertTrue(len(policies) == 1, len(policies))
        self.assertTrue(policies[0].get("name") == "pol1")

        # find policies action tokentype
        policies = P.match_policies(action="tokentype")
        self.assertTrue(len(policies) == 2, policies)
        # find policies action serial
        policies = P.match_policies(action="serial")
        self.assertTrue(len(policies) == 1, policies)
        # find policies with scope authorization
        policies = P.match_policies(scope=SCOPE.AUTHZ)
        self.assertTrue(len(policies) == 3, policies)
        # find policies authorization and realm2
        policies = P.match_policies(action="tokentype", scope=SCOPE.AUTHZ)
        self.assertTrue(len(policies) == 2, policies)
        # find policies with user admin
        policies = P.match_policies(scope="admin", adminuser="admin")
        self.assertTrue(len(policies) == 1, "{0!s}".format(len(policies)))
        # find policies with resolver2 and authorization. THe result should
        # be pol2 and pol2a
        policies = P.match_policies(resolver="resolver2", scope=SCOPE.AUTHZ)
        self.assertTrue(len(policies) == 2, policies)

        # find policies with realm1 and authorization. We also include the
        # "*" into the result list. We find pol2 and pol3
        policies = P.match_policies(realm="realm1", scope=SCOPE.AUTHZ)
        self.assertTrue(len(policies) == 2, policies)

        # find policies with resolver1 and authorization.
        # All other authorization policies will also match, since they either
        # user * or
        # have no destinct information about resolvers
        policies = P.match_policies(resolver="resolver1", scope=SCOPE.AUTHZ)
        self.assertTrue(len(policies) == 3, policies)

    def test_04_delete_policy(self):
        delete_policy(name="pol4")
        P = PolicyClass()
        pol4 = P.match_policies(name="pol4")
        self.assertTrue(pol4 == [], pol4)

    def test_05_export_policies(self):
        P = PolicyClass()
        policies = P.match_policies()
        file = export_policies(policies)
        self.assertTrue("[pol1]" in file, file)
        self.assertTrue("[pol2]" in file, file)
        self.assertTrue("[pol3]" in file, file)

    def test_06_import_policies(self):
        P = PolicyClass()
        file = export_policies(P.match_policies())
        delete_policy("pol1")
        delete_policy("pol2")
        delete_policy("pol3")
        P = PolicyClass()
        policies = P.match_policies()
        self.assertFalse(_check_policy_name("pol1", policies), policies)
        self.assertFalse(_check_policy_name("pol2", policies), policies)
        self.assertFalse(_check_policy_name("pol3", policies), policies)
        # Now import the policies again
        num = import_policies(file)
        self.assertTrue(num == 4, num)
        P = PolicyClass()
        policies = P.match_policies()
        self.assertTrue(_check_policy_name("pol1", policies), policies)
        self.assertTrue(_check_policy_name("pol2", policies), policies)
        self.assertTrue(_check_policy_name("pol3", policies), policies)

    def test_07_client_policies(self):
        delete_policy(name="pol2a")
        set_policy(name="pol1", scope="s", client="172.16.0.3, 172.16.0.4/24")
        set_policy(name="pol2", scope="s", client="192.168.0.0/16, "
                                                  "-192.168.1.1")
        set_policy(name="pol3", scope="s", client="10.0.0.1, 10.0.0.2, "
                                                  "10.0.0.3")
        set_policy(name="pol4", scope="s")

        # One policy with matching client, one without any clients
        P = PolicyClass()
        p = P.match_policies(client="10.0.0.1")
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)
        self.assertTrue(len(p) == 2, p)

        # client matches pol4 and pol2
        p = P.match_policies(client="192.168.2.3")
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)
        self.assertTrue(len(p) == 2, p)

        # client only matches pol4, since it is excluded in pol2
        p = P.match_policies(client="192.168.1.1")
        self.assertTrue(_check_policy_name("pol4", p), p)
        self.assertTrue(len(p) == 1, p)

        # client="" throws a ParameterError
        with self.assertRaises(ParameterError):
            P.match_policies(client="")

    def test_08_user_policies(self):
        set_policy(name="pol1", scope="s", user="*")
        set_policy(name="pol2", scope="s", user="admin, root, user1")
        set_policy(name="pol3", scope="s", user="*, !user1")
        set_policy(name="pol4", scope="s", user="*, -root")

        # get policies for user1
        P = PolicyClass()
        p = P.match_policies(user="user1")
        self.assertTrue(len(p) == 3, (len(p), p))
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertFalse(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)
        # get policies for root
        p = P.match_policies(user="root")
        self.assertTrue(len(p) == 3, p)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertFalse(_check_policy_name("pol4", p), p)
        # get policies for admin
        p = P.match_policies(user="admin")
        self.assertTrue(len(p) == 4, p)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)
        # get policies for empty user
        p = P.match_policies(user="")
        self.assertEqual(len(p), 3)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)

    def test_08a_adminuser_policies(self):
        set_policy(name="pol1", scope="admin", adminuser="*", user="")
        set_policy(name="pol2", scope="admin", adminuser="admin, root, user1", user="*")
        set_policy(name="pol3", scope="admin", adminuser="*, !user1", user="")
        set_policy(name="pol4", scope="admin", adminuser="*, -root", user="")

        # get policies for user1
        P = PolicyClass()
        p = P.match_policies(scope=SCOPE.ADMIN, adminuser="user1")
        self.assertTrue(len(p) == 3, (len(p), p))
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertFalse(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)
        # get policies for root
        p = P.match_policies(scope=SCOPE.ADMIN, adminuser="root")
        self.assertTrue(len(p) == 3, p)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertFalse(_check_policy_name("pol4", p), p)
        # get policies for admin
        p = P.match_policies(scope=SCOPE.ADMIN, adminuser="admin")
        self.assertTrue(len(p) == 4, p)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)
        # get policies for empty user
        p = P.match_policies(scope=SCOPE.ADMIN, adminuser="")
        self.assertEqual(len(p), 3)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)

    def test_09_realm_resolver_policy(self):
        set_policy(name="pol1", scope="s", realm="r1")
        set_policy(name="pol2", scope="s", realm="r1", resolver="reso1")
        set_policy(name="pol3", scope="s", realm="", resolver="reso2")
        set_policy(name="pol4", scope="s", realm="r2", active=True)

        P = PolicyClass()
        p = P.match_policies(realm="r1")
        self.assertTrue(len(p) == 3, p)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertFalse(_check_policy_name("pol4", p), p)

        p = P.match_policies(realm="r2")
        self.assertTrue(len(p) == 2, p)
        self.assertFalse(_check_policy_name("pol1", p), p)
        self.assertFalse(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)

        # Check cases in which we pass an empty realm or realm=None
        p = P.match_policies(realm="")
        self.assertEqual(len(p), 1)
        self.assertTrue(_check_policy_name("pol3", p), p)

        p = P.match_policies(realm=None)
        self.assertEqual(len(p), 4)

        p = P.match_policies(resolver="reso1")
        self.assertEqual(len(p), 3)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertFalse(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)

        p = P.match_policies(resolver="reso2")
        self.assertTrue(len(p) == 3, p)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertFalse(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)

        # Check case in which we pass an empty resolver
        p = P.match_policies(resolver="")
        self.assertEqual(len(p), 2)
        self.assertTrue(_check_policy_name("pol1", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)

    def test_10_action_policies(self):
        set_policy(name="pol1", action="enroll, init, disable")
        set_policy(name="pol2", action="enroll, otppin=1")
        set_policy(name="pol3", action="*, -disable")
        set_policy(name="pol4", action="*, -otppin=2")

        P = PolicyClass()
        p = P.match_policies(action="enroll")
        self.assertTrue(len(p) == 4, (len(p), p))

        p = P.match_policies(action="init")
        self.assertTrue(len(p) == 3, (len(p), p))

        p = P.match_policies(action="disable")
        self.assertTrue(len(p) == 2, (len(p), p))

        p = P.match_policies(action="otppin")
        self.assertTrue(len(p) == 2, (len(p), p))

        # Check cases in which we pass an empty action or action=None
        p = P.match_policies(action="")
        # Here, we get pol3 and pol4
        self.assertEqual(len(p), 2)
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)

        p = P.match_policies(action=None)
        self.assertEqual(len(p), 4)

    def test_11_get_policy_definitions(self):
        p = get_static_policy_definitions()
        self.assertTrue("admin" in p, p)

        p = get_static_policy_definitions(scope="admin")
        self.assertTrue("enable" in p, p)

    def test_12_get_allowed_tokentypes(self):
        set_policy(name="tt1", scope=SCOPE.AUTHZ, action="tokentype=hotp "
                                                         "totp, enroll")
        set_policy(name="tt2", scope=SCOPE.AUTHZ, action="tokentype=motp")

        P = PolicyClass()
        ttypes = P.get_action_values("tokentype", scope=SCOPE.AUTHZ)
        self.assertTrue("motp" in ttypes)
        self.assertTrue("totp" in ttypes)
        self.assertTrue("hotp" in ttypes)
        self.assertFalse("spass" in ttypes)

        type_policies = P.get_action_values("tokentype", scope=SCOPE.AUTHZ)
        self.assertTrue("motp" in type_policies.keys())
        self.assertTrue("totp" in type_policies.keys())
        self.assertTrue("hotp" in type_policies.keys())
        self.assertFalse("spass" in type_policies.keys())

        # motp is defined in policy "tt2"
        self.assertEqual(type_policies.get("motp"), ["tt2"])
        # totp and hotp is defined in policy "tt1"
        self.assertEqual(type_policies.get("hotp"), ["tt1"])
        self.assertEqual(type_policies.get("totp"), ["tt1"])

    def test_13_get_allowed_serials(self):
        set_policy(name="st1", scope=SCOPE.AUTHZ, action="serial=OATH")
        set_policy(name="st2", scope=SCOPE.AUTHZ, action="serial=mOTP ")

        P = PolicyClass()
        ttypes = P.get_action_values("serial", scope=SCOPE.AUTHZ)
        self.assertTrue("OATH" in ttypes)
        self.assertTrue("mOTP" in ttypes)
        self.assertFalse("TOTP" in ttypes)

        serial_policies = P.get_action_values("serial", scope=SCOPE.AUTHZ)
        self.assertEqual(serial_policies.get("OATH"), ["st1"])
        self.assertEqual(serial_policies.get("mOTP"), ["st2"])

    def test_14_fail_unique_policies(self):
        # create policies with two different texts
        set_policy(name="email1", scope=SCOPE.AUTH, action="emailtext=text 1")
        set_policy(name="email2", scope=SCOPE.AUTH, action="emailtext=text 2")

        # As there are two policies with different action values,
        # a PolicyError is raised.
        P = PolicyClass()
        self.assertRaises(PolicyError, P.get_action_values,
                          action="emailtext", scope=SCOPE.AUTH,
                          unique=True,
                          allow_white_space_in_action=True)

    def test_15_ui_tokentypes(self):
        P = PolicyClass()
        logged_in_user = {"username": "admin",
                          "role": "admin",
                          "realm": "realm1"}
        # Without policies, the admin gets all
        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertTrue("hotp" in tt)
        self.assertTrue("totp" in tt)
        self.assertTrue("motp" in tt)
        self.assertTrue("sms" in tt)
        self.assertTrue("spass" in tt)
        self.assertTrue("sshkey" in tt)
        self.assertTrue("email" in tt)
        self.assertTrue("certificate" in tt)
        self.assertTrue("yubico" in tt)
        self.assertTrue("yubikey" in tt)
        self.assertTrue("radius" in tt)

        # An admin may only enroll Yubikeys
        set_policy(name="tokenEnroll", scope=SCOPE.ADMIN,
                   action="enrollYUBIKEY")
        P = PolicyClass()

        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertFalse("hotp" in tt)
        self.assertFalse("totp" in tt)
        self.assertFalse("motp" in tt)
        self.assertFalse("sms" in tt)
        self.assertFalse("spass" in tt)
        self.assertFalse("sshkey" in tt)
        self.assertFalse("email" in tt)
        self.assertFalse("certificate" in tt)
        self.assertFalse("yubico" in tt)
        self.assertTrue("yubikey" in tt)
        self.assertFalse("radius" in tt)

        # A user may enroll nothing
        set_policy(name="someUserAction", scope=SCOPE.USER,
                   action="disable")
        P = PolicyClass()
        tt = P.ui_get_enroll_tokentypes("127.0.0.1", {"username": "kurt",
                                                      "realm": "realm",
                                                      "role": "user"})
        self.assertEqual(len(tt), 0)
        delete_policy("tokenEnroll")

        # Two admins:
        # adminA is allowed to enroll tokens in all realms
        # adminB is allowed to enroll tokens only in realmB

        set_policy(name="polAdminA", scope=SCOPE.ADMIN, adminuser="adminA",
                   action="enrollHOTP, enrollTOTP")
        set_policy(name="polAdminB", scope=SCOPE.ADMIN, adminuser="adminB",
                   realm="realmB",
                   action="enrollHOTP")
        P = PolicyClass()
        # realm is empty, since in case of an admin, this is the admin realm
        rights = P.ui_get_enroll_tokentypes(None, {"role": SCOPE.ADMIN,
                                                   "realm": None,
                                                   "username": "adminA"})
        self.assertTrue("hotp" in rights)
        self.assertTrue("totp" in rights)
        rights = P.ui_get_enroll_tokentypes(None, {"role": SCOPE.ADMIN,
                                                   "realm": "",
                                                   "username": "adminB"})
        self.assertTrue("totp" not in rights)
        self.assertTrue("hotp" in rights)
        rights = P.ui_get_enroll_tokentypes(None, {"role": SCOPE.ADMIN,
                                                   "realm": "",
                                                   "username": "adminC"})
        self.assertEqual(rights, {})
        delete_policy("polAdminA")
        delete_policy("polAdminB")

    def test_16_admin_realm(self):
        P = PolicyClass()
        logged_in_user = {"username": "admin",
                          "role": "admin",
                          "realm": "realm1"}
        # Without policies, the admin gets all
        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertTrue("hotp" in tt)
        self.assertTrue("totp" in tt)
        self.assertTrue("motp" in tt)
        self.assertTrue("sms" in tt)
        self.assertTrue("spass" in tt)
        self.assertTrue("sshkey" in tt)
        self.assertTrue("email" in tt)
        self.assertTrue("certificate" in tt)
        self.assertTrue("yubico" in tt)
        self.assertTrue("yubikey" in tt)
        self.assertTrue("radius" in tt)

        set_policy(name="tokenEnroll", scope=SCOPE.ADMIN,
                   adminrealm=["realm2"],
                   action="enrollYUBIKEY")
        # Update policy: An admin in realm1 may only enroll Yubikeys
        set_policy(name="tokenEnroll", scope=SCOPE.ADMIN,
                   adminrealm=["realm1"],
                   action="enrollYUBIKEY")
        P = PolicyClass()

        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertFalse("hotp" in tt)
        self.assertFalse("totp" in tt)
        self.assertFalse("motp" in tt)
        self.assertFalse("sms" in tt)
        self.assertFalse("spass" in tt)
        self.assertFalse("sshkey" in tt)
        self.assertFalse("email" in tt)
        self.assertFalse("certificate" in tt)
        self.assertFalse("yubico" in tt)
        self.assertTrue("yubikey" in tt)
        self.assertFalse("radius" in tt)

        # An admin in another admin realm may enroll nothing.
        logged_in_user = {"username": "admin",
                          "role": "admin",
                          "realm": "OtherRealm"}
        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertFalse("hotp" in tt)
        self.assertFalse("totp" in tt)
        self.assertFalse("motp" in tt)
        self.assertFalse("sms" in tt)
        self.assertFalse("spass" in tt)
        self.assertFalse("sshkey" in tt)
        self.assertFalse("email" in tt)
        self.assertFalse("certificate" in tt)
        self.assertFalse("yubico" in tt)
        self.assertFalse("yubikey" in tt)
        self.assertFalse("radius" in tt)
        delete_policy("tokenEnroll")

    def test_17_ui_get_rights(self):
        P = PolicyClass()
        # Check invalid scope
        with self.assertRaises(PolicyError):
            P.ui_get_rights(SCOPE.ENROLL, "realm1", "admin")

        # Without policies, the admin gets all
        rights = P.ui_get_rights(SCOPE.ADMIN, "realm1", "admin")
        self.assertTrue(len(rights) >= 60)

        # An admin may only enroll Yubikeys
        set_policy(name="tokenEnroll", scope=SCOPE.ADMIN,
                   action="enrollYUBIKEY")
        P = PolicyClass()
        rights = P.ui_get_rights(SCOPE.ADMIN, "realm1", "admin")
        self.assertEqual(rights, ["enrollYUBIKEY"])

        # A user may do something else...
        set_policy(name="userpol", scope=SCOPE.USER, action="enable")
        P = PolicyClass()
        rights = P.ui_get_rights(SCOPE.USER, "realm2", "user")
        # there was still another policy...
        self.assertEqual(set(rights), {"enable", "disable"})

        delete_policy("tokenEnroll")
        delete_policy("userpol")
        # Two admins:
        # adminA is allowed to enroll tokens in all realms
        # adminB is allowed to enroll tokens only in realmB
        set_policy(name="polAdminA", scope=SCOPE.ADMIN, adminuser="adminA",
                   action="enrollHOTP, enrollTOTP")
        set_policy(name="polAdminB", scope=SCOPE.ADMIN, adminuser="adminB",
                   realm="realmB",
                   action="enrollHOTP")
        P = PolicyClass()
        # realm is empty, since in case of an admin, this is the admin realm
        rights = P.ui_get_rights(SCOPE.ADMIN, realm=None, username="adminA")
        self.assertTrue("enrollTOTP" in rights)
        self.assertTrue("enrollHOTP" in rights)
        rights = P.ui_get_rights(SCOPE.ADMIN, realm=None, username="adminB")
        self.assertTrue("enrollTOTP" not in rights)
        self.assertTrue("enrollHOTP" in rights)
        rights = P.ui_get_rights(SCOPE.ADMIN, realm=None, username="adminC")
        self.assertEqual(rights, [])
        delete_policy("polAdminA")
        delete_policy("polAdminB")

    def test_17b_ui_rights_users_in_different_resolvers(self):
        # Create a realm with two resolvers

        rid = save_resolver({"resolver": "passwd",
                             "type": "passwdresolver",
                             "fileName": FILE_PASSWD})
        self.assertTrue(rid > 0, rid)

        rid = save_resolver({"resolver": "passwords",
                             "type": "passwdresolver",
                             "fileName": FILE_PASSWORDS})
        self.assertTrue(rid > 0, rid)

        # create user realm
        (added, failed) = set_realm("realm4",
                                    ["passwd", "passwords"])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 2)

        # A user may do something else...
        set_policy(name="userpol41", scope=SCOPE.USER, action="enable",
                   realm="realm4", resolver="passwd")
        set_policy(name="userpol42", scope=SCOPE.USER, action="remove",
                   realm="realm4", resolver="passwords")
        P = PolicyClass()

        # The two users are in different resolvers and get different rights
        rights = P.ui_get_rights(SCOPE.USER, "realm4", "postfix")
        self.assertEqual(set(rights), {"enable", "disable"})

        rights = P.ui_get_rights(SCOPE.USER, "realm4", "usernotoken")
        self.assertEqual(set(rights), {"disable", "remove"})

        delete_policy("userpol41")
        delete_policy("userpol42")
        delete_realm("realm4")
        delete_resolver("passwords")
        delete_resolver("passwd")

    def test_18_policy_match_policies_with_time(self):
        set_policy(name="time1", scope=SCOPE.AUTHZ,
                   action="tokentype=hotp totp, enroll",
                   time="Mon-Wed: 0-23:59")

        wednesday = dateutil.parser.parse("Jul 03 2019 13:00")
        thursday = dateutil.parser.parse("Jul 04 2019 14:34")

        # Simulate a Wednesday
        with mock.patch('privacyidea.lib.utils.datetime') as mock_dt:
            mock_dt.now.return_value = wednesday

            P = PolicyClass()
            # Regardless of the weekday, ``list_policies`` returns the policy
            policies = P.list_policies(name="time1", scope=SCOPE.AUTHZ)
            self.assertEqual(len(policies), 1)
            self.assertEqual(policies[0]["name"], "time1")
            # And ``match_policies`` returns it on Wednesdays
            policies = P.match_policies(name="time1", scope=SCOPE.AUTHZ)
            self.assertEqual(len(policies), 1)
            self.assertEqual(policies[0]["name"], "time1")

        # Simulate a Thursday
        with mock.patch('privacyidea.lib.utils.datetime') as mock_dt:
            mock_dt.now.return_value = thursday

            P = PolicyClass()
            # Regardless of the weekday, ``list_policies`` returns the policy
            policies = P.list_policies(name="time1", scope=SCOPE.AUTHZ)
            self.assertEqual(len(policies), 1)
            self.assertEqual(policies[0]["name"], "time1")
            # But ``match_policies`` does not return it on Thursdays!
            policies = P.match_policies(name="time1", scope=SCOPE.AUTHZ)
            self.assertEqual(len(policies), 0)

        # Directly specify a time
        # Match on Wednesday
        policies = P.match_policies(name="time1", scope=SCOPE.AUTHZ, time=wednesday)
        self.assertEqual(len(policies), 1)
        self.assertEqual(policies[0]["name"], "time1")

        # No match on Thursday
        policies = P.match_policies(name="time1", scope=SCOPE.AUTHZ, time=thursday)
        self.assertEqual(len(policies), 0)

        delete_policy("time1")

    def test_19_ui_get_menus(self):
        delete_all_policies()
        luser = {"username": "admin", "role": "admin"}

        # Without policies, the admin gets all
        P = PolicyClass()
        menus = P.ui_get_main_menus(luser)
        self.assertTrue(MAIN_MENU.USERS in menus)
        self.assertTrue(MAIN_MENU.TOKENS in menus)
        self.assertTrue(MAIN_MENU.COMPONENTS in menus)
        self.assertTrue(MAIN_MENU.CONFIG in menus)
        self.assertTrue(MAIN_MENU.MACHINES in menus)

        # Admin has only right to enroll HOTP! :-)
        set_policy("pol1", scope=SCOPE.ADMIN, adminuser="admin",
                   action="enrollHOTP")
        P = PolicyClass()
        menus = P.ui_get_main_menus(luser)
        # Thus he can only see the token menu
        self.assertTrue(MAIN_MENU.USERS not in menus)
        self.assertTrue(MAIN_MENU.TOKENS in menus)
        self.assertTrue(MAIN_MENU.COMPONENTS not in menus)
        self.assertTrue(MAIN_MENU.CONFIG not in menus)
        self.assertTrue(MAIN_MENU.MACHINES not in menus)

        set_policy("pol2", scope=SCOPE.ADMIN, adminuser="admin",
                   action=ACTION.USERLIST)
        P = PolicyClass()
        menus = P.ui_get_main_menus(luser)
        # Thus he can only see the token menu
        self.assertTrue(MAIN_MENU.USERS in menus)
        self.assertTrue(MAIN_MENU.TOKENS in menus)
        self.assertTrue(MAIN_MENU.COMPONENTS not in menus)
        self.assertTrue(MAIN_MENU.CONFIG not in menus)
        self.assertTrue(MAIN_MENU.MACHINES not in menus)

        set_policy("pol3", scope=SCOPE.ADMIN, adminuser="admin",
                   action=ACTION.MACHINELIST)
        P = PolicyClass()
        menus = P.ui_get_main_menus(luser)
        # Thus he can only see the token menu
        self.assertTrue(MAIN_MENU.USERS in menus)
        self.assertTrue(MAIN_MENU.TOKENS in menus)
        self.assertTrue(MAIN_MENU.COMPONENTS not in menus)
        self.assertTrue(MAIN_MENU.CONFIG not in menus)
        self.assertTrue(MAIN_MENU.MACHINES in menus)

        set_policy("pol4", scope=SCOPE.ADMIN, adminuser="admin",
                   action=ACTION.SYSTEMDELETE)
        P = PolicyClass()
        menus = P.ui_get_main_menus(luser)
        # Thus he can only see the token menu
        self.assertTrue(MAIN_MENU.USERS in menus)
        self.assertTrue(MAIN_MENU.TOKENS in menus)
        self.assertTrue(MAIN_MENU.COMPONENTS not in menus)
        self.assertTrue(MAIN_MENU.CONFIG in menus)
        self.assertTrue(MAIN_MENU.MACHINES in menus)

        delete_all_policies()

    def test_20_search_values(self):
        P = PolicyClass()
        found, excluded = P._search_value(["v1", "v2"], "v1")
        self.assertTrue(found)

        found, excluded = P._search_value(["v1", "v2"], "v3")
        self.assertFalse(found)

        found, excluded = P._search_value(["v1", "*"], "v3")
        self.assertTrue(found)

        found, excluded = P._search_value(["v1", "-v2"], "v2")
        self.assertTrue(excluded)

        found, excluded = P._search_value(["v1", "v.*"], "v3")
        self.assertTrue(found)
        self.assertFalse(excluded)

        found, excluded = P._search_value(["v1", "r.*"], "v13")
        self.assertFalse(found)
        self.assertFalse(excluded)

    def test_21_check_all_resolver(self):
        # check_all_resolver allows to find a policy for a secondary user
        # resolver.
        # We create one realm "realm1" with the resolvers
        # reso1 (prio 1)
        # reso2 (prio 2)
        # reso3 (prio 3)
        # A user user@realm1 will be identified as user.reso1@realm1.
        # But we will also match policies for reso2.

        # no realm and resolver
        r = get_realms()
        self.assertEqual(r, {})

        r = get_resolver_list()
        self.assertEqual(r, {})

        # create user realm
        for reso in ["reso1", "resoX", "resoA"]:
            rid = save_resolver({"resolver": reso,
                                 "type": "passwdresolver",
                                 "fileName": FILE_PASSWORDS})
            self.assertTrue(rid > 0, rid)

        # create a realm with reso1 being the resolver with the highest priority
        (added, failed) = set_realm("realm1",
                                    ["reso1", "resoX", "resoA"],
                                    priority={"reso1": 1,
                                              "resoX": 2,
                                              "resoA": 3})
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 3)

        user = User(login="cornelius",
                    realm="realm1")
        # The user, that is created, is cornelius.reso1@realm1
        user_str = "{0!s}".format(user)
        self.assertEqual(user_str, "<cornelius.reso1@realm1>")
        # But the user "cornelius" is also contained in other resolves in
        # this realm
        r = user.get_ordererd_resolvers()
        self.assertEqual(r, ["reso1", "resoX", "resoA"])
        self.assertFalse(user.is_empty())
        self.assertTrue(User().is_empty())

        # define a policy with the wrong resolver
        p = set_policy(name="checkAll", scope=SCOPE.AUTHZ, realm="realm1",
                       resolver="resoX",
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        p = set_policy(name="catchAll", scope=SCOPE.AUTHZ, realm="realm1",
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        P = PolicyClass()
        pols = P.match_policies(scope=SCOPE.AUTHZ, realm=user.realm,
                                resolver=user.resolver, user=user.login)
        self.assertEqual(len(pols), 1)

        # Now we change the policy, so that it uses check_all_resolver, i.e.
        p = set_policy(name="checkAll", scope=SCOPE.AUTHZ, realm="realm1",
                       resolver="resoX", check_all_resolvers=True,
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        P = PolicyClass()
        pols = P.match_policies(scope=SCOPE.AUTHZ, realm=user.realm,
                                resolver=user.resolver, user=user.login)
        self.assertEqual(len(pols), 2)

        # delete policy
        delete_policy("checkAll")
        delete_policy("catchAll")
        # delete resolvers and realm
        delete_realm("realm1")
        for reso in ["reso1", "resoX", "resoA"]:
            rid = delete_resolver(reso)
            self.assertTrue(rid > 0, rid)

    def test_22_non_ascii_user(self):
        set_policy(name="polnonascii",
                   action="enroll, otppin=1",
                   user='nönäscii',
                   scope='s')

        P = PolicyClass()
        p = P.match_policies(action="enroll", user='somebodyelse')
        self.assertEqual(len(p), 0)

        p = P.match_policies(action="enroll", user='nönäscii')
        self.assertEqual(len(p), 1)

        delete_policy(name="polnonascii")

    def test_23_priorities(self):
        # create three policies with three different texts and different priorities
        set_policy(name="email1", scope=SCOPE.AUTH, action="emailtext=text 1", priority=4)
        set_policy(name="email2", scope=SCOPE.AUTH, action="emailtext=text 2", priority=1)
        set_policy(name="email3", scope=SCOPE.AUTH, action="emailtext=text 3", priority=77)

        # this chooses email2, because it has the highest priority
        P = PolicyClass()
        self.assertEqual(list(P.get_action_values(action="emailtext", scope=SCOPE.AUTH,
                                                  unique=True, allow_white_space_in_action=True).keys()),
                         ["text 2"])

        delete_policy("email2")

        # with email2 gone, this chooses email1
        self.assertEqual(list(P.get_action_values(action="emailtext", scope=SCOPE.AUTH,
                                                  unique=True, allow_white_space_in_action=True).keys()),
                         ["text 1"])

        # if we now add another policy with priority 77, we get no conflict
        # because email1 is chosen
        set_policy(name="email4", scope=SCOPE.AUTH, action="emailtext=text 4", priority=77)

        self.assertEqual(list(P.get_action_values(action="emailtext", scope=SCOPE.AUTH,
                                                  unique=True, allow_white_space_in_action=True).keys()),
                         ["text 1"])

        # but we get a conflict if we change the priority of email4 to 4
        set_policy(name="email4", scope=SCOPE.AUTH, action="emailtext=text 4", priority=4)

        with self.assertRaises(PolicyError) as cm:
            P.get_action_values(
                action="emailtext", scope=SCOPE.AUTH,
                unique=True, allow_white_space_in_action=True)
        self.assertIn("policies with conflicting actions", str(cm.exception))

        pols = P.match_policies(action="emailtext", scope=SCOPE.AUTH)
        self.assertEqual(len(pols), 3)
        with self.assertRaises(PolicyError) as cm:
            P.check_for_conflicts(pols, "emailtext")

        P.check_for_conflicts([], "emailtext")
        P.check_for_conflicts([pols[0]], "emailtext")

        # we can also change the priority
        set_policy(name="email4", priority=3)

        self.assertEqual(list(P.get_action_values(action="emailtext", scope=SCOPE.AUTH,
                                                  unique=True, allow_white_space_in_action=True).keys()),
                         ["text 4"])

        # now we have
        # email1, priority=4
        # email3, priority=77
        # email4, priority=3

        # export, delete all, re-import
        exported = export_policies(P.match_policies())
        self.assertIn("priority = 4", exported)
        self.assertIn("priority = 77", exported)
        delete_all_policies()
        import_policies(exported)

        pols = P.match_policies(action="emailtext", scope=SCOPE.AUTH)
        self.assertEqual(len(pols), 3)
        # this sorts by priority
        self.assertEqual([p['name'] for p in pols],
                         ['email4', 'email1', 'email3'])

        # priority must be at least 1
        with self.assertRaises(ParameterError):
            set_policy(name="email4", scope=SCOPE.AUTH, priority=0)
        with self.assertRaises(ParameterError):
            set_policy(name="email4", scope=SCOPE.AUTH, priority=-5)

        delete_policy("email1")
        delete_policy("email3")
        delete_policy("email4")

    def test_23_priorities_equal_actions(self):
        # create two policies with the same action values
        set_policy(name="email1", scope=SCOPE.AUTH, action="emailtext='text 1'", priority=1)
        set_policy(name="email2", scope=SCOPE.AUTH, action="emailtext='text 1'", priority=1)

        # this reduces the action values to unique values
        P = PolicyClass()
        self.assertEqual(list(P.get_action_values(scope=SCOPE.AUTH, action="emailtext").keys()),
                         ["text 1"])
        # this is allowed if the policies agree
        self.assertEqual(list(P.get_action_values(scope=SCOPE.AUTH, action="emailtext", unique=True).keys()),
                         ["text 1"])

        set_policy(name="email2", action="emailtext='text 2'")
        with self.assertRaises(PolicyError):
            P.get_action_values(scope=SCOPE.AUTH, action="emailtext", unique=True)

        delete_policy("email1")
        delete_policy("email2")

    def test_24_challenge_text(self):
        g = FakeFlaskG()
        g.client_ip = "10.0.0.1"
        options = {"g": g,
                   "user": User("cornelius", self.realm1)}

        set_policy("chaltext", scope=SCOPE.AUTH, action="{0!s}=Wo du wolle?".format(ACTION.CHALLENGETEXT))
        g.policy_object = PolicyClass()

        val = get_action_values_from_options(SCOPE.AUTH, ACTION.CHALLENGETEXT, options)
        self.assertEqual(val, "Wo du wolle?")

        delete_policy("chaltext")

    def test_25_get_action_values(self):
        # We test action values with different priority and values!
        set_policy("act1", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN), priority=1)
        set_policy("act2", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN), priority=1)
        set_policy("act3", scope=SCOPE.AUTH, action="{0!s}=none".format(ACTION.OTPPIN), priority=3)

        # Now we should get the userstore action value. Both policies act1 and act2 have the unique value
        # with prioritoy 1
        P = PolicyClass()
        audit_data = {}
        r = P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH, unique=True, audit_data=audit_data)

        self.assertIn('userstore', r, r)
        self.assertEqual({'act1', 'act2'}, set(r['userstore']), r)

        # The audit_data contains act1 and act2
        self.assertTrue("act1" in audit_data.get("policies"))
        self.assertTrue("act2" in audit_data.get("policies"))
        self.assertTrue("act3" not in audit_data.get("policies"))
        delete_policy("act1")
        delete_policy("act2")
        delete_policy("act3")

    def test_26_match_policies_user_object(self):
        # We pass a user object instead of user, resolver and realm
        # Create resolver and realm
        rid = save_resolver({"resolver": "reso1",
                             "type": "passwdresolver",
                             "fileName": FILE_PASSWORDS})
        self.assertGreater(rid, 0)
        rid = save_resolver({"resolver": "reso2",
                             "type": "passwdresolver",
                             "fileName": FILE_PASSWD})
        self.assertGreater(rid, 0)

        (added, failed) = set_realm("realm1", ["reso1"])
        self.assertEqual(len(failed), 0)
        self.assertEqual(len(added), 1)

        (added, failed) = set_realm("realm2", ["reso2"])
        self.assertEqual(len(failed), 0)
        self.assertEqual(len(added), 1)

        cornelius = User(login="cornelius", realm="realm1")
        nonascii = User(login="nönäscii", realm="realm1")
        selfservice = User(login="selfservice", realm="realm1")
        whoopsie = User(login="whoopsie", realm="realm2")
        set_policy("act1", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                   user="cornelius, nönäscii")
        set_policy("act2", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                   resolver="reso1")
        set_policy("act3", scope=SCOPE.AUTH, action="{0!s}=none".format(ACTION.OTPPIN),
                   realm="realm1")
        set_policy("act4", scope=SCOPE.AUTH, action="{0!s}=none".format(ACTION.OTPPIN),
                   user="nönäscii", realm="realm1")

        P = PolicyClass()
        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=cornelius)),
                         {"act1", "act2", "act3"})
        r = P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH, user_object=cornelius)
        self.assertIn('userstore', r, r)
        self.assertIn('none', r, r)
        self.assertEqual({'act1', 'act2'}, set(r['userstore']), r)
        self.assertEqual(['act3'], r['none'], r)

        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=nonascii)),
                         {"act1", "act2", "act3", "act4"})
        r = P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH, user_object=nonascii)
        self.assertIn('userstore', r, r)
        self.assertIn('none', r, r)
        self.assertEqual({'act1', 'act2'}, set(r['userstore']), r)
        self.assertEqual({'act3', 'act4'}, set(r['none']), r)

        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=selfservice)),
                         {"act2", "act3"})
        self.assertEqual(P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH,
                                             user_object=selfservice),
                         {"userstore": ["act2"], "none": ["act3"]})

        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=whoopsie)),
                         set())
        self.assertEqual(P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH,
                                             user_object=whoopsie),
                         {})

        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=None)),
                         {"act1", "act2", "act3", "act4"})
        r = P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH, user_object=None)
        self.assertIn('userstore', r, r)
        self.assertIn('none', r, r)
        self.assertEqual({'act1', 'act2'}, set(r['userstore']), r)
        self.assertEqual({'act3', 'act4'}, set(r['none']), r)

        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=User())),
                         set())
        self.assertEqual(P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH,
                                             user_object=User()),
                         {})

        with self.assertRaises(ParameterError):
            P.match_policies(user_object=cornelius, realm="realm3")

        with self.assertRaises(ParameterError):
            P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH,
                                user_object=cornelius, user="selfservice")

        set_policy("act5", scope=SCOPE.AUTH, action="{0!s}=none".format(ACTION.OTPPIN))

        P = PolicyClass()
        # If we pass an empty user object, only policies without user match
        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=User())),
                         {"act5"})
        self.assertEqual(P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH, user_object=User()),
                         {"none": ["act5"]})
        # If we pass None as the user object, all policies match
        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=None)),
                         {"act1", "act2", "act3", "act4", "act5"})
        r = P.get_action_values(action=ACTION.OTPPIN, scope=SCOPE.AUTH, user_object=None)
        self.assertIn('userstore', r, r)
        self.assertIn('none', r, r)
        self.assertEqual({'act1', 'act2'}, set(r['userstore']), r)
        self.assertEqual({'act3', 'act4', 'act5'}, set(r['none']), r)

        # if we pass user_obj ornelius, we only get 4 policies
        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=cornelius)),
                         {"act1", "act2", "act3", "act5"})
        # Provide a user object and parameters
        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=cornelius,
                                                                 user="cornelius",
                                                                 realm="realm1")),
                         {"act1", "act2", "act3", "act5"})
        # For some reason pass the same user_obj and parameters, but realm in upper case
        self.assertEqual(set(p['name'] for p in P.match_policies(user_object=cornelius,
                                                                 user="cornelius",
                                                                 realm="REALM1")),
                         {"act1", "act2", "act3", "act5"})

        delete_policy("act1")
        delete_policy("act2")
        delete_policy("act3")
        delete_policy("act4")
        delete_policy("act5")
        delete_realm("realm1")
        delete_realm("realm2")

        delete_resolver("reso1")
        delete_resolver("reso2")

    def test_27_reload_policies(self):
        # First, remove all policies
        policy_object = PolicyClass()
        delete_all_policies()
        self.assertEqual(policy_object.match_policies(), [])
        # Now, add a policy and check if the policies have been reloaded
        set_policy("act1", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN), priority=1)
        self.assertEqual([p["name"] for p in policy_object.match_policies()], ["act1"])
        self.assertEqual(policy_object.match_policies()[0]["priority"], 1)
        # Update the policy and check if the policies have been reloaded
        set_policy("act1", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN), priority=2)
        self.assertEqual(policy_object.match_policies()[0]["priority"], 2)
        # Add a second policy, check
        set_policy("act2", scope=SCOPE.AUTH, action="{0!s}=none".format(ACTION.OTPPIN), priority=3)
        self.assertEqual([p["name"] for p in policy_object.match_policies()], ["act1", "act2"])
        # Delete a policy, check
        delete_policy("act1")
        self.assertEqual([p["name"] for p in policy_object.match_policies()], ["act2"])
        delete_policy("act2")

    def test_28_conditions(self):
        rid = save_resolver({"resolver": "reso1",
                             "type": "passwdresolver",
                             "fileName": FILE_PASSWORDS})
        self.assertGreater(rid, 0)

        (added, failed) = set_realm("realm1", ["reso1"])
        self.assertEqual(len(failed), 0)
        self.assertEqual(len(added), 1)

        # Set policy with conditions
        set_policy("act1", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                   conditions=[("userinfo", "type", "equals", "verysecure", True)])

        P = PolicyClass()
        self.assertEqual(P.list_policies()[0]["conditions"],
                         [("userinfo", "type", "equals", "verysecure", True)])

        # Update existing policy with conditions
        set_policy("act1", conditions=[
            ("userinfo", "type", "equals", "notverysecure", True),
            ("request", "user_agent", "equals", "vpn", True)
        ])
        P = PolicyClass()

        self.assertEqual(P.list_policies()[0]["conditions"],
                         [("userinfo", "type", "equals", "notverysecure", True),
                          ("request", "user_agent", "equals", "vpn", True)])

        delete_policy("act1")
        delete_realm("realm1")
        delete_resolver("reso1")

    def test_29_filter_by_conditions(self):
        def _names(policies):
            return set(p['name'] for p in policies)

        set_policy("verysecure", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                   conditions=[("userinfo", "type", "equals", "verysecure", True)])
        set_policy("notverysecure", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                   conditions=[("userinfo", "type", "equals", "notverysecure", True),
                               ("userinfo", "groups", "contains", "b", True)])
        P = PolicyClass()

        class MockUser(object):
            login = 'login'
            realm = 'realm'
            resolver = 'resolver'

        empty_user = User()

        user1 = MockUser()
        user1.info = {"type": "verysecure", "groups": ["a", "b", "c"]}

        user2 = MockUser()
        user2.info = {"type": "notverysecure", "groups": ["c"]}

        user3 = MockUser()
        user3.info = {"type": "notverysecure", "groups": ["b", "c"]}

        # no user => policy error
        with self.assertRaisesRegex(PolicyError, ".* an according object is not available.*"):
            P.match_policies(user_object=None)

        # empty user => policy error
        with self.assertRaisesRegex(PolicyError, ".*Unknown key.*"):
            P.match_policies(user_object=empty_user)

        # user1 => verysecure matches
        self.assertEqual(_names(P.match_policies(user_object=user1)),
                         {"verysecure"})
        # user2 => no policy matches
        self.assertEqual(_names(P.match_policies(user_object=user2)),
                         set())
        # user3 => notverysecure matches
        self.assertEqual(_names(P.match_policies(user_object=user3)),
                         {"notverysecure"})

        # an unforeseen error in the comparison function => policy error
        with mock.patch("privacyidea.lib.policy.compare_values") as mock_function:
            mock_function.side_effect = ValueError
            with self.assertRaisesRegex(PolicyError, r".*Invalid comparison.*"):
                P.match_policies(user_object=user1)

        for policy in ["verysecure", "notverysecure"]:
            delete_policy(policy)

        # Policy with initially inactive condition
        set_policy("extremelysecure", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                   conditions=[("userinfo", "type", "equals", "notverysecure", False)])

        # user1 matches, because the condition on type is inactive
        self.assertEqual(_names(P.match_policies(user_object=user1)),
                         {"extremelysecure"})

        # activate the condition
        set_policy("extremelysecure", conditions=[("userinfo", "type", "equals", "notverysecure", True)])

        # user1 does not match anymore, because the condition on type is active
        self.assertEqual(_names(P.match_policies(user_object=user1)),
                         set())

        delete_policy("extremelysecure")

    def test_30_filter_by_conditions_errors(self):
        P = PolicyClass()

        class MockUser(object):
            login = 'login'
            realm = 'realm'
            resolver = 'resolver'

        user1 = MockUser()
        user1.info = {"type": "verysecure", "groups": ["a", "b", "c"]}

        # Various error cases:

        # an unknown section in the condition
        set_policy("unknownsection", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                    conditions=[("somesection", "bla", "equals", "verysecure", True)])
        with self.assertRaisesRegex(PolicyError, r".*unknown section.*"):
            P.match_policies(user_object=user1)
        delete_policy("unknownsection")

        # ... but the error does not occur if the condition is inactive
        set_policy("unknownsection", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                    conditions=[("somesection", "bla", "equals", "verysecure", False)])
        all_policies = P.list_policies()
        self.assertEqual(P.match_policies(user_object=user1), all_policies)
        delete_policy("unknownsection")

        # an unknown key in the condition
        set_policy("unknownkey", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                    conditions=[("userinfo", "bla", "equals", "verysecure", True)])
        with self.assertRaisesRegex(PolicyError, r".*Unknown key.*"):
            P.match_policies(user_object=user1)
        delete_policy("unknownkey")

        # a CompareError
        user4 = MockUser()
        user4.info = {"type": "notverysecure", "number": 5}

        set_policy("error", scope=SCOPE.AUTH, action="{0!s}=userstore".format(ACTION.OTPPIN),
                   conditions=[("userinfo", "number", "contains", "b", True)])
        with self.assertRaisesRegex(PolicyError, r".*Invalid comparison.*"):
            P.match_policies(user_object=user4)
        delete_policy("error")

    def test_31_match_pinode(self):
        # import_admin is only allowed to import on node1
        set_policy("import_node1", scope=SCOPE.ADMIN, action=ACTION.IMPORT,
                   adminuser="import_admin, delete_admin", pinode="pinode1")
        # delete_admin is allowed to do everything everywhere
        set_policy("delete_node2", scope=SCOPE.ADMIN, action=ACTION.DELETE,
                   adminuser="delete_admin", pinode="pinode2, pinode1")
        # enable_admin is allowed to enable on all nodes
        set_policy("enable", scope=SCOPE.ADMIN, action=ACTION.ENABLE,
                   adminuser="enable_admin", pinode="")

        P = PolicyClass()
        # Check what the user "import_admin" is allowed to do
        # Allowed to import on pinode 1
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="import_admin", action=ACTION.IMPORT, pinode="pinode1")
        self.assertEqual({"import_node1"}, set(p['name'] for p in pols),)
        # Not allowed to import on pinode 2
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="import_admin", action=ACTION.IMPORT, pinode="pinode2")
        self.assertEqual(set(), set(p['name'] for p in pols))
        # not allowed to delete on any node
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="import_admin", action=ACTION.DELETE)
        self.assertEqual(set(), set(p['name'] for p in pols))

        # Check what the user "delete_admin" is allowerd to do
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="delete_admin", action=ACTION.IMPORT, pinode="pinode1")
        self.assertEqual({"import_node1"}, set(p['name'] for p in pols))
        # Not allowed to import on pinode 2
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="delete_admin", action=ACTION.IMPORT, pinode="pinode2")
        self.assertEqual(set(), set(p['name'] for p in pols))
        # Allowed to delete on node 1 and node 2
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="delete_admin", action=ACTION.DELETE, pinode="pinode1")
        self.assertEqual(set({"delete_node2"}), set(p['name'] for p in pols))
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="delete_admin", action=ACTION.DELETE, pinode="pinode2")
        self.assertEqual(set({"delete_node2"}), set(p['name'] for p in pols))

        # Check what the user "enable_admin" is allowed to do
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="enable_admin", action=ACTION.ENABLE, pinode="pinode1")
        self.assertEqual({"enable"}, set(p['name'] for p in pols))
        pols = P.match_policies(scope=SCOPE.ADMIN, adminuser="enable_admin", action=ACTION.ENABLE, pinode="pinode2")
        self.assertEqual({"enable"}, set(p['name'] for p in pols))

        # Now check the Match-Object, which uses the pinode from the config: In testing environment it is "Node1".
        g = FakeFlaskG()
        g.client_ip = "127.0.0.1"
        g.audit_object = mock.Mock()
        g.policy_object = PolicyClass()
        g.logged_in_user = {"username": "delete_admin", "role": ROLE.ADMIN, "realm": ""}
        pols = Match.admin(g, "delete", None).policies()
        # There is is no policy for Node1 for the "delete_admin
        self.assertEqual(set(), set(p['name'] for p in pols))

        g.logged_in_user = {"username": "enable_admin", "role": ROLE.ADMIN, "realm": ""}
        pols = Match.admin(g, "enable", None).policies()
        # The "enable_admin" is allowed to enable on all nodes, so also on "Node1"
        self.assertEqual({"enable"}, set(p['name'] for p in pols))

        delete_policy("import_node1")
        delete_policy("delete_node2")
        delete_policy("enable")

    def test_31_filter_by_conditions_tokeninfo(self):
        def _names(policies):
            return set(p['name'] for p in policies)

        from privacyidea.lib.tokenclass import TokenClass
        from privacyidea.models import Token
        serial = "filter_by_conditions_token"
        db_token = Token(serial, tokentype="spass")
        db_token.save()
        token = TokenClass(db_token)
        token.set_tokeninfo({"fixedpin": "true", "otherinfo": "true"})

        P = PolicyClass()

        class MockUser(object):
            login = 'login'
            realm = 'realm'
            resolver = 'resolver'

        user1 = MockUser()
        user1.info = {"email": "foo@bar.com"}

        # Policy with initially inactive condition, setpin is allowed for this token
        set_policy("setpin_pol", scope=SCOPE.USER, action=ACTION.SETPIN,
                   conditions=[("tokeninfo", "fixedpin", "equals", "false", False)])

        # policy matches, because the condition on tokeninfo is inactive
        self.assertEqual(_names(P.match_policies(user_object=user1, serial=serial)),
                         {"setpin_pol"})

        # activate the condition
        set_policy("setpin_pol", conditions=[("tokeninfo", "fixedpin", "equals", "false", True)])

        # policy does not match anymore, because the condition on tokeninfo is active
        # setpin action not returned for our token with tokeninfo "fixedpin" = "true"
        self.assertEqual(_names(P.match_policies(user_object=user1, serial=serial)),
                         set())

        # A request without any serial number will raise a Policy error, since condition
        # on tokeninfo is there, but no dbtoken object is available.
        self.assertRaises(PolicyError, P.match_policies, user_object=user1)

        delete_policy("setpin_pol")
        db_token.delete()

    def test_32_filter_by_conditions_token(self):
        def _names(policies):
            return set(p['name'] for p in policies)

        from privacyidea.lib.tokenclass import TokenClass
        from privacyidea.models import Token
        serial = "filter_by_conditions_token"
        db_token = Token(serial, tokentype="spass")
        db_token.save()

        P = PolicyClass()

        class MockUser(object):
            login = 'login'
            realm = 'realm'
            resolver = 'resolver'

        user1 = MockUser()
        user1.info = {"email": "foo@bar.com"}

        # Policy with initially inactive condition, setpin is allowed for this token
        set_policy("setpin_pol", scope=SCOPE.USER, action=ACTION.SETPIN,
                   conditions=[("token", "tokentype", "equals", "hotp", False)])

        # policy matches, because the condition on tokeninfo is inactive
        self.assertEqual(_names(P.match_policies(user_object=user1, serial=serial)),
                         {"setpin_pol"})

        # activate the condition
        set_policy("setpin_pol", conditions=[("token", "tokentype", "equals", "hotp", True)])

        # policy does not match anymore, because the condition on tokeninfo is active
        # setpin action not returned for our token with tokentype == spass
        self.assertEqual(_names(P.match_policies(user_object=user1, serial=serial)),
                         set())

        # Now set a policy condition with a non-case matching token type!
        set_policy("setpin_pol", conditions=[("token", "tokentype", "equals", "Spass", True)])
        self.assertEqual(_names(P.match_policies(user_object=user1, serial=serial)),
                         set())

        # Now check, if we can compare numbers.
        set_policy("setpin_pol", conditions=[("token", "count", "<", "100", True)])
        self.assertEqual(_names(P.match_policies(user_object=user1, serial=serial)),
                         {"setpin_pol"})
        # The the counter of the token is >=100, the policy will not match anymore
        db_token.count = 102
        db_token.save()
        self.assertEqual(_names(P.match_policies(user_object=user1, serial=serial)),
                         set())

        # A request without any serial number will raise a Policy error, since condition
        # on tokeninfo is there, but no dbtoken object is available.
        self.assertRaises(PolicyError, P.match_policies, user_object=user1)

        # Now check, if a wrong comparison raises an exception
        set_policy("setpin_pol", conditions=[("token", "count", "<", "not a number", True)])
        self.assertRaises(PolicyError, P.match_policies, user_object=user1, serial=serial)

        delete_policy("setpin_pol")
        db_token.delete()

    def test_33_get_allowed_attributes(self):

        class MockUser(object):
            login = 'login'
            realm = 'realm'
            resolver = 'resolver'

        user = MockUser()
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        g.logged_in_user = {"role": "admin", "username": "admin", "realm": ""}

        d = get_allowed_custom_attributes(g, user)
        self.assertEqual({"set": {}, "delete": []}, d)

        set_policy("custom_attr", scope=SCOPE.ADMIN,
                   action="{0!s}=:hello: one two".format(ACTION.SET_USER_ATTRIBUTES))
        set_policy("custom_attr2", scope=SCOPE.ADMIN,
                   action="{0!s}=:hello2: * :hello: three".format(ACTION.SET_USER_ATTRIBUTES))
        set_policy("custom_attr3", scope=SCOPE.ADMIN,
                   action="{0!s}=:*: on off".format(ACTION.SET_USER_ATTRIBUTES))
        set_policy("custom_attr4", scope=SCOPE.ADMIN,
                   action="{0!s}=*".format(ACTION.DELETE_USER_ATTRIBUTES))
        # Also check, that a double entry "one" only appears once
        set_policy("custom_attr5", scope=SCOPE.ADMIN,
                   action="{0!s}=:hello: one".format(ACTION.SET_USER_ATTRIBUTES))
        g.policy_object = PolicyClass()

        d = get_allowed_custom_attributes(g, user)
        self.assertEqual(["*"], d.get("delete"))
        self.assertEqual(sorted(d.get("set").keys()), ["*", "hello", "hello2"])
        self.assertEqual(sorted(d.get("set").get("*")), ["off", "on"])
        self.assertEqual(sorted(d.get("set").get("hello")), ["one", "three", "two"])
        self.assertEqual(sorted(d.get("set").get("hello2")), ["*"])

    def test_40_disable_policy_client_remains(self):
        pname = "client_must_not_vanish"
        test_ip = "1.2.3.4"
        set_policy(pname, scope=SCOPE.AUTH,
                   action="otppin=none", client=test_ip)
        p = PolicyClass()
        plist = p.list_policies(name=pname)
        self.assertIn(test_ip, plist[0].get("client"))
        # Now disable the policy
        enable_policy(pname, enable=False)
        # client is still there
        p = PolicyClass()
        plist = p.list_policies(name=pname)
        self.assertIn(test_ip, plist[0].get("client"))
        # enable policy again
        enable_policy(pname, enable=True)
        # client is still there
        p = PolicyClass()
        plist = p.list_policies(name=pname)
        self.assertIn(test_ip, plist[0].get("client"))
        # clean up
        delete_policy(pname)

class PolicyMatchTestCase(MyTestCase):
    @classmethod
    def setUpClass(cls):
        """ create some policies """
        MyTestCase.setUpClass()
        set_policy(name="pol1",
                   action="audit",
                   scope="user",
                   realm="realm1",
                   resolver="reso",
                   user="foobar",
                   client="0.0.0.0/0",
                   active=True)
        set_policy(name="pol2",
                   action="tokentype=HOTP",
                   scope=SCOPE.AUTHZ,
                   realm="*")
        set_policy(name="pol2a",
                   action="tokentype=TOTP",
                   scope=SCOPE.AUTHZ,
                   realm="realm2")
        set_policy(name="pol3",
                   action="serial=OATH",
                   scope=SCOPE.AUTHZ,
                   realm="realm1",
                   resolver="resolver1")
        set_policy(name="pol4",
                   action="enroll, init, disable , enable, audit",
                   scope="admin",
                   realm="realm2",
                   adminuser="admin, superroot")

    def check_names(self, policies, names):
        self.assertEqual(set(p["name"] for p in policies), set(names))

    def test_01_action_only(self):
        g = FakeFlaskG()
        g.client_ip = "127.0.0.1"
        g.audit_object = mock.Mock()
        g.policy_object = PolicyClass()

        g.audit_object.audit_data = {}
        self.check_names(Match.action_only(g, SCOPE.AUTHZ, None).policies(),
                         {"pol2", "pol2a", "pol3"})
        self.assertEqual(set(g.audit_object.audit_data["policies"]),
                         {"pol2", "pol2a", "pol3"})

        g.audit_object.audit_data = {}
        self.check_names(Match.action_only(g, SCOPE.AUTHZ, "tokentype").policies(),
                         {"pol2", "pol2a"})
        self.assertEqual(set(g.audit_object.audit_data["policies"]),
                         {"pol2", "pol2a"})
        g.audit_object.audit_data = {}
        self.assertEqual(Match.action_only(g, SCOPE.AUTHZ, "tokentype").action_values(unique=False),
                         {"HOTP": ["pol2"], "TOTP": ["pol2a"]})
        self.assertEqual(set(g.audit_object.audit_data["policies"]),
                         {"pol2", "pol2a"})

        g.audit_object.audit_data = {}
        self.check_names(Match.action_only(g, SCOPE.AUTHZ, "no_detail_on_success").policies(),
                         {})
        self.assertEqual(g.audit_object.audit_data, {})

        with self.assertRaises(MatchingError):
            Match.action_only(g, SCOPE.ADMIN, "tokenview")

    def test_02_realm(self):
        g = FakeFlaskG()
        g.client_ip = "127.0.0.1"
        g.audit_object = mock.Mock()
        g.policy_object = PolicyClass()

        g.audit_object.audit_data = {}
        self.check_names(Match.realm(g, SCOPE.AUTHZ, "tokentype", None).policies(),
                         {"pol2", "pol2a"})
        self.check_names(Match.realm(g, SCOPE.AUTHZ, "tokentype", "realm1").policies(),
                         {"pol2"})
        self.check_names(Match.realm(g, SCOPE.AUTHZ, "tokentype", "realm2").policies(),
                         {"pol2", "pol2a"})
        self.check_names(Match.realm(g, SCOPE.AUTHZ, "tokentype", "realm3").policies(),
                         {"pol2"})
        self.check_names(Match.realm(g, SCOPE.AUTHZ, "serial", "realm1").policies(),
                         {"pol3"})

        with self.assertRaises(MatchingError):
            Match.realm(g, SCOPE.ADMIN, "tokentype", "realm1")

    def test_03_user(self):
        g = FakeFlaskG()
        g.client_ip = "127.0.0.1"
        g.audit_object = mock.Mock()
        g.policy_object = PolicyClass()

        class Foobar(User):
            def __init__(self):
                self.login = "foobar"
                self.realm = "realm1"
                self.resolver = "reso"

        class Baz(User):
            def __init__(self):
                self.login = "baz"
                self.realm = "realm1"
                self.resolver = "reso"

        self.check_names(Match.user(g, SCOPE.USER, "audit", Foobar()).policies(),
                         {"pol1"})
        self.check_names(Match.user(g, SCOPE.USER, "audit", Baz()).policies(),
                         {})
        self.check_names(Match.user(g, SCOPE.USER, "audit", None).policies(),
                         {"pol1"})

        with self.assertRaises(MatchingError):
            Match.user(g, SCOPE.ADMIN, "tokentype", Foobar())
        with self.assertRaises(MatchingError):
            Match.user(g, SCOPE.ADMIN, "tokentype", {"username": "bla", "realm": "foo", "role": ROLE.USER})

    def test_04_admin(self):
        g = FakeFlaskG()
        g.client_ip = "127.0.0.1"
        g.audit_object = mock.Mock()
        g.policy_object = PolicyClass()
        g.logged_in_user = {"username": "superroot", "realm": "", "role": ROLE.ADMIN}

        self.check_names(Match.admin(g, "enable", None).policies(),
                         {"pol4"})
        self.check_names(Match.admin(g, "enable", User("cornelius", "realm2")).policies(),
                         {"pol4"})
        self.check_names(Match.admin(g, "enable", User("cornelius", "realm1")).policies(),
                         {})

        g.logged_in_user = {"username": "superroot", "realm": "", "role": ROLE.USER}
        with self.assertRaises(MatchingError):
            self.check_names(Match.admin(g, "enable", User("cornelius", "realm1")).policies(),
                             {"pol4"})

    def test_05_admin_or_user(self):
        g = FakeFlaskG()
        g.client_ip = "127.0.0.1"
        g.audit_object = mock.Mock()
        g.policy_object = PolicyClass()

        g.logged_in_user = {"username": "superroot", "realm": "", "role": ROLE.ADMIN}
        self.check_names(Match.admin_or_user(g, "audit", None).policies(),
                         {"pol4"})
        self.check_names(Match.admin_or_user(g, "audit", User("cornelius", "realm2")).policies(),
                         {"pol4"})
        self.check_names(Match.admin_or_user(g, "audit", User("cornelius", "realm1")).policies(),
                         {})

        g.logged_in_user = {"username": "foobar", "realm": "realm1", "role": ROLE.USER}
        # The user foobar@realm1 matches pol1
        self.check_names(Match.admin_or_user(g, "audit", None).policies(),
                         {"pol1"})
        # A user in a different realm does not match!
        self.check_names(Match.admin_or_user(g, "audit", User("cornelius", "realm2")).policies(),
                         {})
        # A wrong user in a realm does not match!
        self.check_names(Match.admin_or_user(g, "audit", User("cornelius", "realm1")).policies(),
                         {})

        g.logged_in_user = {"username": "baz", "realm": "asdf", "role": ROLE.USER}
        self.check_names(Match.admin_or_user(g, "audit", None).policies(),
                         {})

        g.logged_in_user = {"username": "baz", "realm": "asdf", "role": "something"}
        with self.assertRaises(MatchingError):
            self.check_names(Match.admin_or_user(g, "enable", User("cornelius", "realm1")).policies(),
                             {"pol4"})

    @classmethod
    def tearDownClass(cls):
        delete_all_policies()


# A class to sotre all settings for Alien Invasion
class Settings:

    def __init__(self):
        #Initialize the game setting;s static setting

        #Screen Setting
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color=(13, 12, 12)

        # Ship settings
        self.ship_limit=2

        # Bullet settings
        self.bullet_width=3
        self.bullet_height=15
        self.bullet_color= (255, 255, 255)
        self.bullet_allowed=3

        # Alien settings
        self.fleet_drop_speed = 10

        # How quicky the game speeds up
        self.speedup_scale = 1.1

        self.initialize_dynamic_settings()

    def initialize_dynamic_settings(self):
        """ Initialize the settings that change thropught the game """
        self.ship_speed= 1.5
        self.bullet_speed= 3.0
        self.alien_speed = 1.0

        # fleed direction of 1 represents right and -1 represents left
        self.fleet_direction =1

        # Scoring
        self.alien_points = 50

    def increase_seed(self):
        """ Increase speed settings """
        self.ship_speed *= self.speedup_scale
        self.bullet_speed *= self.speedup_scale
        self.alien_speed *= self.speedup_scale


#variadic postional arguments

"""def product(*nums, scale=1):
  p= scale
  for n in nums:
    p*=n
  return p

def is_prime(n):

primes= [number for number in range(2,100) if is_prime(number)]

print(product(*primes))

"""
"""def authorize(quote, **speaker_info):
    print(">",quote)
    print("-" *(len(quote)+2))
    for k,v in speaker_info.items():
        print(k,v,sep=':')

speaker_info={ "name":"faisal",
                   "class":"10th",
                   "sec":"A",
                   "roll_no":10}

authorize("love in life",**speaker_info)
"""
"""
x=3
foo= 'fighter'
y=4
bar='bell'
z=5
print("{z}^2={x}^2 +{y}^2". format(**locals()))
"""

languages= ["python","java"]
"""lens=[map(len(s),s) for s in languages]
print(lens)
"""
"""def is_even(a):
    if a%2==0:
     return True
#print(map(len, languages))
print(filter(is_even,range(100)))
"""
"""print((lambda val:val ** 2)(3))
print((lambda x,y: x*y)(3,2))
lambda pair:pair[0]* pair[1]
triple = (lambda x: x * 3)(3)
print(triple)

print(map (lambda val:val**2, range(10)))"""

"""it =iter([1,2,3])
print(next(it))
print(next(it))
print(next(it))
"""
def generate_insts(n):
    for i in range(n):
        yield i

g= generate_insts(4)
print(g)


import json
import numpy as np

def ranges(data):
    result = []
    #print (f'{data=}')
    if not data:
    #    print ('no data')
        return result
    idata = iter(data)
    first = prev = next(idata)
    for following in idata:
        if following - prev == 1:
            prev = following
        else:
            result.append((first, prev + 1))
            first = prev = following
    # There was either exactly 1 element and the loop never ran,
    # or the loop just normally ended and we need to account
    # for the last remaining range.
    result.append((first, prev+1))
    return result

def pretty_str_state(state, iter):
    pre_action = state.state['start']['value']
    post_action = state.state['output']['value']
    distance = state.state['x_diff']['value']
    # v_self = state.state['v_self']['value']
    # v_front = state.state['v_front']['value']
    v_diff = state.state['v_diff']['value']
    if iter:
        result = '(' + str(iter) + ') '
    else:
        result = ''
    result += (pre_action + ' -> ' + post_action + ':\n')
    tab = '   '
    result += tab + 'distance: ' + str(distance) + '\n'
    # result += tab + 'v_self: ' + str(v_self) + '\n'
    # result += tab + 'v_front: ' + str(v_front) + '\n'
    result += tab + 'v_diff: ' + str(v_diff)
    return result

def DEPRECATED_draw_spec(x1,y1,x2,y2,w):
        a = (y2-y1)/(x2-x1) # slope
        b = y1-x1*a  # intercept
        # calculate intercept of the edges
        c1 = b+w/2  # y-intercept of first line
        c2 = b-w/2  # y-intercept of second line
        x = np.linspace(x1, x2, 1000)
        y1 = a * x + c1
        y2 = a * x + c2
        return x, y1, y2

def save_trace_to_json(trace, filename="demo.json"):
    trace_json = json.dumps([s.state for s in trace])
    with open(filename, "w") as f:
        f.write(trace_json)

def red(text):
    return "\033[91m" + text + "\033[0m"
def green(text):
    return "\033[92m" + text + "\033[0m"
def orange(text):
    return "\033[93m" + text + "\033[0m"
def blue(text):
    return "\033[94m" + text + "\033[0m"

# takes a trace and returns a map with keys being transitions and values being the samples from the trace
def analyze_trace(trace):
    result = {('SLOWER', 'SLOWER'): [], ('SLOWER', 'FASTER'): [],
              ('FASTER', 'FASTER'): [], ('FASTER', 'SLOWER'): []}
    iter = 0
    for s in trace:
        # print(pretty_str_state(s, iter))
        iter += 1
        # print('-'*50)
        pre_action = s.state['start']['value']
        if pre_action:
            post_action = s.state['output']['value']
            result[(pre_action, post_action)].append(s)
    return result


import os
import time

def limpesa_e_time(segundos):
    time.sleep(segundos)
    os.system('cls')

def apresentacao_de_dados(fila):
    print('Apresentação dos dados: ')
    for posicao, valor in enumerate(fila):
        print(
            f'Posicao do chamado = {posicao} | Nome do Usuario: {valor}', end=' | ')
        print('')
        time.sleep(1)

def armazenamento_de_dados(lista01, lista02, fila):
    for chave, valor in fila.items():
        if valor == 1:
            lista01.append(chave)
        if valor == 2:
            lista02.append(chave)

def apresentacao_de_dados_dicionarios(lista01, lista02):
    for i in lista01:
        print(i, end=' | ')
        time.sleep(1)
    for i in lista02:
        print(i, end=' | ')
        time.sleep(1)

def apresentacao_de_dados_dicionarios_inutilizado(fila):
    posicao_valor = 0
    print('Apresentação dos dados: ')
    for i, y in enumerate(fila):
        for posicao, valor in enumerate(y):

            print(
                f'Posicao do chamado = {posicao_valor} | Nome do Usuario: {valor}', end=' | ')
            print('')
            posicao_valor += 1
            time.sleep(1)

def inserir_dados_em_dicionario(fila, chave, dado_para_inserir):
    fila[chave] = dado_para_inserir

def remover_com_o_indice_desejado(fila_das_chaves, variavel_coringa, indice, dicionario):
    if indice > -1:
        if indice <= len(fila_das_chaves):
            print('Removendo elemento...')
            variavel_coringa = fila_das_chaves[indice]
            del dicionario[variavel_coringa]
            limpesa_e_time(2)
        else:
            print('INDICE NÃO EXISTE...')
            limpesa_e_time(2)
    else:
        print('INDICE INFERIOR A 0')
        limpesa_e_time(2)

# inserir dados no final da fila

def incersao_De_dados_enqueue(dado, fila):
    fila.append(dado)

# Remoção - no inicio

def remover_no_inicio_da_fila_dequeue(fila):
    if len(fila) == 0:
        limpesa_e_time(2)
        return "A fila está vazia, não é possível remover"
    else:
        limpesa_e_time(2)
        return fila.pop(0)

# Primeiro elemento - peek

def peek(fila):
    if len(fila) == 0:
        return "Fila vazia"
    else:
        return fila[0]

# retorna bool de fila esta vazia

def is_empty(fila):
    return len(fila) == 0

# retorna o tamanho da fila

def size(fila):
    return len(fila)

# Reverse

def puxa_o_ultimo_elemento_queuereverse(fila):
    filaReversa = []
   # return fila [::-1]
    while not is_empty(fila):
        item = fila.pop()  # dequeue(fila)
        incersao_De_dados(filaReversa, item)
    return filaReversa

Atividade 03 - storyboard/funcoes_filas_prioridade.py


import sys
import time
import signal
import threading
import numpy as np
from PyQt5 import QtWidgets
from PyQt5.QtCore import QTimer
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
sys.path.append("..")
from Modules import Module, Analyzer

class InputPlotter(Analyzer):
    def __init__(self, id=None, standalone=False):
        super().__init__(id)

        self.parameterInputs.append({"name": "channel", "module": None, "sourceIndex": 0, "default": 0.0})
        self.inputs.append({"name": "input", "module": None, "sourceIndex": 0, "default": np.zeros((Analyzer.pixelcount, 6))})

        self.standalone = standalone
        self.standaloneT = 0
        self.updateFunction = None

        self.maxSampleTime = 60 * 5          # [s]
        self.maxTimeWidth = 5                # [s]
        self.manualControlTime = 5           # [s]
        self.x = []
        self.y = []
        self.yMin = 0.0
        self.yMax = 1.0
        self.running = False
        self.ready = False

        if self.standalone:
            def signal_handler(sig, frame):
                self.running = False
                self.widget.graphWidget.close()

            signal.signal(signal.SIGINT, signal_handler)
            threading.Thread(target=self.run, args=(self, )).start()
            while not self.running:
                time.sleep(0.1)

        else:
            self.widget = MainWindow()
            self.app = QtWidgets.QApplication(sys.argv)
            threading.Thread(target=self.app.exec_).start()
            self.widget.show()

    def stop(self):
        self.running = False
        self.widget.close()

    def run(self, ref):
        ref.app = QtWidgets.QApplication(sys.argv)
        ref.widget = MainWindow()
        ref.widget.show()

        self.running = True
        setattr(ref, "app", ref.app)
        setattr(ref, "widget", ref.widget)

        if ref.standalone:
            ref.timer = QTimer()
            ref.timer.timeout.connect(ref.standaloneUpdate)
            ref.timer.start(int(1000 / Module.framerate))

        while ref.widget.graphWidget.isVisible():
            ref.app.processEvents()
        ref.widget.close()
        ref.app.quit()

    def isRunning(self):
        return self.widget.graphWidget.isVisible()

    def isReady(self):
        return self.ready

    def update(self, t):
        if(Module.framerate == 0):
            return False
        self.ready = True
        if self.standalone:
            while not self.inputs[0] or not self.parameterInputs[0]:
                print("waiting")
                time.sleep(0.1)
        if not super().update(t):
            return False

        channel = int(self._getParameterValue(0))
        output = self._getInput(0)[:,channel]

        if self.inputs[0]["module"]:
            module = self.inputs[0]
            moduleName = f"{module['module'].superClassType}.{module['module'].__module__}"
            self.widget.setWindowTitle(f"Input Plotter [{self.id}, Channel: {channel}]: {moduleName} (ID: {module['module'].id}, Output: {module['sourceIndex']})")
            self.widget.updateValues(output)
        else:
            self.widget.setWindowTitle(f"Input Plotter [{self.id}, Channel: {channel}]: Unconnected")

        self.yMin = min(self.yMin, np.min(output))
        self.yMax = max(self.yMax, np.max(output))
        self.widget.plotItem.setYRange(self.yMin * 1.1 - 0.1, self.yMax * 1.1, padding=0)
        return True

    def standaloneUpdate(self):
        if not self.running:
            return
        self.standaloneT += 1 / Module.framerate
        if not self.isReady():      # Start time increment only when analyzer is ready
            self.standaloneT = 0
        if self.updateFunction:
            try:
                self.updateFunction(self.standaloneT)
            except Exception as e:
                self.end()
                print(e)

class LinePlot(pg.GraphicsObject):
    def __init__(self, color, width):
        super(LinePlot, self).__init__()
        self.picture = QtGui.QPicture()
        self.color = color
        self.width = width

    def setData(self, x, y):
        self.x = x
        self.y = y
        self.generate()

    def generate(self):
        p = QtGui.QPainter(self.picture)
        p.setPen(pg.mkPen(self.color, width=self.width))
        for x in self.x:
            y = self.y[x]
            if y > 0.001:       # only draw positive bars
                p.drawLine(QtCore.QPointF(x, 0), QtCore.QPointF(x, y))

    def paint(self, p, *args):
        p.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        return QtCore.QRectF(self.picture.boundingRect())

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.graphWidget = pg.plot()
        self.setCentralWidget(self.graphWidget)
        self.setGeometry(300, 300, 1920, 500)
        self.graphWidget.setBackground('#212124')

        self.color = (0, 142, 211)
        self.plotItem = self.graphWidget.getPlotItem()
        self.plotItem.showGrid(x=True, y=True, alpha=0.3)
        self.plotItem.setMouseEnabled(x=True, y=False)
        self.plotItem.hideButtons()

        self.x = np.arange(Module.pixelcount)
        self.y = np.zeros(Module.pixelcount)

        self.bars = LinePlot(self.color, 3)
        self.dots = pg.ScatterPlotItem(size=8, brush=pg.mkBrush(self.color), pen=pg.mkPen(None))
        self.plotItem.addItem(self.bars)
        self.plotItem.addItem(self.dots)

        xRange = Module.pixelcount
        self.plotItem.setXRange(-0.02 * xRange, xRange * 1.02, padding=0)

    def closeEvent(self, event):
        event.accept()

    def updateValues(self, y):
        self.y = y
        self.bars.setData(self.x, self.y)
        self.dots.setData(self.x, self.y)

if __name__ == '__main__':
    from Modules import Coefficient, Generator, Function, Analyzer
    Module.framerate = 60
    Module.pixelcount = 288

    enable = 1.0
    freq = 0.01
    rep = -1.0
    amp = 0.3
    offset = 0.5
    phase = 0
    variance = 0.01
    colorChannel = 0.0

    sine = Generator.Sine(0)
    sine.setParameterInput(0, Coefficient(3, enable))
    sine.setParameterInput(1, Coefficient(4, freq))
    sine.setParameterInput(2, Coefficient(5, rep))
    sine.setParameterInput(3, Coefficient(6, amp))
    sine.setParameterInput(4, Coefficient(7, offset))
    sine.setParameterInput(5, Coefficient(8, phase))

    pdf = Function.Pdf(1)
    pdf.setParameterInput(0, sine)
    pdf.setParameterInput(1, Coefficient(9, variance))

    plotter = Analyzer.InputPlotter(2, standalone=True)
    # plotter.setParameterInput(0, Coefficient(10, colorChannel))
    plotter.setInput(0, pdf)

    def update(t):
        sine.update(t)
        pdf.update(t)
        plotter.update(t)

    plotter.updateFunction = update
    while not plotter.isReady(): pass    # Wait until plotter is ready
    while plotter.isRunning():
        time.sleep(0.1)


import numpy as np
import tensorflow as tf
from abc import abstractmethod
from rl.core.function_approximators.normalizers import NormalizerStd, Normalizer
from rl.core.oracles.oracle import Oracle
from rl.core.utils.tf2_utils import tf_float, ts_to_array, array_to_ts, var_assign
from rl.core.utils.misc_utils import flatten

class tfOracle(Oracle):
    """ A minimal wrapper of tensorflow functions. """

    def __init__(self, ts_fun, ts_var=None, **kwargs):
        """ If ts_var is None, the input needs to be provided explicitly to ts_fun. Otherwise,
            ts_fun takes no input except for some keyword arguments. """
        self._ts_fun = ts_fun  # a function that returns tf.Tensor(s)
        self._ts_var = ts_var

    def fun(self, x, **kwargs):
        return ts_to_array(self.ts_fun(array_to_ts(x)), **kwargs)

    def grad(self, x, **kwargs):
        return flatten(ts_to_array(self.ts_grad(array_to_ts(x), **kwargs)))

    def ts_fun(self, ts_x, **kwargs):
        if self._ts_var is None:
            return self._ts_fun(ts_x, **kwargs)
        else:
            var_assign(self._ts_var, ts_x)
            return self._ts_fun(**kwargs)

    def ts_grad(self, ts_x, **kwargs):
        """ If x is not provided, the cached value from the previous call of
         `grad` will be returned. """
        ts_var = self._ts_var or ts_x
        with tf.GradientTape() as tape:
            tape.watch(ts_var)
            ts_loss = self.ts_fun(ts_x, **kwargs)
        return tape.gradient(ts_loss, ts_var)

    def update(self, ts_fun=None, ts_var=None, *args, **kwargs):
        if ts_fun is not None:
            self._ts_fun = ts_fun
        if ts_var is not None:
            self._ts_var = ts_var

class tfLikelihoodRatioOracle(tfOracle):
    """
    An Oracle based on the loss function below: if use_log_loss is True

        E_{x} E_{y ~ q | x} [ w * log p(y|x) * f(x, y) ]

    otherwise, it uses

        E_{x} E_{y ~ q | x} [ p(y|x)/q(y|x) * f(x, y) ]

    where p is the variable distribution, q is a constant
    distribution, and f is a scalar function.

    When w = p/q, then the gradients of two loss functions are equivalent.

    The expectation is approximated by unbiased samples from q. To minimize
    the variance of sampled gradients, the implementation of 'grad' is
    based on a normalizer, which can shift, rescale, or clip f.

    """
    def __init__(self, ts_logp_fun, ts_var,
                 nor=None, biased=False,
                 use_log_loss=False, normalized_is=False):
        # ts_var needs to be prvided.
        assert use_log_loss in (True, False, None)
        self._ts_logp_fun = ts_logp_fun
        self._biased = biased
        self._use_log_loss = use_log_loss
        self._normalized_is = normalized_is  # normalized importance sampling
        if nor is None:
            if biased:  # use the current samples
                self._nor = NormalizerStd((1,), unscale=True, clip_thre=None, momentum=0.0)
            else:  # use a moving average
                self._nor = NormalizerStd((1,), unscale=True, clip_thre=None, momentum=None)
        else:
            assert isinstance(nor, Normalizer)
            self._nor = nor
        super().__init__(self.ts_surrogate_loss, ts_var)

    def ts_surrogate_loss(self):
        """ Return the loss function as tf.Tensor and a list of tf.plyeholders
        required to evaluate the loss function. """
        ts_f = self._ts_f
        ts_w_or_logq = self._ts_w_or_logq
        ts_logp = self._ts_logp_fun()  # the function part
        if tf.equal(self._use_log_loss, True):  # ts_w_or_logq is w
            ts_w = ts_w_or_logq
            ts_loss = tf.reduce_sum(ts_w * ts_f * ts_logp)
        elif tf.equal(self._use_log_loss, False): # ts_w_or_logq is logq
            ts_w = tf.exp(ts_logp - ts_w_or_logq)
            ts_loss = tf.reduce_sum(ts_w*ts_f)
        else:  # ts_w_or_logq is logq
            # Another implementation of `self._use_log_loss==False`
            ts_w = tf.stop_gradient(tf.exp(ts_logp - ts_w_or_logq))
            ts_loss = tf.reduce_sum(ts_w * ts_f * ts_logp)
        if self._normalized_is:  # normalized importance sampling
            return ts_loss / tf.reduce_sum(ts_w)
        else: # regular importance sampling
            return ts_loss / tf.cast(ts_f.shape[0], tf_float)

    def update(self, f, w_or_logq, update_nor=True, **kwargs):
        """ Update the function with Monte-Carlo samples.

            f: sampled function values
            w_or_logq: importance weight or the log probability of the sampling distribution
            update_nor: whether to update the normalizer using the current sample
        """
        super().update(**kwargs)
        if self._biased:
            self._nor.update(f)
        f_normalized = self._nor.normalize(f)  # cv
        if self._use_log_loss:  # ts_w_or_logq is w
            assert np.all(w_or_logq >= 0)
        # these are treated as constants
        assert f_normalized.shape==w_or_logq.shape
        self._ts_f = array_to_ts(f_normalized)
        self._ts_w_or_logq = array_to_ts(w_or_logq)
        if not self._biased and update_nor:
            self._nor.update(f)


# context_processors.py

from .models import Product

def liked_products(request):
    liked_products = []
    if request.user.is_authenticated:
        liked_products = Product.objects.filter(liked=request.user)
    return {'liked_products': liked_products}
def brought_products(request):
    brought_products = []
    if request.user.is_authenticated:
        brought_products = Product.objects.filter(brought=request.user)
    return {'brought_products': brought_products}


from datetime import datetime
import telebot
from bot import config
from Banks import PrivatValut as pr
from Keyboards import currency_kb
from Banks import mono
import sys

import subprocess

from Keyboards import chosen_currensy_kb as ch_kb
bot = telebot.TeleBot(config.TOKEN)
coast_categories = [100]

@bot.message_handler(commands=['exchange'])
def send_curr(message):
    send_privat_course(message)

@bot.message_handler(commands=['start'])
def welcome(message):
    bot.send_message(message.chat.id, "Приветствую, {0.first_name}. Меня зовут {1.first_name}, "
                                      "я создан, что бы помогать следить за актуальным курсом валют. "
                                      "Надеюсь, я буду полезен.  "
                     .format(message.from_user, bot.get_me()),
                     parse_mode='html')

    bot.send_message(message.chat.id, "Вы хотите, чтобы я отправил вам акутальный курс валют?",
                     reply_markup=currency_kb.markup_send_curr)

@bot.message_handler(content_types=['text'])
def manage_buttons(message):
    if message.text == "Курс валют":
        send_privat_course(message)
    elif message.text == "Да, отправляй":
        send_privat_course(message)
        send_chosen_curr(message)
    elif message.text == "Польский злотый":
        send_zloty(message)

def send_privat_course(message):
    subprocess.Popen([sys.executable, '../Banks/PrivatValut.py'])
    now = datetime.now()
    bot.send_message(message.chat.id, "Курс валют к гривне на " + str(now.day) + "." + str(now.month) +
                     "." + str(now.year) + ":\n\n" + "USD/Доллар: \n" + "покупка " + str(pr.usd_buy)
                     + " продажа " + str(pr.usd_sale) + ":\n\n"
                     + "Euro/Евро: \n" + "покупка " + str(pr.euro_buy) + " продажа "
                     + str(pr.euro_sale) + " UAH" + ":\n\n" + "BTC/Биткоин: \n" + "покупка "
                     + str(pr.btc_buy) + " $" + " продажа " + str(pr.btc_sale) + " $")

def send_chosen_curr(message):
    bot.send_message(message.chat.id, "Вы можете следить за курсом выбраной вами валюты. "
                                      "Какую валюты вы хотите отслеживать? (Курс выбраной вами валюты будет оцениваться"
                                      "монобанком)", reply_markup=ch_kb.markup_chosen_curr)

def send_zloty(message):
    subprocess.Popen([sys.executable, '../Banks/PrivatValut.py'])
    now = datetime.now()
    bot.send_message(message.chat.id, "Курс злотого на " + str(now.day) + "." + str(now.month) + "." +
                     str(now.year) + "." +
                     ":\n\n" + "Zloty/Злотый: \n\n" + "покупка: " + str(mono.zloty_buy) + "продажа: " +
                     str(mono.zloty_sell))

bot.polling(none_stop=True)