import logging
import os
from unittest import TestCase
from unittest.mock import patch

import pytest
from kubernetes.dynamic import Resource
from kubernetes.dynamic.exceptions import ResourceNotFoundError

import reconcile.utils.oc
from reconcile.utils.oc import (
    GET_REPLICASET_MAX_ATTEMPTS,
    LABEL_MAX_KEY_NAME_LENGTH,
    LABEL_MAX_KEY_PREFIX_LENGTH,
    LABEL_MAX_VALUE_LENGTH,
    OC,
    OC_Map,
    OCCli,
    OCLogMsg,
    OCNative,
    PodNotReadyError,
    StatusCodeError,
    equal_spec_template,
    validate_labels,
)
from reconcile.utils.openshift_resource import OpenshiftResource as OR
from reconcile.utils.secret_reader import (
    SecretNotFound,
    SecretReader,
)

@patch.dict(os.environ, {"USE_NATIVE_CLIENT": "False"}, clear=True)
class TestGetOwnedPods(TestCase):
    @patch.object(OCCli, "get")
    @patch.object(OCCli, "get_obj_root_owner")
    def test_get_owned_pods(self, oc_get_obj_root_owner, oc_get):
        owner_body = {"kind": "ownerkind", "metadata": {"name": "ownername"}}
        owner_resource = OR(owner_body, "", "")

        oc_get.return_value = {
            "items": [
                {
                    "metadata": {
                        "name": "pod1",
                        "ownerReferences": [
                            {
                                "controller": True,
                                "kind": "ownerkind",
                                "name": "ownername",
                            }
                        ],
                    }
                },
                {
                    "metadata": {
                        "name": "pod2",
                        "ownerReferences": [
                            {
                                "controller": True,
                                "kind": "notownerkind",
                                "name": "notownername",
                            }
                        ],
                    }
                },
                {
                    "metadata": {
                        "name": "pod3",
                        "ownerReferences": [
                            {
                                "controller": True,
                                "kind": "ownerkind",
                                "name": "notownername",
                            }
                        ],
                    }
                },
            ]
        }
        oc_get_obj_root_owner.side_effect = [
            owner_resource.body,
            {
                "kind": "notownerkind",
                "metadata": {"name": "notownername"},
            },
            {"kind": "ownerkind", "metadata": {"name": "notownername"}},
        ]

        oc = OC("cluster", "server", "token", local=True)
        pods = oc.get_owned_pods("namespace", owner_resource)
        self.assertEqual(len(pods), 1)
        self.assertEqual(pods[0]["metadata"]["name"], "pod1")

@patch.dict(os.environ, {"USE_NATIVE_CLIENT": "False"}, clear=True)
class TestValidatePodReady(TestCase):
    @patch.object(OCCli, "get")
    def test_validate_pod_ready_all_good(self, oc_get):
        oc_get.return_value = {
            "status": {
                "containerStatuses": [
                    {
                        "name": "container1",
                        "ready": True,
                    },
                    {"name": "container2", "ready": True},
                ]
            }
        }
        oc = OC("cluster", "server", "token", local=True)
        oc.validate_pod_ready("namespace", "podname")

    @patch.object(OCCli, "get")
    def test_validate_pod_ready_one_missing(self, oc_get):
        oc_get.return_value = {
            "status": {
                "containerStatuses": [
                    {
                        "name": "container1",
                        "ready": True,
                    },
                    {"name": "container2", "ready": False},
                ]
            }
        }

        oc = OC("cluster", "server", "token", local=True)
        with self.assertRaises(PodNotReadyError):
            # Bypass the retry stuff
            oc.validate_pod_ready.__wrapped__(oc, "namespace", "podname")

@patch.dict(os.environ, {"USE_NATIVE_CLIENT": "False"}, clear=True)
class TestGetObjRootOwner(TestCase):
    @patch.object(OCCli, "get")
    def test_owner(self, oc_get):
        obj = {
            "metadata": {
                "name": "pod1",
                "ownerReferences": [
                    {"controller": True, "kind": "ownerkind", "name": "ownername"}
                ],
            }
        }
        owner_obj = {"kind": "ownerkind", "metadata": {"name": "ownername"}}

        oc_get.side_effect = [owner_obj]

        oc = OC("cluster", "server", "token", local=True)
        result_owner_obj = oc.get_obj_root_owner("namespace", obj)
        self.assertEqual(result_owner_obj, owner_obj)

    def test_no_owner(self):
        obj = {
            "metadata": {
                "name": "pod1",
            }
        }

        oc = OC("cluster", "server", "token", local=True)
        result_obj = oc.get_obj_root_owner("namespace", obj)
        self.assertEqual(result_obj, obj)

    def test_controller_false_return_obj(self):
        """Returns obj if all ownerReferences have controller set to false"""
        obj = {"metadata": {"name": "pod1", "ownerReferences": [{"controller": False}]}}

        oc = OC("cluster", "server", "token", local=True)
        result_obj = oc.get_obj_root_owner("namespace", obj)
        self.assertEqual(result_obj, obj)

    @patch.object(OCCli, "get")
    def test_controller_false_return_controller(self, oc_get):
        """Returns owner if all ownerReferences have controller set to false
        and allow_not_controller is set to True
        """
        obj = {
            "metadata": {
                "name": "pod1",
                "ownerReferences": [
                    {"controller": False, "kind": "ownerkind", "name": "ownername"}
                ],
            }
        }
        owner_obj = {"kind": "ownerkind", "metadata": {"name": "ownername"}}
        oc_get.side_effect = [owner_obj]

        oc = OC("cluster", "server", "token", local=True)
        result_obj = oc.get_obj_root_owner("namespace", obj, allow_not_controller=True)
        self.assertEqual(result_obj, owner_obj)

    @patch.object(OCCli, "get")
    def test_cont_true_allow_true_ref_not_found_return_obj(self, oc_get):
        """Returns obj if controller is true, allow_not_found is true,
        but referenced object does not exist '{}'
        """
        obj = {
            "metadata": {
                "name": "pod1",
                "ownerReferences": [
                    {"controller": True, "kind": "ownerkind", "name": "ownername"}
                ],
            }
        }
        owner_obj = {}

        oc_get.side_effect = [owner_obj]

        oc = OC("cluster", "server", "token", local=True)
        result_obj = oc.get_obj_root_owner("namespace", obj, allow_not_found=True)
        self.assertEqual(result_obj, obj)

    @patch.object(OCCli, "get")
    def test_controller_true_allow_false_ref_not_found_raise(self, oc_get):
        """Throws an exception if controller is true, allow_not_found false,
        but referenced object does not exist
        """
        obj = {
            "metadata": {
                "name": "pod1",
                "ownerReferences": [
                    {"controller": True, "kind": "ownerkind", "name": "ownername"}
                ],
            }
        }

        oc_get.side_effect = StatusCodeError

        oc = OC("cluster", "server", "token", local=True)
        with self.assertRaises(StatusCodeError):
            oc.get_obj_root_owner("namespace", obj, allow_not_found=False)

@patch.dict(os.environ, {"USE_NATIVE_CLIENT": "False"}, clear=True)
class TestPodOwnedPVCNames(TestCase):
    def test_no_volumes(self):
        pods = [{"spec": {"volumes": []}}]
        oc = OC("cluster", "server", "token", local=True)
        owned_pvc_names = oc.get_pod_owned_pvc_names(pods)
        self.assertEqual(len(owned_pvc_names), 0)

    def test_other_volumes(self):
        pods = [{"spec": {"volumes": [{"configMap": {"name": "cm"}}]}}]
        oc = OC("cluster", "server", "token", local=True)
        owned_pvc_names = oc.get_pod_owned_pvc_names(pods)
        self.assertEqual(len(owned_pvc_names), 0)

    def test_ok(self):
        pods = [{"spec": {"volumes": [{"persistentVolumeClaim": {"claimName": "cm"}}]}}]
        oc = OC("cluster", "server", "token", local=True)
        owned_pvc_names = oc.get_pod_owned_pvc_names(pods)
        self.assertEqual(len(owned_pvc_names), 1)
        self.assertEqual(list(owned_pvc_names)[0], "cm")

@patch.dict(os.environ, {"USE_NATIVE_CLIENT": "False"}, clear=True)
class TestGetStorage(TestCase):
    def test_none(self):
        resource = {"spec": {"what": "ever"}}
        oc = OC("cluster", "server", "token", local=True)
        storage = oc.get_storage(resource)
        self.assertIsNone(storage)

    def test_ok(self):
        size = "100Gi"
        resource = {
            "spec": {
                "volumeClaimTemplates": [
                    {"spec": {"resources": {"requests": {"storage": size}}}}
                ]
            }
        }
        oc = OC("cluster", "server", "token", local=True)
        result = oc.get_storage(resource)
        self.assertEqual(result, size)

class TestValidateLabels(TestCase):
    def test_ok(self):
        self.assertFalse(validate_labels({"my.company.com/key-name": "value"}))

    def test_long_value(self):
        v = "a" * LABEL_MAX_VALUE_LENGTH
        self.assertFalse(validate_labels({"my.company.com/key-name": v}))

        v = "a" * (LABEL_MAX_VALUE_LENGTH + 1)
        r = validate_labels({"my.company.com/key-name": v})
        self.assertEqual(len(r), 1)

    def test_long_keyname(self):
        kn = "a" * LABEL_MAX_KEY_NAME_LENGTH
        self.assertFalse(validate_labels({f"my.company.com/{kn}": "value"}))

        kn = "a" * (LABEL_MAX_KEY_NAME_LENGTH + 1)
        r = validate_labels({f"my.company.com/{kn}": "value"})
        self.assertEqual(len(r), 1)

    def test_long_key_prefix(self):
        prefix = "a" * LABEL_MAX_KEY_PREFIX_LENGTH
        self.assertFalse(validate_labels({f"{prefix}/key": "value"}))

        prefix = "a" * (LABEL_MAX_KEY_PREFIX_LENGTH + 1)
        r = validate_labels({f"{prefix}/key": "value"})
        self.assertEqual(len(r), 1)

    def test_invalid_value(self):
        r = validate_labels({"my.company.com/key-name": "b@d"})
        self.assertEqual(len(r), 1)

    def test_invalid_key_name(self):
        r = validate_labels({"my.company.com/key@name": "value"})
        self.assertEqual(len(r), 1)

    def test_invalid_key_prefix(self):
        r = validate_labels({"my@company.com/key-name": "value"})
        self.assertEqual(len(r), 1)

    def test_reserved_key_prefix(self):
        r = validate_labels({"kubernetes.io/key-name": "value"})
        self.assertEqual(len(r), 1)

        r = validate_labels({"k8s.io/key-name": "value"})
        self.assertEqual(len(r), 1)

    def test_many_wrong(self):
        longstr = "a" * (LABEL_MAX_KEY_PREFIX_LENGTH + 1)
        key_prefix = "b@d." + longstr + ".com"
        key_name = "b@d-" + longstr
        value = "b@d-" + longstr
        r = validate_labels(
            {f"{key_prefix}/{key_name}": value, "kubernetes.io/b@d": value}
        )
        self.assertEqual(len(r), 10)

class TestOCMapInit(TestCase):
    def test_missing_serverurl(self):
        """
        When a cluster with a missing serverUrl is passed into OC_Map, it
        should be skipped.
        """
        cluster = {
            "name": "test-1",
            "serverUrl": "",
            "automationToken": {"path": "some-path", "field": "some-field"},
        }
        oc_map = OC_Map(clusters=[cluster])

        self.assertIsInstance(oc_map.get(cluster["name"]), OCLogMsg)
        self.assertEqual(
            oc_map.get(cluster["name"]).message, f'[{cluster["name"]}] has no serverUrl'
        )
        self.assertEqual(len(oc_map.clusters()), 0)

    def test_missing_automationtoken(self):
        """
        When a cluster with a missing automationToken is passed into OC_Map, it
        should be skipped.
        """
        cluster = {
            "name": "test-1",
            "serverUrl": "http://localhost",
            "automationToken": None,
        }
        oc_map = OC_Map(clusters=[cluster])

        self.assertIsInstance(oc_map.get(cluster["name"]), OCLogMsg)
        self.assertEqual(
            oc_map.get(cluster["name"]).message,
            f'[{cluster["name"]}] has no automation token',
        )
        self.assertEqual(len(oc_map.clusters()), 0)

    @patch.object(SecretReader, "read_all", autospec=True)
    def test_automationtoken_not_found(self, mock_secret_reader):
        mock_secret_reader.side_effect = SecretNotFound

        cluster = {
            "name": "test-1",
            "serverUrl": "http://localhost",
            "automationToken": {"path": "some-path", "field": "some-field"},
        }

        oc_map = OC_Map(clusters=[cluster])

        self.assertIsInstance(oc_map.get(cluster["name"]), OCLogMsg)
        self.assertEqual(
            oc_map.get(cluster["name"]).message, f'[{cluster["name"]}] secret not found'
        )
        self.assertEqual(len(oc_map.clusters()), 0)

    @patch.object(SecretReader, "read_all", autospec=True)
    def test_server_url_mismatch(self, mock_secret_reader):
        mock_secret_reader.return_value = {"server": "foo", "some-field": "bar"}

        cluster = {
            "name": "test-1",
            "serverUrl": "http://localhost",
            "automationToken": {"path": "some-path", "field": "some-field"},
        }

        oc_map = OC_Map(clusters=[cluster])

        self.assertIsInstance(oc_map.get(cluster["name"]), OCLogMsg)
        self.assertEqual(
            oc_map.get(cluster["name"]).message,
            f'[{cluster["name"]}] server URL mismatch',
        )
        self.assertEqual(len(oc_map.clusters()), 0)

class TestOCMapGetClusters(TestCase):
    @patch.object(SecretReader, "read_all", autospec=True)
    def test_clusters_errors_empty_return(self, mock_secret_reader):
        """
        clusters() shouldn't return the names of any clusters that didn't
        initialize a client successfully.
        """
        mock_secret_reader.return_value = {
            "server": "http://localhost",
            "some-field": "bar",
        }

        cluster = {
            "name": "test-1",
            "serverUrl": "http://localhost",
        }

        oc_map = OC_Map(clusters=[cluster])

        self.assertEqual(oc_map.clusters(), [])
        self.assertIsInstance(oc_map.oc_map.get(cluster["name"]), OCLogMsg)

    @patch.object(reconcile.utils.oc, "OC", autospec=True)
    @patch.object(SecretReader, "read_all", autospec=True)
    def test_clusters_errors_with_include_errors(self, mock_secret_reader, mock_oc):
        """
        With the include_errors kwarg set to true, clusters that didn't
        initialize a client are still included.
        """
        mock_secret_reader.return_value = {
            "server": "http://localhost",
            "some-field": "bar",
        }

        cluster_1 = {
            "name": "test-1",
            "serverUrl": "http://localhost",
        }

        cluster_2 = {
            "name": "test-2",
            "serverUrl": "http://localhost",
            "automationToken": {"path": "some-path", "field": "some-field"},
        }

        cluster_names = [cluster_1["name"], cluster_2["name"]]

        oc_map = OC_Map(clusters=[cluster_1, cluster_2])

        self.assertEqual(oc_map.clusters(include_errors=True), cluster_names)
        self.assertIsInstance(oc_map.oc_map.get(cluster_1["name"]), OCLogMsg)

    @patch.object(reconcile.utils.oc, "OC", autospec=True)
    @patch.object(SecretReader, "read_all", autospec=True)
    def test_namespace_with_cluster_admin(self, mock_secret_reader, mock_oc):
        mock_secret_reader.return_value = {
            "server": "http://localhost",
            "some-field": "bar",
        }

        cluster_1 = {
            "name": "cl1",
            "serverUrl": "http://localhost",
            "clusterAdminAutomationToken": {"path": "some-path", "field": "some-field"},
            "automationToken": {"path": "some-path", "field": "some-field"},
        }
        cluster_2 = {
            "name": "cl2",
            "serverUrl": "http://localhost",
            "clusterAdminAutomationToken": {"path": "some-path", "field": "some-field"},
            "automationToken": {"path": "some-path", "field": "some-field"},
        }
        namespace_1 = {"name": "ns1", "clusterAdmin": True, "cluster": cluster_1}

        namespace_2 = {"name": "ns2", "cluster": cluster_2}

        oc_map = OC_Map(namespaces=[namespace_1, namespace_2])

        self.assertEqual(oc_map.clusters(), ["cl1", "cl2"])
        self.assertEqual(oc_map.clusters(privileged=True), ["cl1"])

        # both clusters are present as non privileged clusters in the map
        self.assertIsInstance(oc_map.get(cluster_1["name"]), OC)
        self.assertIsInstance(oc_map.get(cluster_2["name"]), OC)

        # only cluster_1 is present as privileged cluster in the map
        self.assertIsInstance(oc_map.get(cluster_1["name"], privileged=True), OC)
        self.assertIsInstance(oc_map.get(cluster_2["name"], privileged=True), OCLogMsg)

    @patch.object(reconcile.utils.oc, "OC", autospec=True)
    @patch.object(SecretReader, "read_all", autospec=True)
    def test_missing_cluster_automation_token(self, mock_secret_reader, mock_oc):
        mock_secret_reader.return_value = {
            "server": "http://localhost",
            "some-field": "bar",
        }

        cluster_1 = {
            "name": "cl1",
            "serverUrl": "http://localhost",
            "automationToken": {"path": "some-path", "field": "some-field"},
        }
        namespace_1 = {"name": "ns1", "clusterAdmin": True, "cluster": cluster_1}

        oc_map = OC_Map(namespaces=[namespace_1])

        # check that non-priv OC got instantiated but priv one not
        self.assertEqual(oc_map.clusters(), ["cl1"])
        self.assertEqual(oc_map.clusters(privileged=True), [])
        self.assertEqual(
            oc_map.clusters(include_errors=True, privileged=True), [cluster_1["name"]]
        )

        self.assertIsInstance(oc_map.get(cluster_1["name"]), OC)
        self.assertFalse(oc_map.get(cluster_1["name"], privileged=True))

    @patch.object(reconcile.utils.oc, "OC", autospec=True)
    @patch.object(SecretReader, "read_all", autospec=True)
    def test_internal_clusters(self, mock_secret_reader, mock_oc):
        mock_secret_reader.return_value = {
            "server": "http://localhost",
            "some-field": "bar",
        }

        cluster = {
            "name": "cl1",
            "serverUrl": "http://localhost",
            "internal": True,
            "automationToken": {"path": "some-path", "field": "some-field"},
        }
        namespace = {"name": "ns1", "cluster": cluster}

        # internal cluster must be in oc_map when internal is enabled
        internal_oc_map = OC_Map(internal=True, namespaces=[namespace])
        self.assertIsInstance(internal_oc_map.get(cluster["name"]), OC)

        # internal cluster must not be in oc_map when internal is disabled
        oc_map = OC_Map(internal=False, namespaces=[namespace])
        self.assertFalse(oc_map.get(cluster["name"]))

    @patch.object(reconcile.utils.oc, "OC", autospec=True)
    @patch.object(SecretReader, "read_all", autospec=True)
    def test_disabled_integration(self, mock_secret_reader, mock_oc):
        mock_secret_reader.return_value = {
            "server": "http://localhost",
            "some-field": "bar",
        }

        calling_int = "calling_integration"
        cluster = {
            "name": "cl1",
            "serverUrl": "http://localhost",
            "disable": {"integrations": [calling_int.replace("_", "-")]},
            "automationToken": {"path": "some-path", "field": "some-field"},
        }
        namespace = {"name": "ns1", "cluster": cluster}

        oc_map = OC_Map(integration=calling_int, namespaces=[namespace])
        self.assertFalse(oc_map.get(cluster["name"]))

@pytest.fixture
def oc_cli(monkeypatch) -> OCCli:
    monkeypatch.setenv("USE_NATIVE_CLIENT", "False")
    return OC("cluster", "server", "token", local=True)  # type: ignore[return-value]

@pytest.fixture
def pod():
    return {
        "apiVersion": "v1",
        "kind": "Pod",
        "metadata": {
            "name": "pod1",
        },
        "spec": {
            "volumes": [
                {"secret": {"secretName": "secret1"}},
                {"configMap": {"name": "configmap1"}},
            ],
            "containers": [
                {
                    "envFrom": [
                        {
                            "secretRef": {"name": "secret2"},
                        },
                        {"configMapRef": {"name": "configmap2"}},
                    ],
                    "env": [
                        {
                            "valueFrom": {
                                "secretKeyRef": {"name": "secret3", "key": "secretkey3"}
                            }
                        },
                        {
                            "valueFrom": {
                                "configMapKeyRef": {
                                    "name": "configmap3",
                                    "key": "configmapkey3",
                                }
                            }
                        },
                    ],
                }
            ],
        },
    }

def test_get_resources_used_in_pod_spec_unsupported_kind(oc_cli):
    with pytest.raises(KeyError):
        oc_cli.get_resources_used_in_pod_spec({}, "Deployment")

def test_get_resources_used_in_pod_spec_secret(oc_cli, pod):
    expected = {"secret1": set(), "secret2": set(), "secret3": {"secretkey3"}}
    results = oc_cli.get_resources_used_in_pod_spec(pod["spec"], "Secret")
    assert results == expected

def test_get_resources_used_in_pod_spec_configmap(oc_cli, pod):
    expected = {
        "configmap1": set(),
        "configmap2": set(),
        "configmap3": {"configmapkey3"},
    }
    results = oc_cli.get_resources_used_in_pod_spec(pod["spec"], "ConfigMap")
    assert results == expected

def test_secret_used_in_pod_true(oc_cli, pod):
    result = oc_cli.secret_used_in_pod("secret1", pod)
    assert result is True

def test_secret_used_in_pod_false(oc_cli, pod):
    result = oc_cli.secret_used_in_pod("secret9999", pod)
    assert result is False

def test_configmap_used_in_pod_true(oc_cli, pod):
    result = oc_cli.configmap_used_in_pod("configmap1", pod)
    assert result is True

def test_configmap_used_in_pod_false(oc_cli, pod):
    result = oc_cli.configmap_used_in_pod("configmap9999", pod)
    assert result is False

def test_oc_map_exception_on_missing_cluster():
    cluster = {
        "name": "test-1",
        "serverUrl": "",
        "automationToken": {"path": "some-path", "field": "some-field"},
    }
    oc_map = OC_Map(clusters=[cluster])

    assert isinstance(oc_map.get(cluster["name"]), OCLogMsg)
    with pytest.raises(OCLogMsg) as ctx:
        oc_map.get_cluster(cluster["name"])

    assert ctx.value.message == "[test-1] has no serverUrl"
    assert ctx.value.log_level == logging.ERROR

@pytest.mark.parametrize(
    "t1, t2, expected",
    [
        # trivial examples
        ({"a": "b"}, {"a": "b"}, True),
        ({"a": "b", "c": "d"}, {"c": "d", "a": "b"}, True),
        ({"a": "b", "c": "d"}, {"a": "b"}, False),
        # w/o pod-template-hash
        (
            # t1
            {
                "metadata": {},
                "spec": {"containers": [{"command": ["foobar"], "image": "lalala"}]},
            },
            # t2
            {
                "metadata": {},
                "spec": {"containers": [{"command": ["foobar"], "image": "lalala"}]},
            },
            # expected
            True,
        ),
        (
            # t1
            {
                "metadata": {},
                "spec": {"containers": [{"command": ["foobar"], "image": "lalala"}]},
            },
            # t2
            {
                "metadata": {},
                "spec": {
                    "containers": [{"command": ["something else"], "image": "lalala"}]
                },
            },
            # expected
            False,
        ),
        # with pod-template-hash
        (
            # t1
            {
                "metadata": {
                    "labels": {"a": "b", "pod-template-hash": "lala"},
                },
                "spec": {"containers": [{"command": ["foobar"], "image": "lalala"}]},
            },
            # t2
            {
                "metadata": {"labels": {"a": "b"}},
                "spec": {"containers": [{"command": ["foobar"], "image": "lalala"}]},
            },
            # expected
            True,
        ),
    ],
)
def test_equal_spec_template(t1, t2, expected):
    assert equal_spec_template(t1, t2) == expected

@pytest.fixture()
def deployment():
    return {
        "apiVersion": "apps/v1",
        "kind": "Deployment",
        "metadata": {
            "annotations": {"qontract.update": "2022-07-12T09:15:14"},
            "creationTimestamp": "2022-07-12T07:36:50Z",
            "generation": 5,
            "name": "busybox",
        },
        "spec": {
            "replicas": 2,
            "selector": {"matchLabels": {"deployment": "busybox"}},
            "strategy": {
                "rollingUpdate": {"maxSurge": "25%", "maxUnavailable": "25%"},
                "type": "RollingUpdate",
            },
            "template": {
                "metadata": {"labels": {"deployment": "busybox"}},
                "spec": {
                    "containers": [
                        {
                            "command": ["/bin/sleep", "1000000"],
                            "image": "busybox",
                            "name": "busybox",
                        }
                    ]
                },
            },
        },
    }

@pytest.fixture()
def replicasets(deployment):
    return [
        # last active
        {
            "apiVersion": "apps/v1",
            "kind": "ReplicaSet",
            "metadata": {
                "name": "busybox-current",
                "creationTimestamp": "2022-07-12T09:37:12Z",
                "ownerReferences": [
                    {
                        "apiVersion": "apps/v1",
                        "blockOwnerDeletion": True,
                        "controller": True,
                        "kind": "Deployment",
                        "name": "busybox",
                        "uid": "dab46569-9a6a-43d1-ab6d-53aa410fb737",
                    }
                ],
            },
            "spec": {
                "replicas": 2,
                "selector": {
                    "matchLabels": {
                        "deployment": "busybox",
                        "pod-template-hash": "hashhashhash",
                    }
                },
                "template": deployment["spec"]["template"],
            },
        },
        # older rs
        {
            "apiVersion": "apps/v1",
            "kind": "ReplicaSet",
            "metadata": {
                "name": "busybox-old-one",
                "creationTimestamp": "2022-07-12T09:35:12Z",
                "ownerReferences": [
                    {
                        "apiVersion": "apps/v1",
                        "blockOwnerDeletion": True,
                        "controller": True,
                        "kind": "Deployment",
                        "name": "busybox",
                        "uid": "dab46569-9a6a-43d1-ab6d-53aa410fb737",
                    }
                ],
            },
            "spec": {
                "replicas": 2,
                "selector": {
                    "matchLabels": {
                        "deployment": "busybox",
                        "pod-template-hash": "hashhashhash",
                    }
                },
                "template": {
                    "metadata": {
                        "labels": {
                            "deployment": "busybox",
                            "pod-template-hash": "hashhashhash",
                        }
                    },
                    "spec": {
                        "containers": [
                            {
                                "command": ["something different"],
                                "image": "busybox",
                                "name": "busybox",
                            }
                        ],
                    },
                },
            },
        },
        # another RS
        {
            "apiVersion": "apps/v1",
            "kind": "ReplicaSet",
            "metadata": {
                "name": "busybox-older-one",
                "creationTimestamp": "2022-07-12T09:35:12Z",
                "ownerReferences": [
                    {
                        "apiVersion": "apps/v1",
                        "blockOwnerDeletion": True,
                        "controller": True,
                        "kind": "Deployment",
                        "name": "busybox",
                        "uid": "dab46569-9a6a-43d1-ab6d-53aa410fb737",
                    }
                ],
            },
            "spec": {
                "replicas": 2,
                "selector": {
                    "matchLabels": {
                        "deployment": "busybox",
                        "pod-template-hash": "hashhashhash",
                    }
                },
                "template": {
                    "metadata": {
                        "labels": {
                            "deployment": "busybox",
                            "pod-template-hash": "hashhashhash",
                        }
                    },
                    "spec": {
                        "containers": [
                            {
                                "command": ["something different whatever"],
                                "image": "busybox",
                                "name": "busybox",
                            }
                        ],
                    },
                },
            },
        },
    ]

def test_get_owned_replicasets(
    mocker,
    oc_cli: OCCli,
    deployment,
):
    oc__get = mocker.patch.object(oc_cli, "get", autospec=True)
    oc__get_obj_root_owner = mocker.patch.object(
        oc_cli, "get_obj_root_owner", autospec=True
    )
    oc__get.return_value = {"items": ["stub1", "stub2", "stub3"]}
    oc__get_obj_root_owner.side_effect = [
        deployment,
        deployment,
        {"kind": "ownerkind", "metadata": {"name": "notownername"}},
    ]
    owned_replicasets = oc_cli.get_owned_replicasets("namespace", deployment)
    assert len(owned_replicasets) == 2

def test_get_replicaset(
    patch_sleep,
    mocker,
    oc_cli: OCCli,
    deployment,
    replicasets,
):
    oc__get_owned_replicasets = mocker.patch.object(
        oc_cli, "get_owned_replicasets", autospec=True
    )
    oc__get_owned_replicasets.return_value = replicasets

    assert (
        oc_cli.get_replicaset("namespace", deployment)["metadata"]["name"]
        == "busybox-current"
    )

def test_get_replicaset_fail(
    patch_sleep,
    mocker,
    oc_cli: OCCli,
    deployment,
):
    oc__get_owned_replicasets = mocker.patch.object(
        oc_cli, "get_owned_replicasets", autospec=True
    )
    oc__get_owned_replicasets.return_value = []

    with pytest.raises(ResourceNotFoundError):
        # pylint: disable-next=expression-not-assigned
        oc_cli.get_replicaset("namespace", deployment)["metadata"]["name"]
    assert oc__get_owned_replicasets.call_count == GET_REPLICASET_MAX_ATTEMPTS

def test_get_replicaset_allow_empty(
    patch_sleep,
    mocker,
    oc_cli: OCCli,
    deployment,
):
    oc__get_owned_replicasets = mocker.patch.object(
        oc_cli, "get_owned_replicasets", autospec=True
    )
    oc__get_owned_replicasets.return_value = []
    assert oc_cli.get_replicaset("namespace", deployment, allow_empty=True) == {}

@pytest.fixture
def api_resources():
    k1_g1 = Resource(
        prefix="", kind="kind1", group="group1", api_version="v1", namespaced=True
    )
    k1_g11 = Resource(
        prefix="", kind="kind1", group="group11", api_version="v1", namespaced=True
    )
    k2_g2 = Resource(
        prefix="", kind="kind2", group="group2", api_version="v2", namespaced=False
    )
    return {"kind1": [k1_g1, k1_g11], "kind2": [k2_g2]}

@pytest.fixture
def oc_api_resources(monkeypatch, mocker, api_resources) -> OCCli:
    monkeypatch.setenv("USE_NATIVE_CLIENT", "False")
    get_api_resources = mocker.patch.object(OCCli, "get_api_resources", autospec=True)
    get_api_resources.return_value = api_resources
    return OC("cluster", "server", "token", local=True, init_api_resources=True)  # type: ignore[return-value]

def test_is_kind_namespaced(oc_api_resources):
    assert oc_api_resources.is_kind_namespaced("kind1")

def test_is_kind_namespaced_full_name(oc_api_resources):
    assert oc_api_resources.is_kind_namespaced("kind1.group11")

def test_is_kind_not_namespaced(oc_api_resources):
    assert not oc_api_resources.is_kind_namespaced("kind2")

def test_is_kind_not_namespaced_full_name(oc_api_resources):
    assert not oc_api_resources.is_kind_namespaced("kind2.group2")

@pytest.fixture
def oc_native(
    monkeypatch,
    mocker,
    api_resources: dict,
) -> OCNative:
    monkeypatch.setenv("USE_NATIVE_CLIENT", "True")
    get_api_resources = mocker.patch.object(OCCli, "get_api_resources", autospec=True)
    get_api_resources.return_value = api_resources
    mocker.patch.object(OCNative, "_get_client", autospec=True)
    return OC("cluster", "server", "token", local=True)  # type: ignore[return-value]

def test_oc_native_get(oc_native: OCNative) -> None:
    oc_native.get("namespace", "kind1", "name")

    oc_native.client.resources.get.assert_called_once_with(
        api_version="group1/v1",
        kind="kind1",
    )
    oc_native.client.resources.get.return_value.get.assert_called_once_with(
        namespace="namespace",
        name="name",
        _request_timeout=60,
    )

def test_oc_native_get_items(oc_native: OCNative) -> None:
    oc_native.get_items("kind1", labels={"label1": "value1"})

    oc_native.client.resources.get.assert_called_once_with(
        api_version="group1/v1",
        kind="kind1",
    )
    oc_native.client.resources.get.return_value.get.assert_called_once_with(
        namespace="",
        label_selector="label1=value1",
        _request_timeout=60,
    )

def test_oc_native_get_items_with_resource_names(oc_native: OCNative) -> None:
    oc_native.get_items("kind1", labels={"label1": "value1"}, resource_names=["name"])

    oc_native.client.resources.get.assert_called_once_with(
        api_version="group1/v1",
        kind="kind1",
    )
    oc_native.client.resources.get.return_value.get.assert_called_once_with(
        namespace="",
        name="name",
        label_selector="label1=value1",
        _request_timeout=60,
    )

def test_oc_native_get_all(oc_native: OCNative) -> None:
    oc_native.get_all("kind1")

    oc_native.client.resources.get.assert_called_once_with(
        api_version="group1/v1",
        kind="kind1",
    )
    oc_native.client.resources.get.return_value.get.assert_called_once_with(
        _request_timeout=60,
    )


'''
Created on Feb 14, 2017

@author: Razvan
'''
from src.repo.repository import Repository
from src.domain.student_validator import StudentValidator
from src.domain.grade_validator import GradeValidator
from src.domain.student import Student
from src.domain.grade import Grade
from src.domain.assignment_validator import AssignmentValidator
from src.domain.assignment import Assignment

class FileRepository(Repository):
    '''
    classdocs
    '''

    def __init__(self, validatorClass, fileName):
        Repository.__init__(self, validatorClass)
        self.__fileName = fileName
        self.__loadFromFile()

    def findById(self, objID):
        for elem in super().getAll():
            if elem.id == objID:
                return True
        return False

    def save(self, obj):
        Repository.save(self, obj)

        self.__saveToFile()

    def remove(self, objId):
        Repository.remove(self, objId)

        self.__saveToFile()

    def __saveToFile(self):
        with open(self.__fileName, "w") as f:
            for elem in self.getAll():

                if elem.validator == StudentValidator:
                    f.write(str(elem.id) + ";" + elem.name + ";" + str(elem.group) + "\n")

                if elem.validator == GradeValidator:
                    f.write(str(elem.id) + ";" + str(elem.studentId) + ";" +
                            str(elem.lab) + ";" + str(elem.problem) + ";" +
                            str(elem.grade) + "\n")

                if elem.validator == AssignmentValidator:
                    f.write(str(elem.id) + ";" + str(elem.lab) + ";" + str(elem.problem) +
                            ";" + str(elem.studID))

    def __loadFromFile(self):
        with open(self.__fileName, "r") as f:
            for line in f:

                if self._Repository__validator == StudentValidator:
                    line = line.strip()
                    line = line.split(";")
                    super().save(Student(int(line[0]), line[1], int(line[2])))

                if self._Repository__validator == GradeValidator:
                    line = line.strip()
                    line = line.split(";")
                    super().save(Grade(int(line[0]), int(line[1]), int(line[2]),
                                       int(line[3]), int(line[4])))

                if self._Repository__validator == AssignmentValidator:
                    line = line.strip()
                    line = line.split(";")
                    super().save(Assignment(int(line[0]), int(line[1]), int(line[2]),
                                       int(line[3])))


#! python
import glob, os, time
from Tkinter import *
from pygame import mixer
from bin.io.json_config import PodcastDirectoryConfig

class PodcastCollection:
	# initialize. shows where the full path to the
	# podcast files are and sets the oldest file in the
	# directory to play next
	def __init__(self, podcast_path):
		print('Initializing Podcast Collection From ' + podcast_path)
		self.path = podcast_path
		self.config = PodcastDirectoryConfig(podcast_path)

	# get the oldest file from the directory and
	# set it to play next
	def get_next_file(self):
		files = sorted(os.listdir(self.path), key=os.path.getmtime)
		self.current_file = self.path + os.sep + files[0]

		# check if the file has been played
		for file in files:
			if self.config.is_episode_played(file) == False:
				self.current_file = self.path + os.sep + file

		self.config.episode_played(file)
		self.config.save()

		print("Setting file to play: '" + self.current_file + "'")

	# play the current file
	def play(self):
		self.get_next_file()
		root = Tk()
		mixer.init()
		mixer.music.load(self.current_file)
		mixer.music.play()
		root.mainloop()


import cv2
import matplotlib.pyplot as plt

face_cascade = cv2.CascadeClassifier('/Users/heisenberg/anaconda3/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('/Users/heisenberg/anaconda3/lib/python3.7/site-packages/cv2/data/haarcascade_eye.xml')

video_capture = cv2.VideoCapture(0)   # -1 is used if 3rd party webcam is used, for default it's 0
while True:
    # img = cv2.imread('lala.JPG')
    _, img = video_capture.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
        cv2.putText(img, 'Face', (x, y - 4), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,255,255), 1, cv2.LINE_AA)
        roi_gray = gray[y:y + h, x:x + w]
        roi_color = img[y:y + h, x:x + w]

        eyes = eye_cascade.detectMultiScale(roi_gray)
        for (ex, ey, ew, eh) in eyes:
            cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 5)
            #cv2.putText(img, 'Eyes', (x, y - 4), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 1, cv2.LINE_AA)

    #plt.imshow(img)
    #plt.show()
    cv2.imshow('img',img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

video_capture.release()
cv2.destroyAllWindows()


import random
rps = ['''
    _______
---'   ____)
      (_____)
      (_____)
      (____)
---.__(___)
''','''
    _______
---'   ____)____
          ______)
          _______)
         _______)
---.__________)
''', '''
    _______
---'   ____)____
          ______)
       __________)
      (____)
---.__(___)
''']
user_input = int(input("What do you choose? Type 0 for Rock, 1 for Paper or 2 for Scissors."))
computer = random.randint(0,2)
print(f"{rps[user_input]}\n\nComputer chose:\n{rps[computer]}")
if user_input == computer:
    print("DRAW!")
if computer > user_input:
    if user_input == 0 and computer == 2:
        print("You win :)")
    print("You lose :(")
else:
    if user_input == 2 and computer == 0:
        print("You lose :(")
    print("You win :)")


"""
Created on 2022, 24 Aug (24/08/22) at 19:28
    Title: main_grayscale.py - ...
    Description:
        -   ...
@author: Supantha Sen, sunnymac, IISc Bangalore
"""

# Importing Modules
from matplotlib import image, pyplot as plt
from PIL import Image

# Importing Custom Modules
from image_grayscale import color2gray

...
'''Lena Image Computation'''
img_lena = image.imread("./Image_Samples/lena_color.tiff")    #RGB reading of Image

img_lena_gray = color2gray(img_lena)

plt.subplot(1,2,1)
plt.imshow(img_lena)
plt.title('Input Color Image')

plt.subplot(1,2,2)
plt.imshow(img_lena_gray, cmap='gray')
plt.title("Output Grayscale Image")
plt.show()

img_gray = Image.fromarray(img_lena_gray)
img_gray.save("./Image_Results/lena_grayscale.tiff")
img_gray.show()


from model import Model
from layer import Layer

X_train = [[0, 0, 1]]
y_train = [0]
X_test = [[1, 1, 1]]
y_test = [1]

test = Model(learning_rate=0.01)

test.add(Layer(3, 'relu'))
test.add(Layer(3, 'relu'))
test.add(Layer(1))

test.initialize(X_train)
test.fit(X_train, y_train, 100)
test.predict (X_test, y_test)
test.acc()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2021/1/29 20:49
# @Author  : CoderCharm
# @File    : casbin_custom_orm.py
# @Software: PyCharm
# @Github  : github/CoderCharm
# @Email   : wg_python@163.com
# @Desc    :
"""

加一个自定义的解析函数

"""

import casbin
from casbin import util
import casbin_sqlalchemy_adapter

adapter = casbin_sqlalchemy_adapter.Adapter('sqlite:///test.db')

e = casbin.Enforcer('./custom_model.conf', adapter, True)

# 添加
# e.add_policy("999", "/api/user", "GET")
# 删除
# e.remove_policy("999", "/api/user", "GET")

def params_match(full_name_k1: str, key2: str):
    """
    去掉url ?后面的参数 只取路径
    :param full_name_k1:
    :param key2:
    :return:
    """
    key1 = full_name_k1.split("?")[0]
    return util.key_match2(key1, key2)

def params_match_func(*args):
    name1 = args[0]
    name2 = args[1]
    return params_match(name1, name2)

e.add_function("ParamsMatch", params_match_func)

sub = "999"  # the user that wants to access a resource.
obj = "/api/user?aaa=1"  # the resource that is going to be accessed.
act = "GET"  # the operation that the user performs on the resource.

if e.enforce(sub, obj, act):
    # permit alice to read data1casbin_sqlalchemy_adapter
    print("通过")
else:
    # deny the request, show an error
    print("拒绝")


import time

def fibo_re(n):
    if n < 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibo_re(n - 1) + fibo_re(n - 2)

def fibo_gen():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, b + a

start_one = time.time()
gen = fibo_gen()
for i in range(10):
    print(next(gen), "Gen")
end_one = time.time()

def fibo_simple(n):
    fib_num_one = 1
    fib_num_two = 1
    for _ in range(2, n):
        fib_num_one, fib_num_two = fib_num_two, fib_num_two + fib_num_one

    return fib_num_two

start_two = time.time()
print(fibo_re(9), "Recurs")
end_two = time.time()

start_three = time.time()
print(fibo_simple(9), "Simple")
end_three = time.time()

def check_type(check):
    def decor(func):
        def wrapper(*args):
            any_list = []
            for _, arg in enumerate(args):
                if check == "str":
                    any_list.append(str(arg))
                elif check == "int":
                    try:
                        if type(arg) == int:
                            any_list.append(int(arg))
                        elif type(arg) == float:
                            any_list.append(float(arg))
                        else:
                            any_list.append(int(arg))
                    except ValueError:
                        raise TypeError(f"Argument {i} must be of type {type}")
                else:
                    raise ValueError(f"Unsupported type: {check}")
            return func(*any_list)

        return wrapper

    return decor

@check_type("str")
def add_two_symbols(a, b):
    return str(a) + str(b)

@check_type("int")
def add_three_symbols(a, b, c):
    return a + b + c

number_names = {
    0: "zero",
    1: "one",
    2: "two",
    3: "three",
    4: "four",
    5: "five",
    6: "six",
    7: "seven",
    8: "eight",
    9: "nine",
    10: "ten",
    11: "eleven",
    12: "twelve",
    13: "thirteen",
    14: "fourteen",
    15: "fifteen",
    16: "sixteen",
    17: "seventeen",
    18: "eighteen",
    19: "nineteen",
}

def dic_numbers(func):
    def wrapper(numbers_str):
        numbers = numbers_str.split()
        names = [number_names[int(n)] for n in numbers]
        sorted_names = sorted(names)
        sorted_numbers = [
            str(list(number_names.keys())[list(number_names.values()).index(name)])
            for name in sorted_names
        ]
        return func(" ".join(sorted_numbers))

    return wrapper

@dic_numbers
def numbers_name(numbers_str):
    return numbers_str


import argparse
import utils
import os

def main(config):
    X_train = utils.read_csv(config["X_train_filepath"])
    y_train = utils.read_csv(config["y_train_filepath"])

    model = utils.train_model(X_train,y_train,config)
    utils.save_model(model,config)
    return model

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='Process some integers.')
    parser.add_argument('--config', type=str, required=True,
                        help=' Path to config file with parameters')

    args = parser.parse_args()
    config = utils.read_json(args.config)
    main(config)


from rest_framework import serializers, validators, fields
from .models import Distributor, State, District, Due, Subscription, Package, Product, Quantity as Qty, Type, PaymentMode, PaymentMethod
from logs.models import Quantity
from django.utils import timezone
from salesman.models import Salesman, Inventory
from retailers.models import Retailer, Request
from ledger.models import Invoice, BalanceSheet, Balance
from uuid import uuid4
from django.utils.timezone import now, timedelta

class DistributorSerializer(serializers.ModelSerializer):

    class Meta:
        model = Distributor
        fields = ('name', 'gst_number', 'district', 'address', 'gst_entity', 'gst_state', 'drug_license', 'food_license', 'user')

    def create(self, validated_data:dict):
        state = State.objects.get(pk=validated_data["state"])
        district = District.objects.get(pk=validated_data["district"])
        validated_data["state"], validated_data["district"] = state, district
        return Distributor(**validated_data)

    def update(self, instance:Distributor, validated_data:dict):
        instance.name = validated_data.get(validated_data['name'], instance.name)
        instance.save()
        return instance

class InventorySerializer(serializers.ModelSerializer):
    quantity = serializers.IntegerField()

    class Meta:
        model = Product
        fields = '__all__'

    def create(self, validated_data):
        product = Product.objects.create(**validated_data)
        quantity = Qty.objects.create(product=product, quantity=validated_data["quantity"])
        quantity_log = Quantity.objects.create(product=product, type='A', quantity=validated_data["quantity"], remarks="Added items to the inventory", updated_by=validated_data["distributor"].user)
        return super().create(validated_data)

class BaseInventorySerializer(serializers.ModelSerializer):

    class Meta:
        model = Product
        fields = ('id', 'name', 'image', 'type', 'mrp', 'hsn', 'base_price')

    def get_queryset(self):
        return Product.objects.filter(distributor__user=self.request.user)

class BaseTypeView(serializers.ModelSerializer):

    class Meta:
        model = Type
        fields = ('name')

    def create(self, validated_data):
        return super().create(validated_data)

class TypeCreationSerializer(serializers.ModelSerializer):

    class Meta:
        model = Type
        fields = '__all__'

    def create(self, validated_data):
        return super().create(validated_data)

    def get_queryset(self):
        return Type.objects.filter(distributor__user=self.request.user)

class SalesmanSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='user.first_name', read_only=True)
    mobile = serializers.CharField(source='user.mobile', read_only=True)

    class Meta:
        model = Salesman
        fields = ( 'id', 'name', 'mobile')

class SalesmanTransferSerializer(serializers.Serializer):
    salesman = serializers.IntegerField()
    product = serializers.IntegerField()
    quantity = serializers.IntegerField()

    def validate_product(self, product):
        try:
            user = self.context["user"]
            distributor = Distributor.objects.get(user=user)
            product = Product.objects.get(pk=product, distributor=distributor)
            return product
        except Product.DoesNotExist:
            raise validators.ValidationError("Product is not associated or does not exist")

    def validate_salesman(self, salesman):
        try:
            salesman_obj = Salesman.objects.get(pk=salesman)
            return salesman_obj
        except Salesman.DoesNotExist:
            raise validators.ValidationError("Salesman does not exist")

    def validate_quantity(self, quantity):
        try:
            quantity_check = Qty.objects.get(product=self.initial_data["product"])
            if quantity <= quantity_check.quantity:
                return quantity
            else:
                raise validators.ValidationError("Product quantity exceeded")
        except Qty.DoesNotExist:
            raise validators.ValidationError("Invalid product")

    def create(self, validated_data):
        try:
            salesman_inventory = Inventory.objects.get(salesman=validated_data["salesman"].pk, product=validated_data["product"])
            salesman_inventory.quantity = salesman_inventory.quantity + validated_data["quantity"]
            salesman_inventory.save()
            current_quantity = Qty.objects.get(product=self.validated_data["product"])
            current_quantity.quantity = current_quantity.quantity - validated_data["quantity"]
            current_quantity.save()
            return salesman_inventory
        except Inventory.DoesNotExist:
            new_inventory = Inventory(salesman=self.validated_data["salesman"].pk, product=self.validated_data["product"], quantity=self.validated_data["quantity"])
            new_inventory.save()
            current_quantity = Qty.objects.get(product=self.validated_data["product"])
            current_quantity.quantity = current_quantity.quantity - self.validated_data["quantity"]
            current_quantity.save()
            return new_inventory

    def update(self, instance, validated_data):
        return instance

class SalesmanAddSerializer(serializers.Serializer):
    salesman = serializers.IntegerField()

    def validate_salesman(self, salesman):
        try:
            salesman = Salesman.objects.get(pk=salesman)
            return salesman
        except Salesman.DoesNotExist:
            raise serializers.ValidationError("Salesman does not exist")

    def create(self, validated_data):
        user = self.context["user"]
        distributor = Distributor.objects.get(user=user)
        salesman = self.validated_data["salesman"]
        salesman.distributor.add(distributor)
        return salesman

class SalesmanDeleteSerializer(serializers.Serializer):
    salesman = serializers.IntegerField()

    def validate_salesman(self, salesman):
        try:
            salesman = Salesman.objects.get(pk=salesman)
            return salesman
        except Salesman.DoesNotExist:
            raise serializers.ValidationError("Salesman does not exist")

    def create(self, validated_data):
        user = self.context["user"]
        distributor = Distributor.objects.get(user=user)
        salesman = self.validated_data["salesman"]
        salesman.distributor.remove(distributor)
        return salesman

class RetailerAddSerializer(serializers.Serializer):
    retailer = serializers.IntegerField()
    opening_balance = serializers.FloatField()

    def validate_retailer(self, retailer):
        try:
            retailer = Retailer.objects.get(pk=retailer)
            return retailer
        except Retailer.DoesNotExist:
            raise serializers.ValidationError("Retailer does not exist")

    def create(self, validated_data):
        user = self.context["user"]
        distributor = Distributor.objects.get(user=user)
        retailer = self.validated_data["retailer"]
        try:
            check_balance = Balance.objects.get(retailer=retailer, distributor=distributor)
        except Balance.DoesNotExist:
            Balance.objects.create(retailer=retailer, distributor=distributor, opening_balance=validated_data["opening_balance"], closing_balance=validated_data["opening_balance"])
        retailer.distributors.add(distributor)
        return retailer

class RetailerDeleteSerializer(serializers.Serializer):
    retailer = serializers.IntegerField()

    def validate_retailer(self, retailer):
        try:
            retailer = Retailer.objects.get(pk=retailer)
            return retailer
        except Retailer.DoesNotExist:
            raise serializers.ValidationError("Retailer does not exist")

    def create(self, validated_data):
        user = self.context["user"]
        distributor = Distributor.objects.get(user=user)
        retailer = self.validated_data["retailer"]
        retailer.distributors.remove(distributor)
        return retailer

class PaymentModeSerializer(serializers.ModelSerializer):
    image = serializers.ReadOnlyField(source='provider.url')

    class Meta:
        model = PaymentMode
        fields = ('name', 'image')

class PaymentMethodListSerializer(serializers.ModelSerializer):
    mode = serializers.ReadOnlyField(source='mode.name')
    image = serializers.ReadOnlyField(source='mode.provider.url')
    class Meta:
        model = PaymentMethod
        fields = ('mode', 'image', 'account_name', 'account_id', 'is_bank', 'ifsc')

class PaymentMethodSerializer(serializers.ModelSerializer):
    class Meta:
        model = PaymentMethod
        fields = ('mode', 'account_name', 'account_id', 'is_bank', 'ifsc')

    def create(self, validated_data):
        validated_data["distributor"] = Distributor.objects.get(user=self.context["user"])
        return super().create(validated_data)

class PackageListSerializer(serializers.ModelSerializer):

    class Meta:
        model = Package
        fields = ('name', 'amount', 'duration')

class SubscriptionSerializer(serializers.ModelSerializer):

    class Meta:
        model = Subscription
        fields = ('package', 'amount_paid', 'order_id', 'payment_id', 'payment_signature')

    def validate_amount_paid(self, amount_paid):
        package = Package.objects.get(id=self.initial_data["package"])
        if amount_paid != package.amount:
            raise serializers.ValidationError("Invalid amount request")
        return amount_paid

    def create(self, validated_data):
        distributor = Distributor.objects.get(user=self.context["user"])
        validated_data["distributor"] = distributor
        validated_data["transaction_id"] = uuid4()
        package = validated_data["package"]
        due_cal = now() + timedelta(days=package.duration)
        subscription = Subscription.objects.create(**validated_data)
        try:
            due_details = Due.objects.get(distributor=distributor)
            due_details.subscription = subscription
            new_due_cal = due_cal + timedelta(days=package.duration)
            due_details.due_date = new_due_cal
            due_details.updated_at = now()
            due_details.save()
        except Due.DoesNotExist:
            new_due_date = Due.objects.create(distributor=distributor, subscription=subscription, due_date=due_cal)
        return subscription

class TransactionListSerializer(serializers.ModelSerializer):
    retailer = serializers.ReadOnlyField(source='retailer.name')
    payment_name = serializers.ReadOnlyField(source='payment_mode.mode.name')
    payment_image = serializers.ReadOnlyField(source='payment_mode.mode.provider.url')
    uid = serializers.ReadOnlyField(source='invoice.uid')

    class Meta:
        model = BalanceSheet
        fields = ('retailer', 'id', 'payment_name', 'payment_image', 'amount', 'uid', 'invoice', 'closing_balance', 'is_credit', 'created_at')

class BalanceSheetListSerializer(serializers.ModelSerializer):
    image = serializers.ReadOnlyField(source='payment_mode.mode.provider.url')

    class Meta:
        model = BalanceSheet
        fields = ('id', 'amount', 'is_credit', 'image', 'created_at', )


from __future__ import print_function
from zope.interface import implementer
from twisted.trial import unittest
from twisted.internet import defer, protocol, reactor
from twisted.internet.error import ConnectionRefusedError
from foolscap.api import RemoteInterface, Referenceable, flushEventualQueue, \
     BananaError, Tub
from foolscap.util import allocate_tcp_port
from foolscap.referenceable import RemoteReference
from foolscap.furl import encode_furl, decode_furl
from foolscap.test.common import (HelperTarget, RIHelper, ShouldFailMixin,
                                  MakeTubsMixin)
from foolscap.tokens import NegotiationError, Violation

class RIConstrainedHelper(RemoteInterface):
    def set(obj=RIHelper): return None

@implementer(RIConstrainedHelper)
class ConstrainedHelper(Referenceable):
    def __init__(self, name="unnamed"):
        self.name = name

    def remote_set(self, obj):
        self.obj = obj

class Base(ShouldFailMixin, MakeTubsMixin):

    debug = False

    def setUp(self):
        self.tubA, self.tubB, self.tubC, self.tubD = self.makeTubs(4)

    def tearDown(self):
        d = defer.DeferredList([s.stopService() for s in self.services])
        d.addCallback(flushEventualQueue)
        return d

    def createCharacters(self):
        self.alice = HelperTarget("alice")
        self.bob = HelperTarget("bob")
        self.bob_url = self.tubB.registerReference(self.bob, "bob")
        self.carol = HelperTarget("carol")
        self.carol_url = self.tubC.registerReference(self.carol, "carol")
        # cindy is Carol's little sister. She doesn't have a phone, but
        # Carol might talk about her anyway.
        self.cindy = HelperTarget("cindy")
        # more sisters. Alice knows them, and she introduces Bob to them.
        self.charlene = HelperTarget("charlene")
        self.christine = HelperTarget("christine")
        self.clarisse = HelperTarget("clarisse")
        self.colette = HelperTarget("colette")
        self.courtney = HelperTarget("courtney")
        self.dave = HelperTarget("dave")
        self.dave_url = self.tubD.registerReference(self.dave, "dave")

    def createInitialReferences(self):
        # we must start by giving Alice a reference to both Bob and Carol.
        if self.debug: print("Alice gets Bob")
        d = self.tubA.getReference(self.bob_url)
        def _aliceGotBob(abob):
            if self.debug: print("Alice got bob")
            self.abob = abob # Alice's reference to Bob
            if self.debug: print("Alice gets carol")
            d = self.tubA.getReference(self.carol_url)
            return d
        d.addCallback(_aliceGotBob)
        def _aliceGotCarol(acarol):
            if self.debug: print("Alice got carol")
            self.acarol = acarol # Alice's reference to Carol
            d = self.tubB.getReference(self.dave_url)
            return d
        d.addCallback(_aliceGotCarol)
        def _bobGotDave(bdave):
            self.bdave = bdave
        d.addCallback(_bobGotDave)
        return d

    def createMoreReferences(self):
        # give Alice references to Carol's sisters
        dl = []

        url = self.tubC.registerReference(self.charlene, "charlene")
        d = self.tubA.getReference(url)
        def _got_charlene(rref):
            self.acharlene = rref
        d.addCallback(_got_charlene)
        dl.append(d)

        url = self.tubC.registerReference(self.christine, "christine")
        d = self.tubA.getReference(url)
        def _got_christine(rref):
            self.achristine = rref
        d.addCallback(_got_christine)
        dl.append(d)

        url = self.tubC.registerReference(self.clarisse, "clarisse")
        d = self.tubA.getReference(url)
        def _got_clarisse(rref):
            self.aclarisse = rref
        d.addCallback(_got_clarisse)
        dl.append(d)

        url = self.tubC.registerReference(self.colette, "colette")
        d = self.tubA.getReference(url)
        def _got_colette(rref):
            self.acolette = rref
        d.addCallback(_got_colette)
        dl.append(d)

        url = self.tubC.registerReference(self.courtney, "courtney")
        d = self.tubA.getReference(url)
        def _got_courtney(rref):
            self.acourtney = rref
        d.addCallback(_got_courtney)
        dl.append(d)

        return defer.DeferredList(dl)

class Gifts(Base, unittest.TestCase):
    # Here we test the three-party introduction process as depicted in the
    # classic Granovetter diagram. Alice has a reference to Bob and another
    # one to Carol. Alice wants to give her Carol-reference to Bob, by
    # including it as the argument to a method she invokes on her
    # Bob-reference.

    def testGift(self):
        #defer.setDebugging(True)
        self.createCharacters()
        d = self.createInitialReferences()
        def _introduce(res):
            d2 = self.bob.waitfor()
            if self.debug: print("Alice introduces Carol to Bob")
            # send the gift. This might not get acked by the time the test is
            # done and everything is torn down, so we use callRemoteOnly
            self.abob.callRemoteOnly("set", obj=(self.alice, self.acarol))
            return d2 # this fires with the gift that bob got
        d.addCallback(_introduce)
        def _bobGotCarol(xxx_todo_changeme):
            (balice,bcarol) = xxx_todo_changeme
            if self.debug: print("Bob got Carol")
            self.bcarol = bcarol
            if self.debug: print("Bob says something to Carol")
            d2 = self.carol.waitfor()
            # handle ConnectionDone as described before
            self.bcarol.callRemoteOnly("set", obj=12)
            return d2
        d.addCallback(_bobGotCarol)
        def _carolCalled(res):
            if self.debug: print("Carol heard from Bob")
            self.assertEqual(res, 12)
        d.addCallback(_carolCalled)
        return d
    testGift.timeout = 10

    def testImplicitGift(self):
        # in this test, Carol was registered in her Tub (using
        # registerReference), but Cindy was not. Alice is given a reference
        # to Carol, then uses that to get a reference to Cindy. Then Alice
        # sends a message to Bob and includes a reference to Cindy. The test
        # here is that we can make gifts out of references that were not
        # passed to registerReference explicitly.

        #defer.setDebugging(True)
        self.createCharacters()
        # the message from Alice to Bob will include a reference to Cindy
        d = self.createInitialReferences()
        def _tell_alice_about_cindy(res):
            self.carol.obj = self.cindy
            cindy_d = self.acarol.callRemote("get")
            return cindy_d
        d.addCallback(_tell_alice_about_cindy)
        def _introduce(a_cindy):
            # alice now has references to carol (self.acarol) and cindy
            # (a_cindy). She sends both of them (plus a reference to herself)
            # to bob.
            d2 = self.bob.waitfor()
            if self.debug: print("Alice introduces Carol to Bob")
            # send the gift. This might not get acked by the time the test is
            # done and everything is torn down, so explicitly silence any
            # ConnectionDone error that might result. When we get
            # callRemoteOnly(), use that instead.
            self.abob.callRemoteOnly("set", obj=(self.alice,
                                                 self.acarol,
                                                 a_cindy))
            return d2 # this fires with the gift that bob got
        d.addCallback(_introduce)
        def _bobGotCarol(xxx_todo_changeme1):
            (b_alice,b_carol,b_cindy) = xxx_todo_changeme1
            if self.debug: print("Bob got Carol")
            self.assertTrue(b_alice)
            self.assertTrue(b_carol)
            self.assertTrue(b_cindy)
            self.bcarol = b_carol
            if self.debug: print("Bob says something to Carol")
            d2 = self.carol.waitfor()
            if self.debug: print("Bob says something to Cindy")
            d3 = self.cindy.waitfor()

            # handle ConnectionDone as described before
            b_carol.callRemoteOnly("set", obj=4)
            b_cindy.callRemoteOnly("set", obj=5)
            return defer.DeferredList([d2,d3])
        d.addCallback(_bobGotCarol)
        def _carolAndCindyCalled(res):
            if self.debug: print("Carol heard from Bob")
            ((carol_s, carol_result), (cindy_s, cindy_result)) = res
            self.assertTrue(carol_s)
            self.assertTrue(cindy_s)
            self.assertEqual(carol_result, 4)
            self.assertEqual(cindy_result, 5)
        d.addCallback(_carolAndCindyCalled)
        return d

    # test gifts in return values too

    def testReturn(self):
        self.createCharacters()
        d = self.createInitialReferences()
        def _introduce(res):
            self.bob.obj = self.bdave
            return self.abob.callRemote("get")
        d.addCallback(_introduce)
        def _check(adave):
            # this ought to be a RemoteReference to dave, usable by alice
            self.assertTrue(isinstance(adave, RemoteReference))
            return adave.callRemote("set", 12)
        d.addCallback(_check)
        def _check2(res):
            self.assertEqual(self.dave.obj, 12)
        d.addCallback(_check2)
        return d

    def testReturnInContainer(self):
        self.createCharacters()
        d = self.createInitialReferences()
        def _introduce(res):
            self.bob.obj = {"foo": [(set([self.bdave]),)]}
            return self.abob.callRemote("get")
        d.addCallback(_introduce)
        def _check(obj):
            adave = list(obj["foo"][0][0])[0]
            # this ought to be a RemoteReference to dave, usable by alice
            self.assertTrue(isinstance(adave, RemoteReference))
            return adave.callRemote("set", 12)
        d.addCallback(_check)
        def _check2(res):
            self.assertEqual(self.dave.obj, 12)
        d.addCallback(_check2)
        return d

    def testOrdering(self):
        self.createCharacters()
        self.bob.calls = []
        d = self.createInitialReferences()
        def _introduce(res):
            # we send three messages to Bob. The second one contains the
            # reference to Carol.
            dl = []
            dl.append(self.abob.callRemote("append", obj=1))
            dl.append(self.abob.callRemote("append", obj=self.acarol))
            dl.append(self.abob.callRemote("append", obj=3))
            return defer.DeferredList(dl)
        d.addCallback(_introduce)
        def _checkBob(res):
            # this runs after all three messages have been acked by Bob
            self.assertEqual(len(self.bob.calls), 3)
            self.assertEqual(self.bob.calls[0], 1)
            self.assertTrue(isinstance(self.bob.calls[1], RemoteReference))
            self.assertEqual(self.bob.calls[2], 3)
        d.addCallback(_checkBob)
        return d

    def testContainers(self):
        self.createCharacters()
        self.bob.calls = []
        d = self.createInitialReferences()
        d.addCallback(lambda res: self.createMoreReferences())
        def _introduce(res):
            # we send several messages to Bob, each of which has a container
            # with a gift inside it. This exercises the ready_deferred
            # handling inside containers.
            dl = []
            cr = self.abob.callRemote
            dl.append(cr("append", set([self.acharlene])))
            dl.append(cr("append", frozenset([self.achristine])))
            dl.append(cr("append", [self.aclarisse]))
            dl.append(cr("append", obj=(self.acolette,)))
            dl.append(cr("append", {'a': self.acourtney}))
            # TODO: pass a gift as an attribute of a Copyable
            return defer.DeferredList(dl)
        d.addCallback(_introduce)
        def _checkBob(res):
            # this runs after all three messages have been acked by Bob
            self.assertEqual(len(self.bob.calls), 5)

            bcharlene = self.bob.calls.pop(0)
            self.assertTrue(isinstance(bcharlene, set))
            self.assertEqual(len(bcharlene), 1)
            self.assertTrue(isinstance(list(bcharlene)[0], RemoteReference))

            bchristine = self.bob.calls.pop(0)
            self.assertTrue(isinstance(bchristine, frozenset))
            self.assertEqual(len(bchristine), 1)
            self.assertTrue(isinstance(list(bchristine)[0], RemoteReference))

            bclarisse = self.bob.calls.pop(0)
            self.assertTrue(isinstance(bclarisse, list))
            self.assertEqual(len(bclarisse), 1)
            self.assertTrue(isinstance(bclarisse[0], RemoteReference))

            bcolette = self.bob.calls.pop(0)
            self.assertTrue(isinstance(bcolette, tuple))
            self.assertEqual(len(bcolette), 1)
            self.assertTrue(isinstance(bcolette[0], RemoteReference))

            bcourtney = self.bob.calls.pop(0)
            self.assertTrue(isinstance(bcourtney, dict))
            self.assertEqual(len(bcourtney), 1)
            self.assertTrue(isinstance(bcourtney['a'], RemoteReference))

        d.addCallback(_checkBob)
        return d

    def create_constrained_characters(self):
        self.alice = HelperTarget("alice")
        self.bob = ConstrainedHelper("bob")
        self.bob_url = self.tubB.registerReference(self.bob, "bob")
        self.carol = HelperTarget("carol")
        self.carol_url = self.tubC.registerReference(self.carol, "carol")
        self.dave = HelperTarget("dave")
        self.dave_url = self.tubD.registerReference(self.dave, "dave")

    def test_constraint(self):
        self.create_constrained_characters()
        self.bob.calls = []
        d = self.createInitialReferences()
        def _introduce(res):
            return self.abob.callRemote("set", self.acarol)
        d.addCallback(_introduce)
        def _checkBob(res):
            self.assertTrue(isinstance(self.bob.obj, RemoteReference))
        d.addCallback(_checkBob)
        return d

    # this was used to alice's reference to carol (self.acarol) appeared in
    # alice's gift table at the right time, to make sure that the
    # RemoteReference is kept alive while the gift is in transit. The whole
    # introduction pattern is going to change soon, so it has been disabled
    # until I figure out what the new scheme ought to be asserting.

    def OFF_bobGotCarol(self, xxx_todo_changeme4):
        (balice,bcarol) = xxx_todo_changeme4
        if self.debug: print("Bob got Carol")
        # Bob has received the gift
        self.bcarol = bcarol

        # wait for alice to receive bob's 'decgift' sequence, which was sent
        # by now (it is sent after bob receives the gift but before the
        # gift-bearing message is delivered). To make sure alice has received
        # it, send a message back along the same path.
        def _check_alice(res):
            if self.debug: print("Alice should have the decgift")
            # alice's gift table should be empty
            brokerAB = self.abob.tracker.broker
            self.assertEqual(brokerAB.myGifts, {})
            self.assertEqual(brokerAB.myGiftsByGiftID, {})
        d1 = self.alice.waitfor()
        d1.addCallback(_check_alice)
        # the ack from this message doesn't always make it back by the time
        # we end the test and hang up the connection. That connectionLost
        # causes the deferred that this returns to errback, triggering an
        # error, so we must be sure to discard any error from it. TODO: turn
        # this into balice.callRemoteOnly("set", 39), which will have the
        # same semantics from our point of view (but in addition it will tell
        # the recipient to not bother sending a response).
        balice.callRemote("set", 39).addErrback(lambda ignored: None)

        if self.debug: print("Bob says something to Carol")
        d2 = self.carol.waitfor()
        d = self.bcarol.callRemote("set", obj=12)
        d.addCallback(lambda res: d2)
        d.addCallback(self._carolCalled)
        d.addCallback(lambda res: d1)
        return d

class Bad(Base, unittest.TestCase):

    # if the recipient cannot claim their gift, the caller should see an
    # errback.

    def setUp(self):
        Base.setUp(self)

    def test_swissnum(self):
        self.createCharacters()
        d = self.createInitialReferences()
        d.addCallback(lambda res: self.tubA.getReference(self.dave_url))
        def _introduce(adave):
            # now break the gift to insure that Bob is unable to claim it.
            # The first way to do this is to simple mangle the swissnum,
            # which will result in a failure in remote_getReferenceByName.
            # NOTE: this will have to change when we modify the way gifts are
            # referenced, since tracker.url is scheduled to go away.
            adave.tracker.url = adave.tracker.url + ".MANGLED"
            return self.shouldFail(KeyError, "Bad.test_swissnum",
                                   "unable to find reference for name starting with 'da'",
                                   self.acarol.callRemote, "set", adave)
        d.addCallback(_introduce)
        # make sure we can still talk to Carol, though
        d.addCallback(lambda res: self.acarol.callRemote("set", 14))
        d.addCallback(lambda res: self.assertEqual(self.carol.obj, 14))
        return d

    def test_tubid(self):
        self.createCharacters()
        d = self.createInitialReferences()
        d.addCallback(lambda res: self.tubA.getReference(self.dave_url))
        def _introduce(adave):
            # The second way is to mangle the tubid, which will result in a
            # failure during negotiation. We mangle it by reversing the
            # characters: this makes it syntactically valid but highly
            # unlikely to remain the same. NOTE: this will have to change
            # when we modify the way gifts are referenced, since tracker.url
            # is scheduled to go away.
            (tubid, location_hints, name) = decode_furl(adave.tracker.url)
            tubid = "".join(reversed(tubid))
            adave.tracker.url = encode_furl(tubid, location_hints, name)
            return self.shouldFail(BananaError, "Bad.test_tubid", "unknown TubID",
                                   self.acarol.callRemote, "set", adave)
        d.addCallback(_introduce)
        return d

    def test_location(self):
        self.createCharacters()
        d = self.createInitialReferences()
        d.addCallback(lambda res: self.tubA.getReference(self.dave_url))
        def _introduce(adave):
            # The third way is to mangle the location hints, which will
            # result in a failure during negotiation as it attempts to
            # establish a TCP connection.

            (tubid, location_hints, name) = decode_furl(adave.tracker.url)
            # highly unlikely that there's anything listening on this port
            location_hints = ["tcp:127.0.0.1:2"]
            adave.tracker.url = encode_furl(tubid, location_hints, name)
            return self.shouldFail(ConnectionRefusedError, "Bad.test_location",
                                   "Connection was refused by other side",
                                   self.acarol.callRemote, "set", adave)
        d.addCallback(_introduce)
        return d

    def test_hang(self):
        f = protocol.Factory()
        f.protocol = protocol.Protocol # ignores all input
        p = reactor.listenTCP(0, f, interface="127.0.0.1")
        self.createCharacters()
        d = self.createInitialReferences()
        d.addCallback(lambda res: self.tubA.getReference(self.dave_url))
        def _introduce(adave):
            # The next form of mangling is to connect to a port which never
            # responds, which could happen if a firewall were silently
            # dropping the TCP packets. We can't accurately simulate this
            # case, but we can connect to a port which accepts the connection
            # and then stays silent. This should trigger the overall
            # connection timeout.
            (tubid, location_hints, name) = decode_furl(adave.tracker.url)
            location_hints = ["tcp:127.0.0.1:%d" % p.getHost().port]
            adave.tracker.url = encode_furl(tubid, location_hints, name)
            self.tubD._test_options['connect_timeout'] = 2
            return self.shouldFail(NegotiationError, "Bad.test_hang",
                                   "no connection established within client timeout",
                                   self.acarol.callRemote, "set", adave)
        d.addCallback(_introduce)
        def _stop_listening(res):
            d1 = p.stopListening()
            def _done_listening(x):
                return res
            d1.addCallback(_done_listening)
            return d1
        d.addBoth(_stop_listening)
        return d

    def testReturn_swissnum(self):
        self.createCharacters()
        d = self.createInitialReferences()
        def _introduce(res):
            # now break the gift to insure that Alice is unable to claim it.
            # The first way to do this is to simple mangle the swissnum,
            # which will result in a failure in remote_getReferenceByName.
            # NOTE: this will have to change when we modify the way gifts are
            # referenced, since tracker.url is scheduled to go away.
            self.bdave.tracker.url = self.bdave.tracker.url + ".MANGLED"
            self.bob.obj = self.bdave
            return self.shouldFail(KeyError, "Bad.testReturn_swissnum",
                                   "unable to find reference for name starting with 'da'",
                                   self.abob.callRemote, "get")
        d.addCallback(_introduce)
        # make sure we can still talk to Bob, though
        d.addCallback(lambda res: self.abob.callRemote("set", 14))
        d.addCallback(lambda res: self.assertEqual(self.bob.obj, 14))
        return d

class LongFURL(Base, unittest.TestCase):
    # make sure the old 200-byte limit on gift FURLs is gone
    def setUp(self):
        def mangleLocation(portnum):
            loc = "127.0.0.1:%d" % portnum
            loc = ",".join([loc]*15) # 239 bytes of location, 281 of FURL
            return loc
        (self.tubA, self.tubB,
         self.tubC, self.tubD) = self.makeTubs(4, mangleLocation)

    def testGift(self):
        self.createCharacters()
        d = self.createInitialReferences()
        def _introduce(res):
            d2 = self.bob.waitfor()
            if self.debug: print("Alice introduces Carol to Bob")
            # send the gift. This might not get acked by the time the test is
            # done and everything is torn down, so we use callRemoteOnly
            self.abob.callRemoteOnly("set", obj=(self.alice, self.acarol))
            return d2 # this fires with the gift that bob got
        d.addCallback(_introduce)
        def _bobGotCarol(xxx_todo_changeme2):
            (balice,bcarol) = xxx_todo_changeme2
            if self.debug: print("Bob got Carol")
            self.bcarol = bcarol
            if self.debug: print("Bob says something to Carol")
            d2 = self.carol.waitfor()
            # handle ConnectionDone as described before
            self.bcarol.callRemoteOnly("set", obj=12)
            return d2
        d.addCallback(_bobGotCarol)
        def _carolCalled(res):
            if self.debug: print("Carol heard from Bob")
            self.assertEqual(res, 12)
        d.addCallback(_carolCalled)
        return d

class Enabled(Base, unittest.TestCase):
    def setUp(self):
        self.services = [Tub() for i in range(4)]
        self.tubA, self.tubB, self.tubC, self.tubD = self.services
        for s in self.services:
            s.startService()
            p = allocate_tcp_port()
            s.listenOn("tcp:%d:interface=127.0.0.1" % p)
            s.setLocation("127.0.0.1:%d" % p)
        self.tubIDs = [self.tubA.getShortTubID(),
                       self.tubB.getShortTubID(),
                       self.tubC.getShortTubID(),
                       self.tubD.getShortTubID()]

    def get_connections(self, tub):
        self.assertFalse(tub.waitingForBrokers)
        return set([tr.getShortTubID() for tr in list(tub.brokers.keys())])

    def testGiftsEnabled(self):
        # enabled is the default, so this shouldn't change anything
        self.tubB.setOption("accept-gifts", True)
        self.createCharacters()
        d = self.createInitialReferences()
        def _introduce(res):
            d2 = self.bob.waitfor()
            d3 = self.abob.callRemote("set", obj=(self.alice, self.acarol))
            d3.addCallback(lambda _: d2)
            return d3 # this fires with the gift that bob got
        d.addCallback(_introduce)
        def _bobGotCarol(xxx_todo_changeme3):
            (balice,bcarol) = xxx_todo_changeme3
            A,B,C,D = self.tubIDs
            b_connections = self.get_connections(self.tubB)
            self.assertIn(C, b_connections)
            self.assertEqual(b_connections, set([A, C, D]))
        d.addCallback(_bobGotCarol)
        return d

    def testGiftsDisabled(self):
        self.tubB.setOption("accept-gifts", False)
        self.createCharacters()
        self.bob.obj = None
        d = self.createInitialReferences()
        d.addCallback(lambda _:
                      self.shouldFail(Violation, "testGiftsDisabled",
                                      "gifts are prohibited in this Tub",
                                      self.abob.callRemote,
                                      "set", obj=(self.alice, self.acarol)))
        d.addCallback(lambda _: self.assertFalse(self.bob.obj))
        def _check_tub(_):
            A,B,C,D = self.tubIDs
            b_connections = self.get_connections(self.tubB)
            self.failIfIn(C, b_connections)
            self.assertEqual(b_connections, set([A, D]))
        d.addCallback(_check_tub)
        return d

    def testGiftsDisabledReturn(self):
        self.tubA.setOption("accept-gifts", False)
        self.createCharacters()
        d = self.createInitialReferences()
        def _created(_):
            self.bob.obj = self.bdave
            return self.shouldFail(Violation, "testGiftsDisabledReturn",
                                   "gifts are prohibited in this Tub",
                                   self.abob.callRemote,
                                   "get")
        d.addCallback(_created)
        def _check_tub(_):
            A,B,C,D = self.tubIDs
            a_connections = self.get_connections(self.tubA)
            self.failIfIn(D, a_connections)
            self.assertEqual(a_connections, set([B,C]))
        return d


import re

numbers = lambda x: [int(m) for m in re.findall(r'-?\d+', x)]
manhattan = lambda x,y : abs(x[0]-y[0]) + abs(x[1]-y[1])
distances, seen = {}, set()

with open("input.txt")  as f:
    for line in f:
        x_s,y_s,x_b,y_b = numbers(line)
        sensor, beacon = (x_s,y_s), (x_b,y_b)
        distances[sensor] = (beacon, manhattan(sensor,beacon))

find_y = 2_000_000
for sensor, (beacon, distance) in distances.items():
    x,y = sensor[0], sensor[1]
    cost_to_reach_y = abs(find_y - y)
    if cost_to_reach_y > distance:
        continue
    remaining_moves = distance - cost_to_reach_y
    no_beacon_x = set(range(x-remaining_moves,x+remaining_moves+1))
    if beacon[1] == find_y:
        no_beacon_x.remove(beacon[0])
    seen |= no_beacon_x
print(f"Part 1: {len(seen)}")


#for i in "banana":
    #print(i)

# ciclo for range()
#for i in range(1,11):
    #print(i)

# for i in range(1,11,2):
#     print(i)

# ciclo for con break
# frutas=["manzana", "banana", "cereza"]
# for x in frutas:
#     print(x)
#     if x == "banana":
#         break

# ciclo for con continue
frutas=["manzana", "banana", "cereza"]
for x in frutas:
    if x == "banana":
        continue
    print(x)

# ciclo for con else
for i in range(6):
    print(i)
else:
    print("ciclo finalizado")


import subprocess

def get_int():
	iw_out = subprocess.Popen(['iwconfig'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
	out_iw, err_iw = iw_out.communicate()

	for lines in out_iw.split('\n'):
		if "ESSID:" in lines:
			return lines.split('    ')[0]

print(get_int())


from linearmodel import LinearModel
import numpy as np

A = np.array([[-2, 1], [-1, 1], [0, 1]])
B = np.array([2, 5, 6])
C = np.array([2, 3])

lm = LinearModel(A, B, C)
lm.optimize()

# if __name__=="__main__":
#     print(lm.tableau)
#     print(lm.optimalSoln())
#     print(lm.optimalVal())


import numpy as np #Partimos importanto la libreria numpy con np

num=np.array([2,1,3,8,5,6,7,4,10,9]) #Para crear un nparray hay que hacerlo dentro de una variable, entre parentesis y el los vectores entre corchetes

for i in range(1,num.size): #Realizamos el primer bucle for que será nuestro recorrido partiendo de la posición 1 hasta la logitud de nuestro array
    for j in range(num.size - i):#Dentro del primer for realizamos un segundo bucle for que sera nuestra posición dentro del array, le restamos el recorrido cada vez que termine.
        if num[j] > num[j + 1]:#Comparamos si nuestro array en la posición(j) actual num[j] es menor a la posicion(j) siguiente num[j+1]
            temp = num[j] #Si es menor entonces asignamos el valor de la posición actual a una variable temporaria(temp)
            num[j] = num[j + 1] #despues hacemos el cambio, a la posición actual(num[j]) le asignamos el valor de la posición siguente(num[j+1])
            num[j + 1] = temp #y a la posición siguiente(num[j+1]) le asignamos el valor de la variable temporaria
print(num)

Programas/Listas, tuplas y diccionarios/Guía arraysnumpy/Ejer6AlgOrdMayorMenor.py


pessoas = list()
dados = dict()
media = k = 0
while True:
    dados['nome'] = str(input('Digite o seu nome: '))
    dados['sexo'] = str(input('Digite o seu sexo [M/F]: ')).upper().strip()[0]
    while dados['sexo'] not in 'MF':
        print('Tente novamente!', end = ' ')
        dados['sexo'] = str(input('Digite o seu sexo [M/F]: ')).upper().strip()[0]
    dados['idade'] = int(input('Digite a sua idade: '))
    pessoas.append(dados.copy())
    op = str(input('Deseja continuar? [S/N]: ')).upper().strip()[0]
    while op not in 'SN':
        print('Opção inválida, digite novemente!')
        op = str(input('Deseja continuar? [S/N]: ')).upper().strip()[0]
    if op == 'N':
        break
print(':==' * 20)
print(f'O total de pessoas cadastradas foi {len(pessoas)}')
for p in pessoas:
    media += p['idade']
media /= len(pessoas)
print(f'A média de idade do grupo é de {media:.2f}')
print('As mulheres do grupo são:', end = ' ')
for i, p in enumerate(pessoas):
    if k == 0 and p['sexo'] == 'F':
        print(f'{p["nome"]}', end = '')
        k = 1
    elif p['sexo'] == 'F':
        print(f', {p["nome"]}', end = '')
print()
print('As pessoas com a idade acima da média são:', end = ' ')
k = 0
for i, p in enumerate(pessoas):
    if k == 0 and p['idade'] >= media:
        print(f'{p["nome"]}', end = '')
        k = 1
    elif p['idade'] >= media:
        print(f', {p["nome"]}', end = '')
print()
print(':==' * 20)


import pymel.core as pm

import System
import Freeform.Rigging
import System.Diagnostics

import os
import sys
import glob

import freeform_utils
import v1_core
import v1_shared
from v1_shared.shared_utils import get_first_or_default, get_index_or_default, get_last_or_default
from v1_shared.decorators import csharp_error_catcher
from maya_utils.decorators import undoable

class ControlColorSet(object):
    def __init__(self):
        self.process = System.Diagnostics.Process.GetCurrentProcess()
        self.ui = Freeform.Rigging.ControlColorSet.ControlColorSet(self.process)
        self.vm = self.ui.DataContext

        # Load Event Handlers
        self.vm.CloseWindowEventHandler += self.close
        self.vm.SaveColorsHandler += self.save_color_set
        self.vm.ApplySelectedHandler += self.apply_selected_to_color
        self.vm.PickMaterialHandler += self.pick_material
        self.vm.SaveSettingHandler += self.save_setting

        material_category = v1_core.global_settings.GlobalSettings().get_sub_category(freeform_utils.materials.MaterialSettings.material_category, create_category = True)
        use_color_set = material_category.get("use_color_set")
        if use_color_set != None:
            self.vm.UseColorSet = use_color_set

        self.get_colors_from_settings()

    def show(self):
        '''
        Show the UI
        '''
        self.ui.Show()

    @csharp_error_catcher
    def close(self, vm, event_args):
        '''
        close(self, vm, event_args)
        Close the UI and un-register event methods

        Args:
            vm (Freeform.Rigging.RigSwitcher.RigSwitcherVM): C# view model object sending the command
            event_args (None): Unused, but must exist to register on a C# event
        '''
        self.vm.SaveColorsCall(None);

        self.vm.CloseWindowEventHandler -= self.close
        self.vm.SaveColorsHandler -= self.save_color_set
        self.vm.ApplySelectedHandler -= self.apply_selected_to_color
        self.vm.PickMaterialHandler -= self.pick_material
        self.vm.SaveSettingHandler -= self.save_setting

    @csharp_error_catcher
    def save_color_set(self, vm, event_args):
        '''
        save_color_set(self, vm, event_args)
        Save all colors in the UI to the user settings json file
        '''
        material_category = v1_core.global_settings.GlobalSettings().get_sub_category(freeform_utils.materials.MaterialSettings.material_category)
        # Remove all current color entires, preserving 'use_color_set' value from UI
        material_category = {"use_color_set" : self.vm.UseColorSet}
        v1_core.global_settings.GlobalSettings().save_sub_category(material_category, freeform_utils.materials.MaterialSettings.material_category)

        for colorSet in event_args.ColorSetList:
            for color in colorSet.ColorList:
                material_color = self.get_color(color.ColorR, color.ColorG, color.ColorB)
                transparent_color = self.get_color(255-color.Alpha, 255-color.Alpha, 255-color.Alpha)
                material_setting = freeform_utils.materials.MaterialSettings(color.ShadingGroup, material_color, transparent_color, 1)
                arg_list = [colorSet.Name, color.Name.upper()]
                freeform_utils.materials.save_material_setting(material_setting, *arg_list)

        freeform_utils.materials.apply_color_set()

    @csharp_error_catcher
    def apply_selected_to_color(self, vm, event_args):
        obj = get_first_or_default(pm.ls(selection=True))

        if type(obj) == pm.nt.Blinn:
            scene_material = obj
        else:
            scene_material = get_first_or_default(freeform_utils.materials.get_material_list(obj)) if obj else None

        if scene_material:
            color = scene_material.color.get()
            event_args.Color.ColorR = round(color[0] * 255.0)
            event_args.Color.ColorG = round(color[1] * 255.0)
            event_args.Color.ColorB = round(color[2] * 255.0)

            event_args.Color.Alpha = round((1 - scene_material.transparency.get()[0]) * 255.0)
            event_args.Color.Translucence = scene_material.translucence.get()

    @csharp_error_catcher
    def pick_material(self, vm, event_args):
        if pm.objExists(event_args.Color.MaterialName):
            pm.select(event_args.Color.MaterialName, r=True)

    @csharp_error_catcher
    def save_setting(self, vm, event_args):
        '''
        save_setting(self, vm, event_args)
        Set and save an attribute in the user's custom settings file

        Args:
            vm (Rigging.RiggerVM): C# view model object sending the command
            event_args (Save*EventArgs): Passes name and value of the settings attribute to save
        '''
        material_category = v1_core.global_settings.GlobalSettings().get_sub_category(event_args.category)
        material_category[event_args.name] = event_args.value

        v1_core.global_settings.GlobalSettings().save_sub_category(material_category, freeform_utils.materials.MaterialSettings.material_category)

    def get_colors_from_settings(self):
        material_category = v1_core.global_settings.GlobalSettings().get_sub_category(freeform_utils.materials.MaterialSettings.material_category)
        for set_name, set_data in material_category.items():
            if type(set_data) == dict:
                if set_name != self.vm.DefaultColorSet.Name:
                    c_color_set = Freeform.Rigging.ControlColorSet.ColorSet(set_name)
                    self.vm.AddColorSet(c_color_set)
                else:
                    c_color_set = self.vm.DefaultColorSet

                for side, material_data in set_data.items():
                    c_color = self.create_c_color(side, material_data)
                    c_color_set.AddColor(c_color)

    def create_c_color(self, name, material_data):
        c_color = Freeform.Rigging.ControlColorSet.ControlColor(name.lower())
        c_color.ColorR = round(material_data["color"][0] * 255.0)
        c_color.ColorG = round(material_data["color"][1] * 255.0)
        c_color.ColorB = round(material_data["color"][2] * 255.0)
        c_color.Alpha = round((1 - material_data["transparency"][0]) * 255.0)
        c_color.Translucence = material_data["translucence"]

        return c_color

    def get_color(self, r, g, b):
        '''
        Takes rgb as color byte's and converts them to 0-1 color values
        '''
        return pm.dt.Color(r/255.0, g/255.0, b/255.0)


# 수들의 합 7
# Gold 1, segtree

import sys
input = sys.stdin.readline

def update(start,end,node,index,num):
    if index<start or index>end: return
    if start==end:
        tree[node]=num
        return

    mid = (start+end)//2
    update(start,mid,node*2,index,num)
    update(mid+1,end,node*2+1,index,num)
    tree[node] = tree[node*2]+tree[node*2+1]

def query(start,end,left,right,node):
    if left>end or right<start: return 0
    if left<=start and end<=right: return tree[node]

    mid = (start+end)//2
    return query(start,mid,left,right,node*2)+query(mid+1,end,left,right,node*2+1)

n,m = map(int,input().split())
arr = [0]*n
tree = [0]*(4*n)
for _ in range(m):
    c,i,j = map(int,input().split())
    if c==0:
        if i>j:
            i,j = j,i
        print(query(0,n-1,i-1,j-1,1))
    else:
        update(0,n-1,1,i-1,j)


from helper_functions.sentence_type_categorizer import check_tag_question, check_question

# Function to check whether the Encountered 'To' in the sentence is an ellipsis licensor or not
def To(Parsed, row_index):
    Parsed_l = len(Parsed) # Length of Parsed array would essentially mean length of all tokens in the sentence (The code treats each line as a sentence, so if multiple sentences are in a line, this code fails)
    row = Parsed[row_index] # Word, Parent, Dependency Relation, POS Tag and Lemma details for the 'To Be' type helper verb is stored in 'row' variable
    ellipsis = True # We first assume the helper verb as an indicator of Ellipsis and then apply the rules to see if our assumption is True or not
    parent = (int)(row[1]) # Index of Parent Node.

    sent_type = "normal"

    # RULE: If The sentence is a tag type question and the 'To' aux is at the third last or the fourth last position (negation cases) in the Tag question then it is a Licensor
    if check_tag_question(Parsed):
        sent_type = "tag"
        if row_index == len(Parsed)-3 or row_index == len(Parsed)-4:
            ellipsis = True
            return 1
    elif check_question(Parsed):
        sent_type = "question"

    #NEW_CHANGE: New rule added:
    # RULE: If punctuations ',', '.', ';', '!', '?' occur right after 'To' aux verb then the 'To' aux verb is a Licensor
    if (row_index != Parsed_l-1) and (Parsed[row_index+1][0] in ['.', ',', ';', '?', '!']):
        ellipsis = True
        return 1 # RULE: If above condition is not true only then apply the remaining rule below.

    # RULE: If a conjunction occurs right after 'to' it is a licensor
    if (row_index != Parsed_l-1) and (Parsed[row_index+1][2] == 'cc'):
        ellipsis = True
        return 1

    # RULE: If the dependency relation of 'To' with its parent is not that of an Open Clausal Complement then it is not a Licensor.
    if(row[2] != 'xcomp'):
        ellipsis = False

    # Return 0 if 'To be' verb is not a Licensor and 1 if it is a licensor.
    if(ellipsis):
        return(1)
    return(0)