from typing import List

from bs4 import BeautifulSoup, Tag

from ..models.form_data_entry import FormDataEntry

class FormDataEntryParser:
    """
    A parser for HTML form elements.
    """

    # A series of class constants that can be overridden by derived classes.
    _default_name = None
    _default_value = None
    _default_type = None
    _default_is_selected = True

    __suitable_tags = ("button", "input", "select", "textarea", )

    def parse(self, html: str) -> List[FormDataEntry]:
        """
        Parse an HTML form element tag and generates a collection of form
        elements. A collection is returned as some elements such as "select"
        have multiple options.

        :param html: A string containing only the HTML tag, or a Beautiful
            Soup object of the tag.
        """

        bs4_parser = self._make_bs4_parser(html)

        attribute_name = self._get_name_attr(bs4_parser)
        attribute_value = self._get_value_attr(bs4_parser)
        attribute_selected = self._get_selected_state(bs4_parser)

        form_element = FormDataEntry(
            name=attribute_name,
            value=attribute_value,
            is_submitable=attribute_selected)

        return [form_element, ]

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        # This parser works for all form element types.
        return tag_name in self.__suitable_tags

    def _make_bs4_parser(self, html: str) -> 'bs4.Tag':
        """
        Creates a BeautifulSoup parser object for the given HTML fragment.
        Assumes if an HTML fragment is provided, the fragment is the desired
        tag to be parsed.
        """

        bs4_parser = html
        if not isinstance(html, (Tag, BeautifulSoup, )):
            # Only create a beautiful soup object if one isn't provided.
            bs4_parser = BeautifulSoup(html, "html5lib")

            # html5lib builds a full and valid DOM when parsing.
            bs4_parser = bs4_parser.body.next_element

        return bs4_parser

    def _get_value_attr(self, bs4_parser: 'bs4.Tag') -> str:
        """
        Returns the element's "value" attribute value. Defaults to class
        constant DEFAULT_VALUE when attribute is not defined.
        """

        return bs4_parser.attrs.get("value", self._default_value)

    def _get_name_attr(self, bs4_parser: 'bs4.Tag') -> str:
        """
        Returns the element's "name" attribute value. Defaults to class
        constant DEFAULT_NAME when attribute is not defined.
        """

        return bs4_parser.attrs.get("name", self._default_name)

    def _get_type_attr(self, bs4_parser: 'bs4.Tag') -> str:
        """
        Returns the element's "type" attrbute value. Defaults to class
        constant DEFAULT_TYPE when attribute is not defined.
        """

        return bs4_parser.attrs.get("type", self._default_type)

    def _get_selected_state(self, bs4_parser: 'bs4.Tag') -> bool:
        """
        Returns the elements "selected" status. Always returns true for
        unspecified form elements.
        """

        return self._default_is_selected

    def _get_tag_name(self, bs4_parser: 'bs4.Tag') -> str:
        """
        Returns the element's name/type
        """

        return bs4_parser.name

class ButtonFormElementParser(FormDataEntryParser):
    """
    A parser for HTML form button elements.
    """

    # Button default type is submit when undefined.
    _default_type = "submit"

    # Buttons require user activation to be "selected"
    _default_is_selected = False

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "button"

class InputFormElementParser(FormDataEntryParser):
    """
    A parser for HTML form input elements.
    """

    # Inputs without a defined type are defaulted to text
    _default_type = "text"

    # Inputs are defaulted to text, which implies the default value will be blank.
    _default_value = ""

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "input"

class SelectFormElementParser(FormDataEntryParser):

    _default_is_selected = False

    def parse(self, html: str) -> List[FormDataEntry]:
        """
        Overrides base class to present a select element and its options set
        as a collection of form elements. This parser treats the select
        options as if they were individual checkbox or radio input types.
        """

        bs4_parser = self._make_bs4_parser(html)

        elements = []

        for option in bs4_parser.find_all("option"):

            name = self._get_name_attr(bs4_parser)
            value = self._get_value_attr(option)
            is_selected = self._get_selected_state(option)

            elements.append(
                FormDataEntry(name=name,
                              value=value,
                              is_submitable=is_selected))

        return elements

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "select"

    def _get_selected_state(self, bs4_parser: 'bs4.Tag') -> bool:
        """
        Overrides base class to use element's "selected" attribute.
        """

        return bs4_parser.has_attr("selected")

    def _get_value_attr(self, bs4_parser: 'bs4.Tag') -> str:
        """
        Overrides base class to get element's "value" attribute or text value.
        """

        return bs4_parser.attrs.get("value", bs4_parser.get_text())

class TextareaFormElementParser(FormDataEntryParser):
    """
    Parser for HTML textarea elements.
    """

    _default_value = ""

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "textarea"

    def _get_value_attr(self, bs4_parser: 'bs4.Tag') -> str:
        """
        Overrides base classs to get the value from the element's
        .get_text() method.

        :param bs4_parser: A Beautiful Soup object, or object containing a get
        """

        return (bs4_parser.get_text() or self._default_value)

class SelectableInputFormElementParser(InputFormElementParser):
    """
    A parser for HTML form input elements of type "checkbox" or "radio"
    """

    _default_type = "checkbox"
    _default_value = "on"
    _default_is_selected = False

    __suitable_types = ("checkbox", "radio", )

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "input" and type_attribute in self.__suitable_types

    def _get_selected_state(self, bs4_parser: 'bs4.Tag') -> bool:
        """
        Overrides the base class to return the actual "checked" state of the
        element.
        """

        return bs4_parser.has_attr("checked")

class ColorInputFormElementParser(InputFormElementParser):
    """
    Parser for HTML input elements of type "color"
    """

    _default_type = "color"
    _default_value = "#000000"

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "input" and type_attribute == "color"

class RangeInputFormElementParser(InputFormElementParser):
    """
    Parser for HTML input elements of type "range"
    """

    _default_type = "range"

    __default_min_value = 0
    __default_max_value = 100

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "input" and type_attribute == "range"

    def _convert_str_to_int(self, value: str, default: int = None) -> int:
        """
        A convenience method for converting a string value to an integer and
        defining a default when the conversion fails.
        """

        try:
            return int(value)
        except:
            return default

    def _get_value_attr(self, bs4_parser: 'bs4.Tag') -> str:
        """
        Overrides the base class to return a generated default value when the
        value attribute is not defined.
        """

        value = bs4_parser.attrs.get("value", None)

        if value is None:

            attribute_min = self._convert_str_to_int(
                bs4_parser.attrs.get("min", self.__default_min_value), self.__default_min_value)

            attribute_max = self._convert_str_to_int(
                bs4_parser.attrs.get("max", self.__default_max_value), self.__default_max_value)

            if attribute_max < attribute_min:
                value = str(attribute_min)
            else:
                value = str(attribute_min + (attribute_max - attribute_min) // 2)

        return value

class SubmitInputFormElementParser(InputFormElementParser):
    """
    Parser for HTML input elements of type "submit"
    """

    _default_type = "submit"
    _default_value = "submit"
    _default_is_selected = False

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "input" and type_attribute == "submit"

class ButtonInputFormElementParser(SubmitInputFormElementParser):
    """
    Parser for HTML input elements of type "button" and "reset"
    """

    _default_type = "button"
    _default_value = None
    _default_is_selected = False

    __suitable_types = ("button", "reset", "search", )

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "input" and type_attribute in self.__suitable_types

class ImageInputFormElementParser(SubmitInputFormElementParser):
    """
    Parser for HTML input elements of type "image"
    """

    _default_type = "image"
    _default_value = "0"

    __name_attribute_suffixes = ("x", "y", )

    def parse(self, html: str) -> List[FormDataEntry]:
        """
        Overrides base class to return two FormElement objects. As this input
        element type provides an coordinate that indicates where a user has
        clicked on the image.
        """

        # The only difference for this element and other input elements is
        # there are two fields generated for x, y coordinates. Use the base
        # class parse, then clone them into two separate FormElement objects.

        form_element = super().parse(html)[0]

        form_elements = []
        for suffix in self.__name_attribute_suffixes:

            element_name = suffix
            if form_element.name is not None:
                element_name = "%s.%s" % (form_element.name, suffix, )

            form_elements.append(FormDataEntry(
                name=element_name,
                value=form_element.value,
                is_submitable=form_element.is_submitable))

        return form_elements

    def suitable(self, tag_name: str, type_attribute: str) -> bool:
        """
        Determine if the parser is appropriate for the given HTML element tag
        and type.

        :param tag_name: The HTML element name

        :param type_attribute: The HTML element "type" attribute. If no
            attribute is present, provide None.
        """

        return tag_name == "input" and type_attribute == "image"

    def _get_value_attr(self, bs4_parser: 'bs4.Tag') -> str:
        """
        Overrides InputFormElementParser to always return a value of "0". This
        element type indicates the coordinates where the image was clicked
        when submitted.
        """

        return self._default_value


import json
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def create_graph_from_json(file_path):
    """
    Cria um grafo a partir de um arquivo JSON.

    :param file_path: Caminho do arquivo JSON.
    :return: Grafo criado a partir do arquivo JSON.
    """
    with open(file_path, 'r') as file:
        graph_data = json.load(file)

    graph = nx.Graph()

    for city in graph_data:
        city_name = city['nome']
        connections = city['conexoes']

        for connection in connections:
            destination = connection['destino']
            weight = connection['vertice']
            graph.add_edge(city_name, destination, weight=weight)

    return graph

def dijkstra_shortest_path(graph, start, end):
    """
    Calcula o caminho mais curto entre duas cidades usando o algoritmo de Dijkstra.

    :param graph: Grafo representando as cidades e suas conexões.
    :param start: Cidade de origem.
    :param end: Cidade de destino.
    :return: Lista com o caminho mais curto entre a cidade de origem e a cidade de destino.
    """
    distances = {node: float('inf') for node in graph.nodes}
    distances[start] = 0

    previous_nodes = {node: None for node in graph.nodes}

    unvisited_nodes = list(graph.nodes)

    while unvisited_nodes:
        current_node = min(unvisited_nodes, key=lambda node: distances[node])
        unvisited_nodes.remove(current_node)

        if distances[current_node] == float('inf'):
            break

        for neighbor in graph.neighbors(current_node):
            new_distance = distances[current_node] + graph[current_node][neighbor]['weight']
            if new_distance < distances[neighbor]:
                distances[neighbor] = new_distance
                previous_nodes[neighbor] = current_node

    path = []
    current_node = end

    while current_node is not None:
        path.insert(0, current_node)
        current_node = previous_nodes[current_node]

    return path

def generate_graph_gif(graph, start, end, output_path,
                       node_color='lightblue', visited_node_color='green', edge_color='gray', visited_edge_color='lightgray',
                       frame_interval=1000):
    """
    Gera um GIF mostrando o funcionamento do algoritmo de Dijkstra.

    :param graph: Grafo representando as cidades e suas conexões.
    :param start: Cidade de origem.
    :param end: Cidade de destino.
    :param output_path: Caminho onde o GIF será salvo.
    :param node_color: Cor dos nós (padrão: 'lightblue').
    :param visited_node_color: Cor dos nós visitados (padrão: 'green').
    :param edge_color: Cor das arestas (padrão: 'gray').
    :param visited_edge_color: Cor das arestas visitadas (padrão: 'lightgray').
    :param frame_interval: Intervalo entre os frames em milissegundos (padrão: 1000).
    """
    fig, ax = plt.subplots(figsize=(8, 6))
    pos = nx.spring_layout(graph)

    def update(frame):
        ax.clear()

        nx.draw(graph, pos, with_labels=True, node_size=500, font_size=10, width=1.5,
                node_color=[node_color if node != path[frame] else visited_node_color for node in graph.nodes],
                edge_color=[edge_color if graph.has_edge(path[frame], node) else visited_edge_color for node in graph.nodes])
        labels = nx.get_edge_attributes(graph,'weight')
        nx.draw_networkx_edge_labels(graph,pos,edge_labels=labels)

        plt.title(f"Frame {frame + 1} - Shortest Path: {', '.join(path[:frame+1])}")

    path = dijkstra_shortest_path(graph, start, end)

    ani = animation.FuncAnimation(fig, update, frames=len(path), interval=frame_interval)
    ani.save(output_path, writer='pillow')

# Caminho do arquivo JSON, caminho de saída do GIF e as cidades de origem e destino
json_file_path = 'grafo.json'
output_gif_path = '/data/dijkstra.gif'
start_city = input("Digite o nó de início: \n")
end_city = input("Digite o nó de chegada: \n")

# Cria o grafo a partir do arquivo JSON
graph = create_graph_from_json(json_file_path)

# Gera o GIF mostrando o funcionamento do algoritmo de Dijkstra
generate_graph_gif(graph, start_city, end_city, output_gif_path)

print(f"GIF gerado com sucesso em '{output_gif_path}'!")


import unicodedata
from django.core.cache import cache
import pickle

from lib.data_views.exceptions import DataViewCacheTTLError

class DataViewCacheDecorator(object):
    """
    How to cache query set results in django is as following:

    https://docs.djangoproject.com/en/1.7/ref/models/querysets/#pickling-querysets
    >>> import pickle
    >>> query = pickle.loads(s)  # Assuming 's' is the pickled string.
    >>> qs = MyModel.objects.all()
    >>> qs.query = query  # Restore the original 'query'.

    To use with DataViews, a DataView has a method to return a queryset (the view on the data)

    at the entry of the method, we should check if we can find a cache-entry for this request
    to determine the request a hash fo the arguments, the app_name, and the model_name is made

    at leaving the method, and if there was no cache to be found, we will cache the results
    using the same hashing methods for the next visit of the method.
    """

    def __init__(self, fn, ttl=None, cache_key=None):
        self.fn = fn

        if not isinstance(ttl, (int, long)):
            raise DataViewCacheTTLError("Cache TTL should be integer.")

        self.ttl = ttl
        self.cache_key = cache_key

    def __call__(self, *args, **kwargs):
        cache_key = self.get_cache_key(*args, **kwargs)
        data = None
        result = cache.get(cache_key)

        if result:
            #get class ref
            qs = self.fn.im_self.get_queryset()
            qs.query = pickle.loads(result)
            data = qs

        if not data:
            data = self.fn()

            pickled_result = pickle.dumps(result)
            cache.set(cache_key, pickled_result, self.ttl)

        return result

    def get_cache_key(self, *args, **kwargs):
        cache_key = self.cache_key
        if cache_key is None:
            cache_key = self.create_cache_key(*args, **kwargs)
        return cache_key

    def create_cache_key(self, *args, **kwargs):
        key = ".".join('{0}:{1}'.format(
            str(key), str(value)) for key, value in kwargs.iteritems())
        cache_key = '{0}:{1}'.format(self.fn.im_self.__name__, key)
        return "".join(
            ch for ch in unicode(cache_key) if (unicodedata.category(ch)[0] != "C" and unicodedata.category(ch)[0] != "Z")
        )


import unittest
from unittest import mock

from scrapy.item import ABCMeta, Field, Item, ItemMeta

class ItemTest(unittest.TestCase):
    def assertSortedEqual(self, first, second, msg=None):
        return self.assertEqual(sorted(first), sorted(second), msg)

    def test_simple(self):
        class TestItem(Item):
            name = Field()

        i = TestItem()
        i["name"] = "name"
        self.assertEqual(i["name"], "name")

    def test_init(self):
        class TestItem(Item):
            name = Field()

        i = TestItem()
        self.assertRaises(KeyError, i.__getitem__, "name")

        i2 = TestItem(name="john doe")
        self.assertEqual(i2["name"], "john doe")

        i3 = TestItem({"name": "john doe"})
        self.assertEqual(i3["name"], "john doe")

        i4 = TestItem(i3)
        self.assertEqual(i4["name"], "john doe")

        self.assertRaises(KeyError, TestItem, {"name": "john doe", "other": "foo"})

    def test_invalid_field(self):
        class TestItem(Item):
            pass

        i = TestItem()
        self.assertRaises(KeyError, i.__setitem__, "field", "text")
        self.assertRaises(KeyError, i.__getitem__, "field")

    def test_repr(self):
        class TestItem(Item):
            name = Field()
            number = Field()

        i = TestItem()
        i["name"] = "John Doe"
        i["number"] = 123
        itemrepr = repr(i)

        self.assertEqual(itemrepr, "{'name': 'John Doe', 'number': 123}")

        i2 = eval(itemrepr)
        self.assertEqual(i2["name"], "John Doe")
        self.assertEqual(i2["number"], 123)

    def test_private_attr(self):
        class TestItem(Item):
            name = Field()

        i = TestItem()
        i._private = "test"
        self.assertEqual(i._private, "test")

    def test_raise_getattr(self):
        class TestItem(Item):
            name = Field()

        i = TestItem()
        self.assertRaises(AttributeError, getattr, i, "name")

    def test_raise_setattr(self):
        class TestItem(Item):
            name = Field()

        i = TestItem()
        self.assertRaises(AttributeError, setattr, i, "name", "john")

    def test_custom_methods(self):
        class TestItem(Item):
            name = Field()

            def get_name(self):
                return self["name"]

            def change_name(self, name):
                self["name"] = name

        i = TestItem()
        self.assertRaises(KeyError, i.get_name)
        i["name"] = "lala"
        self.assertEqual(i.get_name(), "lala")
        i.change_name("other")
        self.assertEqual(i.get_name(), "other")

    def test_metaclass(self):
        class TestItem(Item):
            name = Field()
            keys = Field()
            values = Field()

        i = TestItem()
        i["name"] = "John"
        self.assertEqual(list(i.keys()), ["name"])
        self.assertEqual(list(i.values()), ["John"])

        i["keys"] = "Keys"
        i["values"] = "Values"
        self.assertSortedEqual(list(i.keys()), ["keys", "values", "name"])
        self.assertSortedEqual(list(i.values()), ["Keys", "Values", "John"])

    def test_metaclass_with_fields_attribute(self):
        class TestItem(Item):
            fields = {"new": Field(default="X")}

        item = TestItem(new="New")
        self.assertSortedEqual(list(item.keys()), ["new"])
        self.assertSortedEqual(list(item.values()), ["New"])

    def test_metaclass_inheritance(self):
        class ParentItem(Item):
            name = Field()
            keys = Field()
            values = Field()

        class TestItem(ParentItem):
            keys = Field()

        i = TestItem()
        i["keys"] = 3
        self.assertEqual(list(i.keys()), ["keys"])
        self.assertEqual(list(i.values()), [3])

    def test_metaclass_multiple_inheritance_simple(self):
        class A(Item):
            fields = {"load": Field(default="A")}
            save = Field(default="A")

        class B(A):
            pass

        class C(Item):
            fields = {"load": Field(default="C")}
            save = Field(default="C")

        class D(B, C):
            pass

        item = D(save="X", load="Y")
        self.assertEqual(item["save"], "X")
        self.assertEqual(item["load"], "Y")
        self.assertEqual(D.fields, {"load": {"default": "A"}, "save": {"default": "A"}})

        # D class inverted
        class E(C, B):
            pass

        self.assertEqual(E(save="X")["save"], "X")
        self.assertEqual(E(load="X")["load"], "X")
        self.assertEqual(E.fields, {"load": {"default": "C"}, "save": {"default": "C"}})

    def test_metaclass_multiple_inheritance_diamond(self):
        class A(Item):
            fields = {"update": Field(default="A")}
            save = Field(default="A")
            load = Field(default="A")

        class B(A):
            pass

        class C(A):
            fields = {"update": Field(default="C")}
            save = Field(default="C")

        class D(B, C):
            fields = {"update": Field(default="D")}
            load = Field(default="D")

        self.assertEqual(D(save="X")["save"], "X")
        self.assertEqual(D(load="X")["load"], "X")
        self.assertEqual(
            D.fields,
            {
                "save": {"default": "C"},
                "load": {"default": "D"},
                "update": {"default": "D"},
            },
        )

        # D class inverted
        class E(C, B):
            load = Field(default="E")

        self.assertEqual(E(save="X")["save"], "X")
        self.assertEqual(E(load="X")["load"], "X")
        self.assertEqual(
            E.fields,
            {
                "save": {"default": "C"},
                "load": {"default": "E"},
                "update": {"default": "C"},
            },
        )

    def test_metaclass_multiple_inheritance_without_metaclass(self):
        class A(Item):
            fields = {"load": Field(default="A")}
            save = Field(default="A")

        class B(A):
            pass

        class C:
            fields = {"load": Field(default="C")}
            not_allowed = Field(default="not_allowed")
            save = Field(default="C")

        class D(B, C):
            pass

        self.assertRaises(KeyError, D, not_allowed="value")
        self.assertEqual(D(save="X")["save"], "X")
        self.assertEqual(D.fields, {"save": {"default": "A"}, "load": {"default": "A"}})

        # D class inverted
        class E(C, B):
            pass

        self.assertRaises(KeyError, E, not_allowed="value")
        self.assertEqual(E(save="X")["save"], "X")
        self.assertEqual(E.fields, {"save": {"default": "A"}, "load": {"default": "A"}})

    def test_to_dict(self):
        class TestItem(Item):
            name = Field()

        i = TestItem()
        i["name"] = "John"
        self.assertEqual(dict(i), {"name": "John"})

    def test_copy(self):
        class TestItem(Item):
            name = Field()

        item = TestItem({"name": "lower"})
        copied_item = item.copy()
        self.assertNotEqual(id(item), id(copied_item))
        copied_item["name"] = copied_item["name"].upper()
        self.assertNotEqual(item["name"], copied_item["name"])

    def test_deepcopy(self):
        class TestItem(Item):
            tags = Field()

        item = TestItem({"tags": ["tag1"]})
        copied_item = item.deepcopy()
        item["tags"].append("tag2")
        assert item["tags"] != copied_item["tags"]

class ItemMetaTest(unittest.TestCase):
    def test_new_method_propagates_classcell(self):
        new_mock = mock.Mock(side_effect=ABCMeta.__new__)
        base = ItemMeta.__bases__[0]

        with mock.patch.object(base, "__new__", new_mock):

            class MyItem(Item):
                def f(self):
                    # For rationale of this see:
                    # https://github.com/python/cpython/blob/ee1a81b77444c6715cbe610e951c655b6adab88b/Lib/test/test_super.py#L222
                    return (
                        __class__  # noqa  https://github.com/scrapy/scrapy/issues/2836
                    )

            MyItem()

        (first_call, second_call) = new_mock.call_args_list[-2:]

        mcs, class_name, bases, attrs = first_call[0]
        assert "__classcell__" not in attrs
        mcs, class_name, bases, attrs = second_call[0]
        assert "__classcell__" in attrs

class ItemMetaClassCellRegression(unittest.TestCase):
    def test_item_meta_classcell_regression(self):
        class MyItem(Item, metaclass=ItemMeta):
            def __init__(self, *args, **kwargs):
                # This call to super() trigger the __classcell__ propagation
                # requirement. When not done properly raises an error:
                # TypeError: __class__ set to <class '__main__.MyItem'>
                # defining 'MyItem' as <class '__main__.MyItem'>
                super().__init__(*args, **kwargs)

if __name__ == "__main__":
    unittest.main()


from django.db import models
from django import forms
from django.contrib.auth.models import User
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.db.models import Avg
from datetime import datetime

# Create your models here.

DEMO_CHOICES =(
    ("Dog Owner", "Dog Owner"),
    ("Dog Sitter", "Dog Sitter"),
    ("Dog Walker" , "Dog Walker")
)

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    status = models.CharField(max_length = 20, choices = DEMO_CHOICES, default="Dog Owner")
    province = models.CharField(max_length = 50, default="Metro Manila")
    city = models.CharField(max_length = 50, default="Quezon City")

    def __str__(self):
        return self.user.username

#Dog Owner
class Dog(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    birth_date = models.DateField()
    sex = models.CharField(max_length=1, default='')
    color = models.CharField(max_length=100)
    weight = models.IntegerField()
    behavior = models.TextField()
    dietary_restrictions = models.TextField()
    comments = models.TextField()

    def __str__(self):
        return f"{self.name}"

#Dog sitter/walker
class Rating(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    rating = models.IntegerField(default=0)

    def __str__(self):
        return f"{self.profile} : {self.rating} by {self.user}"

class Description(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    address = models.TextField(default='')
    description = models.TextField(default='')
    rates = models.TextField(default='')

    def average_rating(self) -> float: #avg ratings
        return Rating.objects.filter(description=self).aggregate(Avg("rating"))["rating__avg"] or 0

    def __str__(self):
        return f"{self.user} description"

#bookings
class Booking(models.Model):
    cash = 'Cash'
    card = 'Card'
    OL = 'Online Payment'

    dogsitter = models.ForeignKey(User, related_name='sitter', on_delete=models.CASCADE)
    dogowner = models.ForeignKey(User, related_name='owner', on_delete=models.CASCADE)
    date_start = models.DateTimeField(default=datetime.now, blank=True)
    date_end = models.DateTimeField(default=datetime.now, blank=True)
    # dropoff_time = models.TimeField(default='10:00')
    # pickup_time = models.TimeField(default='10:00')

    payment_choices = [
        (cash, 'Cash'),
        (card, 'Card'),
        (OL, 'Online Payment')
    ]

    payment = models.CharField(
        max_length=20,
        choices=payment_choices,
        default=cash)
    accepted = models.BooleanField(default=False)
    def __str__(self):
        return f"{self.pk}"

#https://medium.com/geekculture/django-implementing-star-rating-e1deff03bb1c


from hamcrest import ( assert_that,
                       has_items,
                       contains_exactly,
                       contains_string,
                       equal_to,
                       has_entries,
                       has_entry,
                       matches_regexp )
from unittest.mock import patch
from unittest import TestCase
from pprint import pprint
import itertools
import requests
import os.path

from ycmd import handlers
from ycmd.tests.clangd import setUpModule, tearDownModule # noqa
from ycmd.tests.clangd import ( IsolatedYcmd,
                                SharedYcmd,
                                PathToTestFile,
                                RunAfterInitialized )
from ycmd.tests.test_utils import ( BuildRequest,
                                    ChunkMatcher,
                                    CombineRequest,
                                    LineColMatcher,
                                    LocationMatcher,
                                    ErrorMatcher,
                                    UnixOnly,
                                    WithRetry,
                                    WaitUntilCompleterServerReady )
from ycmd.utils import ReadFile

def RunGoToTest_all( app, folder, command, test ):
  req = test[ 'req' ]
  filepath = PathToTestFile( folder, req[ 0 ] )
  request = {
    'completer_target' : 'filetype_default',
    'filepath'         : filepath,
    'contents'         : ReadFile( filepath ),
    'filetype'         : 'cpp',
    'line_num'         : req[ 1 ],
    'column_num'       : req[ 2 ],
    'command_arguments': [ command ] + ( [] if len( req ) < 4 else req[ 3 ] ),
  }

  response = test[ 'res' ]

  if isinstance( response, list ):
    expect = {
      'response': requests.codes.ok,
      'data': contains_exactly( *[
        LocationMatcher(
          PathToTestFile( folder, os.path.normpath( location[ 0 ] ) ),
          location[ 1 ],
          location[ 2 ],
          **( {} if len( location ) < 4 else location[ 3 ] )
        ) for location in response
      ] )
    }
  elif isinstance( response, tuple ):
    expect = {
      'response': requests.codes.ok,
      'data': LocationMatcher(
        PathToTestFile( folder, os.path.normpath( response[ 0 ] ) ),
        response[ 1 ],
        response[ 2 ],
        **( {} if len( response ) < 4 else response[ 3 ] )
      )
    }
  else:
    expect = {
      'response': requests.codes.internal_server_error,
      'data': ErrorMatcher( RuntimeError, test[ 'res' ] )
    }

  RunAfterInitialized( app, {
    'request': request,
    'route'  : '/run_completer_command',
    'expect' : expect
  } )

def RunGetSemanticTest( app,
                        filepath,
                        filetype,
                        test,
                        command,
                        response = requests.codes.ok ):
  contents = ReadFile( filepath )
  common_args = {
    'completer_target' : 'filetype_default',
    'command_arguments': command,
    'line_num'         : 10,
    'column_num'       : 3,
    'filepath'         : filepath,
    'contents'         : contents,
    'filetype'         : filetype
  }

  request = common_args
  request.update( test[ 0 ] )
  test = { 'request': request,
           'route': '/run_completer_command',
           'expect': { 'response': response,
                       'data': test[ 1 ] } }
  RunAfterInitialized( app, test )

def RunFixItTest( app, line, column, lang, file_path, check ):
  contents = ReadFile( file_path )

  language_options = {
    'cpp11': {
      'filetype'         : 'cpp',
    },
    'cuda': {
      'filetype'         : 'cuda',
    },
    'objective-c': {
      'filetype'         : 'objc',
    },
  }

  args = {
    'completer_target' : 'filetype_default',
    'contents'         : contents,
    'filepath'         : file_path,
    'command_arguments': [ 'FixIt' ],
    'line_num'         : line,
    'column_num'       : column,
  }
  args.update( language_options[ lang ] )
  test = { 'request': args, 'route': '/detailed_diagnostic' }
  # First get diags.
  diags = RunAfterInitialized( app, test )
  while 'message' in diags and 'diagnostics' in diags[ 'message' ].lower():
    receive_diags = { 'request': args, 'route': '/receive_messages' }
    RunAfterInitialized( app, receive_diags )
    diags = RunAfterInitialized( app, test )

  results = app.post_json( '/run_completer_command',
                           BuildRequest( **args ) ).json

  pprint( results )
  check( results )

def FixIt_Check_cpp11_Ins( results ):
  # First fixit
  #   switch(A()) { // expected-error{{explicit conversion to}}
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
      'kind': 'quickfix',
      'chunks': contains_exactly(
        has_entries( {
          'replacement_text': equal_to( 'static_cast<int>(' ),
          'range': has_entries( {
            'start': has_entries( { 'line_num': 16, 'column_num': 10 } ),
            'end'  : has_entries( { 'line_num': 16, 'column_num': 10 } ),
          } ),
        } ),
        has_entries( {
          'replacement_text': equal_to( ')' ),
          'range': has_entries( {
            'start': has_entries( { 'line_num': 16, 'column_num': 13 } ),
            'end'  : has_entries( { 'line_num': 16, 'column_num': 13 } ),
          } ),
        } )
      ),
      'location': has_entries( { 'line_num': 16, 'column_num': 1 } )
    } ) )
  } ) )

def FixIt_Check_cpp11_InsMultiLine( results ):
  # Similar to FixIt_Check_cpp11_1 but inserts split across lines
  #
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
      'kind': 'quickfix',
      'chunks': contains_exactly(
        has_entries( {
          'replacement_text': equal_to( 'static_cast<int>(' ),
          'range': has_entries( {
            'start': has_entries( { 'line_num': 26, 'column_num': 7 } ),
            'end'  : has_entries( { 'line_num': 26, 'column_num': 7 } ),
          } ),
        } ),
        has_entries( {
          'replacement_text': equal_to( ')' ),
          'range': has_entries( {
            'start': has_entries( { 'line_num': 28, 'column_num': 2 } ),
            'end'  : has_entries( { 'line_num': 28, 'column_num': 2 } ),
          } ),
        } )
      ),
      'location': has_entries( { 'line_num': 25, 'column_num': 14 } )
    } ) )
  } ) )

def FixIt_Check_cpp11_Del( results ):
  # Removal of ::
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
      'kind': 'quickfix',
      'chunks': contains_exactly(
        has_entries( {
          'replacement_text': equal_to( '' ),
          'range': has_entries( {
            'start': has_entries( { 'line_num': 35, 'column_num': 7 } ),
            'end'  : has_entries( { 'line_num': 35, 'column_num': 9 } ),
          } ),
        } )
      ),
      'location': has_entries( { 'line_num': 35, 'column_num': 7 } )
    } ) )
  } ) )

def FixIt_Check_cpp11_Repl( results ):
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
      'kind': 'quickfix',
      'text': "change 'bar' to 'foo'",
      'chunks': contains_exactly(
        has_entries( {
          'replacement_text': equal_to( 'foo' ),
          'range': has_entries( {
            'start': has_entries( { 'line_num': 40, 'column_num': 6 } ),
            'end'  : has_entries( { 'line_num': 40, 'column_num': 9 } ),
          } ),
        } )
      ),
      'location': has_entries( { 'line_num': 40, 'column_num': 6 } )
    } ) )
  } ) )

def FixIt_Check_cpp11_DelAdd( results ):
  assert_that( results, has_entries( {
    'fixits': has_items(
      has_entries( {
        'kind': 'quickfix',
        'chunks': contains_exactly(
          has_entries( {
            'replacement_text': equal_to( '' ),
            'range': has_entries( {
              'start': has_entries( { 'line_num': 48, 'column_num': 3 } ),
              'end'  : has_entries( { 'line_num': 48, 'column_num': 4 } ),
            } ),
          } ),
          has_entries( {
            'replacement_text': equal_to( '~' ),
            'range': has_entries( {
              'start': has_entries( { 'line_num': 48, 'column_num': 9 } ),
              'end'  : has_entries( { 'line_num': 48, 'column_num': 9 } ),
            } ),
          } ),
        ),
        'location': has_entries( { 'line_num': 48, 'column_num': 3 } )
      } ),
      has_entries( {
        'chunks': contains_exactly(
          has_entries( {
            'replacement_text': equal_to( '= default;' ),
            'range': has_entries( {
              'start': has_entries( { 'line_num': 48, 'column_num': 15 } ),
              'end'  : has_entries( { 'line_num': 48, 'column_num': 17 } ),
            } ),
          } ),
        ),
        'location': has_entries( { 'line_num': 48, 'column_num': 3 } )
      } ),
      # Unresolved, requires /resolve_fixit request
      has_entries( {
        'text': 'Move function body to declaration',
        'resolve': True,
        'command': has_entries( { 'command': 'clangd.applyTweak' } )
      } ),
    )
  } ) )

def FixIt_Check_objc( results ):
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
      'kind': 'quickfix',
      'chunks': contains_exactly(
        has_entries( {
          'replacement_text': equal_to( 'id' ),
          'range': has_entries( {
            'start': has_entries( { 'line_num': 5, 'column_num': 3 } ),
            'end'  : has_entries( { 'line_num': 5, 'column_num': 3 } ),
          } ),
        } )
      ),
      'location': has_entries( { 'line_num': 5, 'column_num': 3 } )
    } ) )
  } ) )

def FixIt_Check_objc_NoFixIt( results ):
  # and finally, a warning with no fixits
  assert_that( results, equal_to( { 'fixits': [] } ) )

def FixIt_Check_cpp11_MultiFirst( results ):
  assert_that( results, has_entries( {
    'fixits': has_items(
      # first fix-it at 54,16
      has_entries( {
        'kind': 'quickfix',
        'chunks': contains_exactly(
          has_entries( {
            'replacement_text': equal_to( 'foo' ),
            'range': has_entries( {
              'start': has_entries( { 'line_num': 54, 'column_num': 16 } ),
              'end'  : has_entries( { 'line_num': 54, 'column_num': 19 } ),
            } ),
          } )
        ),
        'location': has_entries( { 'line_num': 54, 'column_num': 15 } )
      } ),
    )
  } ) )

def FixIt_Check_cpp11_MultiSecond( results ):
  assert_that( results, has_entries( {
    'fixits': has_items(
      # second fix-it at 54,52
      has_entries( {
        'kind': 'quickfix',
        'chunks': contains_exactly(
          has_entries( {
            'replacement_text': equal_to( '' ),
            'range': has_entries( {
              'start': has_entries( { 'line_num': 54, 'column_num': 52 } ),
              'end'  : has_entries( { 'line_num': 54, 'column_num': 53 } ),
            } ),
          } ),
          has_entries( {
            'replacement_text': equal_to( '~' ),
            'range': has_entries( {
              'start': has_entries( { 'line_num': 54, 'column_num': 58 } ),
              'end'  : has_entries( { 'line_num': 54, 'column_num': 58 } ),
            } ),
          } ),
        ),
        'location': has_entries( { 'line_num': 54, 'column_num': 51 } )
      } ),
      has_entries( {
        'kind': 'quickfix',
        'chunks': contains_exactly(
          has_entries( {
            'replacement_text': equal_to( '= default;' ),
            'range': has_entries( {
              'start': has_entries( { 'line_num': 54, 'column_num': 64 } ),
              'end'  : has_entries( { 'line_num': 54, 'column_num': 67 } ),
            } ),
          } )
        ),
        'location': has_entries( { 'line_num': 54, 'column_num': 51 } )
      } ),
    )
  } ) )

def FixIt_Check_unicode_Ins( results ):
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
      'kind': 'quickfix',
      'chunks': contains_exactly(
        has_entries( {
          'replacement_text': equal_to( '=' ),
          'range': has_entries( {
            'start': has_entries( { 'line_num': 21, 'column_num': 9 } ),
            'end'  : has_entries( { 'line_num': 21, 'column_num': 11 } ),
          } ),
        } )
      ),
      'location': has_entries( { 'line_num': 21, 'column_num': 16 } )
    } ) )
  } ) )

def FixIt_Check_cpp11_Note( results ):
  assert_that( results, has_entries( {
    'fixits': has_items(
      # First note: put parens around it
      has_entries( {
        'kind': 'quickfix',
        'text': contains_string( 'parentheses around the assignment' ),
        'chunks': contains_exactly(
          ChunkMatcher( '(',
                        LineColMatcher( 59, 8 ),
                        LineColMatcher( 59, 8 ) ),
          ChunkMatcher( ')',
                        LineColMatcher( 61, 12 ),
                        LineColMatcher( 61, 12 ) )
        ),
        'location': LineColMatcher( 60, 1 ),
      } ),

      # Second note: change to ==
      has_entries( {
        'kind': 'quickfix',
        'text': contains_string( '==' ),
        'chunks': contains_exactly(
          ChunkMatcher( '==',
                        LineColMatcher( 60, 8 ),
                        LineColMatcher( 60, 9 ) )
        ),
        'location': LineColMatcher( 60, 1 ),
      } ),
    )
  } ) )

def FixIt_Check_cpp11_SpellCheck( results ):
  assert_that( results, has_entries( {
    'fixits': has_items(
      # Change to SpellingIsNotMyStrongPoint
      has_entries( {
        'kind': 'quickfix',
        'text': contains_string( "change 'SpellingIsNotMyStringPiont' to "
                                 "'SpellingIsNotMyStrongPoint'" ),
        'chunks': contains_exactly(
          ChunkMatcher( 'SpellingIsNotMyStrongPoint',
                        LineColMatcher( 72, 9 ),
                        LineColMatcher( 72, 35 ) )
        ),
        'location': LineColMatcher( 72, 9 ),
      } ),
      has_entries( {
        'kind': 'refactor',
        'text': contains_string( "Add using-declaration for "
                                 "SpellingIsNotMyStringPiont and "
                                 "remove qualifier" ),
        'resolve': True
      } ) )
  } ) )

def FixIt_Check_cuda( results ):
  assert_that( results, has_entries( {
    'fixits': has_items(
      has_entries( {
        'kind': 'quickfix',
        'text': contains_string(
           "change 'int' to 'void'" ),
        'chunks': contains_exactly(
          ChunkMatcher( 'void',
                        LineColMatcher( 3, 12 ),
                        LineColMatcher( 3, 15 ) )
        ),
        'location': LineColMatcher( 3, 12 ),
      } ) )
  } ) )

def FixIt_Check_SubexprExtract_Resolved( results ):
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
        'text': 'Extract subexpression to variable',
        'chunks': contains_exactly(
          ChunkMatcher( 'auto placeholder = i + 3;\n  ',
                        LineColMatcher( 84, 3 ),
                        LineColMatcher( 84, 3 ) ),
          ChunkMatcher( 'placeholder',
                        LineColMatcher( 84, 14 ),
                        LineColMatcher( 84, 21 ) ),
        )
    } ) )
  } ) )

def FixIt_Check_RawStringReplace_Resolved( results ):
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
        'text': 'Convert to raw string',
        'chunks': contains_exactly(
          ChunkMatcher( 'R"(\\\\r\\asd\n\\v)"',
                        LineColMatcher( 80, 19 ),
                        LineColMatcher( 80, 36 ) ),
        )
    } ) )
  } ) )

def FixIt_Check_MacroExpand_Resolved( results ):
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
        'text': "Expand macro 'DECLARE_INT'",
        'chunks': contains_exactly(
          ChunkMatcher( 'int i',
                        LineColMatcher( 83,  3 ),
                        LineColMatcher( 83, 17 ) ),
        )
    } ) )
  } ) )

def FixIt_Check_AutoExpand_Resolved( results ):
  assert_that( results, has_entries( {
    'fixits': has_items( has_entries( {
        'text': "Replace with deduced type",
        'chunks': contains_exactly(
          ChunkMatcher( 'const char *',
                        LineColMatcher( 80, 1 ),
                        LineColMatcher( 80, 6 ) ),
        )
    } ) )
  } ) )

def RunRangedFixItTest( app, rng, expected, chosen_fixit = 0 ):
  contents = ReadFile( PathToTestFile( 'FixIt_Clang_cpp11.cpp' ) )
  args = {
    'completer_target' : 'filetype_default',
    'contents'         : contents,
    'filepath'         : PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
    'command_arguments': [ 'FixIt' ],
    'range'            : rng,
    'filetype'         : 'cpp'
  }
  app.post_json( '/event_notification',
                 CombineRequest( args, {
                   'event_name': 'FileReadyToParse',
                 } ),
                 expect_errors = True )
  WaitUntilCompleterServerReady( app, 'cpp' )
  response = app.post_json( '/run_completer_command',
                            BuildRequest( **args ) ).json
  args[ 'fixit' ] = response[ 'fixits' ][ chosen_fixit ]
  response = app.post_json( '/resolve_fixit',
                            BuildRequest( **args ) ).json
  print( 'Resolved fixit response = ' )
  print( response )
  expected( response )

class SubcommandsTest( TestCase ):
  # This test is isolated to trigger objcpp hooks, rather than fetching
  # completer from cache.
  @IsolatedYcmd()
  def test_Subcommands_DefinedSubcommands( self, app ):
    file_path = PathToTestFile( 'GoTo_Clang_ZeroBasedLineAndColumn_test.cc' )
    RunAfterInitialized( app, {
        'request': {
          'completer_target': 'filetype_default',
          'line_num': 10,
          'column_num': 3,
          'filetype': 'objcpp',
          'filepath': file_path
        },
        'expect': {
          'response': requests.codes.ok,
          'data': contains_exactly( *sorted( [ 'ExecuteCommand',
                                               'FixIt',
                                               'Format',
                                               'GetDoc',
                                               'GetDocImprecise',
                                               'GetType',
                                               'GetTypeImprecise',
                                               'GoTo',
                                               'GoToCallees',
                                               'GoToCallers',
                                               'GoToDeclaration',
                                               'GoToDefinition',
                                               'GoToDocumentOutline',
                                               'GoToImprecise',
                                               'GoToImplementation',
                                               'GoToInclude',
                                               'GoToReferences',
                                               'GoToSymbol',
                                               'GoToType',
                                               'RefactorRename',
                                               'RestartServer',
                                               'GoToAlternateFile' ] ) )
        },
        'route': '/defined_subcommands',
    } )

  @WithRetry()
  @SharedYcmd
  def test_Subcommands_ServerNotInitialized( self, app ):
    for cmd in [
      'ExecuteCommand',
      'FixIt',
      'Format',
      'GetDoc',
      'GetDocImprecise',
      'GetType',
      'GetTypeImprecise',
      'GoTo',
      'GoToCallees',
      'GoToCallers',
      'GoToDeclaration',
      'GoToDefinition',
      'GoToDocumentOutline',
      'GoToImprecise',
      'GoToImplementation',
      'GoToInclude',
      'GoToReferences',
      'GoToType',
      'RefactorRename',
      'GoToAlternateFile',
    ]:
      with self.subTest( cmd = cmd ):
        completer = handlers._server_state.GetFiletypeCompleter( [ 'cpp' ] )

        @patch.object( completer, '_ServerIsInitialized', return_value = False )
        def Test( app, cmd, *args ):
          request = {
            'line_num': 1,
            'column_num': 1,
            'event_name': 'FileReadyToParse',
            'filetype': 'cpp',
            'command_arguments': [ cmd ]
          }
          app.post_json( '/event_notification',
                         BuildRequest( **request ),
                         expect_errors = True )
          response = app.post_json(
            '/run_completer_command',
            BuildRequest( **request ),
            expect_errors = True
          )
          assert_that( response.status_code,
                       equal_to( requests.codes.server_error ) )
          assert_that( response.json,
                       ErrorMatcher( RuntimeError,
                                     'Server is initializing. Please wait.' ) )

        Test( app, cmd )

  @SharedYcmd
  def test_Subcommands_GoTo_ZeroBasedLineAndColumn( self, app ):
    file_path = PathToTestFile( 'GoTo_Clang_ZeroBasedLineAndColumn_test.cc' )
    RunAfterInitialized( app, {
        'request': {
            'contents': ReadFile( file_path ),
            'completer_target': 'filetype_default',
            'command_arguments': [ 'GoToDefinition' ],
            'line_num': 10,
            'column_num': 3,
            'filetype': 'cpp',
            'filepath': file_path
        },
        'expect': {
            'response': requests.codes.ok,
            'data': {
                'filepath': os.path.abspath( file_path ),
                'line_num': 2,
                'column_num': 8
            }
        },
        'route': '/run_completer_command',
    } )

  @SharedYcmd
  def test_Subcommands_GoTo_all( self, app ):
    for test, cmd in itertools.product(
      [
        # Local::x -> definition/declaration of x
        { 'req': ( 'goto.cc', 23, 21 ), 'res': ( 'goto.cc', 4, 9 ) },
        # Local::in_line -> definition/declaration of Local::in_line
        { 'req': ( 'goto.cc', 24, 26 ), 'res': ( 'goto.cc', 6, 10 ) },
        # Local -> definition/declaration of Local
        { 'req': ( 'goto.cc', 24, 16 ), 'res': ( 'goto.cc', 2, 11 ) },
        # Local::out_of_line -> definition of Local::out_of_line
        { 'req': ( 'goto.cc', 25, 27 ), 'res': ( 'goto.cc', 14, 13 ) },
        # GoToDeclaration alternates between definition and declaration
        { 'req': ( 'goto.cc', 14, 13 ), 'res': ( 'goto.cc', 11, 10 ) },
        { 'req': ( 'goto.cc', 11, 10 ), 'res': ( 'goto.cc', 14, 13 ) },
        # test -> definition and declaration of test
        { 'req': ( 'goto.cc', 21,  5 ), 'res': ( 'goto.cc', 19, 5 ) },
        { 'req': ( 'goto.cc', 19,  5 ), 'res': ( 'goto.cc', 21, 5 ) },
        # Unicøde
        { 'req': ( 'goto.cc', 34,  9 ), 'res': ( 'goto.cc', 32, 26 ) },
        # Another_Unicøde
        { 'req': ( 'goto.cc', 36, 17 ), 'res': ( 'goto.cc', 32, 54 ) },
        { 'req': ( 'goto.cc', 36, 25 ), 'res': ( 'goto.cc', 32, 54 ) },
        { 'req': ( 'goto.cc', 38,  3 ), 'res': ( 'goto.cc', 36, 28 ) },
        # Expected failures
        { 'req': ( 'goto.cc', 13,  1 ), 'res': 'Cannot jump to location' },
        { 'req': ( 'goto.cc', 16,  6 ), 'res': 'Cannot jump to location' },
      ],
      [ 'GoToImprecise', 'GoToDefinition', 'GoTo' ] ):
      with self.subTest( test = test, cmd = cmd ):
        RunGoToTest_all( app, '', cmd, test )

  @SharedYcmd
  def test_Subcommands_GoToDeclaration_all( self, app ):
    for test in [
      # Local::x -> definition/declaration of x
      { 'req': ( 'goto.cc', 23, 21 ), 'res': ( 'goto.cc', 4, 9 ) },
      # Local::in_line -> definition/declaration of Local::in_line
      { 'req': ( 'goto.cc', 24, 26 ), 'res': ( 'goto.cc', 6, 10 ) },
      # Local -> definition/declaration of Local
      { 'req': ( 'goto.cc', 24, 16 ), 'res': ( 'goto.cc', 2, 11 ) },
      # Local::out_of_line -> declaration of Local::out_of_line
      { 'req': ( 'goto.cc', 25, 27 ), 'res': ( 'goto.cc', 11, 10 ) },
      # GoToDeclaration alternates between definition and declaration
      { 'req': ( 'goto.cc', 14, 13 ), 'res': ( 'goto.cc', 11, 10 ) },
      { 'req': ( 'goto.cc', 11, 10 ), 'res': ( 'goto.cc', 14, 13 ) },
      # test -> definition and declaration of test
      { 'req': ( 'goto.cc', 21,  5 ), 'res': ( 'goto.cc', 19, 5 ) },
      { 'req': ( 'goto.cc', 19,  5 ), 'res': ( 'goto.cc', 21, 5 ) },
      # Unicøde
      { 'req': ( 'goto.cc', 34,  9 ), 'res': ( 'goto.cc', 32, 26 ) },
      # Another_Unicøde
      { 'req': ( 'goto.cc', 36, 17 ), 'res': ( 'goto.cc', 32, 54 ) },
      { 'req': ( 'goto.cc', 36, 25 ), 'res': ( 'goto.cc', 32, 54 ) },
      { 'req': ( 'goto.cc', 38,  3 ), 'res': ( 'goto.cc', 36, 28 ) },
      # Expected failures
      { 'req': ( 'goto.cc', 13,  1 ), 'res': 'Cannot jump to location' },
      { 'req': ( 'goto.cc', 16,  6 ), 'res': 'Cannot jump to location' },
    ]:
      with self.subTest( test = test ):
        RunGoToTest_all( app, '', 'GoToDeclaration', test )

  @SharedYcmd
  def test_Subcommands_GoToInclude( self, app ):
    for test, cmd in itertools.product( [
        { 'req': ( 'main.cpp',  1,  6 ), 'res': ( 'a.hpp',        1, 1 ) },
        { 'req': ( 'main.cpp',  2, 14 ), 'res': ( 'system/a.hpp', 1, 1 ) },
        { 'req': ( 'main.cpp',  3,  1 ), 'res': ( 'quote/b.hpp',  1, 1 ) },
        # FIXME: should fail since b.hpp is included with angled brackets but
        # its folder is added with -iquote.
        { 'req': ( 'main.cpp',  4, 10 ), 'res': ( 'quote/b.hpp',  1, 1 ) },
        { 'req': ( 'main.cpp',  5, 11 ), 'res': ( 'system/c.hpp', 1, 1 ) },
        { 'req': ( 'main.cpp',  6, 11 ), 'res': ( 'system/c.hpp', 1, 1 ) },
        # Expected failures
        { 'req': ( 'main.cpp',  7,  1 ), 'res': 'Cannot jump to location' },
      ],
      [ 'GoToImprecise', 'GoToInclude', 'GoTo' ] ):
      with self.subTest( test = test, cmd = cmd ):
        RunGoToTest_all( app, 'test-include', cmd, test )

  @SharedYcmd
  def test_Subcommands_GoToAlternateFile( self, app ):
    for test in [
            { 'req': ( 'go-to-alternate-file/a.cpp', 1, 1 ),
              'res': ( 'go-to-alternate-file/a.h', 1, 1 ) },
            { 'req': ( 'go-to-alternate-file/a.h', 1, 1 ),
              'res': ( 'go-to-alternate-file/a.cpp', 1, 1 ) },
    ]:
      with self.subTest( test = test ):
        RunGoToTest_all( app, '', 'GoToAlternateFile', test )

  @SharedYcmd
  def test_Subcommands_GoToReferences( self, app ):
    for test in [
      # Function
      { 'req': ( 'goto.cc', 14, 21 ), 'res': [ ( 'goto.cc', 11, 10 ),
                                               ( 'goto.cc', 14, 13 ),
                                               ( 'goto.cc', 25, 22 ) ] },
      # Namespace
      { 'req': ( 'goto.cc', 24, 17 ), 'res': [ ( 'goto.cc',  2, 11 ),
                                               ( 'goto.cc', 14,  6 ),
                                               ( 'goto.cc', 23, 14 ),
                                               ( 'goto.cc', 24, 15 ),
                                               ( 'goto.cc', 25, 15 ) ] },
      # Expected failure
      { 'req': ( 'goto.cc', 27,  8 ), 'res': 'Cannot jump to location' },
    ]:
      with self.subTest( test = test ):
        RunGoToTest_all( app, '', 'GoToReferences', test )

  @IsolatedYcmd()
  def test_Subcommands_GoToSymbol( self, app ):
    for test in [
      # In same file - 1 result
      { 'req': ( 'goto.cc', 1, 1, [ 'out_of_line' ] ),
        'res': ( 'goto.cc', 14, 13, {
          'description': 'Function: out_of_line',
          'extra_data': { 'kind': 'Function', 'name': 'out_of_line', } }
        ) },
      # In same file - multiple results
      { 'req': ( 'goto.cc', 1, 1, [ 'line' ] ),
        'res': [
          ( 'goto.cc', 6, 10, {
            'description': 'Function: in_line',
            'extra_data': { 'kind': 'Function', 'name': 'in_line' },
          } ),
          ( 'goto.cc', 14, 13, {
            'description': 'Function: out_of_line',
            'extra_data': { 'kind': 'Function', 'name': 'out_of_line' },
          } ),
      ] },
      # None
      { 'req': ( 'goto.cc', 1, 1, [ 'none' ] ), 'res': 'Symbol not found' },

      # Note we don't actually have any testdata that has a full index, so we
      # can't test multiple files easily, but that's really a clangd thing, not
      # a ycmd thing.
    ]:
      with self.subTest( test = test ):
        RunGoToTest_all( app, '', 'GoToSymbol', test )

  @SharedYcmd
  def test_Subcommands_GoToDocumentOutline( self, app ):
    for test in [
      # In same file - multiple results
      { 'req': ( 'goto.cc', 1, 1 ),
        'res': [
          ( 'goto.cc', 2, 1, {
            'description': "Namespace: Local",
            'extra_data': { 'kind': 'Namespace', 'name': 'Local' } } ),
          ( 'goto.cc', 14, 1, {
            'description': "Function: Local::out_of_line",
            'extra_data': { 'kind': 'Function',
                            'name': 'Local::out_of_line' } } ),
          ( 'goto.cc', 6, 5, {
            'description': "Function: in_line",
            'extra_data': { 'kind': 'Function', 'name': 'in_line' } } ),
          ( 'goto.cc', 11, 5, {
            'description': 'Function: out_of_line',
            'extra_data': { 'kind': 'Function', 'name': 'out_of_line' } } ),
          ( 'goto.cc', 19, 1, {
            'description': "Function: test",
            'extra_data': { 'kind': 'Function', 'name': 'test' } } ),
          ( 'goto.cc', 21, 1, {
            'description': "Function: test",
            'extra_data': { 'kind': 'Function', 'name': 'test' } } ),
          ( 'goto.cc', 30, 1, {
            'description': "Function: unicode",
            'extra_data': { 'kind': 'Function', 'name': 'unicode' } } ),
          ( 'goto.cc', 4, 5, {
            'description': "Variable: x",
            'extra_data': { 'kind': 'Variable', 'name': 'x' } } ),
        ] } ]:
      with self.subTest( test = test ):
        RunGoToTest_all( app, '', 'GoToDocumentOutline', test )

  @SharedYcmd
  def test_Subcommands_GoToImplementation( self, app ):
    for test in [
      { 'req': ( 'virtual.cpp', 1, 9 ),
        'res': [
          ( 'virtual.cpp', 5, 8 ),
          ( 'virtual.cpp', 13, 8, ),
          ( 'virtual.cpp', 9, 8 ),
      ] },
      { 'req': ( 'virtual.cpp', 2, 15 ),
        'res': [
          ( 'virtual.cpp', 10, 15 ),
          ( 'virtual.cpp', 6, 7 ),
      ] },
      { 'req': ( 'virtual.cpp', 9, 8 ),
        'res': ( 'virtual.cpp', 14, 8 ) },
      { 'req': ( 'virtual.cpp', 13, 15 ),
        'res': [
          ( 'virtual.cpp', 5, 8 ),
          ( 'virtual.cpp', 13, 8, ),
          ( 'virtual.cpp', 9, 8 ),
      ] },
      { 'req': ( 'virtual.cpp', 10, 15 ),
        'res': 'Cannot jump to location' },
    ]:
      with self.subTest( test = test ):
        RunGoToTest_all( app, '', 'GoToImplementation', test )

  @SharedYcmd
  def test_Subcommands_GoToCallers( self, app ):
    for test in [
      { 'req': ( 'call_hierarchy.cc', 1, 6 ), # Simple case.
        'res': [ ( 'call_hierarchy.cc', 4, 10 ) ] },
      { 'req': ( 'call_hierarchy.cc', 6, 6 ),
        'res': [
          ( 'call_hierarchy.cc', 15, 3 ), # More than one location in response.
          ( 'call_hierarchy.cc', 11, 3 ),
          ( 'call_hierarchy.cc',  7, 3 ), # Recursive call.
      ] },
      { 'req': ( 'call_hierarchy.cc', 3, 6 ), # Top of call hierarchy.
        'res': 'No incoming calls found.' }
    ]:
      with self.subTest( test = test ):
        RunGoToTest_all( app, '', 'GoToCallers', test )

  @SharedYcmd
  def test_Subcommands_GetType( self, app ):
    for test, cmd in itertools.product( [
        # Basic pod types
        [ { 'line_num': 24, 'column_num':  3 },
          has_entry( 'message', equal_to( 'struct Foo {}' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 12, 'column_num':  2 }, 'Foo',
        [ { 'line_num': 12, 'column_num':  8 },
          has_entry( 'message', equal_to( 'struct Foo {}' ) ),
          requests.codes.ok ],
        [ { 'line_num': 12, 'column_num':  9 },
          has_entry( 'message', equal_to( 'struct Foo {}' ) ),
          requests.codes.ok ],
        [ { 'line_num': 12, 'column_num': 10 },
          has_entry( 'message', equal_to( 'struct Foo {}' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 13, 'column_num':  3 }, 'int',
        [ { 'line_num': 13, 'column_num':  7 },
          has_entry( 'message', equal_to( 'public: int x; // In Foo' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 15, 'column_num':  7 }, 'char' ],

        # Function
        # [ { 'line_num': 22, 'column_num':  2 }, 'int main()' ],
        [ { 'line_num': 22, 'column_num':  6 },
          'int main()',
          requests.codes.ok ],

        # Declared and canonical type
        # On Ns::
        [ { 'line_num': 25, 'column_num':  3 },
          'namespace Ns',
          requests.codes.ok ],
        # On Type (Type)
        # [ { 'line_num': 25, 'column_num':  8 },
        # 'Ns::Type => Ns::BasicType<char>' ],
        # On "a" (Ns::Type)
        # [ { 'line_num': 25, 'column_num': 15 },
        # 'Ns::Type => Ns::BasicType<char>' ],
        # [ { 'line_num': 26, 'column_num': 13 },
        # 'Ns::Type => Ns::BasicType<char>' ],

        # Cursor on decl for refs & pointers
        [ { 'line_num': 39, 'column_num':  3 },
          has_entry( 'message', equal_to( 'struct Foo {}' ) ),
          requests.codes.ok ],
        [ { 'line_num': 39, 'column_num': 11 },
          has_entry( 'message', equal_to( 'Foo &rFoo = foo; // In main' ) ),
          requests.codes.ok ],
        [ { 'line_num': 39, 'column_num': 15 },
          has_entry( 'message', equal_to( 'Foo foo; // In main' ) ),
          requests.codes.ok ],
        [ { 'line_num': 40, 'column_num':  3 },
          has_entry( 'message', equal_to( 'struct Foo {}' ) ),
          requests.codes.ok ],
        [ { 'line_num': 40, 'column_num': 11 },
          has_entry( 'message', equal_to( 'Foo *pFoo = &foo; // In main' ) ),
          requests.codes.ok ],
        [ { 'line_num': 40, 'column_num': 18 },
          has_entry( 'message', equal_to( 'Foo foo; // In main' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 42, 'column_num':  3 }, 'const Foo &' ],
        [ { 'line_num': 42, 'column_num': 16 },
          has_entry( 'message',
                     equal_to( 'const Foo &crFoo = foo; // In main' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 43, 'column_num':  3 }, 'const Foo *' ],
        [ { 'line_num': 43, 'column_num': 16 },
          has_entry( 'message',
                     equal_to( 'const Foo *cpFoo = &foo; // In main' ) ),
          requests.codes.ok ],

        # Cursor on usage
        [ { 'line_num': 45, 'column_num': 13 },
          has_entry( 'message',
                     equal_to( 'const Foo &crFoo = foo; // In main' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 45, 'column_num': 19 }, 'const int' ],
        [ { 'line_num': 46, 'column_num': 13 },
          has_entry( 'message',
                     equal_to( 'const Foo *cpFoo = &foo; // In main' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 46, 'column_num': 20 }, 'const int' ],
        [ { 'line_num': 47, 'column_num': 12 },
          has_entry( 'message', equal_to( 'Foo &rFoo = foo; // In main' ) ),
          requests.codes.ok ],
        [ { 'line_num': 47, 'column_num': 17 },
          has_entry( 'message', equal_to( 'public: int y; // In Foo' ) ),
          requests.codes.ok ],
        [ { 'line_num': 48, 'column_num': 12 },
          has_entry( 'message', equal_to( 'Foo *pFoo = &foo; // In main' ) ),
          requests.codes.ok ],
        [ { 'line_num': 48, 'column_num': 18 },
          has_entry( 'message', equal_to( 'public: int x; // In Foo' ) ),
          requests.codes.ok ],

        # Auto in declaration
        # [ { 'line_num': 28, 'column_num':  3 }, 'struct Foo &' ],
        # [ { 'line_num': 28, 'column_num': 11 }, 'struct Foo &' ],
        [ { 'line_num': 28, 'column_num': 18 },
          has_entry( 'message', equal_to( 'Foo foo; // In main' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 29, 'column_num':  3 }, 'Foo *' ],
        # [ { 'line_num': 29, 'column_num': 11 }, 'Foo *' ],
        [ { 'line_num': 29, 'column_num': 18 },
          has_entry( 'message', equal_to( 'Foo foo; // In main' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 31, 'column_num':  3 }, 'const Foo &' ],
        # [ { 'line_num': 31, 'column_num': 16 }, 'const Foo &' ],
        # [ { 'line_num': 32, 'column_num':  3 }, 'const Foo *' ],
        # [ { 'line_num': 32, 'column_num': 16 }, 'const Foo *' ],

        # Auto in usage
        # [ { 'line_num': 34, 'column_num': 14 }, 'const Foo' ],
        # [ { 'line_num': 34, 'column_num': 21 }, 'const int' ],
        # [ { 'line_num': 35, 'column_num': 14 }, 'const Foo *' ],
        # [ { 'line_num': 35, 'column_num': 22 }, 'const int' ],
        [ { 'line_num': 36, 'column_num': 13 },
          has_entry( 'message', equal_to( 'auto &arFoo = foo; // In main' ) ),
          requests.codes.ok ],
        [ { 'line_num': 36, 'column_num': 19 },
          has_entry( 'message', equal_to( 'public: int y; // In Foo' ) ),
          requests.codes.ok ],
        # [ { 'line_num': 37, 'column_num': 13 }, 'Foo *' ],
        [ { 'line_num': 37, 'column_num': 20 },
          has_entry( 'message', equal_to( 'public: int x; // In Foo' ) ),
          requests.codes.ok ],

        # Unicode
        [ { 'line_num': 51, 'column_num': 13 },
          has_entry( 'message', equal_to( 'Unicøde *ø; // In main' ) ),
          requests.codes.ok ],

        # Bound methods
        # On Win32, methods pick up an __attribute__((thiscall)) to annotate
        # their calling convention.  This shows up in the type, which isn't
        # ideal, but also prohibitively complex to try and strip out.
        [ { 'line_num': 53, 'column_num': 15 },
          has_entry( 'message', matches_regexp(
              r'int bar\(int i\)(?: '
              r'__attribute__\(\(thiscall\)\))?; // In Foo' ) ),
          requests.codes.ok ],
        [ { 'line_num': 54, 'column_num': 18 },
          has_entry( 'message', matches_regexp(
              r'int bar\(int i\)(?: _'
              r'_attribute__\(\(thiscall\)\))?; // In Foo' ) ),
          requests.codes.ok ],
        # Multi-line function declaration
        [ { 'line_num': 58, 'column_num': 20 },
          has_entry( 'message', equal_to(
              'unsigned long long long_function_name(unsigned long long first, '
              'unsigned long long second)' ) ),
          requests.codes.ok ],
        [ { 'line_num': 61, 'column_num': 20 },
          has_entry( 'message', equal_to(
              'unsigned long long long_function_name(unsigned long long first, '
              'unsigned long long second); // In namespace ns' ) ),
          requests.codes.ok ],
      ],
      [ 'GetType', 'GetTypeImprecise' ] ):
      with self.subTest( test = test, cmd = cmd ):
        RunGetSemanticTest( app,
                            PathToTestFile( 'GetType_Clang_test.cc' ),
                            'cpp',
                            test,
                            [ cmd ],
                            test[ 2 ] )

  @UnixOnly
  @IsolatedYcmd()
  def test_Subcommands_GetDoc( self, app ):
    for test, cmd in itertools.product( [
        # from local file
        [ { 'line_num': 5, 'column_num': 10 },
          has_entry( 'detailed_info', equal_to(
            'function docstring_int_main_TU_file\n\n→ void\ndocstring\n\n'
            'void docstring_int_main_TU_file()' ) ),
          requests.codes.ok ],
        # from header
        [ { 'line_num': 6, 'column_num': 10 },
          has_entry( 'detailed_info', equal_to(
            'function docstring_from_header_file\nprovided by "docstring.h"'
            '\n\n→ void\ndocstring\n\n'
            'void docstring_from_header_file()' ) ),
          requests.codes.ok ],
        # no docstring
        [ { 'line_num': 7, 'column_num': 7 },
          has_entry( 'detailed_info', equal_to(
            'variable x\n\nType: int\nValue = 3\n\n'
            '// In docstring_int_main_TU_file\nint x = 3' ) ),
          requests.codes.ok ],
        # no hover
        [ { 'line_num': 8, 'column_num': 1 },
          ErrorMatcher( RuntimeError, 'No documentation available.' ),
          requests.codes.server_error ]
      ],
      [ 'GetDoc', 'GetDocImprecise' ] ):
      with self.subTest( test = test, cmd = cmd ):
        RunGetSemanticTest( app,
                            PathToTestFile( 'GetDoc_Clang_test.cc' ),
                            'cpp',
                            test,
                            [ cmd ],
                            test[ 2 ] )

  @SharedYcmd
  def test_Subcommands_FixIt_all( self, app ):
    for line, column, language, filepath, check in [
      [ 16, 1,  'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_Ins ],
      [ 25, 14, 'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_InsMultiLine ],
      [ 35, 7,  'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_Del ],
      [ 40, 6,  'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_Repl ],
      [ 48, 3,  'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_DelAdd ],
      [ 5, 3,   'objective-c', PathToTestFile( 'objc', 'FixIt_Clang_objc.m' ),
        FixIt_Check_objc ],
      [ 7, 1,   'objective-c', PathToTestFile( 'objc', 'FixIt_Clang_objc.m' ),
        FixIt_Check_objc_NoFixIt ],
      [ 3, 12,  'cuda', PathToTestFile( 'cuda', 'fixit_test.cu' ),
        FixIt_Check_cuda ],
      # multiple errors on a single line; both with fixits. The cursor is on the
      # first one (so just that one is fixed)
      [ 54, 15, 'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_MultiFirst ],
      # should put closest fix-it first?
      [ 54, 51, 'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_MultiSecond ],
      # unicode in line for fixit
      [ 21, 16, 'cpp11', PathToTestFile( 'unicode.cc' ),
        FixIt_Check_unicode_Ins ],
      # FixIt attached to a "child" diagnostic (i.e. a Note)
      [ 60, 1,  'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_Note ],
      # FixIt due to forced spell checking
      [ 72, 9,  'cpp11', PathToTestFile( 'FixIt_Clang_cpp11.cpp' ),
        FixIt_Check_cpp11_SpellCheck ],
    ]:
      with self.subTest( line = line,
                         column = column,
                         language = language,
                         filepath = filepath,
                         check = check ):
        RunFixItTest( app, line, column, language, filepath, check )

  @WithRetry()
  @SharedYcmd
  def test_Subcommands_FixIt_Ranged( self, app ):
    for test in [
      [ {
          'start': { 'line_num': 80, 'column_num': 1 },
          'end': { 'line_num': 80, 'column_num': 4 },
        },
        FixIt_Check_AutoExpand_Resolved ],
      [ {
          'start': { 'line_num': 83, 'column_num': 3 },
          'end': { 'line_num': 83, 'column_num': 13 },
        },
        FixIt_Check_MacroExpand_Resolved ],
      [ {
          'start': { 'line_num': 84, 'column_num': 14 },
          'end': { 'line_num': 84, 'column_num': 20 },
        },
        FixIt_Check_SubexprExtract_Resolved ],
      [ {
          'start': { 'line_num': 80, 'column_num': 19 },
          'end': { 'line_num': 80, 'column_num': 35 },
        },
        FixIt_Check_RawStringReplace_Resolved ],
    ]:
      with self.subTest( test = test ):
        RunRangedFixItTest( app, test[ 0 ], test[ 1 ] )

  @WithRetry()
  @SharedYcmd
  def test_Subcommands_FixIt_AlreadyResolved( self, app ):
    filename = PathToTestFile( 'FixIt_Clang_cpp11.cpp' )
    request = {
      'completer_target' : 'filetype_default',
      'contents'         : ReadFile( filename ),
      'filepath'         : filename,
      'command_arguments': [ 'FixIt' ],
      'line_num'         : 16,
      'column_num'       : 1,
      'filetype'         : 'cpp'
    }
    app.post_json( '/event_notification',
                   CombineRequest( request, {
                     'event_name': 'FileReadyToParse',
                   } ),
                   expect_errors = True )
    WaitUntilCompleterServerReady( app, 'cpp' )
    expected = app.post_json( '/run_completer_command',
                              BuildRequest( **request ) ).json
    print( 'expected = ' )
    print( expected )
    request[ 'fixit' ] = expected[ 'fixits' ][ 0 ]
    actual = app.post_json( '/resolve_fixit',
                            BuildRequest( **request ) ).json
    print( 'actual = ' )
    print( actual )
    assert_that( actual, equal_to( expected ) )

  @WithRetry()
  @IsolatedYcmd( { 'clangd_args': [ '-hidden-features' ] } )
  def test_Subcommands_FixIt_ClangdTweaks( self, app ):
    selection = {
        'start': { 'line_num': 80, 'column_num': 19 },
        'end': { 'line_num': 80, 'column_num': 4 }
    }

    def NoFixitsProduced( results ):
      assert_that( results, has_entries( {
        'fixits': contains_exactly( has_entries( {
          'chunks': [],
          'location': LocationMatcher(
                        PathToTestFile( 'FixIt_Clang_cpp11.cpp' ), 1, 1 )
        } ) )
      } ) )
    RunRangedFixItTest( app, selection, NoFixitsProduced, 2 )

  @SharedYcmd
  def test_Subcommands_RefactorRename( self, app ):
    basic_cpp = PathToTestFile( 'basic.cpp' )
    gettype_clang_text_cc = PathToTestFile( 'GetType_Clang_test.cc' )
    goto_clang_zerobasedline = PathToTestFile(
        'GoTo_Clang_ZeroBasedLineAndColumn_test.cc' )
    test = {
      'request': {
        'filetype': 'cpp',
        'completer_target': 'filetype_default',
        'contents': ReadFile( basic_cpp ),
        'filepath': basic_cpp,
        'command_arguments': [ 'RefactorRename', 'Bar' ],
        'line_num': 17,
        'column_num': 4,
      },
      'expect': {
        'response': requests.codes.ok,
        'data': has_entries( {
          'fixits': contains_exactly( has_entries( {
            'chunks': contains_exactly(
              ChunkMatcher( 'Bar',
                            LocationMatcher( gettype_clang_text_cc, 12, 8 ),
                            LocationMatcher( gettype_clang_text_cc, 12, 11 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( gettype_clang_text_cc, 24, 3 ),
                            LocationMatcher( gettype_clang_text_cc, 24, 6 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( gettype_clang_text_cc, 39, 3 ),
                            LocationMatcher( gettype_clang_text_cc, 39, 6 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( gettype_clang_text_cc, 40, 3 ),
                            LocationMatcher( gettype_clang_text_cc, 40, 6 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( gettype_clang_text_cc, 42, 9 ),
                            LocationMatcher( gettype_clang_text_cc, 42, 12 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( gettype_clang_text_cc, 43, 9 ),
                            LocationMatcher( gettype_clang_text_cc, 43, 12 ) ),
              ChunkMatcher(
                'Bar',
                LocationMatcher( goto_clang_zerobasedline, 2, 8 ),
                LocationMatcher( goto_clang_zerobasedline, 2, 11 ) ),
              ChunkMatcher(
                'Bar',
                LocationMatcher( goto_clang_zerobasedline, 10, 3 ),
                LocationMatcher( goto_clang_zerobasedline, 10, 6 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( basic_cpp, 1, 8 ),
                            LocationMatcher( basic_cpp, 1, 11 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( basic_cpp, 9, 3 ),
                            LocationMatcher( basic_cpp, 9, 6 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( basic_cpp, 15,  8 ),
                            LocationMatcher( basic_cpp, 15, 11 ) ),
              ChunkMatcher( 'Bar',
                            LocationMatcher( basic_cpp, 17, 3 ),
                            LocationMatcher( basic_cpp, 17, 6 ) ),
            )
          } ) )
        } )
      },
      'route': '/run_completer_command'
    }
    RunAfterInitialized( app, test )


from bs4 import BeautifulSoup

from .provider import Property, Provider

class Zonaprop(Provider):
    name: str = 'zonaprop'

    async def props_from_source(self, source: str):
        page_link = self.config['base_url'] + source
        page = 1
        processed_ids = []

        while True:
            page_content = BeautifulSoup(await self.request(page_link), 'lxml')
            properties = page_content.find_all('div', class_='postingCard')

            if not properties:
                return

            for prop in properties:
                # if data-id was already processed we exit
                if prop['data-id'] in processed_ids:
                    return
                processed_ids.append(prop['data-id'])
                title = prop.find('a', class_='go-to-posting').get_text().strip()
                price_section = prop.find('span', class_='firstPrice')
                if price_section is not None:
                    title = title + ' ' + price_section['data-price']

                yield Property(title=title,
                               url=self.config['base_url'] + prop['data-to-posting'],
                               internal_id=prop['data-id'],
                               provider=self.name)

            page += 1
            page_link = self.config['base_url'] + source.replace('.html', f'-pagina-{page}.html')


from typing import *
from tkinter import Tk
import pyperclip

def addToClipBoard(text: str):
    """Function to replace a clipboard.

    Args:
        text (str): Text to be copied.
    """

    pyperclip.copy(text)

def num_states(number: int, start: int = 0, character: str = "s") -> List[str]:
    """This function creates a list of strings to act as states for FSMs.

    Args:
        number (int): Number of states to be created.
        start (int): Start number to be used. Defaults to 0.
        character (str, optional): Character to be used. Defaults to "s".

    Returns:
        List[str]: A list of state strings.
    """

    # Create result list and initialize starting number.
    result = []
    num = start

    # Iterate through the range specified by the number parameter.
    for _ in range(number):

        # Add a new state to the list
        result.append(f"{character}{num}")

        # Increment the number of states
        num += 1

    return result

def fsm_template(states: List[str], arrows: List[str], character: str = "s", starting: str = "s0") -> None:
    """This function creates a template for creating and minimizing FSMs.

    Args:
        states (List[str]): List of states to be included.
        arrows (List[str]): List of possible arrows per state.
        character (str, optional): Character to be used in the "=>" operation. Defaults to "s".
    """

    # Initialize the final string
    final_str = "fsm:\n"

    # Iterate through the states provided.
    for element in states:

        # Iterate through the possible arrow descriptions.
        for arrow in arrows:

            # Add a state change to the string.
            final_str += f"({element}, {arrow}) => {character};\n"

    # Finalize the string by declarations.
    final_str += f"""--declarations--
e=#n#;
animate=this;
simulateToStep=-1;
input=null;
s0={starting};
F=;
displayMode=1;
showMinimizedFSM=true;
--declarations-end--"""

    return final_str

def pda_template(states: List[str], entry_alphabet: List[str], stack_alphabet: List[str], starting: str = "s0", protected_stack_character: str = "k", character: str = "s"):
    """Function to create a PDA template for the Xwizard.

    Args:
        states (List[str]): List of states to be used for the Xwizard
        entry_alphabet (List[str]): Entry Alphabet
        stack_alphabet (List[str]): Stack Alphabet
        starting (str, optional): Starting state. Defaults to "s0".
        protected_stack_character (str, optional): Stack Character k0. Defaults to "k".
        character (str, optional): State character for the transitions. Defaults to "s".
    """

    if not "lambda" in entry_alphabet:
        entry_alphabet.append("lambda")

    if not protected_stack_character in stack_alphabet:
        stack_alphabet.append(protected_stack_character)

    # Initialize the final string
    final_str = "pda:\n"

    # Iterate through the states provided.
    for state in states:

        # Iterate through the possible entry characters.
        for entry_character in entry_alphabet:

            # Iterate Through the possible stack characters
            for stack_character in stack_alphabet:

                # Add a state change to the string.
                final_str += f"({state}, {entry_character}, {stack_character}) => ({character}, );\n"

    # Finalize the string by declarations.
    final_str += f"""--declarations--
e=#n#;
s0={starting};
F=;
kSymb={protected_stack_character};
inputs=null;
simSteps=0
--declarations-end--
"""

    return final_str


#%%
import os
from kaggle.api.kaggle_api_extended import KaggleApi
#%%
def extract_data():
    try:
        api = KaggleApi()
        api.authenticate()

        api.dataset_download_files(dataset='katehighnam/beth-dataset', path='./data', unzip=True)
        val = os.listdir('./data')
    except Exception as e:
        val = str(e)
    return val


#!/usr/bin/env python

import sys
import math
import numpy as np
from matplotlib import pyplot as plt
from csaps import ISmoothingSpline, csaps
from data.flatterise import SERIE_SIZE
from load_serie import load_serie

def build_box_plot(series: list[float]) -> dict:
    # медиана
    median = np.median(series)
    # первый квартиль
    q1 = np.percentile(series, 25)
    # третий квартиль
    q3 = np.percentile(series, 75)

    # межквартильный размах
    iqr = q3 - q1

    # нижняя граница
    lower_bound = q1 - 1.5 * iqr
    # верхняя граница
    upper_bound = q3 + 1.5 * iqr

    return {
        'median': median,
        'q1': q1,
        'q3': q3,
        'lower_bound': lower_bound,
        'upper_bound': upper_bound
    }

def denoize_serie(data, smooth):
    dns, sm = create_denoized_spline(data, smooth)

    smooth_serie = [sm.Y(i) for i in range(len(data) - 1)]
    filtred_serie = [dns.Y(i) for i in range(len(data) - 2)]

    return smooth_serie, filtred_serie

def aproximete_spline(data: list[float], smooth: float) -> ISmoothingSpline:
    x = np.linspace(0, len(data) - 1, num=len(data))
    return csaps(x, data, smooth=smooth)

def create_denoized_spline(data: list[float], smooth: float) -> (ISmoothingSpline, ISmoothingSpline):
    sm = aproximete_spline(data, smooth)

    smooth_serie = np.array([])
    for i in range(len(data)):
        y = sm(i)
        smooth_serie = np.append(smooth_serie, y)

    diffs = np.subtract(smooth_serie, data)

    bx = build_box_plot(diffs)
    lower_bound, upper_bound = (bx['lower_bound'], bx['upper_bound'])

    weigths = [1.0] * len(data)
    for index in filter(lambda i: diffs[i] < lower_bound or diffs[i] > upper_bound, range(len(diffs))):
        weigths[index] = 0.01

    x = np.linspace(0, len(data) - 1, len(data))
    dns = csaps(x, data, weights=weigths, smooth=smooth)

    return dns, sm

def main():
    file: str = sys.argv[1]
    smooth: float = float(sys.argv[2])
    number: int = int(sys.argv[3])

    serie = load_serie(file, number, SERIE_SIZE)

    smooth_serie, filtred_serie = denoize_serie(serie, smooth)

    # plot
    plt.plot(serie, marker='o', linestyle='None')
    plt.plot(smooth_serie, color='red')
    plt.plot(filtred_serie, color='green')

    plt.show()

if __name__ == "__main__":
    main()


#!/usr/bin/env python
# coding: utf-8

# In[47]:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import model_selection
np.random.seed(3)

# In[48]:

dt=pd.read_csv("dataset.csv")

# In[49]:

X=dt.drop(["diagnosis"],axis=1)
Y=dt["diagnosis"]

# In[50]:

M=X.mean()
M=np.array(M).reshape((1,5))
SD=np.std(X)
Y.shape

# In[51]:

SD=np.array(SD).reshape(1,5)

# In[52]:

X=np.array(X)
X=np.divide(X-M,SD)
X=X.T
Y=np.array(Y).reshape((1,569))

# In[53]:

layers=[5,12,7,5,1]
L=len(layers)
S=L-1
m=Y.shape[1]

# In[54]:

parameters={}
for l in range (1,L):
    parameters["W"+str(l)]=2*np.random.randn(layers[l],layers[l-1])-1
    parameters["b"+str(l)]=np.zeros((layers[l],1))

# In[55]:

Zi={}
Ai={}
At=X
Ai["A"+str(0)]=X

# In[56]:

dW={}
db={}

# In[57]:

learning_rate=0.5
costs=[]
t=10000
for i in range(0,t):

    #forward prop
    for j in range(1,S):
        Z=np.dot(parameters["W"+str(j)],At)+parameters["b"+str(j)]
        Ai["A"+str(j)]=np.tanh(Z)
        At=Ai["A"+str(j)]
    Z=np.dot(parameters["W"+str(S)],At)+parameters["b"+str(S)]
    AL=1/(1+np.exp(-Z))

    #cost calculation
    loss=np.multiply(np.log(AL),Y)+np.multiply(np.log(1-AL),(1-Y))
    cost=-np.sum(loss)/m
    cost=float(np.squeeze(cost))

    #back prop
    dAL=-(np.divide(Y, AL)-np.divide(1-Y,1-AL))
    dZ=np.multiply(dAL,AL*(1-AL))
    dW["dW"+str(S)]=np.dot(dZ,Ai["A"+str(S-1)].T)/m
    db["db"+str(S)]=np.sum(dZ,axis=1,keepdims=True)/m
    dA_prev = np.dot(parameters["W"+str(S)].T,dZ)

    for l in reversed(range(1,S)):
        dZ=np.multiply(dA_prev,1-np.power(Ai["A"+str(l)],2))
        dW["dW"+str(l)]=np.dot(dZ,Ai["A"+str(l-1)].T)/m
        db["db"+str(l)]=np.sum(dZ,axis=1,keepdims=True)/m
        dA_prev = np.dot(parameters["W"+str(l)].T,dZ)

    for k in range(1,L):
        parameters["W" + str(k)] = parameters["W" + str(k)]- learning_rate*dW["dW"+str(k)]
        parameters["b" + str(k)] = parameters["b" + str(k)]- learning_rate*db["db"+str(k)]
    costs.append(cost)
    if i % 1000 == 0:
            print ("Cost after iteration %i: %f" %(i, cost))
print ("dW1 = "+ str(dW["dW1"]))
print ("db1 = "+ str(db["db1"]))
print ("dW2 = "+ str(dW["dW2"]))
print ("db2 = "+ str(db["db2"]))

# In[58]:

x = np.linspace(0, t, t)
y=costs
plt.plot(x,y,'r')

# In[59]:

At=X
for j in range(1,S):
    Zi["Z"+str(j)]=np.dot(parameters["W"+str(j)],At)+parameters["b"+str(j)]
    Ai["A"+str(j)]=np.tanh(Zi["Z"+str(j)])
    At=Ai["A"+str(j)]
Zi["Z"+str(S)]=np.dot(parameters["W"+str(S)],At)+parameters["b"+str(S)]
AL=1/(1+np.exp(-Zi["Z"+str(S)]))
predictions=(AL>0.5)

# In[60]:

print ('Accuracy: %d' % float((np.dot(Y,predictions.T) + np.dot(1-Y,1-predictions.T))/float(Y.size)*100) + '%')

# In[ ]:


import sys
sys.path.append("../")

from datasets import load_dataset,  load_metric
from datasets import DatasetDict, set_caching_enabled
from pprint import pprint

from transformers import BertTokenizerFast, BertModel, DataCollatorWithPadding
from torch import nn
from torch.utils.data import DataLoader
import torch
from tqdm import tqdm

##使用 datasets写一个demo
##关闭cache
set_caching_enabled(False)

def process_data(ds: DatasetDict, tokenizer: BertTokenizerFast, max_len=256)-> DatasetDict:
    ## 分词
    ds = ds.map(lambda x: tokenizer(x['text'], max_length=max_len), batched=True,
                remove_columns=['text'])
    ds.set_format(type='torch', columns=ds.column_names)
    return ds

class ImdbModel(nn.Module):
    def __init__(self):
        super(ImdbModel, self).__init__()
        self.bert = BertModel.from_pretrained("bert-base-uncased")
        self.classifier = nn.Sequential(
            nn.Linear(768, 200),
            nn.ReLU(),
            nn.Linear(200, 2)
        )

    def forward(self, input_ids, token_type_ids, attention_mask):
        bert_cls = self.bert(input_ids, token_type_ids, attention_mask)[0][:, 0]
        logit = self.classifier(bert_cls)
        return logit

def trainer(opt, loss_fn, train_dl, val_dl, epoch, model, metric, device):
    model = model.to(device)
    for ep in range(epoch):
        total_loss, total_acc, num = 0, 0, 0
        for batch in tqdm(train_dl, desc='train epoch'):
            opt.zero_grad()
            y_true = batch['labels'].to(device)
            inp = {
                'input_ids': batch['input_ids'].to(device),
                'token_type_ids': batch['token_type_ids'].to(device),
                'attention_mask': batch['attention_mask'].to(device)
            }
            y_pred = model(**inp)
            loss = loss_fn(y_pred, y_true)

            total_acc += metric.compute(references=y_true.cpu().numpy(), predictions=y_pred.cpu().argmax(dim=-1).numpy())['accuracy']
            total_loss += loss.item()
            num += 1
            loss.backward()
            opt.step()
        total_acc /= num
        total_loss /= num
        model.eval()
        val_loss, val_acc, val_num = 0, 0, 0
        for batch in tqdm(val_dl, desc='val epoch'):
            opt.zero_grad()
            y_true = batch['label']
            inp = {
                'input_ids': batch['input_ids'],
                'token_type_ids': batch['token_type_ids'],
                'attention_mask': batch['attention_mask']
            }
            y_pred = model(**inp)
            val_loss += loss_fn(y_pred, y_true).item()
            total_acc += metric.compute(references=y_true.numpy(), predictions=y_pred.argmax(dim=-1).numpy())['accuracy']
            val_num += 1
        val_loss /= val_num
        val_acc /= val_num
        pprint("epoch: {}, loss: {}, acc: {} val_loss: {} val_acc: {}".format(ep, total_loss, total_acc, val_loss, val_acc))

def run():
    imdb_train = load_dataset('imdb', split='train').shuffle(seed=123)
    imdb_test = load_dataset('imdb', split='test').shuffle(seed=321)
    imdb_split = imdb_train.train_test_split(test_size=0.2, seed=123)
    imdb_train = imdb_split['train']
    imdb_val = imdb_split['test']

    device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')

    # tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
    tokenizer = BertTokenizerFast.from_pretrained('bert-base-uncased')

    imdb_train = process_data(ds=imdb_train, tokenizer=tokenizer).rename_column('label', 'labels')
    imdb_val = process_data(ds=imdb_val, tokenizer=tokenizer).rename_column('label', 'labels')
    imdb_test = process_data(ds=imdb_test, tokenizer=tokenizer).rename_column('label', 'labels')

    data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
    train_dl = DataLoader(imdb_train, batch_size=16, collate_fn=data_collator)
    val_dl = DataLoader(imdb_val, batch_size=16, collate_fn=data_collator)
    test_dl = DataLoader(imdb_test, batch_size=16, collate_fn=data_collator)

    model = ImdbModel()

    opt = torch.optim.AdamW(model.parameters(), lr=0.01)
    loss = nn.CrossEntropyLoss()
    metric = load_metric('accuracy')
    trainer(opt, loss_fn=loss, train_dl=train_dl, val_dl=val_dl, epoch=10, model=model, metric=metric, device=device)


from flask import Blueprint,render_template,flash,redirect,url_for,request
from flask_login import current_user,login_required
from .models import Notes
from . import db
view = Blueprint("view", __name__)

@view.route("/",methods=["GET","POST"])
@login_required
def home():
    if request.method == "POST":
        notes = request.form.get("note")
        if len(notes) <1:
            flash("Note must be a character", category="success")
        else:
            user = Notes(data = notes, user_id = current_user.id)
            db.session.add(user)
            db.session.commit()
            flash("Note successfully added!!", category= "success")
    return render_template("notes.html",user = current_user)

@view.route("/delete/<int:id>")
def delete(id):
    v = Notes.query.get(id)
    db.session.delete(v)
    db.session.commit()
    flash("Note successfuly deleted!!",category="success")
    return redirect(url_for("view.home"))

@view.route("/update/<int:id>", methods=["GET","POST"])
def Update(id):
    v = Notes.query.filter_by(id=id).first()
    if request.method == "POST":
        data=request.form.get("note")

        v.data=data
        db.session.add(v)
        db.session.commit()
        flash("Note updated",category="success")
        return redirect(url_for("view.home"))

    return render_template("update.html", v=v, user= current_user,)


#coding=utf-8

class Solution(object):
    def multiply(self, num1, num2):
        """
        :type num1: str
        :type num2: str
        :rtype: str
        """
        result = "0"
        if num1 == "0" or num2 == "0":
            return result

        # 获得num1和num2的数字表示
        num1 = self.string2num(num1)
        num2 = self.string2num(num2)
        multiply = num1 * num2

        result = self.num2string(multiply)
        return result

    def string2num(self, string):
        # 字符变为数字
        num = 0
        for char in string:
            num = num * 10 + ord(char) - ord("0")
        return num

    def num2string(self, num):
        # 数字变为字符
        string = ""
        while num != 0:
            char = chr(num % 10 + ord("0"))
            string = char + string
            num //= 10
        return string

if __name__ == '__main__':
    num1 = "0"
    num2 = "456"
    result = Solution().multiply(num1, num2)
    print(result)
    print(0*456)


import sys
import threading
import time
from PyQT_frame import AnalyzerUI
from CV_video import Video
from PyQt5 import QtWidgets

app = QtWidgets.QApplication(sys.argv)
ex = AnalyzerUI()
v = Video()

def run():
    t = 0
    while t < 2000:
        ex.video_label.setPixmap(v.updateFrame())
        ex.text_label.setText(v.text)
        time.sleep(0.01)
        t += 1

    v.close()

ex.capture_btn.clicked.connect(v.saveImg)
ex.analysis_btn.clicked.connect(v.analysis)
th = threading.Thread(target=run)
th.start()

sys.exit(app.exec_())