from __future__ import division

import warnings

import numpy as np
from scipy import linalg
from sklearn.covariance import empirical_covariance, log_likelihood
from sklearn.utils.extmath import squared_norm
from sklearn.utils.validation import check_X_y

from regain.covariance.graphical_lasso_ import GraphicalLasso, init_precision
from regain.math import batch_logdet
from regain.norm import l1_od_norm
from regain.prox import prox_logdet, soft_thresholding
from regain.update_rules import update_rho
from regain.utils import Convergence, error_norm_time
from regain.validation import check_norm_prox

def batch_log_likelihood(emp_cov, precision):
    """Gaussian log-likelihood without constant term."""
    return batch_logdet(precision) - np.sum(emp_cov * precision, axis=(-1, -2))

def loss(emp_cov, precision, n_samples: np.ndarray = None) -> float:
    """Loss function for time-varying graphical lasso."""
    if n_samples is None:
        # 1 sample for each batch, ie, do not scale.
        batch_dim = emp_cov.shape[0]
        n_samples = np.ones(batch_dim)

    return np.sum(-n_samples * batch_log_likelihood(emp_cov, precision))

def objective(n_samples, emp_cov, K, Z_0, Z_1, Z_2, alpha, beta, psi) -> float:
    """Objective function for time-varying graphical lasso."""
    obj: float = loss(emp_cov, K, n_samples=n_samples)

    if isinstance(alpha, np.ndarray):
        obj += np.sum(l1_od_norm(alpha * Z_0))
    else:
        obj += alpha * np.sum(l1_od_norm(Z_0))

    if isinstance(beta, np.ndarray):
        obj += sum(b[0][0] * m for b, m in zip(beta, map(psi, Z_2 - Z_1)))
    else:
        obj += beta * sum(map(psi, Z_2 - Z_1))

    return obj

def time_graphical_lasso(
    emp_cov,
    alpha=0.01,
    rho=1,
    beta=1,
    max_iter=100,
    n_samples=None,
    verbose=False,
    psi="laplacian",
    tol=1e-4,
    rtol=1e-4,
    return_history=False,
    return_n_iter=True,
    mode="admm",
    compute_objective=True,
    stop_at=None,
    stop_when=1e-4,
    update_rho_options=None,
    init="empirical",
):
    """Time-varying graphical lasso solver.

    Solves the following problem via ADMM:
        min sum_{i=1}^T -n_i log_likelihood(S_i, K_i) + alpha*||K_i||_{od,1}
            + beta sum_{i=2}^T Psi(K_i - K_{i-1})

    where S_i = (1/n_i) X_i^T \times X_i is the empirical covariance of data
    matrix X (training observations by features).

    Parameters
    ----------
    emp_cov : ndarray, shape (n_features, n_features)
        Empirical covariance of data.
    alpha, beta : float, optional
        Regularisation parameter.
    rho : float, optional
        Augmented Lagrangian parameter.
    max_iter : int, optional
        Maximum number of iterations.
    n_samples : ndarray
        Number of samples available for each time point.
    tol : float, optional
        Absolute tolerance for convergence.
    rtol : float, optional
        Relative tolerance for convergence.
    return_history : bool, optional
        Return the history of computed values.
    return_n_iter : bool, optional
        Return the number of iteration before convergence.
    verbose : bool, default False
        Print info at each iteration.
    update_rho_options : dict, optional
        Arguments for the rho update.
        See regain.update_rules.update_rho function for more information.
    compute_objective : bool, default True
        Choose to compute the objective value.
    init : {'empirical', 'zero', ndarray}
        Choose how to initialize the precision matrix, with the inverse
        empirical covariance, zero matrix or precomputed.

    Returns
    -------
    K : numpy.array, 3-dimensional (T x d x d)
        Solution to the problem for each time t=1...T .
    history : list
        If return_history, then also a structure that contains the
        objective value, the primal and dual residual norms, and tolerances
        for the primal and dual residual norms at each iteration.

    """
    psi, prox_psi, psi_node_penalty = check_norm_prox(psi)

    Z_0 = init_precision(emp_cov, mode=init)
    Z_1 = Z_0.copy()[:-1]  # np.zeros_like(emp_cov)[:-1]
    Z_2 = Z_0.copy()[1:]  # np.zeros_like(emp_cov)[1:]

    U_0 = np.zeros_like(Z_0)
    U_1 = np.zeros_like(Z_1)
    U_2 = np.zeros_like(Z_2)

    Z_0_old = np.zeros_like(Z_0)
    Z_1_old = np.zeros_like(Z_1)
    Z_2_old = np.zeros_like(Z_2)

    # divisor for consensus variables, accounting for two less matrices
    divisor = np.full(emp_cov.shape[0], 3, dtype=float)
    divisor[0] -= 1
    divisor[-1] -= 1

    if n_samples is None:
        n_samples = np.ones(emp_cov.shape[0])

    checks = [
        Convergence(
            obj=objective(n_samples, emp_cov, Z_0, Z_0, Z_1, Z_2, alpha, beta, psi)
        )
    ]
    for iteration_ in range(max_iter):
        # update K
        A = Z_0 - U_0
        A[:-1] += Z_1 - U_1
        A[1:] += Z_2 - U_2
        A /= divisor[:, None, None]
        # soft_thresholding_ = partial(soft_thresholding, lamda=alpha / rho)
        # K = np.array(map(soft_thresholding_, A))
        A += A.transpose(0, 2, 1)
        A /= 2.0

        A *= -rho * divisor[:, None, None] / n_samples[:, None, None]
        A += emp_cov

        lamda = np.expand_dims(n_samples / (rho * divisor), -1)
        K = prox_logdet(A, lamda)

        # update Z_0
        A = K + U_0
        A += A.transpose(0, 2, 1)
        A /= 2.0
        Z_0 = soft_thresholding(A, lamda=alpha / rho)

        # other Zs
        A_1 = K[:-1] + U_1
        A_2 = K[1:] + U_2
        if not psi_node_penalty:
            prox_e = prox_psi(A_2 - A_1, lamda=2.0 * beta / rho)
            Z_1 = 0.5 * (A_1 + A_2 - prox_e)
            Z_2 = 0.5 * (A_1 + A_2 + prox_e)
        else:
            Z_1, Z_2 = prox_psi(
                np.concatenate((A_1, A_2), axis=1),
                lamda=0.5 * beta / rho,
                rho=rho,
                tol=tol,
                rtol=rtol,
                max_iter=max_iter,
            )

        # update residuals
        U_0 += K - Z_0
        U_1 += K[:-1] - Z_1
        U_2 += K[1:] - Z_2

        # diagnostics, reporting, termination checks
        rnorm = np.sqrt(
            squared_norm(K - Z_0)
            + squared_norm(K[:-1] - Z_1)
            + squared_norm(K[1:] - Z_2)
        )

        snorm = rho * np.sqrt(
            squared_norm(Z_0 - Z_0_old)
            + squared_norm(Z_1 - Z_1_old)
            + squared_norm(Z_2 - Z_2_old)
        )

        obj = (
            objective(n_samples, emp_cov, Z_0, K, Z_1, Z_2, alpha, beta, psi)
            if compute_objective
            else np.nan
        )

        # if np.isinf(obj):
        #     Z_0 = Z_0_old
        #     break

        check = Convergence(
            obj=obj,
            rnorm=rnorm,
            snorm=snorm,
            e_pri=np.sqrt(K.size + 2 * Z_1.size) * tol
            + rtol
            * max(
                np.sqrt(squared_norm(Z_0) + squared_norm(Z_1) + squared_norm(Z_2)),
                np.sqrt(squared_norm(K) + squared_norm(K[:-1]) + squared_norm(K[1:])),
            ),
            e_dual=np.sqrt(K.size + 2 * Z_1.size) * tol
            + rtol
            * rho
            * np.sqrt(squared_norm(U_0) + squared_norm(U_1) + squared_norm(U_2)),
            # precision=Z_0.copy()
        )
        Z_0_old = Z_0.copy()
        Z_1_old = Z_1.copy()
        Z_2_old = Z_2.copy()

        if verbose:
            print(check)

        checks.append(check)
        if stop_at is not None:
            if abs(check.obj - stop_at) / abs(stop_at) < stop_when:
                break

        if check.rnorm <= check.e_pri and check.snorm <= check.e_dual:
            break

        rho_new = update_rho(
            rho, rnorm, snorm, iteration=iteration_, **(update_rho_options or {})
        )
        # scaled dual variables should be also rescaled
        U_0 *= rho / rho_new
        U_1 *= rho / rho_new
        U_2 *= rho / rho_new
        rho = rho_new

        # assert is_pos_def(Z_0)
    else:
        warnings.warn("Objective did not converge.")

    covariance_ = np.array([linalg.pinvh(x) for x in Z_0])
    return_list = [Z_0, covariance_]
    if return_history:
        return_list.append(checks)
    if return_n_iter:
        return_list.append(iteration_ + 1)
    return return_list

class TimeGraphicalLasso(GraphicalLasso):
    """Sparse inverse covariance estimation with an l1-penalized estimator.

    Parameters
    ----------
    alpha : positive float, default 0.01
        Regularization parameter for precision matrix. The higher alpha,
        the more regularization, the sparser the inverse covariance.

    beta : positive float, default 1
        Regularization parameter to constrain precision matrices in time.
        The higher beta, the more regularization,
        and consecutive precision matrices in time are more similar.

    psi : {'laplacian', 'l1', 'l2', 'linf', 'node'}, default 'laplacian'
        Type of norm to enforce for consecutive precision matrices in time.

    rho : positive float, default 1
        Augmented Lagrangian parameter.

    over_relax : positive float, deafult 1
        Over-relaxation parameter (typically between 1.0 and 1.8).

    tol : positive float, default 1e-4
        Absolute tolerance to declare convergence.

    rtol : positive float, default 1e-4
        Relative tolerance to declare convergence.

    max_iter : integer, default 100
        The maximum number of iterations.

    verbose : boolean, default False
        If verbose is True, the objective function, rnorm and snorm are
        printed at each iteration.

    assume_centered : boolean, default False
        If True, data are not centered before computation.
        Useful when working with data whose mean is almost, but not exactly
        zero.
        If False, data are centered before computation.

    time_on_axis : {'first', 'last'}, default 'first'
        If data have time as the last dimension, set this to 'last'.
        Useful to use scikit-learn functions as train_test_split.

    update_rho_options : dict, default None
        Options for the update of rho. See `update_rho` function for details.

    compute_objective : boolean, default True
        Choose if compute the objective function during iterations
        (only useful if `verbose=True`).

    init : {'empirical', 'zeros', ndarray}, default 'empirical'
        How to initialise the inverse covariance matrix. Default is take
        the empirical covariance and inverting it.

    Attributes
    ----------
    covariance_ : array-like, shape (n_times, n_features, n_features)
        Estimated covariance matrix

    precision_ : array-like, shape (n_times, n_features, n_features)
        Estimated precision matrix.

    n_iter_ : int
        Number of iterations run.

    """

    def __init__(
        self,
        alpha=0.01,
        beta=1.0,
        mode="admm",
        rho=1.0,
        tol=1e-4,
        rtol=1e-4,
        psi="laplacian",
        max_iter=100,
        verbose=False,
        assume_centered=False,
        return_history=False,
        update_rho_options=None,
        compute_objective=True,
        stop_at=None,
        stop_when=1e-4,
        suppress_warn_list=False,
        init="empirical",
    ):
        super(TimeGraphicalLasso, self).__init__(
            alpha=alpha,
            rho=rho,
            tol=tol,
            rtol=rtol,
            max_iter=max_iter,
            verbose=verbose,
            assume_centered=assume_centered,
            mode=mode,
            update_rho_options=update_rho_options,
            compute_objective=compute_objective,
            init=init,
        )
        self.beta = beta
        self.psi = psi
        self.return_history = return_history
        self.stop_at = stop_at
        self.stop_when = stop_when
        self.suppress_warn_list = suppress_warn_list

    def get_observed_precision(self):
        """Getter for the observed precision matrix.

        Returns
        -------
        precision_ : array-like,
            The precision matrix associated to the current covariance object.

        """
        return self.get_precision()

    def _fit(self, emp_cov, n_samples):
        """Fit the TimeGraphicalLasso model to X.

        Parameters
        ----------
        emp_cov : ndarray, shape (n_time, n_features, n_features)
            Empirical covariance of data.

        """

        out = time_graphical_lasso(
            emp_cov,
            alpha=self.alpha,
            rho=self.rho,
            beta=self.beta,
            mode=self.mode,
            n_samples=n_samples,
            tol=self.tol,
            rtol=self.rtol,
            psi=self.psi,
            max_iter=self.max_iter,
            verbose=self.verbose,
            return_n_iter=True,
            return_history=self.return_history,
            update_rho_options=self.update_rho_options,
            compute_objective=self.compute_objective,
            stop_at=self.stop_at,
            stop_when=self.stop_when,
            init=self.init,
        )
        if self.return_history:
            self.precision_, self.covariance_, self.history_, self.n_iter_ = out
        else:
            self.precision_, self.covariance_, self.n_iter_ = out
        return self

    def fit(self, X, y):
        """Fit the TimeGraphicalLasso model to X.

        Parameters
        ----------
        X : ndarray, shape = (n_samples * n_times, n_dimensions)
            Data matrix.
        y : ndarray, shape = (n_times,)
            Indicate the temporal belonging of each sample.

        """
        # Covariance does not make sense for a single feature
        X, y = check_X_y(
            X,
            y,
            accept_sparse=False,
            dtype=np.float64,
            order="C",
            ensure_min_features=2,
            estimator=self,
        )

        n_dimensions = X.shape[1]
        self.classes_, n_samples = np.unique(y, return_counts=True)
        n_times = self.classes_.size

        # n_samples = np.array([x.shape[0] for x in X])
        if self.assume_centered:
            self.location_ = np.zeros((n_times, n_dimensions))
        else:
            self.location_ = np.array([X[y == cl].mean(0) for cl in self.classes_])

        emp_cov = np.array(
            [
                empirical_covariance(X[y == cl], assume_centered=self.assume_centered)
                for cl in self.classes_
            ]
        )

        return self._fit(emp_cov, n_samples)

    def score(self, X, y):
        """Computes the log-likelihood of a Gaussian data set with
        `self.covariance_` as an estimator of its covariance matrix.

        Parameters
        ----------
        X : array-like, shape = (n_samples, n_features)
            Test data of which we compute the likelihood, where n_samples is
            the number of samples and n_features is the number of features.
            X is assumed to be drawn from the same distribution than
            the data used in fit (including centering).

        y :  array-like, shape = (n_samples,)
            Class of samples.

        Returns
        -------
        res : float
            The likelihood of the data set with `self.covariance_` as an
            estimator of its covariance matrix.

        """
        # Covariance does not make sense for a single feature
        X, y = check_X_y(
            X,
            y,
            accept_sparse=False,
            dtype=np.float64,
            order="C",
            ensure_min_features=2,
            estimator=self,
        )

        # compute empirical covariance of the test set
        test_cov = np.array(
            [
                empirical_covariance(
                    X[y == cl] - self.location_[i], assume_centered=True
                )
                for i, cl in enumerate(self.classes_)
            ]
        )

        res = sum(
            X[y == cl].shape[0] * log_likelihood(S, K)
            for S, K, cl in zip(test_cov, self.get_observed_precision(), self.classes_)
        )

        return res

    def error_norm(self, comp_cov, norm="frobenius", scaling=True, squared=True):
        """Compute the Mean Squared Error between two covariance estimators.
        (In the sense of the Frobenius norm).

        Parameters
        ----------
        comp_cov : array-like, shape = [n_features, n_features]
            The covariance to compare with.

        norm : str
            The type of norm used to compute the error. Available error types:
            - 'frobenius' (default): sqrt(tr(A^t.A))
            - 'spectral': sqrt(max(eigenvalues(A^t.A))
            where A is the error ``(comp_cov - self.covariance_)``.

        scaling : bool
            If True (default), the squared error norm is divided by n_features.
            If False, the squared error norm is not rescaled.

        squared : bool
            Whether to compute the squared error norm or the error norm.
            If True (default), the squared error norm is returned.
            If False, the error norm is returned.

        Returns
        -------
        The Mean Squared Error (in the sense of the Frobenius norm) between
        `self` and `comp_cov` covariance estimators.

        """
        return error_norm_time(
            self.covariance_, comp_cov, norm=norm, scaling=scaling, squared=squared
        )


from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime
import pushFCMNotification

def schedule_func():
    num = 1
    print(num)
    num += 1

    print(datetime.today())
    tokens = [pushFCMNotification.token_ella, pushFCMNotification.token_alpha]
    # for tok in tokens:
    #     pushFCMNotification.send_to_firebase_cloud_messaging(tok)
    pushFCMNotification.send_to_firebase_cloud_group_messaging(tokens)

if __name__ == "__main__":
    pushFCMNotification.init_app()

    scheduler = BlockingScheduler(timezone='Asia/Seoul', job_defaults={'max_instances': 1})
    scheduler.add_job(schedule_func, 'interval', minutes=1)

    # starting now
    for j in scheduler.get_jobs():
        j.modify(next_run_time=datetime.now())

    scheduler.start()


import cv2
import numpy as np
import os

def verticalflip(img):
    origin = img.copy()
    verticalflip_img = cv2.flip(origin, 0)
    return verticalflip_img

def horizontalflip(img):
    origin = img.copy()
    horizontalflip_img = cv2.flip(origin, 1)
    return horizontalflip_img

def bothflip(img):
    origin = img.copy()
    bothflip_img = cv2.flip(origin, -1)
    return bothflip_img

def all_image_augmentation():
    image_list = [img for img in os.listdir('./eval')]
    image_list = sorted(image_list)
    print(image_list)
    for i in image_list:
        path = f'./eval/{i}'
        print(path)
        img = cv2.imread(path)
        verticalflip_img = verticalflip(img)
        horizontalflip_img = horizontalflip(img)
        bothflip_img = bothflip(img)
        cv2.imwrite(path[:20]+'-01.png', verticalflip_img)
        cv2.imwrite(path[:20]+'-02.png', horizontalflip_img)
        cv2.imwrite(path[:20]+'-03.png', bothflip_img)

if __name__ == '__main__':
    all_image_augmentation()


from setuptools import setup, find_packages

with open('requirements.txt', 'r') as f:
    requires = f.read().splitlines()

with open('README.md', 'r') as f:
    readme = f.read()

setup(name='hdmi-cec-to-adb',
      version='0.2',
      author='Paul Pavlish',
      author_email='hello@paulpavlish.com',
      url='https://github.com/paulsaccount/hdmi_cec_to_adb',
      description='hdmi_cec_to_adb',
      packages=find_packages(exclude=['*tests*']),
      long_description=readme,
      long_description_content_type='text/markdown',
      install_requires=requires,
      entry_points={
          'console_scripts': [
              'start_hdmi_cec_monitor = hdmi_cec_to_adb.bin.start_hdmi_cec_monitor:main',
          ],
      },
      )


from textwrap import dedent

from pyidenticounter import IdentifierType, PyIdentifierCounter

def test_variable_names():
    code = dedent(
        """\
        city = 'Tokyo'

        def greeting(name):
            print('Hello', name)

        def second_greeting():
            age = 10
            name = 'Jack'
            text = greeting(name)
            print(text + str(age))
    """
    )
    checker = PyIdentifierCounter()
    identifiers = checker.check(code)
    expected = ["city", "age", "name", "text"]
    actual = [
        report.name for report in identifiers if report.type == IdentifierType.VAR
    ]
    assert actual == expected

def test_func_method_names():
    code = dedent(
        """\
        city = 'Tokyo'

        def func1():
            def func2():
                pass
            def func3():
                pass
            pass

        class MyClass:
            def new(self):
                pass

            class InnerClass:
                def method2():
                    pass
    """
    )
    checker = PyIdentifierCounter()
    identifiers = checker.check(code)
    expected = ["func1", "func2", "func3", "new", "method2"]
    actual = [
        report.name for report in identifiers if report.type == IdentifierType.FUNC
    ]
    assert actual == expected

def test_func_class_names():
    code = dedent(
        """\
        class Person:
            def __init__(self, name):
                self.name = name

        class UserModel:
            class Meta:
                model = Person
                fields = ('id', 'name')

        # dynamic class creation: we cannot detect this one
        DynamicClass = type("NewClassName", (), {})
        """
    )
    checker = PyIdentifierCounter()
    identifiers = checker.check(code)
    expected = ["Person", "UserModel", "Meta"]
    actual = [
        report.name for report in identifiers if report.type == IdentifierType.CLASS
    ]
    assert actual == expected

def test_func_variable_with_annotations():
    code = dedent(
        """\
        class Person:
            age: int
            age_with_default: int = 18

        name: str
        name_with_value: str = 'Micheal'
        """
    )
    checker = PyIdentifierCounter()
    identifiers = checker.check(code)
    expected = ["age", "age_with_default", "name", "name_with_value"]
    actual = [
        report.name for report in identifiers if report.type == IdentifierType.VAR
    ]
    assert actual == expected

def test_func_or_method_args():
    code = dedent(
        """\
        class Person:
            def upper(self, name):
                return name.upper()

        def add(item_a: int, item_b: int):
            return item_a + item_b

        def advanced_add(*numbers):
            return sum(numbers)

        def func3(*args, **kwargs):
          pass
        """
    )
    checker = PyIdentifierCounter()
    identifiers = checker.check(code)
    expected = ["name", "item_a", "item_b", "numbers", "args", "kwargs"]
    actual = [
        report.name for report in identifiers if report.type == IdentifierType.ARG
    ]
    assert actual == expected


from convexhull import *
import cv2
import numpy
from ultralytics import YOLO
import tkinter
import matplotlib
import matplotlib.pyplot as plt
import tkinter
import os
import time
matplotlib.use('TkAgg')

def get3point(pp):
    return pp[:3]

src_img = [320,192]

def cam_c1(img,pts1):
    pts1 = numpy.float32(pts1)
    pts2 = numpy.float32([[src_img[0]/5,src_img[1]],[0,src_img[1]],[src_img[0],src_img[1]/5]])
    M = cv2.getAffineTransform(pts1,pts2)
    return cv2.warpAffine(img,M,(900,700))

def cam_c2(img,pts1):
    pts1 = numpy.float32(pts1)
    pts2 = numpy.float32([[src_img[0],src_img[1]/5],[src_img[0],src_img[1]],[src_img[0]/5,src_img[1]]])
    M = cv2.getAffineTransform(pts1,pts2)
    return cv2.warpAffine(img,M,(900,700))

def cam_c3(img,pts1):
    pts1 = numpy.float32(pts1)
    pts2 = numpy.float32([[0,src_img[1]/5],[0,0],[src_img[0]/5,0]])
    M = cv2.getAffineTransform(pts1,pts2)
    return cv2.warpAffine(img,M,(900,700))

def cam_c4(img,pts1):
    pts1 = numpy.float32(pts1)
    pts2 = numpy.float32([[src_img[0]/5,0],[src_img[0],0],[src_img[0],src_img[1]/5]])
    M = cv2.getAffineTransform(pts1,pts2)
    return cv2.warpAffine(img,M,(900,700))

def rv_cam_c1(img,pts1):
    pts1 = numpy.float32(pts1)
    pts2 = numpy.float32([[src_img[0]/5,src_img[1]],[0,src_img[1]],[src_img[0],src_img[1]/5]])
    M = cv2.getAffineTransform(pts2,pts1)
    return cv2.warpAffine(img,M,(640, 384))

def rv_cam_c2(img,pts1):
    pts1 = numpy.float32(pts1)
    pts2 = numpy.float32([[src_img[0],src_img[1]/5],[src_img[0],src_img[1]],[src_img[0]/5,src_img[1]]])
    M = cv2.getAffineTransform(pts2,pts1)
    return cv2.warpAffine(img,M,(640, 384))

def rv_cam_c3(img,pts1):
    pts1 = numpy.float32(pts1)
    pts2 = numpy.float32([[0,src_img[1]/5],[0,0],[src_img[0]/5,0]])
    M = cv2.getAffineTransform(pts2,pts1)
    return cv2.warpAffine(img,M,(640, 384))

def rv_cam_c4(img,pts1):
    pts1 = numpy.float32(pts1)
    pts2 = numpy.float32([[src_img[0]/5,0],[src_img[0],0],[src_img[0],src_img[1]/5]])
    M = cv2.getAffineTransform(pts2,pts1)
    return cv2.warpAffine(img,M,(640, 384))
#fdffg
model = YOLO('best (1).pt')
def extractOutput(path):

    video_cam1 = cv2.VideoCapture(path+'/'+'CAM_1.mp4')
    video_cam2 = cv2.VideoCapture(path+'/'+'CAM_2.mp4')
    video_cam3 = cv2.VideoCapture(path+'/'+'CAM_3.mp4')
    video_cam4 = cv2.VideoCapture(path+'/'+'CAM_4.mp4')

    font = cv2.FONT_HERSHEY_SIMPLEX
    fontScale = 1
    thickness = 2
    count = 1
    while True:
        a=time.time()
        res1, frame_cam1 = video_cam1.read()
        res2, frame_cam2 = video_cam2.read()
        res3, frame_cam3 = video_cam3.read()
        res4, frame_cam4 = video_cam4.read()

        raw1 = frame_cam1
        raw2 = frame_cam2
        raw3 = frame_cam3
        raw4 = frame_cam4
        if not res1:
            break
        if not res2:
            break
        if not res3:
            break
        if not res4:
            break

        if model(frame_cam1)[0].masks is None:
            continue
        if model(frame_cam2)[0].masks is None:
            continue
        if model(frame_cam3)[0].masks is None:
            continue
        if model(frame_cam4)[0].masks is None:
            continue

        total1 = model(frame_cam1)[0].masks.data[0]
        total2 = model(frame_cam2)[0].masks.data[0]
        total3 = model(frame_cam3)[0].masks.data[0]
        total4 = model(frame_cam4)[0].masks.data[0]

        total1 = total1.clone().detach().cpu()
        total2 = total2.clone().detach().cpu()
        total3 = total3.clone().detach().cpu()
        total4 = total4.clone().detach().cpu()

        total1 = numpy.array(total1)
        total2 = numpy.array(total2)
        total3 = numpy.array(total3)
        total4 = numpy.array(total4)

        total1 = preprocess(total1)
        total2 = preprocess(total2)
        total3 = preprocess(total3)
        total4 = preprocess(total4)

        cors1 = list(get3point(corner(total1)))
        cors2 = list(get3point(corner(total2)))
        cors3 = list(get3point(corner(total3)))
        cors4 = list(get3point(corner(total4)))

        mapmat1 = cv2.resize(frame_cam1, (640, 384))
        mapmat2 = cv2.resize(frame_cam2, (640, 384))
        mapmat3 = cv2.resize(frame_cam3, (640, 384))
        mapmat4 = cv2.resize(frame_cam4, (640, 384))

        cors1.append([0,0])
        cors2.append([0,0])
        cors3.append([0,0])
        cors4.append([0,0])

        image1 = cv2.bitwise_and(total1,cv2.rotate(total4, cv2.ROTATE_180), mask = None)
        image1 = preprocess(image1)

        image2 = cv2.bitwise_and(total2,cv2.rotate(total3, cv2.ROTATE_180), mask = None)
        image2 = preprocess(image2)

        image3 = cv2.bitwise_and(total3,cv2.rotate(total2, cv2.ROTATE_180), mask = None)
        image3 = preprocess(image3)

        image4 = cv2.bitwise_and(total4,cv2.rotate(total1, cv2.ROTATE_180), mask = None)
        image4 = preprocess(image4)
        b=time.time()
        corner1 = getAllCorner(image1)
        temp1 = [f"{i[0]},{i[1]}" for i in corner1]
        raw1 = ",".join(temp1)
        raw1 = f"({raw1})"
        f = open(path+'/CAM_1.txt', 'a')
        f.write(f"frame_{count}.jpg, {raw1}, {b-a}/n")
        f.close()
        b=time.time()
        corner2 = getAllCorner(image2)
        temp2 = [f"{i[0]},{i[1]}" for i in corner2]
        raw2 = ",".join(temp2)
        raw2 = f"({raw2})"
        f = open(path+'/CAM_2.txt', 'a')
        f.write(f"frame_{count}.jpg, {raw2}, {b-a}/n")
        f.close()
        b=time.time()
        corner3 = getAllCorner(image3)
        temp3 = [f"{i[0]},{i[1]}" for i in corner3]
        raw3 = ",".join(temp3)
        raw3 = f"({raw3})"
        f = open(path+'/CAM_3.txt', 'a')
        f.write(f"frame_{count}.jpg, {raw3}, {b-a}/n")
        f.close()
        b=time.time()
        corner4 = getAllCorner(image4)
        temp4 = [f"{i[0]},{i[1]}" for i in corner4]
        raw4 = ",".join(temp4)
        raw4 = f"({raw4})"
        f = open(path+'/CAM_4.txt', 'a')
        f.write(f"frame_{count}.jpg, {raw4}, {b-a}/n")
        f.close()
        count+=1
# extractOutput("C:/Users/ADMIN/Desktop/document/junx/Private_Test/videos/scene4cam_05")
output = "C:/Users/ADMIN/Desktop/document/junx/Private_Test/groundtruth/"
path = "C:/Users/ADMIN/Desktop/document/junx/Private_Test/videos/scene4cam_"
for i in range(1, 15):
    fullpath = path+"0"*(2-len(str(i)))+str(i)
    extractOutput(fullpath)


"""View Prioritization Module"""

from typing import Dict, List

from carla_msgs.msg import CarlaEgoVehicleStatus

from view_prioritization.parser import CameraViewParameter

class ViewPrioritizationModel:
    """Camera View Prioritization Module"""

    MAX_STEERING_ANGLE_DEGREE = 60

    def __init__(self, camera_views: List[CameraViewParameter]):
        self.__camera_views = camera_views

    @staticmethod
    def get_camera_weight(orientation: float, velocity: float) -> int:
        if abs(orientation) < 45:
            speed_influence_weight = int(max(0.0, 0.1 * velocity))
            return 4 + speed_influence_weight
        if abs(orientation) < 90:
            return 2
        return 1

    @staticmethod
    def steer_to_angle(steer: float) -> float:
        """
        Positive steering value results in a negative orientation.
        """
        return ViewPrioritizationModel.MAX_STEERING_ANGLE_DEGREE * -steer

    @staticmethod
    def get_camera_orientation(orientation: float, steer: float) -> float:
        return orientation - ViewPrioritizationModel.steer_to_angle(steer)

    @staticmethod
    def get_orientation_from_car_direction(orientation: float, reverse: bool) -> float:
        if reverse:
            orientation = -orientation + 180
            orientation = orientation % 360 if orientation >= 360 else orientation
        return orientation

    def calculate_camera_prioritization(
        self, vehicle_status: CarlaEgoVehicleStatus
    ) -> Dict[str, float]:
        camera_orientations = [
            self.get_camera_orientation(
                self.get_orientation_from_car_direction(
                    camera_view.orientation, vehicle_status.control.reverse
                ),
                vehicle_status.control.steer,
            )
            for camera_view in self.__camera_views
        ]
        camera_weights = [
            self.get_camera_weight(orientation, vehicle_status.velocity)
            for orientation in camera_orientations
        ]
        normalized_wights = [weight / sum(camera_weights) for weight in camera_weights]
        return {
            camera_view.camera_id: weight
            for camera_view, weight in zip(self.__camera_views, normalized_wights)
        }


import pygame
from source.Utilities import Utilities
from source.UI import UI
from source.StartScreen import StartScreen
from source.EndScreen import EndScreen
from source.NumberLine import NumberLine
from source.Character import Character

class GameController:

    level = 1
    game_state = "start"

    # Error messages constants
    CAT_TOO_FAR_MESSAGE = " moves the cat off of the number line. Try Again!"
    EMPTY_BOX_MESSAGE = "Please type a number and try again."
    NOT_ON_THE_NUMBER_LINE_MESSAGE = " is not on this number line. Try Again."

    # max level for the game.
    MAX_LEVEL = 50

    # constants for cat and mouse pictures.
    LEFT_CAT = "../assets/catLeft.png"
    RIGHT_CAT = "../assets/catRight.png"
    MOUSE = "../assets/mouse.png"

    ADD = pygame.USEREVENT + 1
    SUB = pygame.USEREVENT + 2
    GO = pygame.USEREVENT + 3
    RESTART = pygame.USEREVENT + 4
    QUIT = pygame.USEREVENT + 5
    START = pygame.USEREVENT + 6

    def game_display(self):
        self.screen.fill((255, 255, 255))

        # draw number line
        self.number_line.display()
        self.number_line.display_numbers()
        self.number_line.change_level(self.level)

        # position and draw cat
        self.cat_position = self.cat.set_random_position(-1)

        # position and draw mouse
        self.mouse_position = self.mouse.set_random_position(self.cat_position)

        self.mouse.display()
        self.cat.display()

        # draw level on screen
        self.ui.display_all_help_text()
        self.ui.update_level(self.level)

    def __init__(self, _screen):
        self.screen = _screen

        # setup variables
        self.w, self.h = Utilities.get_width_height()  # width and height of the screen
        self.screen = _screen

        # make start screen
        self.start_screen = StartScreen(self.screen, self.w / 2, self.h / 2)

        # make end screen
        self.end_screen = EndScreen(self.screen, self.w / 2, self.h / 2)

        # make UI
        self.ui = UI(self.screen, self.w / 2, self.h/2 + 50)

        # make Number Line
        self.number_line = NumberLine(self.screen, self.w, self.h)

        # make cat
        self.cat = Character(self.number_line.circle_pos, self.LEFT_CAT, int(self.number_line.spacing * 1.3), int(self.number_line.spacing *1.3), self.screen)
        self.cat_position = -1

        # make mouse
        self.mouse = Character(self.number_line.circle_pos, self.MOUSE, int((self.number_line.spacing/2)*1.3), int((self.number_line.spacing/2)*1.3), self.screen, self.cat.get_x_pos())
        self.mouse_position = -1

        self.end = False

    def loop(self, events):
        # draw UI
        if self.game_state == "start":
            self.start_screen.display(events)
        if self.game_state == "play":
            self.ui.display(events)
        if self.game_state == "end":
            self.end_screen.display(events)

        for event in events:

            if event.type == self.GO or (event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN):
                Utilities.show_error(self.screen, "")  # clear previous error
                input_num = self.ui.user_input.get_input()

                if input_num is not None:

                    if input_num % self.level == 0:
                        new_position = int(input_num/self.level)

                        if self.cat_position + new_position >= 0:

                            if self.cat_position + new_position < self.number_line.num_of_points:
                                self.cat_position = self.cat.move(new_position)
                                self.mouse.display()
                                self.ui.user_input.clear()

                                if self.cat_position == self.mouse_position:
                                    self.mouse_position = self.mouse.set_random_position(self.cat_position)
                                    self.cat.display()
                                    self.level += 1

                                    if self.level > self.MAX_LEVEL:
                                        self.game_state = "end"
                                    else:
                                        self.ui.update_level(self.level)
                                        self.number_line.change_level(self.level)
                            else:
                                Utilities.show_error(self.screen, str(input_num) + self.CAT_TOO_FAR_MESSAGE)
                        else:
                            Utilities.show_error(self.screen, str(input_num) + self.CAT_TOO_FAR_MESSAGE)
                    else:
                        equation = ""
                        if self.ui.user_input.get_input() > 0:
                            equation = str(self.cat_position * self.level) + " + " + str(self.ui.user_input.get_input())
                        else:
                            equation = str(self.cat_position * self.level) + " - " + str(self.ui.user_input.get_input())[1:]
                        Utilities.show_error(self.screen, equation + self.NOT_ON_THE_NUMBER_LINE_MESSAGE)
                else:
                    Utilities.show_error(self.screen, self.EMPTY_BOX_MESSAGE)

            if event.type == self.ADD:
                self.ui.user_input.add(1)
            if event.type == self.SUB:
                self.ui.user_input.add(-1)

            if event.type == self.START:
                self.game_state = "play"
                self.game_display()

            if event.type == self.RESTART:
                self.level = 1
                self.game_state = "play"
                self.game_display()

            if event.type == self.QUIT:
                pygame.event.post(pygame.event.Event(pygame.QUIT))

            if self.ui.user_input.get_input() is not None and self.ui.user_input.get_input() < 0:
                self.cat.set_display_image(self.LEFT_CAT)
                self.cat.erase()
                self.cat.display()
                self.mouse.erase()
                self.mouse.display()
            if self.ui.user_input.get_input() is not None and self.ui.user_input.get_input() > 0:
                self.cat.set_display_image(self.RIGHT_CAT)
                self.cat.erase()
                self.cat.display()
                self.mouse.erase()
                self.mouse.display()


#!/usr/bin/env python3

import json

import requests

SLACK_API_KEY = "get token from https://api.slack.com/custom-integrations/legacy-tokens"
OPENWEATHER_API_KEY = "get token from https://openweathermap.org/appid"
OPENWEATHER_CITY_ID = "find your city id https://openweathermap.org/current#cityid"

# https://openweathermap.org/weather-conditions
WEATHER_CODES = {
    '2': ':lightning:',
    '3': ':rain_cloud:',
    '5': ':rain_cloud:',
    '6': ':snowflake:',
    '7': ':fog:',
    '80': ':cloud:',
    '800': ':sunny:',
    '801': ':sun_small_cloud:',
}

def get_emoji(code):
    code = str(code)
    if code in WEATHER_CODES:
        return WEATHER_CODES.get(code)

    if code[:2] in WEATHER_CODES:
        return WEATHER_CODES.get(code[:2])

    if code[:1] in WEATHER_CODES:
        return WEATHER_CODES.get(code[:1])

def to_celsius(kelvin):
    return kelvin - 273.15

def build_status(text, emoji):
    payload = {
        'status_text': text,
        'status_emoji': emoji
    }
    return json.dumps(payload)

if __name__ == '__main__':
    r = requests.get('http://api.openweathermap.org/data/2.5/weather?id={}&appid={}'.format(OPENWEATHER_CITY_ID,
                                                                                OPENWEATHER_API_KEY))

    weather = r.json().get('weather')[0]
    temp = to_celsius(r.json().get('main').get('temp'))

    text = '{}°C and {}'.format(round(temp), weather.get('description'))
    emoji = get_emoji(weather.get('id'))

    r = requests.post('https://slack.com/api/users.profile.set', data={
        'token': SLACK_API_KEY,
        'profile': build_status(text, emoji)
    })

    if r.status_code != 200:
        print(r.status_code)
        print(r.json())


"""
defaultdict :
The `defaultdict` never raises a `KeyError`. Instead, it returns the value returned by
the function specified when the object was instantiated.

When you need a dictionary and all keys of that dictionary
should be associated with an initial value, use `defaultdict`!
"""

from collections import defaultdict

friends_collage = [('Sahil', 'LJ'), ('Sanjay', 'Goswami'), ('Manthan', 'MJ Science'), ('Harsh', 'Medical'),('Sahil', 'IIM')]

friends_dict = defaultdict(list)

for friend, collage in friends_collage:
    friends_dict[friend].append(collage)

print(friends_dict['Manthan'])
print(friends_dict['Sahil'])
print(friends_dict['Satish']) # If there is no name in list then it returns empty [].
print(friends_dict)

# Another Example

my_company = 'Pied Piper'

pied_piper_coworkers = ['Richard', 'Dinesh', 'Gilfoyle', 'Jared']

other_company_coworkers = [('Tara', 'Apple'), ('Gavin', 'Hooli'), ('Satya', 'Microsoft')]

coworkers_company = defaultdict(lambda: my_company)

for coworker, company in other_company_coworkers:
    coworkers_company[coworker] = company

# coworkers_company.default_factory = None /// this will give keyerror

print(coworkers_company['Dinesh'])
print(coworkers_company['Gavin'])
print(coworkers_company)

Advance Python Developement/Intresting Python Collection/defaultdict.py


import re, getopt, sys, csv
import SimpleITK
import itk

class bcolors:
    """A class to print colored text."""
    HEADER='\033[95m';  OKBLUE='\033[94m'; OKGREEN='\033[92m';
    WARNING='\033[93m'; FAIL='\033[91m';   ENDC='\033[0m';

class FilterSet:
    """The main data structure for holding the filter data"""
    filters = list()    # a list of all the filters
    itk     = set()     # a set of all the ITK filters
    sitk    = set()     # a set of all the SimpleITK filters
    todo    = set()     # a set of the ITK filters not yet in SimpleITK but to be done
    remarks = dict()    # a dictionary of remarks, indexed by filter name

# Global variables
fs              = FilterSet()   # the filter data structure
remarkFile      = ""
onlyRemarksFlag = False
sortByType      = False
quietMode       = False
writelessMode   = False

fieldnames      = ( 'Filter', 'ITK', 'SITK', 'Remark', 'ToDo' )    # fields in the CSV file

#
#
class unix_dialect(csv.Dialect):
    """Describe the usual properties of unix-generated CSV files."""
    delimiter = ','
    quotechar = '"'
    doublequote = True
    skipinitialspace = False
    lineterminator = '\n'
    quoting = csv.QUOTE_MINIMAL

def writeCSV(name):
    """Write the results out to a common-spaced-value file (readable by any spreadsheet program)"""
    csv.register_dialect("unix_dialect", unix_dialect)
    try:
        with open(name, "w") as fp:
            writer = csv.DictWriter(fp, fieldnames=fieldnames, dialect="unix_dialect")
            headers = dict( (n,n) for n in fieldnames)
            writer.writerow(headers)
            for filt in fs.filters:
                if filt in fs.remarks:
                    rem = fs.remarks[filt]
                else:
                    rem = ""
                if len(rem) or not onlyRemarksFlag:
                    writer.writerow( { fieldnames[0]:filt,
                                       fieldnames[1]:filt in fs.itk,
                                       fieldnames[2]:filt in fs.sitk,
                                       fieldnames[3]:rem,
                                       fieldnames[4]:filt in fs.todo,
                                       } )
    except:
        print( bcolors.FAIL, "Error:", bcolors.ENDC, "Couldn't write output file", name, "\n" )
        sys.exit(-1)

#
#
def readCSV(name):
    """Read the filters from a CSV file.

    Note that the only the Remark and ToDo fields are taken from the CSV file.
    The filter names and which toolkits have each filter comes from is not read
    from the file.  Rather that information is loaded from the ITK and SimpleITK
    Python symbol tables.
    """
    try:
        with open(name, "rU") as fp:
            reader = csv.DictReader(fp)
            for row in reader:
                filt = row[fieldnames[0]]

                # Check the file to see if the ITK/SITK flags match what we've pulled from Python.
                iflag = sflag = False
                if len(row[fieldnames[1]]):
                    iflag = row[fieldnames[1]].lower() == "true"
                if len(row[fieldnames[2]]):
                    sflag = row[fieldnames[2]].lower() == "true"

                initk = filt in fs.itk
                insitk = filt in fs.sitk

                if not initk and not insitk:
                    print( bcolors.FAIL, "Warning: ", bcolors.ENDC, "Filter ", filt, \
                                        "not found in either ITK or SimpleITK" )

                if (iflag != initk) or (sflag != insitk):
                    print( bcolors.FAIL, "Warning: ", bcolors.ENDC, \
                                        "mismatch between file and symbol table for filter ", filt )
                    print( "    ", row )

                # Get the remark field from the file.
                if row[fieldnames[3]] != None:
                    if len(row[fieldnames[3]]):
                        fs.remarks[filt] = row[fieldnames[3]]

                # Get the ToDo flag
                if len(row[fieldnames[4]]):
                    if row[fieldnames[4]].lower() == "true":
                        fs.todo.add(filt)

    except:
        print( bcolors.FAIL, "Warning:", bcolors.ENDC, "Couldn't read input file", name, \
                            ".  Proceeding without it.\n" )
    else:
        if not quietMode:
            print( "Read file", remarkFile, "\n" )

#
#
def filterKey(filter_name):
    """Function that produces a key for sorting filters by toolkit.

    If a filter is in ITK, an 'I' gets prepended to the name, if not an 'i'.
    Similarly if the filter is in SimpleITK it gets a 'S', if not an 's'.
    The SimpleITK letter comes after the ITK.  So if the filter # is in both toolkits,
    it gets "IS"; only in ITK gets "Is"; only in SimpleITK gets "iS".
    """
    itag = 'I' if filter_name in fs.itk else 'i'
    stag = 'S' if filter_name in fs.sitk else 's'
    return itag + stag + filter_name

#
#
def usage():
    """command line usage message"""
    print( "" )
    print( "CompareITKandSITKFilters.py [options] [output_file.csv]" )
    print( "" )
    print( "  -h         This help message." )
    print( "  -t         Sort printed filters by toolkit type." )
    print( "  -r string  Add a remark entry in the format \"filter_name:remark string\"." )
    print( "  -o         Only output filters with remarks." )
    print( "  -q         Quiet mode, don't print filter list." )
    print( "  -w         Writeless mode, don't write the output file." )
    print( "" )
    print( "This script compares what image filters ITK (via WrapITK) and SimpleITK implement." )
    print( "It works by comparing the symbol tables of their respective python modules." )
    print( "If no output file name is given, by default, the script writes results to filters.csv." )
    print( "" )

#
#   Handle command line options
#

try:
    opts, args = getopt.getopt(sys.argv[1:], "htoqwr:",
        [ "help", "type", "only", "quiet", "writeless", "remark" ] )
except getopt.GetoptError as err:
    print( str(err) )
    usage()
    sys.exit(2)

for o, a in opts:
    if o in ("-h", "--help"):
        usage()
        sys.exit()
    elif o in ("-t", "--type"):
        sortByType = True
    elif o in ("-o", "--only"):
        onlyRemarksFlag = True
    elif o in ("-q", "--quiet"):
        quietMode = True
    elif o in ("-w", "--writeless"):
        writelessMode = True
    elif o in ("-r", "--remark"):
        words = a.partition(':')
        remarks[words[0]] = words[2]
        print( words[0], remarks[words[0]] )
    else:
        assert False, "unhandled option"

# take the last word left from the args list as the output file name
if len(args):
    remarkFile = args[len(args)-1]

#
#   Get all the ITK and SimpleITK classes from Python symbol tables.
#

sclasses = dir(SimpleITK)
iclasses = dir(itk)

#   Find all the SimpleITK class names that end with "ImageFilter".
#   SimpleITK has a base class that is just "ImageFilter" that we want to omit.
for s in sclasses:
    if re.search(r'ImageFilter$', s):
        if s != "ImageFilter":
            fs.sitk.add(s)

if not quietMode:
    print( "\nSimpleITK has", bcolors.OKBLUE, len(fs.sitk), bcolors.ENDC, "filters." )

#   Find all the ITK class names that end with "ImageFilter" or "ImageSource"
#   ITK has a base class that is just "ImageSource" that we want to omit.
for i in iclasses:
    if re.search(r'ImageFilter$', i) or re.search(r'ImageSource$', i):
        if i != "ImageSource":
            fs.itk.add(i)

if not quietMode:
    print( "ITK has", bcolors.OKBLUE, len(fs.itk), bcolors.ENDC, "filters.\n" )

fs.filters = list(fs.itk.union(fs.sitk))

#
# Sort the filters either by name or toolkit and name
#

if sortByType:
    fs.filters = sorted(fs.filters, key=filterKey)
else:
    fs.filters.sort()

#
#  Read the remarks from file

if remarkFile != "":
    readCSV(remarkFile)

#
#    Print all the filters
#

if not quietMode:
    bothcount = icount = scount = 0
    word = ""

    for filt in fs.filters:
        inI = filt in fs.itk
        inS = filt in fs.sitk
        if inI and inS:
            color = bcolors.OKBLUE
            word = "Both"
            bothcount+=1
        elif inI:
            color = bcolors.OKGREEN
            word = "ITK "
            icount+=1
        else:
            color = bcolors.FAIL
            word = "SITK"
            scount+=1

        rem = ""
        if filt in fs.remarks:
            rem = fs.remarks[filt]
        print( "%50s %s %s %s      %s" % (filt, color, word, bcolors.ENDC, rem) )

    print( "" )
    print( "%3d filters in both toolkits." % bothcount )
    print( "%3d filters in ITK only." % icount )
    print( "%3d filters in SimpleITK only." % scount )
    print( "" )

#
#   Write out the new CSV file
#

if not writelessMode:
    if remarkFile == "":
        remarkFile = "filters.csv"
    writeCSV(remarkFile)
    if not quietMode:
        print( "Wrote file", remarkFile )
        print( "" )


from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.views import APIView
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from rest_framework import status
import logging
from rest_framework_jwt.settings import api_settings
from .utils import generate_save_user_token

from oauth.models import OAuthQQUser
from .serializes import QQAuthUserSerialize
from carts.utils import merge_cart_cookie_to_redis
# Create your views here.
# 创建日志输出器对象
logger = logging.getLogger('django')

# # 2.初始化OAuthQQ对象
# oauthqq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
#                   client_secret=settings.QQ_CLIENT_SECRET,
#                   redirect_uri=settings.QQ_REDIRECT_URI
#                   )

class QQAuthUserView(APIView):
    """用户扫码登录成功的回调函数"""

    def get(self,request):
        """完成oauth2.0认证"""

        # 1.提取code请求参数
        code = request.query_params.get('code')
        if not code:
            return Response({'message':'没有code'},status=status.HTTP_400_BAD_REQUEST)

        # 2.初始化OAuthQQ对象
        oauthqq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                          client_secret=settings.QQ_CLIENT_SECRET,
                          redirect_uri=settings.QQ_REDIRECT_URI
                          )

        try:
            # 3.利用code参数,使用get_access_token()方法,向QQ服务器发送get请求,获取access_token
            access_token = oauthqq.get_access_token(code)

            # 4.利用access_token参数,使用get_open_id()方法,向QQ服务器发送get请求,获取openid
            openid = oauthqq.get_open_id(access_token)
        except Exception as error:
            logger.info(error)
            return Response({'message':'QQ服务器异常'},status=status.HTTP_503_SERVICE_UNAVAILABLE)

        # 使用openid查询该QQ是否在美多商城中绑定过用户
        try:
            oauth_model = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:

            # 没有查到值,说明该openid没绑定美多商城用户,对
            # openid进行加密,响应给前端保存,后续创建新用户绑定使用
            access_token_openid = generate_save_user_token(openid)

            return Response({'access_token':access_token_openid})

        else:
            # 不走except,则走else,说明openid已经绑定美多商城用户
            # 生成JWT token,响应返回
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

            # 获取oauthModel关联/绑定的用户模型对象
            # 查询到oauth_model有值,直接使用该用户
            user = oauth_model.user
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            # return Response({
            #     'user_id': user.id,
            #     'username': user.username,
            #     'token': token
            # })
            response = Response({
                'user_id': user.id,
                'username': user.username,
                'token': token
            })
            # 购物车合并
            return merge_cart_cookie_to_redis(request, user, response)

    def post(self,request):
        """openid绑定用户"""

        # 1.创建序列化器对象
        serializer = QQAuthUserSerialize(data=request.data)

        # 2.数据校验
        serializer.is_valid(raise_exception=True)

        # 3.保存
        user = serializer.save()

        # 生成JWT token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        # 获取oauthModel关联/绑定的用户模型对象
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        response = Response({
            'use_id':user.id,
            'username':user.username,
            'token':token
        })

        # 购物车合并
        return merge_cart_cookie_to_redis(request,user,response)

class QQAuthURLView(APIView):
    """获取QQ登录扫码链接"""

    def get(self,request):
        """返回QQ扫码url"""

        # 1.获取next参数
        next = request.query_params['next']
        if not next:
            next = '/'

        # 2.初始化OAuthQQ对象
        oauthqq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                          client_secret=settings.QQ_CLIENT_SECRET,
                          redirect_uri=settings.QQ_REDIRECT_URI,
                          state=next)

        # 3.调用OAuthQQ中的oauthqq.get_qq_url()方法获取到拼接好的扫码url
        login_url = oauthqq.get_qq_url()

        # 4.响应
        return Response({'login_url':login_url})


from django.shortcuts import render, redirect
from .models import Article
from .forms import ArticleForm

# Create your views here.

# 요청 정보를 받아서..
def index(request):
    # DB에서 가져와서
    articles = Article.objects.order_by('-pk')
    # Template에 전달한다
    context = {
        'articles': articles
    }
    return render(request, 'articles/index.html', context)

# def new(request):
#     article_form = ArticleForm()
#     context = {
#         'article_form': article_form
#     }
#     return render(request, 'articles/new.html', context=context)

# new와 create 함수 합치기
def create(request):
    # form에서 글쓰기를 누르면 실행
    if request.method == 'POST':
        # 입력받은 데이터들 DB에 저장
        article_form = ArticleForm(request.POST)
        # 유효할 경우 실행 (valid)
        if article_form.is_valid():
            article_form.save()
            # index 페이지로 redirect
            return redirect('articles:index')
    # 'GET' method 일때
    # http://127.0.0.1:8000/articles/create 일때 실행
    else:
        article_form = ArticleForm()
    # 유효하지 않을 경우 아래로 이동 (invalid)
    context = {
        'article_form': article_form
    }
    return render(request, 'articles/new.html', context=context)

def detail(request, pk):
    # 특정 글을 가져온다
    article = Article.objects.get(pk=pk)
    # template에 객체 전달
    context = {
        'article': article
    }
    return render(request, 'articles/detail.html', context)


#!/usr/bin/env python

import open_clip
import torch
from PIL import Image

import os
import os.path as osp
import numpy as np
from tqdm import tqdm
import json

from detectron2.data.datasets import load_coco_json
from detectron2.data.detection_utils import read_image
from detectron2.data import MetadataCatalog

import click

def write_json(filename, data):
    with open(filename, 'w') as fp:
        json.dump(data, fp)

def get_caption(images, model):
    images = [images] if not isinstance(images, list) else images
    for i, image in enumerate(images):
        image = Image.fromarray(image) if isinstance(image, np.ndarray) else image
        images[i] = model.transform(image)

    images = torch.stack(images).to(model.device)
    with torch.no_grad(), torch.cuda.amp.autocast():
        generated = model.generate(images)

    caps = [open_clip.decode(g).split("<end_of_text>")[0].replace("<start_of_text>", "") for g in generated]
    return caps

def inference(model, images, batch_size=24):
    captions = []
    for i in range(0, len(images), batch_size):
        chunck = images[i : i + batch_size]
        captions.extend(get_caption(chunck, model))
    return captions

def get_model(device):
    model, _, transform = open_clip.create_model_and_transforms(
        model_name="coca_ViT-L-14", pretrained="mscoco_finetuned_laion2B-s13B-b90k"
    )
    model = model.to(device).eval()
    model.transform = transform
    model.device = device
    return model

def process(model, data_dicts, write_dir, override: bool = False):
    for i, data_dict in enumerate(tqdm(data_dicts)):
        filename = data_dict['file_name']
        annotations = data_dict['annotations']

        image_id = data_dict['image_id']
        json_filename = f'{osp.join(write_dir, str(image_id).zfill(12))}.json'

        if not override and osp.isfile(json_filename):
            continue

        image = read_image(file_name=filename)
        im_crops = []
        bboxes = []
        for _, annotation in enumerate(annotations):
            x, y, w, h = annotation['bbox']
            bboxes.append(annotation['bbox'])

            x, y, w, h = np.intp([x, y, w, h])
            w, h = np.max([[w, 1], [h, 1]], axis=1)
            im_crop = image[y : y + h, x : x + w].copy()
            im_crops.append(im_crop)

        captions = inference(model, im_crops)

        caption_dicts = {
            'file_name': filename,
            'image_id': data_dict['image_id'],
            'captions': [{'bbox': bbox, 'caption': cap} for cap, bbox in zip(captions, bboxes)],
        }

        write_json(json_filename, caption_dicts)

@click.command()
@click.option('--start', type=int, required=True)
@click.option('--end', type=int, required=True)
@click.option('--device', type=str, default='cuda:0')
@click.option('--root', type=str, required=False, default='/workspace/Downloads/datasets/coco/')
@click.option('--year', type=str, default='2017')
@click.option('--type', type=str, default='train')
@click.option('--override/--no-override', type=bool, default=False)
def main(start, end, device, root, year, type, override):
    data_type = f'{type}{year}'
    ann_file = '{}/annotations/instances_{}.json'.format(root, data_type)

    write_dir = osp.join(root, f'captions/{data_type}')
    if not osp.isdir(write_dir):
        os.makedirs(write_dir, exist_ok=True)

    # load coco data

    print("loading coco data")
    filename_resolver = lambda x: osp.join(root, data_type)
    data_dicts = load_coco_json(ann_file, filename_resolver(''))
    meta = MetadataCatalog.get(f'coco_{year}_{type}')
    classes = meta.thing_classes
    cat_id_mapping = meta.get('thing_dataset_id_to_contiguous_id')

    print("loading model")
    model = get_model(device=device)

    process(model, data_dicts[start:end], write_dir, override)

if __name__ == '__main__':
    main()


'''for c in range(1,11):
    print(c)          (usado somente quando eu sei o limite)
print('FIM')'''

'''c = 1
while c < 11:
    print(c)   #Usado também quando eu sei o limite, assim como no for in range()
    c += 1'''

'''numero = 1
while numero != 0:
    numero  = int(input('Digite um valor: '))
print('FIM')    #Usado também quando eu não sei o limite'''

'''letra = 'S'
while letra == 'S':
    numero = int(input('Digite um número: '))
    letra = str(input('Quer continuar? [S/N]: ')).upper()
print('FIM') #podemos criar situações de laços indeterminado'''

n = 1
par = impar = 0
while n != 0:
    n = int(input('Digite um número: '))
    if n != 0:
        if n % 2 == 0:
            par += 1
        else:
            impar += 1
print('Voce digitou {} números pares e {} números impares!'.format(par, impar))


import matplotlib.pyplot as plt
import numpy as np
import cartopy
import cartopy.crs as ccrs
import iris
from matplotlib import animation

v_cube = iris.load_cube('/data/NAS-ph290/ph290/reanalysis/NCEP_v2/vwnd_monthly_low_res.nc')
u_cube = iris.load_cube('/data/NAS-ph290/ph290/reanalysis/NCEP_v2/uwnd_monthly_low_res.nc')
shape = np.shape(v_cube)

level = 0

X = u_cube[0][0].coord('longitude').points
Y = u_cube[0][0].coord('latitude').points

u_cube_tmp = u_cube.collapsed('time',iris.analysis.MEAN)
v_cube_tmp = v_cube.collapsed('time',iris.analysis.MEAN)

plt.close('all')
fig, ax = plt.subplots(1,1)
ax = plt.axes(projection=ccrs.PlateCarree())
Q = ax.quiver(X, Y, u_cube_tmp[level].data, v_cube_tmp[level].data)
plt.gca().coastlines()
# plt.show()
plt.savefig('/home/ph290/Documents/figures/winds_monthly_mean.png')

#anim.save('/home/ph290/Documents/figures/winds_monthly.mp4', writer=writer)


import bpy

from Frame_Ranger import Utility_Function
from Frame_Ranger.Utility_Function import Timeline_Marker_Function

ENUM_Mode = [("DOWN", "Down", "Down"),("UP", "Up", "Up")]

class FR_OT_TMM_Reorder_Timeline_Marker(bpy.types.Operator):
    """Reorder Timeline Marker"""
    bl_idname = "fr_tmm.reorder_timeline_marker"
    bl_label = "Reorder Timeline Marker"
    bl_options = {'UNDO', 'REGISTER'}

    Index: bpy.props.IntProperty()
    Mode: bpy.props.EnumProperty(items=ENUM_Mode)

    Disable_Warning: bpy.props.BoolProperty(default=True)

    def invoke(self, context, event):

        preferences = Utility_Function.get_addon_preferences()

        if preferences.OAM_Timeline_Marker_Warning:
            return context.window_manager.invoke_props_dialog(self)
        else:
            return self.execute(context)

    def draw(self, context):
        layout = self.layout
        layout.label(text="This Operator: ", icon="ERROR")
        box = layout.box()
        box.label(text="Removes All Markers and Recreating it", icon="ERROR")
        box.label(text="Depending on the Situation, It might be destructive")
        box = layout.box()
        box.label(text="You Might Lose All Your Markers", icon="ERROR")
        box.label(text="If this Operator Fails Halfway")
        layout.prop(self, "Disable_Warning", text="Disable Warning")

    def execute(self, context):

        scn = context.scene

        preferences = Utility_Function.get_addon_preferences()

        if preferences.OAM_Timeline_Marker_Warning:
            if self.Disable_Warning:
                preferences.OAM_Timeline_Marker_Warning = False

        timeline_markers_index = scn.timeline_markers_index

        proto_markers = []

        for timeline_marker in scn.timeline_markers:
            proto_marker = Timeline_Marker_Function.collect_marker_data(timeline_marker, type="TIMELINEMARKER")
            proto_markers.append(proto_marker)

        if self.Mode == "UP":
            if self.Index-1 >= 0:

                Timeline_Marker_Function.clear_timeline_markers(scn)
                item = proto_markers.pop(self.Index)
                proto_markers.insert(self.Index-1, item)
                Timeline_Marker_Function.recreate_timeline_markers(proto_markers, scn)
                scn.timeline_markers_index = timeline_markers_index

            Timeline_Marker_Function.index_up(scn)

        if self.Mode == "DOWN":
            if self.Index+1 < len(proto_markers):

                Timeline_Marker_Function.clear_timeline_markers(scn)
                item = proto_markers.pop(self.Index)
                proto_markers.insert(self.Index+1, item)
                # proto_markers = Utility_Function.list_swap_item(proto_markers, self.Index-1, self.Index)
                Timeline_Marker_Function.recreate_timeline_markers(proto_markers, scn)
                scn.timeline_markers_index = timeline_markers_index
            Timeline_Marker_Function.index_down(scn)

        Utility_Function.update_UI()

        return {'FINISHED'}

classes = [FR_OT_TMM_Reorder_Timeline_Marker]

def register():

    for cls in classes:
        bpy.utils.register_class(cls)

def unregister():

    for cls in classes:
        bpy.utils.unregister_class(cls)

if __name__ == "__main__":
    register()


# -*- coding: utf-8 -*-
"""
BLE Client for BlueZ on Linux
"""
import inspect
import logging
import asyncio
import os
import warnings
from typing import Callable, Optional, Union
from uuid import UUID

import async_timeout

from dbus_next.aio import MessageBus
from dbus_next.constants import BusType, ErrorType
from dbus_next.message import Message
from dbus_next.signature import Variant

from bleak.backends.bluezdbus import defs
from bleak.backends.bluezdbus.characteristic import BleakGATTCharacteristicBlueZDBus
from bleak.backends.bluezdbus.manager import get_global_bluez_manager
from bleak.backends.bluezdbus.scanner import BleakScannerBlueZDBus
from bleak.backends.bluezdbus.utils import (
    assert_reply,
    extract_service_handle_from_path,
)
from bleak.backends.client import BaseBleakClient
from bleak.backends.device import BLEDevice
from bleak.backends.service import BleakGATTServiceCollection
from bleak.exc import BleakDBusError, BleakError
from .version import BlueZFeatures

logger = logging.getLogger(__name__)

class BleakClientBlueZDBus(BaseBleakClient):
    """A native Linux Bleak Client

    Implemented by using the `BlueZ DBUS API <https://docs.ubuntu.com/core/en/stacks/bluetooth/bluez/docs/reference/dbus-api>`_.

    Args:
        address_or_ble_device (`BLEDevice` or str): The Bluetooth address of the BLE peripheral to connect to or the `BLEDevice` object representing it.

    Keyword Args:
        timeout (float): Timeout for required ``BleakScanner.find_device_by_address`` call. Defaults to 10.0.
        disconnected_callback (callable): Callback that will be scheduled in the
            event loop when the client is disconnected. The callable must take one
            argument, which will be this client object.
        adapter (str): Bluetooth adapter to use for discovery.
    """

    def __init__(self, address_or_ble_device: Union[BLEDevice, str], **kwargs):
        super(BleakClientBlueZDBus, self).__init__(address_or_ble_device, **kwargs)
        # kwarg "device" is for backwards compatibility
        self._adapter = kwargs.get("adapter", kwargs.get("device", "hci0"))

        # Backend specific, D-Bus objects and data
        if isinstance(address_or_ble_device, BLEDevice):
            self._device_path = address_or_ble_device.details["path"]
            self._device_info = address_or_ble_device.details.get("props")
        else:
            self._device_path = None
            self._device_info = None

        # D-Bus message bus
        self._bus: Optional[MessageBus] = None
        # tracks device watcher subscription
        self._remove_device_watcher: Optional[Callable] = None
        # private backing for is_connected property
        self._is_connected = False
        # indicates disconnect request in progress when not None
        self._disconnecting_event: Optional[asyncio.Event] = None
        # used to ensure device gets disconnected if event loop crashes
        self._disconnect_monitor_event: Optional[asyncio.Event] = None

        # used to override mtu_size property
        self._mtu_size: Optional[int] = None

    # Connectivity methods

    async def connect(self, **kwargs) -> bool:
        """Connect to the specified GATT server.

        Keyword Args:
            timeout (float): Timeout for required ``BleakScanner.find_device_by_address`` call. Defaults to 10.0.

        Returns:
            Boolean representing connection status.

        Raises:
            BleakError: If the device is already connected or if the device could not be found.
            BleakDBusError: If there was a D-Bus error
            asyncio.TimeoutError: If the connection timed out
        """
        logger.debug(f"Connecting to device @ {self.address} with {self._adapter}")

        if self.is_connected:
            raise BleakError("Client is already connected")

        if not BlueZFeatures.checked_bluez_version:
            await BlueZFeatures.check_bluez_version()
        if not BlueZFeatures.supported_version:
            raise BleakError("Bleak requires BlueZ >= 5.43.")
        # A Discover must have been run before connecting to any devices.
        # Find the desired device before trying to connect.
        timeout = kwargs.get("timeout", self._timeout)
        if self._device_path is None:
            device = await BleakScannerBlueZDBus.find_device_by_address(
                self.address, timeout=timeout, adapter=self._adapter
            )

            if device:
                self._device_info = device.details.get("props")
                self._device_path = device.details["path"]
            else:
                raise BleakError(
                    "Device with address {0} was not found.".format(self.address)
                )

        manager = await get_global_bluez_manager()

        # Each BLE connection session needs a new D-Bus connection to avoid a
        # BlueZ quirk where notifications are automatically enabled on reconnect.
        self._bus = await MessageBus(
            bus_type=BusType.SYSTEM, negotiate_unix_fd=True
        ).connect()

        def on_connected_changed(connected: bool) -> None:
            if not connected:
                logger.debug(f"Device disconnected ({self._device_path})")

                self._is_connected = False

                if self._disconnect_monitor_event:
                    self._disconnect_monitor_event.set()
                    self._disconnect_monitor_event = None

                self._cleanup_all()
                if self._disconnected_callback is not None:
                    self._disconnected_callback(self)
                disconnecting_event = self._disconnecting_event
                if disconnecting_event:
                    disconnecting_event.set()

        def on_value_changed(char_path: str, value: bytes) -> None:
            if char_path in self._notification_callbacks:
                handle = extract_service_handle_from_path(char_path)
                self._notification_callbacks[char_path](handle, bytearray(value))

        watcher = manager.add_device_watcher(
            self._device_path, on_connected_changed, on_value_changed
        )
        self._remove_device_watcher = lambda: manager.remove_device_watcher(watcher)

        try:
            try:
                async with async_timeout.timeout(timeout):
                    reply = await self._bus.call(
                        Message(
                            destination=defs.BLUEZ_SERVICE,
                            interface=defs.DEVICE_INTERFACE,
                            path=self._device_path,
                            member="Connect",
                        )
                    )
                assert_reply(reply)

                self._is_connected = True
            except BaseException:
                # calling Disconnect cancels any pending connect request
                if self._bus:
                    # If disconnected callback already fired, this will be a no-op
                    # since self._bus will be None and the _cleanup_all call will
                    # have already disconnected.
                    try:
                        reply = await self._bus.call(
                            Message(
                                destination=defs.BLUEZ_SERVICE,
                                interface=defs.DEVICE_INTERFACE,
                                path=self._device_path,
                                member="Disconnect",
                            )
                        )
                        try:
                            assert_reply(reply)
                        except BleakDBusError as e:
                            # if the object no longer exists, then we know we
                            # are disconnected for sure, so don't need to log a
                            # warning about it
                            if e.dbus_error != ErrorType.UNKNOWN_OBJECT.value:
                                raise
                    except Exception as e:
                        logger.warning(
                            f"Failed to cancel connection ({self._device_path}): {e}"
                        )

                raise

            # Create a task that runs until the device is disconnected.
            self._disconnect_monitor_event = asyncio.Event()
            asyncio.ensure_future(self._disconnect_monitor())

            # Get all services. This means making the actual connection.
            await self.get_services()

            return True
        except BaseException:
            self._cleanup_all()
            raise

    async def _disconnect_monitor(self) -> None:
        # This task runs until the device is disconnected. If the task is
        # cancelled, it probably means that the event loop crashed so we
        # try to disconnected the device. Otherwise BlueZ will keep the device
        # connected even after Python exits. This will only work if the event
        # loop is called with asyncio.run() or otherwise runs pending tasks
        # after the original event loop stops. This will also cause an exception
        # if a run loop is stopped before the device is disconnected since this
        # task will still be running and asyncio complains if a loop with running
        # tasks is stopped.
        try:
            await self._disconnect_monitor_event.wait()
        except asyncio.CancelledError:
            try:
                # by using send() instead of call(), we ensure that the message
                # gets sent, but we don't wait for a reply, which could take
                # over one second while the device disconnects.
                await self._bus.send(
                    Message(
                        destination=defs.BLUEZ_SERVICE,
                        path=self._device_path,
                        interface=defs.DEVICE_INTERFACE,
                        member="Disconnect",
                    )
                )
            except Exception:
                pass

    def _cleanup_all(self) -> None:
        """
        Free all the allocated resource in DBus. Use this method to
        eventually cleanup all otherwise leaked resources.
        """
        logger.debug(f"_cleanup_all({self._device_path})")

        if self._remove_device_watcher:
            self._remove_device_watcher()
            self._remove_device_watcher = None

        if not self._bus:
            logger.debug(f"already disconnected ({self._device_path})")
            return

        # Try to disconnect the System Bus.
        try:
            self._bus.disconnect()

            # work around https://github.com/altdesktop/python-dbus-next/issues/112
            self._bus._sock.close()
        except Exception as e:
            logger.error(
                f"Attempt to disconnect system bus failed ({self._device_path}): {e}"
            )
        else:
            # Critical to remove the `self._bus` object here to since it was
            # closed above. If not, calls made to it later could lead to
            # a stuck client.
            self._bus = None

            # Reset all stored services.
            self.services = BleakGATTServiceCollection()
            self._services_resolved = False

    async def disconnect(self) -> bool:
        """Disconnect from the specified GATT server.

        Returns:
            Boolean representing if device is disconnected.

        Raises:
            BleakDBusError: If there was a D-Bus error
            asyncio.TimeoutError if the device was not disconnected within 10 seconds
        """
        logger.debug(f"Disconnecting ({self._device_path})")

        if self._bus is None:
            # No connection exists. Either one hasn't been created or
            # we have already called disconnect and closed the D-Bus
            # connection.
            logger.debug(f"already disconnected ({self._device_path})")
            return True

        if self._disconnecting_event:
            # another call to disconnect() is already in progress
            logger.debug(f"already in progress ({self._device_path})")
            async with async_timeout.timeout(10):
                await self._disconnecting_event.wait()
        elif self.is_connected:
            self._disconnecting_event = asyncio.Event()
            try:
                # Try to disconnect the actual device/peripheral
                reply = await self._bus.call(
                    Message(
                        destination=defs.BLUEZ_SERVICE,
                        path=self._device_path,
                        interface=defs.DEVICE_INTERFACE,
                        member="Disconnect",
                    )
                )
                assert_reply(reply)
                async with async_timeout.timeout(10):
                    await self._disconnecting_event.wait()
            finally:
                self._disconnecting_event = None

        # sanity check to make sure _cleanup_all() was triggered by the
        # "PropertiesChanged" signal handler and that it completed successfully
        assert self._bus is None

        return True

    async def pair(self, *args, **kwargs) -> bool:
        """Pair with the peripheral.

        You can use ConnectDevice method if you already know the MAC address of the device.
        Else you need to StartDiscovery, Trust, Pair and Connect in sequence.

        Returns:
            Boolean regarding success of pairing.

        """
        # See if it is already paired.
        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=self._device_path,
                interface=defs.PROPERTIES_INTERFACE,
                member="Get",
                signature="ss",
                body=[defs.DEVICE_INTERFACE, "Paired"],
            )
        )
        assert_reply(reply)
        if reply.body[0].value:
            logger.debug(
                f"BLE device @ {self.address} already paired with {self._adapter}"
            )
            return True

        # Set device as trusted.
        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=self._device_path,
                interface=defs.PROPERTIES_INTERFACE,
                member="Set",
                signature="ssv",
                body=[defs.DEVICE_INTERFACE, "Trusted", Variant("b", True)],
            )
        )
        assert_reply(reply)

        logger.debug(
            "Pairing to BLE device @ {0} with {1}".format(self.address, self._adapter)
        )

        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=self._device_path,
                interface=defs.DEVICE_INTERFACE,
                member="Pair",
            )
        )
        assert_reply(reply)

        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=self._device_path,
                interface=defs.PROPERTIES_INTERFACE,
                member="Get",
                signature="ss",
                body=[defs.DEVICE_INTERFACE, "Paired"],
            )
        )
        assert_reply(reply)

        return reply.body[0].value

    async def unpair(self) -> bool:
        """Unpair with the peripheral.

        Returns:
            Boolean regarding success of unpairing.

        """
        warnings.warn(
            "Unpairing is seemingly unavailable in the BlueZ DBus API at the moment."
        )
        return False

    @property
    def is_connected(self) -> bool:
        """Check connection status between this client and the server.

        Returns:
            Boolean representing connection status.

        """
        return self._DeprecatedIsConnectedReturn(
            False if self._bus is None else self._is_connected
        )

    async def _acquire_mtu(self) -> None:
        """Acquires the MTU for this device by calling the "AcquireWrite" or
        "AcquireNotify" method of the first characteristic that has such a method.

        This method only needs to be called once, after connecting to the device
        but before accessing the ``mtu_size`` property.

        If a device uses encryption on characteristics, it will need to be bonded
        first before calling this method.
        """
        # This will try to get the "best" characteristic for getting the MTU.
        # We would rather not start notifications if we don't have to.
        try:
            method = "AcquireWrite"
            char = next(
                c
                for c in self.services.characteristics.values()
                if "write-without-response" in c.properties
            )
        except StopIteration:
            method = "AcquireNotify"
            char = next(
                c
                for c in self.services.characteristics.values()
                if "notify" in c.properties
            )

        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=char.path,
                interface=defs.GATT_CHARACTERISTIC_INTERFACE,
                member=method,
                signature="a{sv}",
                body=[{}],
            )
        )
        assert_reply(reply)

        # we aren't actually using the write or notify, we just want the MTU
        os.close(reply.unix_fds[0])
        self._mtu_size = reply.body[1]

    @property
    def mtu_size(self) -> int:
        """Get ATT MTU size for active connection"""
        if self._mtu_size is None:
            warnings.warn(
                "Using default MTU value. Call _acquire_mtu() or set _mtu_size first to avoid this warning."
            )
            return 23

        return self._mtu_size

    # GATT services methods

    async def get_services(self, **kwargs) -> BleakGATTServiceCollection:
        """Get all services registered for this GATT server.

        Returns:
           A :py:class:`bleak.backends.service.BleakGATTServiceCollection` with this device's services tree.

        """
        if not self.is_connected:
            raise BleakError("Not connected")

        if self._services_resolved:
            return self.services

        manager = await get_global_bluez_manager()

        self.services = await manager.get_services(self._device_path)
        self._services_resolved = True

        return self.services

    # IO methods

    async def read_gatt_char(
        self,
        char_specifier: Union[BleakGATTCharacteristicBlueZDBus, int, str, UUID],
        **kwargs,
    ) -> bytearray:
        """Perform read operation on the specified GATT characteristic.

        Args:
            char_specifier (BleakGATTCharacteristicBlueZDBus, int, str or UUID): The characteristic to read from,
                specified by either integer handle, UUID or directly by the
                BleakGATTCharacteristicBlueZDBus object representing it.

        Returns:
            (bytearray) The read data.

        """
        if not self.is_connected:
            raise BleakError("Not connected")

        if not isinstance(char_specifier, BleakGATTCharacteristicBlueZDBus):
            characteristic = self.services.get_characteristic(char_specifier)
        else:
            characteristic = char_specifier

        if not characteristic:
            # Special handling for BlueZ >= 5.48, where Battery Service (0000180f-0000-1000-8000-00805f9b34fb:)
            # has been moved to interface org.bluez.Battery1 instead of as a regular service.
            if (
                str(char_specifier) == "00002a19-0000-1000-8000-00805f9b34fb"
                and BlueZFeatures.hides_battery_characteristic
            ):
                reply = await self._bus.call(
                    Message(
                        destination=defs.BLUEZ_SERVICE,
                        path=self._device_path,
                        interface=defs.PROPERTIES_INTERFACE,
                        member="GetAll",
                        signature="s",
                        body=[defs.BATTERY_INTERFACE],
                    )
                )
                assert_reply(reply)
                # Simulate regular characteristics read to be consistent over all platforms.
                value = bytearray([reply.body[0]["Percentage"].value])
                logger.debug(
                    "Read Battery Level {0} | {1}: {2}".format(
                        char_specifier, self._device_path, value
                    )
                )
                return value
            if (
                str(char_specifier) == "00002a00-0000-1000-8000-00805f9b34fb"
                and BlueZFeatures.hides_device_name_characteristic
            ):
                # Simulate regular characteristics read to be consistent over all platforms.
                manager = await get_global_bluez_manager()
                value = bytearray(manager.get_device_name(self._device_path).encode())
                logger.debug(
                    "Read Device Name {0} | {1}: {2}".format(
                        char_specifier, self._device_path, value
                    )
                )
                return value

            raise BleakError(
                "Characteristic with UUID {0} could not be found!".format(
                    char_specifier
                )
            )

        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=characteristic.path,
                interface=defs.GATT_CHARACTERISTIC_INTERFACE,
                member="ReadValue",
                signature="a{sv}",
                body=[{}],
            )
        )
        assert_reply(reply)
        value = bytearray(reply.body[0])

        logger.debug(
            "Read Characteristic {0} | {1}: {2}".format(
                characteristic.uuid, characteristic.path, value
            )
        )
        return value

    async def read_gatt_descriptor(self, handle: int, **kwargs) -> bytearray:
        """Perform read operation on the specified GATT descriptor.

        Args:
            handle (int): The handle of the descriptor to read from.

        Returns:
            (bytearray) The read data.

        """
        if not self.is_connected:
            raise BleakError("Not connected")

        descriptor = self.services.get_descriptor(handle)
        if not descriptor:
            raise BleakError("Descriptor with handle {0} was not found!".format(handle))

        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=descriptor.path,
                interface=defs.GATT_DESCRIPTOR_INTERFACE,
                member="ReadValue",
                signature="a{sv}",
                body=[{}],
            )
        )
        assert_reply(reply)
        value = bytearray(reply.body[0])

        logger.debug(
            "Read Descriptor {0} | {1}: {2}".format(handle, descriptor.path, value)
        )
        return value

    async def write_gatt_char(
        self,
        char_specifier: Union[BleakGATTCharacteristicBlueZDBus, int, str, UUID],
        data: Union[bytes, bytearray, memoryview],
        response: bool = False,
    ) -> None:
        """Perform a write operation on the specified GATT characteristic.

        .. note::

            The version check below is for the "type" option to the
            "Characteristic.WriteValue" method that was added to `Bluez in 5.51
            <https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit?id=fa9473bcc48417d69cc9ef81d41a72b18e34a55a>`_
            Before that commit, ``Characteristic.WriteValue`` was only "Write with
            response". ``Characteristic.AcquireWrite`` was `added in Bluez 5.46
            <https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/doc/gatt-api.txt?id=f59f3dedb2c79a75e51a3a0d27e2ae06fefc603e>`_
            which can be used to "Write without response", but for older versions
            of Bluez, it is not possible to "Write without response".

        Args:
            char_specifier (BleakGATTCharacteristicBlueZDBus, int, str or UUID): The characteristic to write
                to, specified by either integer handle, UUID or directly by the
                BleakGATTCharacteristicBlueZDBus object representing it.
            data (bytes or bytearray): The data to send.
            response (bool): If write-with-response operation should be done. Defaults to `False`.

        """
        if not self.is_connected:
            raise BleakError("Not connected")

        if not isinstance(char_specifier, BleakGATTCharacteristicBlueZDBus):
            characteristic = self.services.get_characteristic(char_specifier)
        else:
            characteristic = char_specifier

        if not characteristic:
            raise BleakError("Characteristic {0} was not found!".format(char_specifier))
        if (
            "write" not in characteristic.properties
            and "write-without-response" not in characteristic.properties
        ):
            raise BleakError(
                "Characteristic %s does not support write operations!"
                % str(characteristic.uuid)
            )
        if not response and "write-without-response" not in characteristic.properties:
            response = True
            # Force response here, since the device only supports that.
        if (
            response
            and "write" not in characteristic.properties
            and "write-without-response" in characteristic.properties
        ):
            response = False
            logger.warning(
                "Characteristic %s does not support Write with response. Trying without..."
                % str(characteristic.uuid)
            )

        # See docstring for details about this handling.
        if not response and not BlueZFeatures.can_write_without_response:
            raise BleakError("Write without response requires at least BlueZ 5.46")
        if response or not BlueZFeatures.write_without_response_workaround_needed:
            # TODO: Add OnValueUpdated handler for response=True?
            reply = await self._bus.call(
                Message(
                    destination=defs.BLUEZ_SERVICE,
                    path=characteristic.path,
                    interface=defs.GATT_CHARACTERISTIC_INTERFACE,
                    member="WriteValue",
                    signature="aya{sv}",
                    body=[
                        bytes(data),
                        {"type": Variant("s", "request" if response else "command")},
                    ],
                )
            )
            assert_reply(reply)
        else:
            # Older versions of BlueZ don't have the "type" option, so we have
            # to write the hard way. This isn't the most efficient way of doing
            # things, but it works.
            reply = await self._bus.call(
                Message(
                    destination=defs.BLUEZ_SERVICE,
                    path=characteristic.path,
                    interface=defs.GATT_CHARACTERISTIC_INTERFACE,
                    member="AcquireWrite",
                    signature="a{sv}",
                    body=[{}],
                )
            )
            assert_reply(reply)
            fd = reply.unix_fds[0]
            try:
                os.write(fd, data)
            finally:
                os.close(fd)

        logger.debug(
            "Write Characteristic {0} | {1}: {2}".format(
                characteristic.uuid, characteristic.path, data
            )
        )

    async def write_gatt_descriptor(
        self, handle: int, data: Union[bytes, bytearray, memoryview]
    ) -> None:
        """Perform a write operation on the specified GATT descriptor.

        Args:
            handle (int): The handle of the descriptor to read from.
            data (bytes or bytearray): The data to send.

        """
        if not self.is_connected:
            raise BleakError("Not connected")

        descriptor = self.services.get_descriptor(handle)
        if not descriptor:
            raise BleakError("Descriptor with handle {0} was not found!".format(handle))

        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=descriptor.path,
                interface=defs.GATT_DESCRIPTOR_INTERFACE,
                member="WriteValue",
                signature="aya{sv}",
                body=[bytes(data), {"type": Variant("s", "command")}],
            )
        )
        assert_reply(reply)

        logger.debug(
            "Write Descriptor {0} | {1}: {2}".format(handle, descriptor.path, data)
        )

    async def start_notify(
        self,
        char_specifier: Union[BleakGATTCharacteristicBlueZDBus, int, str, UUID],
        callback: Callable[[int, bytearray], None],
        **kwargs,
    ) -> None:
        """Activate notifications/indications on a characteristic.

        Callbacks must accept two inputs. The first will be a integer handle of the characteristic generating the
        data and the second will be a ``bytearray`` containing the data sent from the connected server.

        .. code-block:: python

            def callback(sender: int, data: bytearray):
                print(f"{sender}: {data}")
            client.start_notify(char_uuid, callback)

        Args:
            char_specifier (BleakGATTCharacteristicBlueZDBus, int, str or UUID): The characteristic to activate
                notifications/indications on a characteristic, specified by either integer handle,
                UUID or directly by the BleakGATTCharacteristicBlueZDBus object representing it.
            callback (function): The function to be called on notification.
        """
        if not self.is_connected:
            raise BleakError("Not connected")

        if inspect.iscoroutinefunction(callback):

            def bleak_callback(s, d):
                asyncio.ensure_future(callback(s, d))

        else:
            bleak_callback = callback

        if not isinstance(char_specifier, BleakGATTCharacteristicBlueZDBus):
            characteristic = self.services.get_characteristic(char_specifier)
        else:
            characteristic = char_specifier

        if not characteristic:
            # Special handling for BlueZ >= 5.48, where Battery Service (0000180f-0000-1000-8000-00805f9b34fb:)
            # has been moved to interface org.bluez.Battery1 instead of as a regular service.
            # The org.bluez.Battery1 on the other hand does not provide a notification method, so here we cannot
            # provide this functionality...
            # See https://kernel.googlesource.com/pub/scm/bluetooth/bluez/+/refs/tags/5.48/doc/battery-api.txt
            if str(char_specifier) == "00002a19-0000-1000-8000-00805f9b34fb" and (
                self._hides_battery_characteristic
            ):
                raise BleakError(
                    "Notifications on Battery Level Char ({0}) is not "
                    "possible in BlueZ >= 5.48. Use regular read instead.".format(
                        char_specifier
                    )
                )
            raise BleakError(
                "Characteristic with UUID {0} could not be found!".format(
                    char_specifier
                )
            )

        self._notification_callbacks[characteristic.path] = bleak_callback

        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=characteristic.path,
                interface=defs.GATT_CHARACTERISTIC_INTERFACE,
                member="StartNotify",
            )
        )
        assert_reply(reply)

    async def stop_notify(
        self,
        char_specifier: Union[BleakGATTCharacteristicBlueZDBus, int, str, UUID],
    ) -> None:
        """Deactivate notification/indication on a specified characteristic.

        Args:
            char_specifier (BleakGATTCharacteristicBlueZDBus, int, str or UUID): The characteristic to deactivate
                notification/indication on, specified by either integer handle, UUID or
                directly by the BleakGATTCharacteristicBlueZDBus object representing it.

        """
        if not self.is_connected:
            raise BleakError("Not connected")

        if not isinstance(char_specifier, BleakGATTCharacteristicBlueZDBus):
            characteristic = self.services.get_characteristic(char_specifier)
        else:
            characteristic = char_specifier
        if not characteristic:
            raise BleakError("Characteristic {} not found!".format(char_specifier))

        reply = await self._bus.call(
            Message(
                destination=defs.BLUEZ_SERVICE,
                path=characteristic.path,
                interface=defs.GATT_CHARACTERISTIC_INTERFACE,
                member="StopNotify",
            )
        )
        assert_reply(reply)

        self._notification_callbacks.pop(characteristic.path, None)


from yhttp import statuscode, json, validate, statuses
from pony.orm import db_session, select

from .rollup import app
from .models import Artist
from .constants import PAGESIZE_MAX

artists = app.route(r'/artists')
artist = app.route(r'/artists/(\d+)')

@artists
@statuscode('204 No Content')
def options(req):
    req.response.headers['Allow'] = 'OPTIONS, GET'

@artist
@validate(nobody=True)
@json
@db_session
def get(req, id):
    artist = select(
        (a.id, a.title, len(a.songs))
        for a in Artist
        if a.id == id
    ).get()

    if artist is None:
        raise statuses.notfound()

    id, title, songs = artist
    return dict(
        id=id,
        title=title,
        songs=songs,
    )

@artists
@validate(nobody=True, fields=dict(
    page=dict(type_=int),
    pagesize=dict(
        type_=int,
        maximum=PAGESIZE_MAX
    )
))
@json
@db_session
def get(req, *, page=1, pagesize=20):
    out = []
    query = select(
        (a.id, a.title, len(a.songs))
        for a in Artist
    )
    for id, title, songs in query.page(page, pagesize):
        out.append(dict(
            id=id,
            title=title,
            songs=songs,
        ))

    return out