from email.mime import image
from turtle import position
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import math
#Use Affine transformation formula to implement image rotation ,twist and mirror
def affine(img,func,degree):
    if func == "mirror":
        kernel = np.array([[-1,0,0],[0,1,0],[0,0,1]])
        img_new=np.zeros(img.shape)
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                position = np.array([i,j,1])
                position_new = np.dot(kernel,position)
                img_new[img.shape[0]-1+position_new[0],position_new[1],:]=img[i,j,:]
        return Image.fromarray(img_new.astype(np.uint8))
    elif func == "rotate":
        kernel = np.array([ [math.cos(degree*math.pi/180.0),    math.sin(degree*math.pi/180.0), 0],\
                            [-math.sin(degree*math.pi/180.0),   math.cos(degree*math.pi/180.0), 0],\
                            [0,                                 0,                              1]])
        img_new=np.zeros([int(img.shape[0]*math.sqrt(2)),int(img.shape[1]*math.sqrt(2)),img.shape[2]])
        positions=[]
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                position = np.array([i,j,1])
                position_new = np.dot(kernel,position)
                positions.append([position_new[0],position_new[1],i,j])
        positions = np.array(positions)
        mina = np.min(positions[:,0],axis=0)
        minb = np.min(positions[:,1],axis=0)
        for i in range(positions.shape[0]):
            img_new[int(positions[i,0]-mina),int(positions[i,1]-minb),:]=img[int(positions[i,2]),int(positions[i,3]),:]
        #Fill the empty area with the mean value of the nearest 8 pixels
        for i in range(img_new.shape[0]):
            for j in range(img_new.shape[1]):
                if np.sum(img_new[i,j,:])==0:
                    img_new[i,j,:]=np.mean(
                        img_new[max(0,i-1):min(img_new.shape[0],i+2),max(0,j-1):min(img_new.shape[1],j+2),:],axis=(0,1))
        return Image.fromarray(img_new.astype(np.uint8))
    elif func == "twist":
        kernel = np.array([[1,math.tan(degree*math.pi/180.0),0],[0,1,0],[0,0,1]])
        img_new = np.zeros([int(img.shape[0]+img.shape[1]*math.tan(degree*math.pi/180.0)),img.shape[1],img.shape[2]])
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                x = int(i*kernel[0,0]+j*kernel[0,1]+kernel[2,0])
                y = int(i*kernel[1,0]+j*kernel[1,1]+kernel[2,1])
                if x>=0 and x<img_new.shape[0] and y>=0 and y<img_new.shape[1]:
                    img_new[x,y,:]=img[i,j,:]
    return Image.fromarray(np.uint8(img_new))
#Read color image to array
filename="Lenna_(test_image).png"
img = np.array(Image.open(filename))
#Mirror
img_mirror = affine(img,"mirror",0)
#Rotate
img_rotate = affine(img,"rotate",30)
#Twist
img_twist = affine(img,"twist",30)
#Show image
plt.figure(figsize=(10,10))
plt.subplot(2,2,1);plt.title("Original Image");plt.imshow(img);plt.axis("off")
plt.subplot(2,2,2);plt.title("Mirror Image");plt.imshow(img_mirror);plt.axis("off")
plt.subplot(2,2,3);plt.title("Rotate Image");plt.imshow(img_rotate);plt.axis("off")
plt.subplot(2,2,4);plt.title("Twist Image");plt.imshow(img_twist);plt.axis("off")
plt.show()


class KthLargest:
    def kthLargest(self, k, nums):
        if not nums or k < 1 or k > len(nums):
            return -1

        low = 0
        high = len(nums) - 1
        while low <= high:
            storeIndex = self.partition(nums, low, high)

            if storeIndex == k - 1:
                return nums[storeIndex]
            elif storeIndex < k - 1:
                # if storeIndex < k - 1, means there are < k - 1 values less than nums[storeIndex]
                # the value we look for should fall in [storeIndex + 1, high]
                low = storeIndex + 1
            else:
                high = storeIndex - 1
        return -1

    # we use nums[end] as the pivot value
    # after this function, we will get a storeIndex
    # which is where the pivot value should be
    # that means there are # of storeIndex values less than nums[storeIndex]
    # note it's nums[storeIndex], because the last swap we did in this function
    def partition(self, nums, start, end):
        pivotValue = nums[end]

        storeIndex = start
        for i in range(start, end):
            if nums[i] > pivotValue: # this line decide we are looking for k th largets
                self.swap(nums, i, storeIndex)
                storeIndex += 1

        self.swap(nums, storeIndex, end)
        return storeIndex

    def swap(self, nums, a, b):
        nums[a], nums[b] = nums[b], nums[a]

def main():
    select = KthLargest()
    print(select.kthLargest(3, [9, 3, 2, 4, 8]))
    print(select.kthLargest(1, [1, 2, 3, 4, 5]))
    print(select.kthLargest(2, [1, 2, 3, 4, 5]))
    print(select.kthLargest(3, [1, 2, 3, 4, 5]))
    print(select.kthLargest(5, [1, 2, 3, 4, 5]))
    print(select.kthLargest(6, [1, 2, 3, 4, 5]))
    print(select.kthLargest(3, [2, 2, 2]))

if __name__ == '__main__':
    main()


#!/usr/local/bin/python3
"""
fpi - Fixed Point Iteration methods comparison.
"""

# basic imports
import os
from sys import argv
import argparse
import logging
import numpy as np

# import local modules
from jacobi import jacobi
from seidel import seidel
from sor import sor
import matreader
def save_solution(func, eps, x, error, residuals, path):
    name = ''.join(os.path.basename(path).split('.')[:-1])

    testdir_path = os.path.join(os.getcwd(), name + '_solutions')
    if not os.path.exists(testdir_path):
        os.makedirs(name=testdir_path, exist_ok=True)

    x_path = os.path.join(testdir_path, func.__name__+'.x.smtx')
    err_path = os.path.join(testdir_path, func.__name__+'.err.smtx')
    res_path = os.path.join(testdir_path, func.__name__+'.res.smtx')

    np.savetxt(x_path, x, fmt='%.10e', delimiter=' ', newline='\n')
    np.savetxt(err_path, error, fmt='%.10e', delimiter=' ', newline='\n')
    np.savetxt(res_path, residuals, fmt='%.10e', delimiter=' ', newline='\n')

def print_solution(func, A, b, eps, to_files=False, path=None):
    print(func.__name__,'computing started...')
    x, iterations, residuals = func(A, b, eps)
    print(func.__name__, 'completed:', iterations, 'iterations')
    # print(x)

    # print(func.__name__, 'error:')
    error = np.dot(A, x) - b
    # print(error)

    # print(func.__name__, 'residuals:')
    # print(residuals, sep='\n')

    if to_files:
        save_solution(func, eps, x, error, residuals, path)

    return x, residuals

def compare(mth1, mth2, x1, x2):
    print(mth1, '-', mth2, ':')
    print(x1-x2)

def build_graph_from(path, option):
    import grapher
    vector_path = os.path.join(path, option + '.res.smtx')

    r_v = matreader.read_vector(vector_path)
    r_v_name = option
    grapher.makeplot_residuals(r_v, r'$\varepsilon^k$', r'$\varepsilon^{k+1}$', r_v_name, path)
    grapher.makeplot_res_from_iters(r_v, r'Iterations', r'Residual', r_v_name, path)

def build_graphs_from(path):
    import grapher

    path_jacobi = os.path.join(path, 'jacobi.res.smtx')
    path_seidel = os.path.join(path, 'seidel.res.smtx')
    path_sor = os.path.join(path, 'sor.res.smtx')

    r_jacobi = matreader.read_vector(path_jacobi)
    r_seidel = matreader.read_vector(path_seidel)
    r_sor = matreader.read_vector(path_sor)

    grapher.makeplots_residuals(r_jacobi, r_seidel, r_sor,
                                r'$\varepsilon^k$', r'$\varepsilon^{k+1}$', path)
    grapher.makeplots_res_from_iters(r_jacobi, r_seidel, r_sor,
                            r'Iterations', r'Residual', path)

if __name__ == '__main__':

    def parse_args():
        """ Parses arguments and returns args object to the main program"""
        parser = argparse.ArgumentParser()
        parser.add_argument("OPT", type=str, nargs='?', default='all',
                            help="'jacobi', 'seidel' or 'sor' computation only")
        parser.add_argument("PATH", type=str,
                            help="The PATH to the matrix we want work to.")
        parser.add_argument("EPS", type=float, nargs='?', default=1e-5,
                            help="epsilon, the discrepancy from the precise solution.")
        parser.add_argument('-s', "--savefiles", action='store_true',
                            help="Save computation results to .smtx files.")
        parser.add_argument('-g', "--grapher", action='store_true',
                            help="Read .smtx vector from PATH and make plot.")
        return parser.parse_args()

    # Enable logging
    LOG = u'{}.log'.format(argv[0])
    logging.basicConfig(format=u'%(filename)s[LINE:%(lineno)d]# %(levelname)-8s [%(asctime)s] \
    %(message)s', level=logging.DEBUG, filename=LOG)

    # parse arguments
    ARGS = parse_args()
    PATH = ARGS.PATH
    OPT = ARGS.OPT
    EPS = ARGS.EPS
    SF = ARGS.savefiles
    GR = ARGS.grapher

    if GR and OPT == 'all':
        build_graphs_from(PATH)
    elif GR:
        build_graph_from(PATH, OPT)
    else:
        # Ax = b
        # Read A, b
        A, b = matreader.read(PATH)
        if OPT == 'all':
            x_jacobi, r_jacobi = print_solution(jacobi, A, b, EPS, SF, PATH)
            x_seidel, r_seidel = print_solution(seidel, A, b, EPS, SF, PATH)
            x_sor, r_sor = print_solution(sor, A, b, EPS, SF, PATH)

            compare('jacobi', 'seidel', x_jacobi, x_seidel)
            compare('jacobi', 'sor', x_jacobi, x_sor)
            compare('sor', 'seidel', x_sor, x_seidel)

        elif OPT == 'jacobi':
            x = print_solution(jacobi, A, b, EPS, SF, PATH)
        elif OPT == 'sor':
            x = print_solution(sor, A, b, EPS, SF, PATH)
        elif OPT == 'seidel':
            x = print_solution(seidel, A, b, EPS, SF, PATH)


import cv2
import os
from PIL import Image
import numpy as np
import pickle

# назначаем необходимые пути
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
image_dir = os.path.join(BASE_DIR,'images')
cascade_loc = os.path.join(BASE_DIR,'cascades/data/haarcascade_frontalface_default.xml')
output_dir = os.path.join(BASE_DIR,'training_output')
# устанавливаем папку вывода результата обучения
try:
	os.mkdir(output_dir)
except FileExistsError:
	print("output folder allready exists")

# инициализация каскадного классификатора по указанному пути
face_cascade = cv2.CascadeClassifier(cascade_loc)

# инициализация распознователя лиц по алгоритму "локальный бинарный паттерн"
recognizer = cv2.face.LBPHFaceRecognizer_create()

# подготовка переменных, в которых хранятся результаты обучения
current_id = 0
label_ids = {}  #dict
y_labels = []
x_train = []

# проходим по всем файлам и папкам среди которых обучаем модель
for root,dirs,files in os.walk(image_dir):
	for file in files:
		# отсеиваем только картинки
		if file.endswith('png') or file.endswith('jpg') or file.endswith('JPG'):
			path = os.path.join(root,file)
			label = os.path.basename(os.path.dirname(path)).replace(" ","-").lower()

			# если это новый для нас "персонаж", то создаем ему ячейку
			if label not in label_ids:
				label_ids[label] = current_id
				current_id += 1
			id_ = label_ids[label]

			# превращаем картинку в массив numpy, используя python image library
			pil_image = Image.open(path).convert("L")  # "L" превращает цветную картинку в черно-белую

			# оптимизируем картинку для изменения размеров
			size = (550,550)
			final_image = pil_image.resize(size, Image.ANTIALIAS)

			image_array = np.array(final_image, 'uint8')  # uint8 неподписанный int от 0 до 255 и переводим его в массив numpy
			# ищем объекты разного размера на входном изображении. Найденные объекты возвращаются в виде списка прямоугольников.
			faces = face_cascade.detectMultiScale(image_array)

			for (x,y,w,h) in faces:
				# roi = region of interrest = регион обнаружения лица(мы его уже нашли)
				roi = image_array[y:y+h,x:x+w]
				x_train.append(roi)   # откладываем данные для обучения
				y_labels.append(id_)   # храним каждое лицо с приписанным ему лейблом

# переключаемся на папку вывода перед началом обучения
os.chdir(output_dir)
with open("labels.pickle", 'wb') as f: # подготовка к записи байтов в виде файла
	print("сохраняем персонажей...", label_ids)
	pickle.dump(label_ids,f)   # сохраняем лейблы для будущего параллельного использования с базой данных по лицам, на основе общего с ней id

# непосредственно обучение собранными данными
recognizer.train(x_train,np.array(y_labels))
recognizer.save("trainner.yml")


import cv2
import mediapipe as mp
import time

class HandDetector():
    def __init__(self, mode=False, max_hands=2, detection_conf=0.5, tracking_conf=0.5):
        self.mode = mode
        self.max_hands = max_hands
        self.detection_conf = detection_conf
        self.tracking_conf = tracking_conf

        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.max_hands,
                                        self.detection_conf, self.tracking_conf)
        self.mpDraw = mp.solutions.drawing_utils

    def find_hands(self, img, draw = True):
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)

        if self.results.multi_hand_landmarks:
            for handLandMrks in self.results.multi_hand_landmarks:
                if draw:
                    self.mpDraw.draw_landmarks(img, handLandMrks,
                                                self.mpHands.HAND_CONNECTIONS)
        return img

    def find_position(self, img, hand_number=0, draw=True):
        land_mark_list = []

        h, w, c = img.shape
        if self.results.multi_hand_landmarks:
            true_hand = self.results.multi_hand_landmarks[hand_number]
            for id, landm in enumerate(true_hand.landmark):
                cx, cy = int(landm.x*w), int(landm.y*h)
                # print(id, cx, cy)
                land_mark_list.append([id, cx, cy])
                if draw:
                    cv2.circle(img, (cx, cy), 7, (255, 255, 255), cv2.FILLED)
        return land_mark_list

def main():
    pTime = 0
    cTime = 0

    capture = cv2.VideoCapture(0)

    detector = HandDetector()

    while True:
        success, img = capture.read()
        img = detector.find_hands(img)
        land_mark_list = detector.find_position(img)
        if len(land_mark_list) != 0:
            print(land_mark_list[4])

        cTime = time.time()
        fps = 1/(cTime-pTime)
        pTime = cTime

        cv2.putText(img, str(int(fps)), (10, 30), cv2.FONT_HERSHEY_PLAIN, 2, (0, 255, 0), 4)

        cv2.imshow("Image", img)
        cv2.waitKey(1)

if __name__ == "__main__":
    main()


__author__ = 'Jatin'
import time
import thread

import scanner
from bluetoothoperations import Bluetoothreceive

# imports end

y = True
scanobj = scanner.Scanner();
blueobj = Bluetoothreceive.bluetoothops();
thread.start_new_thread(blueobj.connect, ())
print("Starting execution")
while y:

    fo = open("writetest.txt", "r+")
    data = scanobj.scan();

    string = str.split(fo.read(), '!');
    print(len(string))
    for value in string:
        print(value + "\n")
    for data in string:
        blueobj.send_data(data)
        # sendobj = Sender.Sender();
        # sendobj.data_to_send(data);
        # sendobj.send_data();
        fo.close()
    print("for exited")
    time.sleep(2);


import contextlib
import os
import pathlib
import re
from unittest import mock

import pytest
from docker import errors as docker_errors
from google.api_core import exceptions as api_exception
from google.auth import exceptions as auth_exception

from composer_local_dev import constants, environment, errors

TEST_DATA_DIR = pathlib.Path(__file__).parent.parent / "test_data"

@pytest.fixture
@mock.patch("composer_local_dev.environment.docker.from_env")
@mock.patch("composer_local_dev.environment.files.resolve_dags_path")
def default_env(mocked_docker, mocked_dags, tmp_path):
    env_dir_path = tmp_path / ".compose" / "my_env"
    env = environment.Environment(
        env_dir_path=env_dir_path,
        project_id="",
        image_version="composer-2.0.8-airflow-2.2.3",
        location="location",
        dags_path=str(pathlib.Path("path")),
        dag_dir_list_interval=10,
    )
    return env

@contextlib.contextmanager
def working_directory(path):
    """Changes working directory and returns to previous on exit"""
    prev_cwd = pathlib.Path.cwd()
    os.chdir(path)
    try:
        yield
    finally:
        os.chdir(prev_cwd)

class TestEnvironment:
    @staticmethod
    def compare_envs(expected_env, actual_env):
        expected_env.docker_client = None
        actual_env.docker_client = None
        assert actual_env.__dict__ == expected_env.__dict__

    @mock.patch("composer_local_dev.environment.docker.from_env")
    def test_get_docker_client_error(self, mocked_docker, tmp_path):
        mocked_docker.side_effect = docker_errors.DockerException(
            "Connection aborted"
        )
        airflow_version = "2.2.5"
        composer_version = "2.0.3"
        exp_err = constants.DOCKER_NOT_AVAILABLE_ERROR.format(
            error="Connection aborted"
        )
        image_version = f"composer-{composer_version}-airflow-{airflow_version}"
        dags_path = str(pathlib.Path(tmp_path))
        with pytest.raises(
            errors.DockerNotAvailableError,
            match=exp_err,
        ):
            environment.Environment(
                image_version=image_version,
                project_id="",
                location="location",
                env_dir_path=pathlib.Path("env"),
                port=9000,
                dags_path=dags_path,
            )

    def test_get_docker_image_tag_from_image_version(self):
        image_version = "composer-2.0.8-airflow-2.2.3"
        expected_image = (
            "us-docker.pkg.dev/cloud-airflow-releaser/"
            "airflow-worker-scheduler-2-2-3/airflow-worker-scheduler-2-2-3:"
            "composer-2.0.8-airflow-2-2-3"
        )
        parsed_image = environment.get_docker_image_tag_from_image_version(
            image_version
        )
        assert expected_image == parsed_image

    @mock.patch("composer_local_dev.environment.artifactregistry_v1")
    def test_assert_image_exists_not_found(self, mocked_artifact):
        mock_client = mock.Mock()
        mock_client.get_tag.side_effect = api_exception.NotFound("")
        mocked_artifact.ArtifactRegistryClient.return_value = mock_client
        image_version = "composer-1.0.0-airflow-2.2.0"
        image_tag = "composer-1.0.0-airflow-2-2-0"
        with pytest.raises(
            errors.ImageNotFoundError,
            match=re.escape(
                constants.IMAGE_TAG_DOES_NOT_EXIST_ERROR.format(
                    image_tag=image_tag
                )
            ),
        ):
            environment.assert_image_exists(image_version)

    @mock.patch("composer_local_dev.environment.artifactregistry_v1")
    def test_assert_image_exists_permission_denied(self, mocked_artifact):
        mock_client = mock.Mock()
        mock_client.get_tag.side_effect = api_exception.PermissionDenied("")
        mocked_artifact.ArtifactRegistryClient.return_value = mock_client
        image_version = "composer-1.0.0-airflow-2.2.0"
        image_tag = "composer-1.0.0-airflow-2-2-0"
        warning = (
            f"Received permission denied when checking image existence "
            f"for {image_tag}"
        )
        with pytest.warns(UserWarning, match=warning):
            environment.assert_image_exists(image_version)

    @mock.patch("composer_local_dev.environment.artifactregistry_v1")
    def test_assert_image_exists_auth_error(self, mocked_artifact):
        mock_client = mock.Mock()
        error_msg = "Test error"
        exp_error = constants.AUTH_INVALID_ERROR.format(error=error_msg)
        mock_client.get_tag.side_effect = (
            auth_exception.DefaultCredentialsError(error_msg)
        )
        mocked_artifact.ArtifactRegistryClient.return_value = mock_client
        image_version = "composer-1.0.0-airflow-2.2.0"
        with pytest.raises(
            errors.InvalidAuthError,
            match=re.escape(exp_error),
        ):
            environment.assert_image_exists(image_version)

    @mock.patch("composer_local_dev.environment.docker.from_env")
    @mock.patch("composer_local_dev.environment.files.resolve_dags_path")
    @mock.patch(
        "composer_local_dev.environment.get_software_config_from_environment"
    )
    def test_from_source_with_empty_pypi_packages(
        self, mocked_fn, mocked_dags, mocked_docker
    ):
        image_version = "composer-2.0.8-airflow-2.2.3"
        mocked_sw = mock.Mock()
        mocked_sw.pypi_packages = {}
        mocked_sw.airflow_config_overrides = {}
        mocked_sw.env_variables = {}
        mocked_sw.image_version = "composer-2.0.8-airflow-2.2.3"
        mocked_fn.return_value = mocked_sw
        env = environment.Environment.from_source_environment(
            "test123",
            "project",
            "us-central1",
            pathlib.Path("composer", "env_dir"),
            8082,
            str(pathlib.Path("dags")),
        )
        expected_env = environment.Environment(
            env_dir_path=pathlib.Path("composer", "env_dir"),
            project_id="project",
            image_version=image_version,
            location="us-central1",
            dags_path=str(pathlib.Path("dags")),
            dag_dir_list_interval=10,
            port=8082,
        )
        self.compare_envs(expected_env, env)

    @mock.patch("composer_local_dev.environment.docker.from_env")
    @mock.patch("composer_local_dev.environment.files.resolve_dags_path")
    @mock.patch(
        "composer_local_dev.environment.get_docker_image_tag_from_image_version"
    )
    @mock.patch(
        "composer_local_dev.environment.get_software_config_from_environment"
    )
    def test_from_source_with_pypi_packages(
        self, mocked_sw_config, mocked_parse_image, mocked_dags, mocked_docker
    ):
        image_version = "composer-2.0.8-airflow-2.2.3"
        packages = {
            "requests": "",
            "black": "==21.0",
            "flake": "[toml]",
        }
        mocked_sw = mock.Mock()
        mocked_sw.pypi_packages = packages
        mocked_sw.airflow_config_overrides = {}
        mocked_sw.env_variables = {}
        mocked_sw.image_version = image_version
        mocked_sw_config.return_value = mocked_sw

        env = environment.Environment.from_source_environment(
            "env_name",
            "project_with_packages",
            "eu-west",
            pathlib.Path("composer", "env_name"),
            None,
            str(pathlib.Path("dags", "folder")),
        )
        expected_env = environment.Environment(
            env_dir_path=pathlib.Path("composer", "env_name"),
            project_id="project_with_packages",
            image_version=image_version,
            location="eu-west",
            dags_path=str(pathlib.Path("dags", "folder")),
            dag_dir_list_interval=10,
            port=8080,
            pypi_packages=packages,
        )
        self.compare_envs(expected_env, env)

    @mock.patch("composer_local_dev.environment.docker.from_env")
    @mock.patch("composer_local_dev.environment.files.resolve_dags_path")
    @mock.patch(
        "composer_local_dev.environment.get_docker_image_tag_from_image_version"
    )
    @mock.patch(
        "composer_local_dev.environment.get_software_config_from_environment"
    )
    def test_from_source_with_env_variables(
        self, mocked_sw_config, mocked_parse_image, mocked_dags, mocked_docker
    ):
        image_version = "composer-2.0.8-airflow-2.2.3"
        airflow_overrides_from_api = {
            "section-key": "VALUE",
            "section-key2": "VALUE",
        }
        env_variables_from_api = {
            "ENV_VARIABLE": "VALUE",
            "OTHER_variable": "123",
        }
        env_variables_parsed = {
            "AIRFLOW__SECTION__KEY": "VALUE",
            "AIRFLOW__SECTION__KEY2": "VALUE",
            "ENV_VARIABLE": "",
            "OTHER_variable": "",
        }
        mocked_sw = mock.Mock()
        mocked_sw.pypi_packages = {}
        mocked_sw.airflow_config_overrides = airflow_overrides_from_api
        mocked_sw.env_variables = env_variables_from_api
        mocked_sw.image_version = image_version
        mocked_sw_config.return_value = mocked_sw

        env = environment.Environment.from_source_environment(
            "env_name",
            "project_with_packages",
            "eu-west",
            pathlib.Path("composer", "env_name"),
            None,
            pathlib.Path("dags", "folder"),
        )
        expected_env = environment.Environment(
            env_dir_path=pathlib.Path("composer", "env_name"),
            project_id="project_with_packages",
            image_version=image_version,
            location="eu-west",
            dags_path=str(pathlib.Path("dags", "folder")),
            dag_dir_list_interval=10,
            port=8080,
            pypi_packages={},
            environment_vars=env_variables_parsed,
        )
        self.compare_envs(expected_env, env)

    @mock.patch("composer_local_dev.environment.docker.from_env")
    @mock.patch("composer_local_dev.environment.files.resolve_dags_path")
    @mock.patch(
        "composer_local_dev.environment.get_docker_image_tag_from_image_version"
    )
    @mock.patch(
        "composer_local_dev.environment.get_software_config_from_environment"
    )
    def test_from_source_with_block_listed_env_vars(
        self, mocked_sw_config, mocked_parse_image, mocked_dags, mocked_docker
    ):
        image_version = "composer-2.0.8-airflow-2.2.3"
        airflow_overrides_from_api = {
            "section-key": "VALUE",
            "core-executor": "Kubernetes",
        }
        env_variables_from_api = {
            "ENV_VARIABLE": "VALUE",
            "AIRFLOW_HOME": "123",
        }
        env_variables_parsed = {
            "AIRFLOW__SECTION__KEY": "VALUE",
            "ENV_VARIABLE": "",
        }
        mocked_sw = mock.Mock()
        mocked_sw.pypi_packages = {}
        mocked_sw.airflow_config_overrides = airflow_overrides_from_api
        mocked_sw.env_variables = env_variables_from_api
        mocked_sw.image_version = image_version
        mocked_sw_config.return_value = mocked_sw

        env = environment.Environment.from_source_environment(
            "env_name",
            "project_with_packages",
            "eu-west",
            pathlib.Path("composer", "env_name"),
            None,
            pathlib.Path("dags", "folder"),
        )
        expected_env = environment.Environment(
            env_dir_path=pathlib.Path("composer", "env_name"),
            project_id="project_with_packages",
            image_version=image_version,
            location="eu-west",
            dags_path=str(pathlib.Path("dags", "folder")),
            dag_dir_list_interval=10,
            port=8080,
            pypi_packages={},
            environment_vars=env_variables_parsed,
        )
        self.compare_envs(expected_env, env)

    @mock.patch("composer_local_dev.environment.docker.from_env")
    @pytest.mark.parametrize(
        "composer_version, airflow_version",
        [
            (
                "2.0.3",
                "2.2.3",
            ),
            (
                "1.10.0",
                "3.0.0",
            ),
        ],
    )
    def test_from_image(
        self, mocked_docker, composer_version, airflow_version, tmp_path
    ):
        image_version = f"composer-{composer_version}-airflow-{airflow_version}"
        dags_path = str(pathlib.Path(tmp_path))
        env = environment.Environment(
            image_version=image_version,
            project_id="",
            location="location",
            env_dir_path=pathlib.Path("env"),
            port=9000,
            dags_path=dags_path,
        )
        expected_env = environment.Environment(
            env_dir_path=pathlib.Path("env"),
            project_id="",
            image_version=image_version,
            location="location",
            dags_path=dags_path,
            dag_dir_list_interval=10,
            port=9000,
            pypi_packages={},
        )
        self.compare_envs(expected_env, env)

    @pytest.mark.parametrize(
        "pypi_packages",
        [
            {
                "requests": "",
                "black": "==21.0",
                "flake": "[toml]",
            },
            {},
        ],
    )
    @pytest.mark.parametrize("port", [None, 8090])
    @mock.patch("composer_local_dev.environment.docker.from_env")
    @mock.patch("composer_local_dev.environment.assert_image_exists")
    def test_create_and_load_from_config(
        self, mocked_docker, mocked_assert, pypi_packages, port, tmp_path
    ):
        env_dir_path = tmp_path / ".compose" / "my_env"
        image_version = "composer-2.0.8-airflow-2.2.3"
        expected_env = environment.Environment(
            env_dir_path=env_dir_path,
            project_id="",
            image_version=image_version,
            location="location",
            dags_path=str(pathlib.Path(tmp_path)),
            dag_dir_list_interval=10,
            port=port,
            pypi_packages=pypi_packages,
        )
        expected_env.create()

        env = environment.Environment.load_from_config(env_dir_path, port)
        env.pypi_packages = (
            pypi_packages  # load_from_config does not load pypi packages
        )
        self.compare_envs(expected_env, env)

    def test_missing_variables_env(self):
        env_dir = (TEST_DATA_DIR / "missing_composer").resolve()
        exp_error = (
            f"Environment variables file '{env_dir / 'variables.env'}' "
            f"not found."
        )
        with pytest.raises(errors.ComposerCliError) as err:
            environment.load_environment_variables(env_dir)
            assert str(err) == exp_error

    def test_load_environment_variables_filter_blocked_env_vars(self):
        env_dir = (TEST_DATA_DIR / "blocked_env_vars").resolve()
        expected_env_vars = {"RANDOM_NAME": "123"}
        env_vars = environment.load_environment_variables(env_dir)
        assert expected_env_vars == env_vars

    def test_load_environment_variables_commented(self):
        env_dir = (TEST_DATA_DIR / "commented_env_vars").resolve()
        expected_env_vars = {"ONLY_NAME": "abc"}
        env_vars = environment.load_environment_variables(env_dir)
        assert expected_env_vars == env_vars

    @mock.patch("composer_local_dev.environment.docker.from_env")
    @mock.patch("composer_local_dev.environment.assert_image_exists")
    def test_environment_vars_to_env_file(
        self, mocked_docker, mock_assert_image, tmp_path
    ):
        environment_vars = {
            "AIRFLOW__CORE__MAX_ACTIVE_RUNS_PER_DAG": "",
            "MY_VALUE": "1",
        }
        env_dir_path = tmp_path / ".compose" / "my_env"
        env_dir_path.mkdir(parents=True)
        image_version = "composer-2.0.8-airflow-2.2.3"
        env = environment.Environment(
            env_dir_path=env_dir_path,
            project_id="",
            image_version=image_version,
            location="location",
            dags_path=str(pathlib.Path(tmp_path)),
            dag_dir_list_interval=10,
            environment_vars=environment_vars,
        )
        env.environment_vars_to_env_file()
        expected_vars = [
            "# AIRFLOW__CORE__MAX_ACTIVE_RUNS_PER_DAG=",
            "# MY_VALUE=",
        ]
        actual_vars = []
        with open(env_dir_path / "variables.env") as fp:
            for line in fp:
                actual_vars.append(line.strip())
        assert actual_vars == expected_vars

    def test_invalid_env_variables(self):
        env_dir = (TEST_DATA_DIR / "invalid_variables").resolve()
        env_file_path = str(env_dir / "variables.env")
        exp_error = constants.INVALID_ENV_VARIABLES_FILE_ERROR.format(
            env_file_path=env_file_path, line="AIRFLOW_KEYVALUE"
        )
        with pytest.raises(errors.FailedToParseVariablesError) as err:
            environment.load_environment_variables(env_dir)
            assert str(err) == exp_error

    @mock.patch("composer_local_dev.environment.docker.from_env")
    @mock.patch(
        "composer_local_dev.environment.get_docker_image_tag_from_image_version"
    )
    def test_missing_requirements(self, mocked_docker, mocked_tag, tmpdir):
        env_dir = pathlib.Path(tmpdir)
        requirement_file = str(env_dir / "requirements.txt")
        env = environment.Environment(
            env_dir_path=env_dir,
            project_id="",
            image_version="",
            location="location",
            dags_path=str(env_dir),
        )
        exp_error = f"Missing '{requirement_file}' file."
        with pytest.raises(errors.ComposerCliError) as err:
            env.assert_requirements_exist()
            assert str(err) == exp_error

    @mock.patch("composer_local_dev.environment.docker.from_env")
    def test_get_container(self, mocked_docker, default_env):
        container = mock.Mock()
        default_env.docker_client.containers.get = mock.Mock(
            return_value=container
        )
        actual_container = default_env.get_container()
        assert actual_container == container

    @mock.patch("composer_local_dev.environment.docker.from_env")
    def test_get_container_assert_running_passing(
        self, mocked_docker, default_env
    ):
        container = mock.Mock()
        container.status = constants.ContainerStatus.RUNNING
        default_env.docker_client.containers.get = mock.Mock(
            return_value=container
        )
        actual_container = default_env.get_container(assert_running=True)
        assert actual_container == container

    @mock.patch("composer_local_dev.environment.docker.from_env")
    def test_get_container_assert_running_failing(
        self, mocked_docker, default_env
    ):
        container = mock.Mock()
        container.status = "other_status"
        default_env.docker_client.containers.get = mock.Mock(
            return_value=container
        )
        with pytest.raises(
            errors.EnvironmentNotRunningError, match=constants.ENV_NOT_RUNNING
        ):
            default_env.get_container(assert_running=True)

    @mock.patch("composer_local_dev.environment.docker.from_env")
    def test_get_container_not_started(self, mocked_docker, default_env):
        default_env.docker_client.containers.get.side_effect = (
            docker_errors.NotFound("")
        )
        with pytest.raises(
            errors.ComposerCliError,
            match=constants.ENV_NOT_RUNNING,
        ):
            default_env.get_container()

    @mock.patch("composer_local_dev.environment.docker.from_env")
    def test_get_container_any_error(self, mocked_docker, default_env):
        default_env.docker_client.containers.get.side_effect = ValueError(
            "Mocked error"
        )
        with pytest.raises(
            ValueError,
            match="Mocked error",
        ):
            default_env.get_container()

    @mock.patch("composer_local_dev.environment.get_image_mounts")
    def test_create_docker_container(self, mocked_mounts, default_env):
        default_env.create_docker_container()
        ports = {
            f"8080/tcp": default_env.port,
        }
        environment = {
            "AIRFLOW__API__AUTH_BACKEND": "airflow.api.auth.backend.default",
            "AIRFLOW__WEBSERVER__EXPOSE_CONFIG": "true",
            "AIRFLOW__CORE__LOAD_EXAMPLES": "false",
            "AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL": default_env.dag_dir_list_interval,
            "AIRFLOW__CORE__DAGS_FOLDER": "/home/airflow/gcs/dags",
            "AIRFLOW__CORE__PLUGINS_FOLDER": "/home/airflow/gcs/plugins",
            "AIRFLOW__WEBSERVER__RELOAD_ON_PLUGIN_CHANGE": "True",
            "COMPOSER_PYTHON_VERSION": "3",
            "AIRFLOW_HOME": "/home/airflow/airflow",
            "AIRFLOW_CONN_GOOGLE_CLOUD_DEFAULT": f"google-cloud-platform://?"
            f"extra__google_cloud_platform__project={default_env.project_id}&"
            f"extra__google_cloud_platform__scope="
            f"https://www.googleapis.com/auth/cloud-platform",
        }
        default_env.docker_client.containers.create.assert_called_with(
            default_env.image_tag,
            name="composer-local-dev-my_env",
            entrypoint="sh /home/airflow/entrypoint.sh",
            environment=environment,
            mounts=mocked_mounts(),
            ports=ports,
            mem_limit=constants.DOCKER_CONTAINER_MEMORY_LIMIT,
            detach=True,
        )

    @pytest.mark.parametrize(
        "container_exists, create_container", [(False, True), (True, False)]
    )
    @mock.patch("composer_local_dev.files.assert_dag_path_exists")
    @mock.patch("composer_local_dev.environment.assert_image_exists")
    @mock.patch("composer_local_dev.environment.files.create_empty_file")
    @mock.patch("composer_local_dev.environment.files.fix_file_permissions")
    @mock.patch("composer_local_dev.environment.files.fix_line_endings")
    def test_start_container(
        self,
        mocked_assert,
        mocked_dag_assert,
        mocked_create,
        mocked_fix,
        mocked_line_fix,
        container_exists,
        create_container,
        default_env,
    ):
        default_env.assert_requirements_exist = mock.Mock()
        default_env.get_container = mock.Mock()
        if not container_exists:
            default_env.get_container.side_effect = (
                errors.EnvironmentNotRunningError()
            )
        default_env.create_docker_container = mock.Mock()
        default_env.wait_for_start = mock.Mock()
        default_env.start()
        default_env.assert_requirements_exist.assert_called_once()
        # do not create container if it exists
        assert default_env.create_docker_container.call_count == int(
            create_container
        )
        default_env.wait_for_start.assert_called_once()

    @mock.patch("composer_local_dev.files.assert_dag_path_exists")
    @mock.patch("composer_local_dev.environment.assert_image_exists")
    @mock.patch("composer_local_dev.environment.files.create_empty_file")
    @mock.patch("composer_local_dev.environment.files.fix_file_permissions")
    @mock.patch("composer_local_dev.environment.files.fix_line_endings")
    def test_start_already_running(
        self,
        mocked_assert,
        mocked_dag_assert,
        mocked_create,
        mocked_fix,
        mocked_line_endings,
        default_env,
    ):
        default_env.assert_requirements_exist = mock.Mock()
        default_env.wait_for_start = mock.Mock()
        container = mock.Mock()
        container.status = "running"
        default_env.get_container = mock.Mock(return_value=container)
        exp_error = constants.ENVIRONMENT_ALREADY_RUNNING.format(name="my_env")
        with pytest.raises(
            errors.EnvironmentAlreadyRunningError, match=exp_error
        ):
            default_env.start()

    @mock.patch("composer_local_dev.files.assert_dag_path_exists")
    @mock.patch("composer_local_dev.environment.assert_image_exists")
    @mock.patch("composer_local_dev.environment.files.create_empty_file")
    @mock.patch("composer_local_dev.environment.files.fix_file_permissions")
    @mock.patch("composer_local_dev.environment.files.fix_line_endings")
    def test_restart_already_running(
        self,
        mocked_assert,
        mocked_dag_assert,
        mocked_create,
        mocked_fix,
        mocked_line_endings,
        default_env,
    ):
        default_env.assert_requirements_exist = mock.Mock()
        default_env.wait_for_start = mock.Mock()
        container = mock.Mock()
        container.status = "running"
        default_env.get_container = mock.Mock(return_value=container)
        exp_error = constants.ENVIRONMENT_ALREADY_RUNNING.format(name="my_env")
        default_env.restart()

    def test_describe_started(self, default_env):
        env_state = "running"
        default_env.status = mock.Mock(return_value=env_state)
        default_env.prepare_env_description = mock.Mock()
        default_env.describe()
        default_env.prepare_env_description.assert_called_with(env_state)

    @mock.patch("composer_local_dev.utils.resolve_gcloud_config_path")
    def test_prepare_env_description_running(self, mocked_gcloud, default_env):
        env_state = "running"
        formatted_state = "[bold green]running[/]"
        port = 8081
        mocked_gcloud.return_value = "path"
        web_url = constants.WEBSERVER_URL_MESSAGE.format(port=port)
        exp_desc = constants.DESCRIBE_ENV_MESSAGE.format(
            name=default_env.name,
            state=formatted_state,
            web_url=web_url,
            image_version=default_env.image_version,
            dags_path=default_env.dags_path,
            gcloud_path="path",
        )
        default_env.get_host_port = mock.Mock(return_value=port)
        description = default_env.prepare_env_description(env_state)
        assert exp_desc == description

    @mock.patch("composer_local_dev.utils.resolve_gcloud_config_path")
    def test_prepare_env_description_not_running(
        self, mocked_gcloud, default_env
    ):
        env_state = "exited"
        formatted_state = "[bold red]exited[/]"
        port = 8081
        mocked_gcloud.return_value = "path"
        web_url = ""
        exp_desc = constants.DESCRIBE_ENV_MESSAGE.format(
            name=default_env.name,
            state=formatted_state,
            web_url=web_url,
            image_version=default_env.image_version,
            dags_path=default_env.dags_path,
            gcloud_path="path",
        )
        default_env.get_host_port = mock.Mock(return_value=port)
        description = default_env.prepare_env_description(env_state)
        assert exp_desc == description

    def test_create_docker_container_duplicate(self, default_env):
        default_env.get_image_mounts = mock.Mock()
        mocked_response = mock.Mock()
        mocked_response.status_code = constants.CONFLICT_ERROR_CODE
        default_env.docker_client.containers.create = mock.Mock(
            side_effect=docker_errors.APIError("", response=mocked_response)
        )

        with pytest.raises(
            errors.ComposerCliError,
            match="Composer local development for environment 'my_env' "
            "is already running. "
            "Stop or restart it if you want to run it.",
        ):
            default_env.create_docker_container()

    def test_create_docker_container_mount_permission(self, default_env):
        default_env.get_image_mounts = mock.Mock()
        mocked_response = mock.Mock()
        mocked_response.status_code = 400
        error = (
            'Bad Request ("invalid mount config for type "bind": '
            "bind source path does not exist"
        )
        default_env.docker_client.containers.create = mock.Mock(
            side_effect=docker_errors.APIError(
                "", explanation=error, response=mocked_response
            )
        )

        with pytest.raises(errors.EnvironmentStartError) as err:
            default_env.create_docker_container()
        assert (
            constants.DOCKER_PERMISSION_ERROR_HINT.format(
                docs_faq_url=constants.COMPOSER_FAQ_MOUNTING_LINK
            )
            in err.value.message
        )

    def test_create_docker_container_pull_not_existing_image(self, default_env):
        default_env.get_image_mounts = mock.Mock()
        response_mock = mock.Mock()
        response_mock.status_code = 450
        side_effect = [
            docker_errors.ImageNotFound("", response=response_mock),
            mock.DEFAULT,
        ]
        default_env.docker_client.containers.create = mock.Mock(
            side_effect=side_effect
        )
        default_env.pull_image = mock.Mock()
        default_env.create_docker_container()
        default_env.pull_image.assert_called_once()

    @mock.patch("composer_local_dev.files.assert_dag_path_exists")
    @mock.patch("composer_local_dev.environment.assert_image_exists")
    @mock.patch("composer_local_dev.environment.files.create_empty_file")
    @mock.patch("composer_local_dev.environment.files.fix_file_permissions")
    @mock.patch("composer_local_dev.environment.files.fix_line_endings")
    def test_start_used_port(
        self,
        mocked_assert,
        mocked_dag_assert,
        mocked_create,
        mocked_fix,
        mocked_line_fix,
        default_env,
    ):
        default_env.port = 8083
        default_env.assert_requirements_exist = mock.Mock()
        container = mock.Mock()
        mocked_response = mock.Mock()
        mocked_response.status_code = constants.SERVER_ERROR_CODE
        mocked_response.reason = (
            "Bind for 0.0.0.0:8080 failed: port is already allocated"
        )
        container.start.side_effect = docker_errors.APIError(
            "", response=mocked_response
        )
        default_env.get_or_create_container = mock.Mock(return_value=container)
        with pytest.raises(
            errors.ComposerCliError,
            match=constants.PORT_IN_USE_ERROR.format(port=8083),
        ):
            default_env.start()

    @pytest.mark.parametrize("remove_container", [True, False])
    def test_stop_container(self, remove_container, default_env):
        container = mock.Mock()
        default_env.get_container = mock.Mock(return_value=container)
        default_env.stop(remove_container=remove_container)
        container.stop.assert_called_once()
        assert container.remove.call_count == int(remove_container)

def get_container_logs_mock(log_lines, status="running"):
    container = mock.Mock()
    container.status = status
    container.logs = mock.Mock(return_value=log_lines)
    return mock.Mock(return_value=container)

class TestWaitForStart:
    @mock.patch(
        "composer_local_dev.environment.time.time",
        side_effect=[1, 1 + constants.OPERATION_TIMEOUT_SECONDS],
    )
    def test_wait_for_start_timeout(self, mocked_time, default_env):
        container = mock.Mock()
        container.status = "running"
        container.logs = mock.Mock(return_value=[b"Log lines"])
        default_env.get_container = mock.Mock(return_value=container)
        with pytest.raises(
            errors.ComposerCliError,
            match=f"Environment did not start in {constants.OPERATION_TIMEOUT_SECONDS} seconds.",
        ):
            default_env.wait_for_start()

    def test_wait_for_start_failed(self, default_env):
        default_env.get_container = get_container_logs_mock([], "not_running")
        with pytest.raises(
            errors.EnvironmentStartError,
            match=constants.ENVIRONMENT_FAILED_TO_START_ERROR,
        ):
            default_env.wait_for_start()

    def test_wait_for_start(self, default_env):
        log_lines = [b"Log lines"] * 10 + [b"Searching for files in path..."]
        default_env.get_container = get_container_logs_mock(log_lines)
        default_env.wait_for_start()

    def test_get_host_port(self, default_env):
        exp_port = 1234
        container_mock = mock.Mock()
        container_mock.ports = {"8080/tcp": [{"HostPort": exp_port}]}
        default_env.get_container = mock.Mock(return_value=container_mock)
        port = default_env.get_host_port()
        assert exp_port == port

    def test_get_host_port_invalid(self, default_env):
        exp_port = 1235
        container_mock = mock.Mock()
        container_mock.ports = {"8080/tcp": []}
        default_env.get_container = mock.Mock(return_value=container_mock)
        default_env.port = exp_port
        port = default_env.get_host_port()
        assert exp_port == port

class TestLogs:
    BINARY_LOG_LINE = b"Log lines\nwith multiline\n"
    BINARY_LOG_LINE_LIST = [b"Log lines", b"with multiline"]
    EXPECTED_LINES = "Log lines\nwith multiline\n\n"
    EXPECTED_LINES_FOR_FOLLOW = "Log lines\nwith multiline\n"
    TEST_10_LINES_FOLLOW = (
        10,
        True,
        BINARY_LOG_LINE_LIST,
        EXPECTED_LINES_FOR_FOLLOW,
    )
    TEST_10_LINES_NOT_FOLLOW = (10, False, BINARY_LOG_LINE, EXPECTED_LINES)
    TEST_ALL_LINES_FOLLOW = (
        "all",
        True,
        BINARY_LOG_LINE_LIST,
        EXPECTED_LINES_FOR_FOLLOW,
    )
    TEST_ALL_LINES_NOT_FOLLOW = ("all", False, BINARY_LOG_LINE, EXPECTED_LINES)

    @pytest.mark.parametrize(
        "max_lines,follow,log_lines,expected_lines",
        [
            TEST_10_LINES_FOLLOW,
            TEST_10_LINES_NOT_FOLLOW,
            TEST_ALL_LINES_FOLLOW,
            TEST_ALL_LINES_NOT_FOLLOW,
        ],
    )
    def test_get_10_lines_follow(
        self, default_env, max_lines, follow, log_lines, expected_lines, capsys
    ):
        log_lines = [b"Log lines", b"with multiline"]
        expected_lines = "Log lines\nwith multiline\n"
        default_env.get_container = get_container_logs_mock(log_lines)
        default_env.logs(max_lines=10, follow=True)
        captured = capsys.readouterr()
        assert expected_lines == captured.out

    def test_container_not_running(self, default_env):
        default_env.docker_client.containers.get.side_effect = (
            docker_errors.NotFound("")
        )
        with pytest.raises(
            errors.EnvironmentNotRunningError,
            match=constants.ENV_NOT_RUNNING,
        ):
            default_env.logs(10, False)

def test_get_environment_variables():
    project_id = "123"
    dag_interval = 105
    extra_vars = {"VAR_1": "123", "VAR_2": "a"}
    expected_vars = {
        "AIRFLOW__API__AUTH_BACKEND": "airflow.api.auth.backend.default",
        "AIRFLOW__WEBSERVER__EXPOSE_CONFIG": "true",
        "AIRFLOW__CORE__LOAD_EXAMPLES": "false",
        "AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL": 105,
        "AIRFLOW__CORE__DAGS_FOLDER": "/home/airflow/gcs/dags",
        "AIRFLOW__CORE__PLUGINS_FOLDER": "/home/airflow/gcs/plugins",
        "AIRFLOW__WEBSERVER__RELOAD_ON_PLUGIN_CHANGE": "True",
        "COMPOSER_PYTHON_VERSION": "3",
        "AIRFLOW_HOME": "/home/airflow/airflow",
        "AIRFLOW_CONN_GOOGLE_CLOUD_DEFAULT": "google-cloud-platform://?"
        "extra__google_cloud_platform__project=123&"
        "extra__google_cloud_platform__scope="
        "https://www.googleapis.com/auth/cloud-platform",
        **extra_vars,
    }
    default_vars = environment.get_default_environment_variables(
        dag_interval, project_id
    )
    actual_vars = {**default_vars, **extra_vars}
    assert expected_vars == actual_vars

@mock.patch("composer_local_dev.environment.docker.types.Mount", autospec=True)
def test_get_image_mounts(mocked_mount):
    path = pathlib.Path("path/dir")
    dags_path = "path/to/dags"
    gcloud_path = "config/path"
    requirements = path / "requirements.txt"
    airflow_db_path = path / "airflow.db"
    expected_mounts = [
        mock.call(
            source=str(requirements),
            target="/home/airflow/composer_requirements.txt",
            type="bind",
        ),
        mock.call(
            source=dags_path, target="/home/airflow/gcs/dags/", type="bind"
        ),
        mock.call(
            source=str(path / "plugins"),
            target="/home/airflow/gcs/plugins/",
            type="bind",
        ),
        mock.call(
            source=str(path / "data"),
            target="/home/airflow/airflow/data/",
            type="bind",
        ),
        mock.call(
            source=gcloud_path,
            target="/home/airflow/.config/gcloud",
            type="bind",
        ),
        mock.call(
            source=str(airflow_db_path),
            target="/home/airflow/airflow/airflow.db",
            type="bind",
        ),
    ]
    actual_mounts = environment.get_image_mounts(
        path, dags_path, gcloud_path, requirements
    )
    assert len(expected_mounts) == len(actual_mounts)
    mocked_mount.assert_has_calls(expected_mounts)

@mock.patch("composer_local_dev.environment.service_v1", autospec=True)
def test_get_software_config_from_environment_api_error(mocked_service):
    error_msg = "Foo error"
    mock_get_environment = mock.Mock()
    mock_get_environment.get_environment.side_effect = (
        api_exception.GoogleAPIError(error_msg)
    )
    mocked_service.EnvironmentsClient.return_value = mock_get_environment
    with pytest.raises(
        errors.ComposerCliError,
        match=constants.COMPOSER_SOFTWARE_CONFIG_API_ERROR.format(
            err=error_msg
        ),
    ):
        environment.get_software_config_from_environment("", "", "")

class TestGetContainer:
    def get_container(self, default_env):
        default_env

class TestGetImageVersion:
    def test_get_image_version_container_missing(self):
        image_version_in_config = "composer-2.0.8-airflow-2.2.30"
        env = mock.Mock()
        env.image_version = image_version_in_config
        env.get_container = mock.Mock(
            side_effect=errors.EnvironmentNotRunningError
        )
        assert image_version_in_config == environment.get_image_version(env)

    def test_get_image_version_no_tags(self):
        image_version_in_config = "composer-2.0.8-airflow-2.2.30"
        env = mock.Mock()
        env.image_version = image_version_in_config
        container = mock.Mock()
        container.image = mock.Mock()
        container.image.tags = []
        env.get_container = mock.Mock(return_value=container)
        assert image_version_in_config == environment.get_image_version(env)

    def test_get_image_version(self):
        image_version_in_config = "composer-2.0.8-airflow-2.2.30"
        image_version_in_container = "composer-2.0.8-airflow-2-2-3"
        expected_image_version = "composer-2.0.8-airflow-2.2.3"
        tag = f"container-name:{image_version_in_container}"
        env = mock.Mock()
        env.image_version = image_version_in_config
        container = mock.Mock()
        container.image = mock.Mock()
        container.image.tags = [tag]
        env.get_container = mock.Mock(return_value=container)
        assert expected_image_version == environment.get_image_version(env)

class TestEnvironmentConfig:
    @mock.patch(
        "composer_local_dev.environment.EnvironmentConfig.load_configuration_from_file"
    )
    @pytest.mark.parametrize(
        "config, error",
        [
            ({}, "composer_project_id"),
            ({"composer_project_id": ""}, "composer_image_version"),
        ],
    )
    def test_from_config_missing_keys(
        self, mocked_load_conf, tmp_path, config, error
    ):
        mocked_load_conf.return_value = config
        exp_error = (
            constants.MISSING_REQUIRED_PARAM_ERROR.format(param=error)
            + constants.ADD_DEBUG_ON_ERROR_INFO
        )
        with pytest.raises(
            errors.MissingRequiredParameterError, match=exp_error
        ):
            environment.EnvironmentConfig(tmp_path, None)

    def test_invalid_config(self):
        env_dir = (
            TEST_DATA_DIR / "one_env" / "composer" / "example_env"
        ).resolve()
        config_path = env_dir / "config.json"
        exp_error = constants.INVALID_CONFIGURATION_FILE_ERROR.format(
            config_path=config_path, error=""
        )
        with pytest.raises(
            errors.FailedToParseConfigError
        ) as err, working_directory(env_dir):
            environment.EnvironmentConfig(env_dir, None)
            assert str(err) == exp_error

    def test_missing_config(self):
        env_dir = (TEST_DATA_DIR / "missing_composer").resolve()
        exp_error = f"Configuration file '{env_dir / 'config.json'}' not found."
        with pytest.raises(errors.ComposerCliError) as err, working_directory(
            env_dir
        ):
            environment.EnvironmentConfig(env_dir, None)
            assert str(err) == exp_error

    @mock.patch(
        "composer_local_dev.environment.EnvironmentConfig.load_configuration_from_file"
    )
    @pytest.mark.parametrize(
        "param, value", [("dag_dir_list_interval", "abc"), ("port", "abc")]
    )
    def test_param_invalid_int(self, mocked_load_conf, tmp_path, param, value):
        valid_config = {
            "composer_image_version": "composer-2.0.25-airflow-2.2.5",
            "composer_location": "us-central1",
            "composer_project_id": "project",
            "dags_path": "/dags/",
            "dag_dir_list_interval": 10,
            "port": 8080,
        }
        valid_config[param] = value
        mocked_load_conf.return_value = valid_config
        exp_error = constants.INVALID_INT_VALUE_ERROR.format(
            param_name=param, value=value
        )
        with pytest.raises(errors.FailedToParseConfigParamIntError) as err:
            environment.EnvironmentConfig(tmp_path, None)
            assert str(err) == exp_error

    @mock.patch(
        "composer_local_dev.environment.EnvironmentConfig.load_configuration_from_file"
    )
    @pytest.mark.parametrize(
        "param, value, allowed_range",
        [
            ("dag_dir_list_interval", -1, "x>=0"),
            ("port", "8000000", "0<=x<=65536"),
        ],
    )
    def test_param_invalid_int_range(
        self, mocked_load_conf, tmp_path, param, value, allowed_range
    ):
        valid_config = {
            "composer_image_version": "composer-2.0.25-airflow-2.2.5",
            "composer_location": "us-central1",
            "composer_project_id": "project",
            "dags_path": "/dags/",
            "dag_dir_list_interval": 10,
            "port": 8080,
        }
        valid_config[param] = value
        mocked_load_conf.return_value = valid_config
        exp_error = constants.INVALID_INT_RANGE_VALUE_ERROR.format(
            param_name=param, value=value, allowed_range=allowed_range
        )
        with pytest.raises(errors.FailedToParseConfigParamIntRangeError) as err:
            environment.EnvironmentConfig(tmp_path, None)
            assert str(err) == exp_error


import pytest

from k8s_builder.cli import main

__author__ = "gazzasaur"
__copyright__ = "gazzasaur"
__license__ = "MIT"

def test_main(capsys):
    """CLI Tests"""
    # capsys is a pytest fixture that allows asserts against stdout/stderr
    # https://docs.pytest.org/en/stable/capture.html
    main(["-f", "myfile.json"])
    captured = capsys.readouterr()
    assert "" in captured.out


"""
25304번: 영수증

문제: 영수증 총액이 실제 금액과 맞는지 확인하기

input:
A - 영수증에 적힌 총 금액

B - 구매 종류의 수

C D - 금액과 개수

output: Yes, No - A의 금액과 C D 계산된 총액과 같으면 yes, 다르면 no

"""

"""
TEST CASE 1:
260000
4
20000 5
30000 2
10000 6
5000 8

OUTPUT 1: Yes

################

TEST CASE 2:
250000
4
20000 5
30000 2
10000 6
5000 8

OUTPUT 2: No
"""

import sys

# input A
input_total = int(input())
# input B
input_num = int(input())

# B만큼 돌아가면서 input 받기
price_total = []
for i in range (input_num):
    input_price = list(map(int, input().split()))
    price_total.append(input_price[0]*input_price[1])
    # print("price total",price_total)

check_total = 0
for i in price_total:
    check_total += i
    # print("check total", check_total)

if input_total == check_total:
    print("Yes")
else:
    print("No")


from typing import Literal
from dataclasses import dataclass
from pydpn._api.api_base import ApiBase
from pydpn._utils.misc import valid_ip

from re import match

class Routing(ApiBase):
    def get_routings(
        self,
        routeType: Literal["ip", "domain"],
        mode: Literal["smart", "direct"],
        page: int = 1,
        size: int = 1000,
    ) -> list:

        if mode == "smart":
            smartDirectSelect = "getRoutingWhitelist"

        elif mode == "direct":
            smartDirectSelect = "getRoutingBlacklist"

        desc = {
            "serviceName": "get_routings",
            "refUrl": f"{self.deeper.hostIp}/{routeType}Config",
            "apiRoute": f"smartRoute/{smartDirectSelect}/{routeType}?pageNo={page}&pageSize={size}",
            "requestMethod": "GET",
            "responseType": dict,
            "responseContent": {"total": int, "list": list},
            "returnType": list,
        }

        return self.deeper._api_call(desc)

    def add_route(self, domainIp, tunnelCode: str = ""):

        if match("^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$", domainIp):
            domainIpSelect = "ip"

        else:
            domainIpSelect = "domain"

        if tunnelCode:
            smartDirectSelect = "addToWhitelist"

        else:
            smartDirectSelect = "addToBlacklist"

        postData = {domainIpSelect: domainIp}
        desc = {
            "serviceName": "switch_node",
            "refUrl": f"{self.deeper.hostIp}/{domainIpSelect}Config",
            "apiRoute": f"smartRoute/{smartDirectSelect}/{domainIpSelect}",
            "requestMethod": "POST",
            "responseType": dict,
            "responseContent": {
                "activeIp": str,
                "activeNum": int,
                "success": bool,
            },
            "returnType": dict,
            "setValue": True,
            "postData": postData,
        }

        return self.deeper._api_call(desc)

    def delete_route(
        self, route: list[str], mode: Literal["smart", "direct"]
    ) -> bool:

        evalInput = [valid_ip(f) for f in route]
        if all(evalInput):
            domainIpSelect = "ip"

        elif any(evalInput):
            raise ValueError("Input must be all ip or all domain not mixed")

        else:
            domainIpSelect = "domain"

        if mode == "smart":
            smartDirectSelect = "deleteFromWhitelist"

        elif mode == "direct":
            smartDirectSelect = "deleteFromBlacklist"

        postData = route
        desc = {
            "serviceName": "switch_node",
            "refUrl": f"{self.deeper.hostIp}/{domainIpSelect}Config",
            "apiRoute": f"smartRoute/{smartDirectSelect}/{domainIpSelect}",
            "requestMethod": "POST",
            "responseType": dict,
            "responseContent": {
                "success": bool,
            },
            "returnType": dict,
            "setValue": True,
            "postData": postData,
        }

        return self.deeper._api_call(desc)


import os
import functools
import json
os.chdir("pages/nothing")

print("pages\\nothing\\list.json 生成工具")

resultList = list(
    filter(lambda x: (x != "index.html" and x != "list.json" and os.path.isfile(x)), os.listdir("./")))

print("检测到", len(resultList), "个目标文件.")

with open("list.json", "w") as f:
    json.dump(resultList, f)

print("文件生成完成。生成结果路径：",os.getcwd()+"\\list.json")


from __future__ import print_function
import sys
import os

###########################################
#  XML parse
from lxml import etree
#import xml.etree.ElementTree as etree

###########################################
# utils
try:
  import utils
  import core as eSEAT_Core
  import Task
except:
  from . import utils
  from . import core as eSEAT_Core
  from . import Task

if sys.version_info.major > 2:
    def unicode(s):
        return str(s)

###########################################
#
#  Class eSEAT Parser
#
class SEATML_Parser():
    def __init__(self, parent, xsd='seatml.xsd', logger=None):
        self.parent = parent
        self.componentName = "eSEAT"
        self._xmlschema = None
        if logger:
            self._logger = parent._logger
        else:
            self._logger = None

        xsd_file = utils.findfile(xsd)

        if xsd_file:
            self.setXsd(xsd_file)
            print ("XSD file '"+xsd+"' = '"+xsd_file+"'.")
        else:
            #print ("Warining:XSD file '"+xsd+"' not found.")
            pass

        self.include_rules = []
        self.seatml_base_dir = ""

    #
    #  set schema-file for seatml
    def setXsd(self, xsd, _dir=None):
        if _dir :
            self._basedir = _dir
        elif os.getenv('SEAT_ROOT') :
            self._basedir = os.getenv('SEAT_ROOT')
        else :
            self._basedir = os.getcwd()
        xmlschema_doc = etree.parse(os.path.join(self._basedir, xsd))
        self._xmlschema = etree.XMLSchema(xmlschema_doc)

    #
    #   Logger
    def setParentLogger(self):
        self._logger = self.parent._logger

    def logInfo(self, msg):
        if self._logger :
            self._logger.info(msg)

    def logError(self, msg):
        if self._logger :
            self._logger.error(msg)

    #
    #  Create communication adaptor
    #
    def createAdaptor(self, tag):
        try:
            name = str(tag.get('name'))
            type = tag.get('type')
            return self.parent.createAdaptor(self.componentName, tag, eSEAT_Core.getGlobals())
        except:
            self.logError(u"invalid parameters(1): " + type + ": " + name)
            return -1

        return 1

    #
    #   Sub parser <message><command><statetransition><log><shell><script>
    #
    def parseCommands(self, r):
        tasks=Task.TaskGroup()

        for c in r.getchildren():
        #
        # <message>
            if c.tag == 'message': # end message
                sendto     = c.get('sendto')
                if not sendto : sendto = c.get('host')
                task = Task.TaskMessage(self.parent, sendto, c.text, c.get('encode'), c.get('input'))
                tasks.addTask(task)
        #
        # <statetransition>
            elif c.tag == 'statetransition': # get statetransition
                task = Task.TaskStatetransition(self.parent, c.get('func'), c.text)
                tasks.addTask(task)
        #
        # <log>
            elif c.tag == 'log': #  logging
                task = Task.TaskLog(self.parent, c.text)
                tasks.addTask(task)
        #
        # <shell>
            elif c.tag == 'shell': # get shell
                sendto = c.get('sendto')
                if not sendto : sendto = c.get('host')
                task = Task.TaskShell(self.parent, sendto, c.text)
                tasks.addTask(task)
        #
        # <script>
            elif c.tag == 'script': # get script
                sendto  = c.get('sendto')
                if not sendto : sendto = c.get('host')
                task = Task.TaskScript(self.parent, sendto,
                    self.getScripts(c), c.get('execfile'), c.get('import'))
                tasks.addTask(task)
        return tasks

    #
    #   delete spaces at the begining of the lines for python script
    #
    def getScripts(self, tag):
        data = skipSps(tag.text)
        for ctag in tag.getchildren():
            data += skipSps(ctag.text)
        return data

    #
    # execute the python script
    #
    def procScript(self, tag, fname, imports):
        if imports :
            import_str="import "+imports
            exec(import_str, eSEAT_Core.getGlobals())

        txt = self.getScripts(tag)
        if fname :
            ffname = utils.findfile(fname)
            if ffname :
                utils.exec_script_file(ffname, eSEAT_Core.getGlobals())
        if txt :
            #sys.path.append('.')
            exec(txt, eSEAT_Core.getGlobals())

    #
    # get attribute of the tag. If the attribute isnot found, set default value
    #
    def getAttribute(self, e, name, def_val=None):
        val = e.get(name)
        if def_val is None: return val
        if not val : val = def_val
        return val
    #
    #  get text of the tag
    #
    def getText(self, e):
        val = e.text
        if not val: val = ''
        return val

    #
    #  Sub parser for GUI items
    #
    def parseGui(self, name, e):
        if not isinstance(self.parent, eSEAT_Core.eSEAT_Gui) : return
        commands = self.parseCommands(e)

        #
        #  <label>
        if e.tag == 'label':
            self.parent.addLabel(name, self.getAttribute(e, 'text'),
                   self.getAttribute(e, 'color'),
                   self.getAttribute(e, 'bg_color'),
                   self.getAttribute(e, 'colspan', 1),
                   self.getAttribute(e, 'rowspan', 1),
                   self.getAttribute(e, 'frame', ''),
                   self.getAttribute(e, 'args', '')
                   )
        #
        #  <brk>
        elif e.tag == 'brk':
            self.parent.addBreak(name, self.getAttribute(e, 'frame', ''))
        #
        #  <space>
        elif e.tag == 'space':
            self.parent.addSpace(name, self.getAttribute(e, 'length', 1),
                            self.getAttribute(e, 'frame', ''))
        #
        #  <frame>
        elif e.tag == 'frame':
            key = self.getAttribute(e, 'name')
            self.parent.addFrame(name, key,
                self.getAttribute(e, 'height'), self.getAttribute(e, 'width'),
                self.getAttribute(e, 'relief', 'flat'),
                self.getAttribute(e, 'color'), self.getAttribute(e, 'bg_color'),
                self.getAttribute(e, 'colspan', 1),
                self.getAttribute(e, 'rowspan', 1),
                self.getAttribute(e, 'frame', '')
                )

        #
        #  <labelframe>
        elif e.tag == 'labelframe':
            key = self.getAttribute(e, 'label')
            self.parent.addLabelframe(name, key,
                self.getAttribute(e, 'height'), self.getAttribute(e, 'width'),
                self.getAttribute(e, 'labelanchor', 'nw'),
                self.getAttribute(e, 'relief', 'groove'),
                self.getAttribute(e, 'color'), self.getAttribute(e, 'bg_color'),
                self.getAttribute(e, 'colspan', 1),
                self.getAttribute(e, 'rowspan', 1),
                self.getAttribute(e, 'frame', '')
                )

        #
        #  <button>
        elif e.tag == 'button':
            key = self.getAttribute(e, 'label')
            #self.parent.registerCommands(name+":gui:"+key, commands)
            self.parent.states[name].registerRule(('gui', key), commands)
            self.parent.addButton(name, key, self.getAttribute(e, 'color'),
                 self.getAttribute(e, 'bg_color'),
                 self.getAttribute(e, 'width'),
                 self.getAttribute(e, 'colspan', 1),
                 self.getAttribute(e, 'rowspan', 1),
                 self.getAttribute(e, 'frame', '')
                 )

        #
        #  <input>
        elif e.tag == 'input':
            key = self.getAttribute(e, 'id')
            #self.parent.registerCommands(name+":gui:"+key, commands)
            self.parent.states[name].registerRule(('gui', key), commands)
            self.parent.addEntry(name, key, self.getAttribute(e, 'width', '20'),
                 self.getText(e),
                 self.getAttribute(e, 'colspan', 1),
                 self.getAttribute(e, 'rowspan', 1),
                 self.getAttribute(e, 'frame', '')
                 )
        #
        #  <text>
        elif e.tag == 'text':
            key = self.getAttribute(e, 'id')
            #self.parent.registerCommands(name+":gui:"+key, commands)
            self.parent.states[name].registerRule(('gui', key), commands)
            self.parent.addText(name, key, self.getAttribute(e, 'width', '20'),
                 self.getAttribute(e, 'height', '3'),
                 self.getAttribute(e, 'colspan', 1),
                 self.getAttribute(e, 'rowspan', 1), self.getText(e),
                 self.getAttribute(e, 'frame', '')
                 )
        #
        #  <combobox>
        elif e.tag == 'combobox':
            key = self.getAttribute(e, 'id')
            self.parent.states[name].registerRule(('gui', key), commands)
            self.parent.addCombobox(name, key, self.getAttribute(e, 'values'),
                 self.getAttribute(e,'default', ''),
                 self.getAttribute(e, 'colspan', 1),
                 self.getAttribute(e, 'rowspan', 1),
                 self.getAttribute(e, 'frame', '')
                 )
        #
        #  <checkbutton>
        elif e.tag == 'checkbutton':
            key = self.getAttribute(e, 'name')
            self.parent.states[name].registerRule(('gui', key), commands)
            self.parent.addCheckbutton(name, key,
                 self.getAttribute(e, 'colspan', 1),
                 self.getAttribute(e, 'rowspan', 1),
                 self.getAttribute(e, 'frame', '')
                 )
        #
        #  <listbox>
        elif e.tag == 'listbox':
            key = self.getAttribute(e, 'name')
            self.parent.states[name].registerRule(('gui', key), commands)
            txtlist = self.getAttribute(e, 'values')
            height = self.getAttribute(e, 'height', len(txtlist.split(',')))
            self.parent.addListbox(name, key, txtlist, height,
                 self.getAttribute(e, 'colspan', 1),
                 self.getAttribute(e, 'rowspan', 1),
                 self.getAttribute(e, 'frame', '')
                 )
        #
        #  <radiobutton>
        elif e.tag == 'radiobutton':
            key = self.getAttribute(e, 'label')
            self.parent.states[name].registerRule(('gui', key), commands)
            var=self.getAttribute(e, 'variable')
            val=self.getAttribute(e, 'value')
            self.parent.addRadiobutton(name, key, var, val,
                 self.getAttribute(e, 'colspan', 1),
                 self.getAttribute(e, 'rowspan', 1),
                 self.getAttribute(e, 'frame', '')
                 )
        #
        #  <scale>
        elif e.tag == 'scale':
            key = self.getAttribute(e, 'name')
            self.parent.states[name].registerRule(('gui', key), commands)
            frm=self.getAttribute(e, 'from', 0)
            to=self.getAttribute(e, 'to', 10)
            res=self.getAttribute(e, 'resolution', 1)
            ori=self.getAttribute(e, 'orientation', 'horizontal')

            self.parent.addScale(name, key, frm, to, res, ori,
                self.getAttribute(e, 'colspan', 1),
                self.getAttribute(e, 'rowspan', 1),
                self.getAttribute(e, 'frame', '')
                )
        #
        #
        elif e.tag == etree.Comment:
           pass
        #
        #  Others
        else:
           self.logError("Invalid tag found: " + unicode(e.tag))

    #
    #  load rules from external seatml file
    #
    def loadRuleFile(self, name, f, sname=None):
        f = f.replace("\\", "\\\\")
        self.logInfo("load script file(loadRuleFile): " + f)

        try:
            doc = etree.parse(f)
        except etree.XMLSyntaxError as e:
            self.logError("invalid xml syntax(loadRuleFile): " + unicode(e))
            return 1
        except IOError as e:
            self.logError("unable to open file " + f + " (loadRuleFile): " + unicode(e))
            return 1

        try:
            if self._xmlschema :
                self._xmlschema.assert_(doc)
        except AssertionError as b:
            self.logError("invalid script file: " + f + " (loadRuleFile): " + unicode(b))
            return 1

        for s in doc.findall('state'):
            if not sname or sname == s.get('name'):
                for e in list(s):
                    if e.tag == 'rule':
                        self.parseRule(name, e)
                return

        self.logError("no rule foud: " + f +":"+unicode(sname))

    #
    #   Sub parser for <rule>tag
    #
    def parseRule(self, name, e):
        #
        # Check attribute 'file'
        if e.get('file'):
            loadfile = os.path.join(self.seatml_base_dir, e.get('file'))
            if loadfile in self.include_rules :
                self.logError("already included: " + e.get('file'))
                return
            self.include_rules.append(loadfile)
            try:
              fname, sname = e.get('file').split(':')
            except:
               fname = e.get('file')
               sname = None

            self.loadRuleFile(name, os.path.join(self.seatml_base_dir, fname), sname)
        else:
            commands = self.parseCommands(e)
            adaptor = e.get('source')
            #
            #  <key>
            keys = e.findall('key')
            if adaptor :
                kond = None
                #
                #  <cond>
                knd = e.find('cond')
                if knd is not None :
                    commands.pre_script = knd.get("execfile")
                    #print (knd.get("execfile"))
                    #print (commands.pre_script)
                    commands.condition = knd.text

                if keys :
                    for k in keys:
                        word = decompString([k.text])

                        for w in word:
                            self.parent.states[name].registerRule((adaptor, w), commands)
                else :
                    self.parent.states[name].registerRuleArray((adaptor, 'ondata'), commands)

            for k in keys:
                source = k.get('source')
                if source is None: source = "default"
                word = decompString([k.text])

                for w in word:
                    self.parent.states[name].registerRule((source, w), commands)

    #
    #   Sub parser for <exec>tag
    #
    def parseExec(self, name, e):
        commands = self.parseCommands(e)
        self.parent.states[name].onexec = commands
        self.logInfo("register <onexec> on " + name)
        return commands

    #
    #   Sub parser for <activated>tag
    #
    def parseActivated(self, e):
        commands = self.parseCommands(e)
        self.parent.states['all'].onactivated = commands
        self.logInfo("register <onactivated> on all")
        return commands

    #
    #   Sub parser for <deactivated>tag
    #
    def parseDeactivated(self, name, e):
        commands = self.parseCommands(e)
        self.parent.states[name].ondeactivated = commands
        self.logInfo("register <ondeactivaetd> on " + name)
        return commands

    #
    #   Sub parser for <exec>tag
    #
    def parseTimeout(self, name, e):
        tout = e.get('timeout')
        commands = self.parseCommands(e)
        commands.timeout = float(tout)
        self.parent.states[name].ontimeout = commands
        self.logInfo("register <ontimeout> on " + name)
        return commands

    #######################################################
    #   eSEAT Markup Language File loader
    #
    def load(self, f):
        self.setParentLogger()
        f = f.replace("\\", "\\\\")
        self.seatml_base_dir = os.path.dirname(f)

        self.logInfo("load script file: " + f)

        try:
            doc = etree.parse(f)
        except etree.XMLSyntaxError as e:
            self.logError("invalid xml syntax: " + unicode(e))
            return 1
        except IOError as e:
            self.logError("unable to open file " + f + ": " + unicode(e))
            return 1

        try:
            if self._xmlschema :
                self._xmlschema.assert_(doc)
        except AssertionError as b:
            self.logError("invalid script file: " + f + ": " + unicode(b))
            return 1

        self.parent.items = {}

        ####
        # Top level tag
        #
        #  <general>
        g=doc.find('general')
        #for g in doc.findall('general'):
        if g is not None:
            self.parent.create_state('all')
            sys.path.append('.')
            sys.path.append('rtm')

            if g.get('name') :
                self.componentName = g.get('name')
                if self.componentName: self.parent.name=self.componentName
                self.parent.setInstanceName(self.componentName)

            if g.get('anonymous') :
                self.parent.ros_anonymous=g.get('anonymous')

            if g.get('rate') :
                self.parent.rate_hz=g.get('rate')

            for a in g.getchildren():
                #
                #  <adaptor>
                if a.tag == 'adaptor':
                    self.createAdaptor(a)
                #
                #  <script>
                elif  a.tag == 'script':
                    self.procScript(a, a.get('execfile'), a.get('import'))
                #
                #  <onexec>
                elif a.tag == 'onexec':
                    self.parseExec('all', a)
                #
                #  <onactivated>
                elif a.tag == 'onactivated':
                    self.parseActivated(a)
                #
                #  <ondeactivated>
                elif a.tag == 'ondeactivated':
                    self.parseDeactivated('all', a)
                #
                #  <var>
                elif a.tag == 'var':
                    eSEAT_Core.setGlobals(g.get('name'), g.get('value'))
                #
                #  <timoute>
                elif a.tag == 'ontimeout':
                    self.parseTimeout('all', a)

                else:
                    pass
        else:
            print('Error in seatml file')
            return -1
        #
        #
        #  <state>
        for s in doc.findall('state'):
            name = s.get('name')
            self.parent.create_state(name)

            for e in list(s):
                #
                #  <onentry><onexit>
                if e.tag == 'onentry' or e.tag == 'onexit':
                    commands = self.parseCommands(e)
                    if e.tag == 'onentry':
                        self.parent.states[name].onentry = commands
                    if e.tag == 'onexit':
                        self.parent.states[name].onexit = commands
                #
                #  <timoute>
                elif e.tag == 'ontimeout':
                    self.parseTimeout(name, e)
                #
                #  <onexec>
                elif e.tag == 'onexec':
                    self.parseExec(name, e)
                #
                #  <ondeactivated>
                elif e.tag == 'ondeactivated':
                    self.parseDeactivated(name, e)
                #
                #  <rule>
                elif e.tag == 'rule':
                    self.include_rules = [ f.replace("\\\\", "\\")]
                    self.parseRule(name, e)

                elif e.tag == etree.Comment:
                    pass

                else:
                #
                # GUI tags
                    self.parseGui(name, e)

            #self.parent.appendState(name)

        ############################################
        #  initialize
        #
        if self.parent.countStates() == 0:
            self.logError("no available state")
            return 1

        self.parent.initStartState("start")
        self.logInfo("loaded successfully")

        return 0

#############################################
# Functions
#
#
# Parse Key String: already not needed
#
def decompString(strs):
    ret = []
    nstrs = strs
    while nstrs.__len__() > 0:
        nstrs2 = []
        for str in nstrs:
            if str.count('(') > 0 or str.count('[') > 0:
                nstrs2.extend(decompStringSub(str))
            else:
                ret.extend([str])
        nstrs = nstrs2
    return ret

def decompStringSub(str):
    ret = []
    bc = str.count('(')
    kc = str.count('[')
    if bc > 0:
        i = str.index('(')
        prestr = str[:i]
        substrs = []
        substr = ''
        level = 0
        i += 1
        while i < str.__len__():
            if str[i] == '(':
                level += 1
                substr += str[i]
            elif str[i] == ')':
                if level == 0:
                    substrs.extend([substr])
                    break
                else:
                    substr += str[i]
                level -= 1
            elif str[i] == '|':
                if level == 0:
                    substrs.extend([substr])
                    substr = ''
                else:
                    substr += str[i]
            else:
                substr += str[i]
            i += 1
        poststr = str[i+1:]
        for s in substrs:
            ret.extend([prestr+s+poststr])
    elif kc > 0:
        i = str.index('[')
        prestr = str[:i]
        substr = ''
        level = 0
        i += 1
        while i < str.__len__():
            if str[i] == '[':
                level += 1
            elif str[i] == ']':
                if level == 0:
                    break
                level -= 1
            substr += str[i]
            i += 1
        poststr = str[i+1:]
        ret.extend([prestr+poststr])
        ret.extend([prestr+substr+poststr])
    else:
        ret.extend([str])
    return ret

#
#  Convert datatype
#
def convertDataType(dtype, data, code='utf-8'):
  if dtype == str:
    if sys.version_info.major == 2:
        return data.encode(code)
    else:
        return data

  elif sys.version_info.major == 2 and dtype == unicode:
    return unicode(data)

  elif dtype == int or dtype == float :
    return dtype(data)
  else:
    if type(data) == str :
        return eval(data)
    return data

#
# Component Name
def formatInstanceName(name):
   fullname=name.split('/')
   rtcname = fullname[len(fullname) -1 ]
   return rtcname.split('.')[0]

#
#  Count spaces at the begining of the line
#
def countSp(s):
  c=0
  for x in s:
    if x != " " and x != "\n":
      return c
    c=c+1
  return c

#
#  Remove spaces at the begining of the lines
#
def skipSps(txt):
  try:
    lines = txt.split("\n")
    c=0
    for x in lines :
      if x : break
      c=c+1
    skip = countSp(lines[c])
    res = ""
    for x in lines :
      if len( x ) >= skip :
        res += x[skip:]+"\n"
  except:
    return txt
  return res


#!/usr/bin/env python

import os
from setuptools import setup
from setuptools import find_packages

VERSION = open('VERSION').read().strip()

CLASSIFIERS = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "Operating System :: OS Independent",
    "Programming Language :: Python",
    "Programming Language :: Python :: 2.7",
    "Programming Language :: Python :: 3.3",
    "Programming Language :: Python :: 3.4",
    "Programming Language :: Python :: 3.5",
    "Programming Language :: Python :: 3.6",
    "Programming Language :: Python :: 3.7",
    "Topic :: System :: Filesystems",
]

with open(os.path.join(os.path.dirname(__file__), "README.rst"), "rt") as f:
    DESCRIPTION = f.read()

BASESPACE_PYTHON_SDK_VERSION = "basespace-python-sdk @ git+https://github.com/emedgene/basespace-python-sdk@0.6.0" \
                               "#subdirectory=src"
REQUIREMENTS = [BASESPACE_PYTHON_SDK_VERSION, "fs~=2.4", "smart-open~=5.1"]

setup(
    name="fs-basespace",
    author="emedgene",
    author_email="pypi@emedgene.com",
    classifiers=CLASSIFIERS,
    description="Illumina Basespace filesystem for PyFilesystem2",
    install_requires=REQUIREMENTS,
    license="MIT",
    long_description=DESCRIPTION,
    packages=find_packages(),
    keywords=["pyfilesystem", "Illumina", "Basespace"],
    platforms=["any"],
    url="https://github.com/emedgene/fs_basespace",
    download_url="https://github.com/emedgene/fs_basespace/tarball/0.2.0",
    version=VERSION,
    entry_points={"fs.opener": ["basespace = fs_basespace.opener:BASESPACEFSOpener"]},
)


import fasttext
import os
import json

from sklearn.cross_validation import KFold

from .DurationRecorder import DurationRecorder
from .FastTextConfig import FastTextConfig
from .TxtReader import TxtReader
from .TxtManipulator import TxtManipulator

class FastTextProcessor:

	def __init__(self):
		self.config = FastTextConfig()
		try:
			self.classifier = fasttext.load_model(self.config.classifier.model_dir+".bin", label_prefix=self.config.training.label_prefix)
		except Exception as ex:
			self.classifier = None
			print("Model not Found")

	def initial_train(self, data_dir):
		input_data = TxtReader.read_txt_to_numpy_list(data_dir)
		kf = KFold(len(input_data), n_folds=10, shuffle=True)

		training_data = './temp_train_data.txt'
		test_data = './temp_test_data.txt'

		index = 0

		for train_indices, test_indices in kf:
			index += 1
			# Create temp training & test data
			TxtManipulator.write_txt_data_from_1d_np_list(training_data, input_data[train_indices])
			TxtManipulator.write_txt_data_from_1d_np_list(test_data, input_data[test_indices])

			DurationRecorder.start_log()

			self.classifier = fasttext.supervised(training_data, output=self.config.classifier.model_dir, dim=self.config.training.dim,
											  lr=self.config.training.lr, epoch=self.config.training.epoch,
											  min_count=self.config.training.min_count, word_ngrams=self.config.training.word_ngrams,
											  thread = self.config.training.thread, silent=self.config.training.silent,
											  bucket= self.config.training.bucket)
			# Increasing epoch

			result = self.classifier.test(test_data)

			precision = result.precision
			recall = result.recall
			DurationRecorder.pr_epoch_logger(index, precision, recall)
			DurationRecorder.pr_epoch_plotter(index, precision, recall)

	def train(self, training_data):
		self.classifier = fasttext.supervised(training_data, output=self.config.classifier.model_dir, dim=self.config.training.dim,
											  lr=self.config.training.lr, epoch=step,
											  min_count=self.config.training.min_count, word_ngrams=self.config.training.word_ngrams,
											  thread = self.config.training.thread, silent=self.config.training.silent,
											  bucket= self.config.training.bucket)

	def test(self, test_data):
		result = self.classifier.test(test_data)
		return result

	def predict(self, predict_data):
		result = self.classifier.predict_proba(predict_data, k=2)
		return result