# Standard Libs
import decouple
import pytest
from unittest.mock import patch

# INTERNAL LIBS
from persephone_client import Persephone

from src.domain.exceptions.service.auditing_trail.model import FailToSaveAuditingTrail
from src.domain.exceptions.service.bank_account.model import BankAccountNotExists
from tests.src.stubs.bank_account_stubs.stub_get_account import (
    jwt_with_bank_account_to_update,
)
from src.services.bank_account.service import UserBankAccountService
from src.repositories.bank_account.repository import UserBankAccountRepository
from tests.src.stubs.project_stubs.stub_data import payload_data_dummy

@pytest.mark.asyncio
@patch.object(
    UserBankAccountRepository, "user_bank_account_id_exists", return_value=True
)
@patch.object(
    UserBankAccountRepository, "update_registered_user_bank_accounts", return_value=True
)
@patch.object(UserBankAccountService, "bank_code_from_client_exists", return_value=True)
@patch.object(Persephone, "send_to_persephone", return_value=[True, True])
@patch.object(decouple.Config, "get", return_value="lala")
async def test_update_user_when_sending_the_right_params_then_return_the_duly_updated_message(
    mock_get,
    mock_send_to_persephone,
    mock_bank_code_from_client_exists,
    mock_update_registered_user_bank_accounts,
    mock_user_bank_account_id_exists,
):
    response = await UserBankAccountService.update_user_bank_account(
        jwt_data=jwt_with_bank_account_to_update,
        bank_account_repository=UserBankAccountRepository,
    )
    updating_message = {"message": "Updated"}
    assert response == updating_message
    assert isinstance(response, dict)
    assert response.get("message") == "Updated"

@pytest.mark.asyncio
async def test_update_user_when_sending_an_invalid_jwt_data_then_return_the_expected_exception():
    with pytest.raises(KeyError):
        await UserBankAccountService.update_user_bank_account(
            jwt_data=payload_data_dummy,
            bank_account_repository=UserBankAccountRepository,
        )

@pytest.mark.asyncio
async def test_update_user_when_sending_an_invalid_bank_repository_call_then_return_the_expected_exception():
    with pytest.raises(AttributeError):
        await UserBankAccountService.update_user_bank_account(
            jwt_data=jwt_with_bank_account_to_update, bank_account_repository=""
        )

@pytest.mark.asyncio
@patch.object(
    UserBankAccountRepository, "user_bank_account_id_exists", return_value=False
)
@patch.object(
    UserBankAccountRepository,
    "update_registered_user_bank_accounts",
    return_value=False,
)
@patch.object(Persephone, "send_to_persephone", return_value=[True, False])
async def test_when_bank_account_and_register_account_are_false_then_raise_the_expected_bad_request(
    mock_get_registered_user_bank_accounts,
    mock_update_registered_user_bank_accounts,
    mock_send_to_persephone,
):
    with pytest.raises(BankAccountNotExists):
        await UserBankAccountService.update_user_bank_account(
            jwt_data=jwt_with_bank_account_to_update,
            bank_account_repository=UserBankAccountRepository,
        )

@pytest.mark.asyncio
@patch.object(
    UserBankAccountRepository, "user_bank_account_id_exists", return_value=True
)
@patch.object(
    UserBankAccountRepository,
    "update_registered_user_bank_accounts",
    return_value=False,
)
@patch.object(Persephone, "send_to_persephone", return_value=[False, False])
@patch.object(decouple.Config, "get", return_value="lala")
async def test_when_register_account_is_false_then_raise_the_expected_fail_to_save_auditing_trail(
    mock_send_to_persephone,
    mock_update_registered_user_bank_accounts,
    mock_user_bank_account_id_exists,
    mock_get,
):
    with pytest.raises(FailToSaveAuditingTrail):
        await UserBankAccountService.update_user_bank_account(
            jwt_data=jwt_with_bank_account_to_update,
            bank_account_repository=UserBankAccountRepository,
        )

@pytest.mark.asyncio
async def test_when_sending_wrong_params_of_repository_then_raise_key_error_as_expected():
    with pytest.raises(AttributeError):
        await UserBankAccountService.update_user_bank_account(
            bank_account_repository=None, jwt_data=jwt_with_bank_account_to_update
        )

@pytest.mark.asyncio
async def test_when_jwt_data_payload_is_invalid_then_raise_type_error_as_expected():
    with pytest.raises(TypeError):
        await UserBankAccountService.update_user_bank_account(
            jwt_data=None, bank_account_repository=UserBankAccountRepository
        )


"""
===============================
app.py: RESTful API for GeMS
===============================
__contact__ = 'swk30.cam@gmail.com'
__date__ = '10.10.2018'
__status__ = 'MVP Complete'
"""

# Dependencies

import os
import sys

from flask import Flask, jsonify, request, make_response
from flask_restful import Api, Resource

from app_utils import similarity_jaccard, similarity_overlap
from upload import api_insert
from db_config import COLLECTION_NAME
from db_utils import db, INDEX_LIST

# Code

app = Flask(__name__)
api = Api(app, catch_all_404s=True)

class Genesets(Resource):
	def __init__(self):
		self.returnParamNames = 'returnParams'
		self.genesParam = 'genes'

	def getOutput(self, query, returnParams, geneList):
		"""
		:param query: Dict
		:param returnParams: List<String> or None
		:param geneList: List<String> or None
		:return: List
		"""
		if geneList is not None:
			geneMatchList = [{'genes': {'$elemMatch': {'$elemMatch': {'$elemMatch': {'$in': [gene]}}}}} for gene in geneList]
			otherQueryList = [{k: v} for k, v in query.items()]
			geneQuery = {'$and': geneMatchList + otherQueryList}
			query = geneQuery

		if 'setName' in query:
			queryString = query['setName']
			queryList = queryString.split(",")
			queryJSON = {'$in':queryList}
			query['setName'] = queryJSON

		output = []
		q = db[COLLECTION_NAME].find(query)
		for p in q:
			if returnParams == None:
				docReturn = {k: v for k, v in p.items() if k != '_id'}
			else:
				docReturn = dict()
				for param in returnParams:
					if param in p:
						docReturn[param] = p[param]
					else:
						docReturn[param] = ""
			output.append(docReturn)
		return output

	def get(self):
		parsedArgs = request.args
		data = {k: v for k, v in parsedArgs.items()}
		hasGenes = False
		params = data.pop(self.returnParamNames, None)
		genes = data.pop(self.genesParam, None)
		if params is not None:
			params = params.split(',')
		if genes is not None:
			genes = genes.split(',')
			hasGenes = True

		# Determine output format (JSON or GMT file)
		getGmt = data.pop('getGmt', None)
		if getGmt in ['True', 'true']:
			getGmt = True
		else:
			getGmt = False

		# Scrape data and present in established format
		if len(data) == 0 and hasGenes is False:
			# Error logic
			output = 404
			return jsonify({"response": output})
		elif getGmt:
			gmtParams = ['setName', 'desc', 'genes']
			output = self.getOutput(data, gmtParams, genes)

			# outputList: list of tab-delimited String (setName-desc-genes)
			outputList = []
			for gs in output:
				name = [gs['setName']]
				desc = [gs['desc']]
				genes = [gene[0][2] for gene in gs['genes'] if gene[0][2] != '']
				combined = name + desc + genes
				combinedStr = '\t'.join(combined)
				outputList.append(combinedStr)

			# Output: GMT file
			tsv = '\n'.join(outputList)
			response = make_response(tsv)
			response.headers['content-type'] = 'application/octet-stream'
			return response
		else:
			# Output: JSON
			output = self.getOutput(data, params, genes)
			return jsonify({"response": output})

	def post(self):
		data = request.get_json()
		hasGenes = False
		params = data.pop(self.returnParamNames, None)
		genes = data.pop(self.genesParam, None)
		if genes is not None:
			hasGenes = True

		if len(data) == 0 and hasGenes is False:
			output = 404
		else:
			output = self.getOutput(data, params, genes)
		return jsonify({"response": output})

class Similar(Resource):
	def __init__(self):
		self.requiredParams = {'setName', 'source', 'subtype', 'user', 'method', 'threshold'}
		self.acceptedMethods = {'jaccard', 'overlap'}
		self.getGeneSet = lambda l : {gene[0][2] for gene in l if gene[0][2] != ''}

	def getGeneMembers(self, inputDict):
		"""
		:param inputDict: Dict
		:return: Set - Empty if invalid
		"""
		testParams = {x for x in inputDict.keys()}
		findGeneset = db[COLLECTION_NAME].find_one({
			'setName': inputDict['setName'],
			'source': inputDict['source'],
			'subtype': inputDict['subtype'],
			'user': inputDict['user']
		})
		if testParams != self.requiredParams:
			return set()
		elif not inputDict['threshold'].replace('.', '').isdigit():
			return set()
		elif inputDict['method'] not in self.acceptedMethods:
			return set()
		elif findGeneset is None:
			return set()
		else:
			returnGenes = self.getGeneSet(findGeneset['genes'])
			return returnGenes

	def get(self):
		parsedArgs = request.args
		input = {k: v for k, v in parsedArgs.items()}

		genes = self.getGeneMembers(input)
		if len(genes) == 0:
			output = 404
		else:
			output = []
			method = input['method']
			threshold = float(input['threshold'])

			# Optimisation: ignore geneset with which the intersection will just be 0
			allGenesets = db[COLLECTION_NAME].find({'genes': {'$elemMatch': {'$elemMatch': {'$elemMatch': {'$in': list(genes)}}}}})
			for geneset in allGenesets:
				compareGenes = self.getGeneSet(geneset['genes'])
				if method == 'jaccard':
					sim = similarity_jaccard(compareGenes, genes)
				elif method == 'overlap':
					sim = similarity_overlap(compareGenes, genes)

				if sim >= threshold:
					output.append({'setName': geneset['setName'],
									'source': geneset['source'],
									'coeff': sim
					})

		return jsonify({"response": output})

class addGenesets(Resource):
	def post(self):
		data = request.get_json()

		if set(data.keys()) != {'headers', 'parsed', 'params'}:
			output = 404
		else:
			try:
				output = [200] + api_insert(data['headers'], data['parsed'], data['params'])
			except AssertionError:
				output = 404
			except Exception:
				output = 404

		return jsonify({"response": output})

class delGenesets(Resource):
	def post(self):
		data = request.get_json()

		try:
			assert 'genesets' in data
			removeList = data['genesets']
			for geneset in removeList:
				assert set(geneset.keys()) == set(INDEX_LIST)
				assert geneset['user'] != 'Public'
				db[COLLECTION_NAME].remove(geneset)
			output = 200
		except AssertionError:
			output = 404
		except Exception:
			output = 404

		return jsonify({"response": output})

api.add_resource(Genesets, "/api/genesets")
api.add_resource(Similar, "/api/similar")
api.add_resource(addGenesets, "/api/insert")
api.add_resource(delGenesets, "/api/remove")

if __name__ == "__main__":
	app.run(host='0.0.0.0', port=1234, debug=True)


import semeion as s
import torch
import sys
import fast_gradient_sign_untargeted as fgsu
import targeted_attack
import misc_functions_2 as mf
from misc_functions import preprocess_image, recreate_image, get_params
import helper_functions as hf

# batch_sizes = [1, 2, 4, 8, 16, 32, 64]
learning_rates = [0.02, 0.03, 0.05, 0.07, 0.09]
linear_layer_sizes = [50, 55, 60, 65, 70, 75, 80]

def run_experiments():
    for bs in [64]:
        for lr in learning_rates:
            for lls in linear_layer_sizes:
                print(bs, lr, lls)
                s.run(bs, 1000, lr, lls)

def run_experiment(noise):
    model = s.run(64, 327, 0.0425, 75, noise)
    torch.save(model, 'SemeionCNN98+Noise35')

def run_untargeted_experiment():
    u_out = open("untargeted_eperiment_out.txt", "w")
    u_out.write("img,original_class,predicted_class,num_iterations,confidence\n")
    data = mf.retreive_semeion_data()

    num_data_points = len(data[0])

    for i in range(num_data_points):
        (original_image, prep_img, target_class, _, pretrained_model) =\
            get_params(i)

        FGS_untargeted = fgsu.FastGradientSignUntargeted(pretrained_model, 0.02)
        pred,iter,conf = FGS_untargeted.generate(original_image, target_class)
        u_out.write("{},{},{},{},{}\n".format(i,target_class,pred,iter,conf))
    u_out.close()

def run_targeted_experiment(size):
    u_out = open("s_noise35.txt", "w")
    u_out.write("img,original_class,target_class,predicted_class,num_iterations,confidence\n")
    data = mf.retreive_semeion_data()
    model = torch.load('SemeionCNN98+Noise35')
    fgst = targeted_attack.FastGradientSignTargeted(model, 0.02)

    if size == -1:
        size = len(data[0])

    for i in range(size):
        for j in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
            o_image, o_class = hf.load_image(i)
            t_class = j
            p_class, iteration, confidence = fgst.generate(o_image, o_class, j)
            u_out.write("{},{},{},{},{},{}\n".format(i, o_class, t_class, p_class, iteration, confidence))
            u_out.flush()
    u_out.close()

if __name__ == '__main__':
    mode = '-t'
    if mode == '-u':
        run_untargeted_experiment()
    elif mode == '-t':
        size = -1
        if len(sys.argv) > 2:
            size = int(sys.argv[2])
        run_targeted_experiment(size)
    else:
        run_experiment(0.35)


# -*- coding: utf-8 -*-

"""Script to display the configuration of the printer.
"""

import sys
import json
import cups
from pibooth.utils import LOGGER, configure_logging
from pibooth.config import PiConfigParser
from pibooth.plugins import create_plugin_manager

def main():
    """Application entry point.
    """
    configure_logging()
    plugin_manager = create_plugin_manager()
    config = PiConfigParser("~/.config/pibooth/pibooth.cfg", plugin_manager)

    conn = cups.Connection()
    name = config.get('PRINTER', 'printer_name')

    if not name or name.lower() == 'default':
        name = conn.getDefault()
        if not name and conn.getPrinters():
            name = list(conn.getPrinters().keys())[0]  # Take first one
    elif name not in conn.getPrinters():
        name = None

    if not name:
        if name.lower() == 'default':
            LOGGER.warning("No printer configured in CUPS (see http://localhost:631)")
            return
        else:
            LOGGER.warning("No printer named '%s' in CUPS (see http://localhost:631)", name)
            return
    else:
        LOGGER.info("Connected to printer '%s'", name)

    f = conn.getPPD(name)
    ppd = cups.PPD(f)
    groups = ppd.optionGroups
    options = []
    for group in groups:
        group_name = "{} - {}".format(group.name, group.text)
        for opt in group.options:
            option = {'group': group_name}
            values = list(map(lambda x: x["choice"], opt.choices))
            texts = list(map(lambda x: x["text"], opt.choices))
            option['keyword'] = opt.keyword
            option['value'] = opt.defchoice
            option['description'] = opt.text
            if values != texts:
                option['choices'] = dict([(v, texts[values.index(v)]) for v in values])
            else:
                option['choices'] = values
            options.append(option)

    if '--json' in sys.argv:
        print(json.dumps(dict([(option['keyword'], option['value']) for option in options])))
    else:
        for option in options:
            print("{} = {}".format(option['keyword'], option['value']))
            print("     Description: {}".format(option['description']))
            if isinstance(option['choices'], dict):
                choices = ["{} = {}".format(value, descr) for value, descr in option['choices'].items()]
                print("     Choices:     {}".format(choices[0]))
                for choice in choices[1:]:
                    print("                  {}".format(choice))
            else:
                print("     Choices:     {}".format(", ".join(option['choices'])))

            print()

if __name__ == "__main__":
    main()


#lab8: Write a program (lab8setup.py) that downloads the data of all 93 countries and save it in an SQL database and a JSON file,
#      then write a second program (lab8.py) that uses the database and JSON file to let the user look up information.
#Name: Quynh Nguyen
#Date: 3/12/18

import requests
from bs4 import BeautifulSoup
from collections import defaultdict, namedtuple
import re
import time
import json
import sqlite3

NUM_SPORTS = 15

def getCountryList() :
    '''Fuction fetch data from the website and store country names in a dictionary, which is stored
       in a json file. Return a list of tuple (country name, url to the country info).
    '''
    try:
        page = requests.get("https://www.olympic.org/pyeongchang-2018/results/en/general/nocs-list.htm", timeout=3)
        page.raise_for_status()    # ask Requests to raise any exception
        soup = BeautifulSoup(page.content, 'lxml')
        baseLink = "https://www.olympic.org/pyeongchang-2018/results/"

        countryDict = defaultdict(list)
        countryList = []
        Country = namedtuple('Country', 'name url')

        for country in soup.find_all('div', class_='CountriesListItem') :
            name = country.find('strong').get_text()
            url = re.sub('../../', baseLink, country.find('a').get('href'))
            countryList.append(Country(name, url))
            countryDict[name[0]].append(name)
            countryDict[name[0]].sort()
        # save dictionary to json file
        with open('countryDict.json', 'w') as fh:
            json.dump(countryDict, fh, indent=3)
        return countryList

    except requests.exceptions.HTTPError as e:
        print ("HTTP Error:", e)
        raise SystemExit
    except requests.exceptions.ConnectionError as e:
        print ("Error Connecting:", e)
        raise SystemExit
    except requests.exceptions.Timeout as e:
        print ("Timeout Error:", e)
        raise SystemExit
    except requests.exceptions.RequestException as e:  # any Requests error
        print ("Request exception: ", e)
        raise SystemExit

def createTables(cur):
    '''Create Sports table and CountryDB table
    '''
    # create new table Sports by removing old Sports table
    cur.execute("DROP TABLE IF EXISTS Sports")
    cur.execute('''CREATE TABLE Sports(
                       id INTEGER NOT NULL PRIMARY KEY UNIQUE,
                       sport TEXT UNIQUE ON CONFLICT IGNORE)''')

    # create new table CountryDB by removing old CountryDB table
    cur.execute("DROP TABLE IF EXISTS CountryDB")
    cur.execute('''CREATE TABLE CountryDB(
                       name TEXT NOT NULL PRIMARY KEY UNIQUE,
                       totalAthletes INTEGER,
                       sport_id1 INTEGER, sport_id2 INTEGER, sport_id3 INTEGER,
                       sport_id4 INTEGER, sport_id5 INTEGER, sport_id6 INTEGER,
                       sport_id7 INTEGER, sport_id8 INTEGER, sport_id9 INTEGER,
                       sport_id10 INTEGER, sport_id11 INTEGER, sport_id12 INTEGER,
                       sport_id13 INTEGER, sport_id14 INTEGER, sport_id15 INTEGER)''')

def saveCountryInfo():
    '''Fetch data from the URL and save data to database
    '''
    conn = sqlite3.connect('CountryInfo.db')
    cur = conn.cursor()
    createTables(cur)

    for i,country in enumerate(getCountryList()) :
        time.sleep(5)
        try :
            page = requests.get(country.url, timeout=3)
            soup = BeautifulSoup(page.content, 'lxml')
            table = soup.find('table', class_='ResTableFull')
            (totalAthletes, sport_IDs) = inspectTable(table, cur)
            #insert data to Countries table
            cur.execute('''INSERT INTO CountryDB VALUES
                (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', tuple([country.name, totalAthletes] + sport_IDs))

        except requests.exceptions.HTTPError as e:
            print ("HTTP Error:", e)
            raise SystemExit
        except requests.exceptions.ConnectionError as e:
            print ("Error Connecting:", e)
            raise SystemExit
        except requests.exceptions.Timeout as e:
            print ("Timeout Error:", e)
            raise SystemExit
        except requests.exceptions.RequestException as e:     # any Requests error
            print ("Request exception: ", e)
            raise SystemExit

    conn.commit()
    # close connection
    conn.close()

def inspectTable(table, cur):
    '''Function inspects the table of information, saves the sports into Sports table
       Return the total atheles and the sport id list
    '''
    total = table.select('tr.MedalStd1 td.StyleCenter b')[0].get_text() #select returns a list of result
    sport_IDs = [None for i in range(NUM_SPORTS)]
    for i,sport in enumerate(table.find_all('tr', class_=re.compile('Res\d', re.I))) :
        #get the sport name
        sportname = sport.find('a').get_text()
        #insert data to Sports table
        cur.execute('''INSERT INTO Sports (sport) VALUES (?)''', (sportname, )) #insert sport in Sports
        cur.execute('SELECT id FROM Sports WHERE sport = ? ', (sportname, )) #get id of that sport
        sport_IDs[i] = cur.fetchone()[0] #save that id in sport_IDs

    return (total, sport_IDs)

saveCountryInfo()


import zmq
import msgpack
import distro

from svupdater.lists import pkglists
from svupdater.packages import Status

def get_os_version():
    """Returns current os version as string."""
    return distro.version()

def get_installed_pkgs():
    """Returns list of names (strings) of installed packages."""
    return list(name for name, pkg in Status().items() if pkg.is_installed())

def get_pkglists():
    """Returns list of dictionaries where each dict represents enabled package
    list. The dict has two keys: pkg_list and enabled_options. pkg_list is name of
    the package list and enabled_options is list of strings enumerating enabled
    options of the package list."""

    def _options(options):
        return [oname for oname, option in options.items() if option["enabled"]]

    ret = []
    for pkglist, data in pkglists().items():
        if data["enabled"]:
            ret.append({"name": pkglist, "options": _options(data["options"])})
    return ret

def collect_data():
    """Collects various system data and returns them as a dictionary."""
    return {
        "os_version": get_os_version(),
        "enabled_pkglists": get_pkglists(),
        "installed_packages": get_installed_pkgs(),
    }

def send(socket, topic, message):
    """Sends message with given topic to given socket. It returns 0 if message
    was sent succesfully, otherwise appropriate error code is returned."""
    try:
        with zmq.Context() as ctx, ctx.socket(zmq.PUSH) as zmq_sock:
            # Size (in bytes) below which messages should always be copied even if
            # in send() copy=False. The initial default value is 65536 (64kB).
            # To disable copying and allow tracking we need to turn it off.
            zmq_sock.copy_threshold = 0
            # Maximum time in ms before a send operation returns with EAGAIN.
            # = send supposed to be blocking for max 5s
            zmq_sock.setsockopt(zmq.SNDTIMEO, 5000)
            # The linger value of 0 specifies no linger period. Pending messages
            # shall be discarded immediately after close.
            # This must be set up to allow closing the socket if sending/waiting
            # for send failed, otherwise close waits untill pending messages are sent.
            zmq_sock.setsockopt(zmq.LINGER, 0)
            zmq_sock.connect(socket)
            tracker = zmq_sock.send_multipart(
                [topic.encode(), msgpack.packb(message, use_bin_type=True)],
                copy=False,
                track=True,
            )
            tracker.wait(5)
        return 0
    except (zmq.ZMQError, zmq.NotDone):
        # Send did not succeed
        return 1


import cv2
import numpy as np
import sys
sys.path.insert(0, './library/filtering')
from library.filtering import my_filtering

def get_my_sobel():
    sobel_x = np.dot(np.array([[1],[2],[1]]),np.array([[-1,0,1]]))
    sobel_y = np.dot(np.array([[-1],[0],[1]]),np.array([[1,2,1]]))
    return sobel_x,sobel_y
def get_sobel():
    derivative = np.array([[-1,0,1]])
    blur = np.array([[1],[2],[1]])

    x = np.dot(blur,derivative)
    y = np.dot(derivative.T,blur.T)
    return x,y

if __name__ == '__main__':
    src = cv2.imread('../image/edge_detection_img.png', cv2.IMREAD_GRAYSCALE)

    sobel_x,sobel_y = get_sobel()

    dst_x = my_filtering(src, sobel_x, 'zero')
    dst_y = my_filtering(src, sobel_y, 'zero')
    dst = np.hypot(dst_x,dst_y)

    # 0~1 사이의 값으로 변경 후 0~255로 변경
    dst_x_Norm = ((dst_x - np.min(dst_x))/np.max(dst_x-np.min(dst_x))*255+0.5).astype(np.uint8)
    dst_y_Norm = ((dst_y - np.min(dst_y))/np.max(dst_y-np.min(dst_y))*255+0.5).astype(np.uint8)

    dst_x2 = np.sqrt(dst_x**2)
    dst_y2 = np.sqrt(dst_y**2)

    cv2.imshow('src', src)
    cv2.imshow('dst_x ', dst_x)
    cv2.imshow('dst_y ', dst_y)
    cv2.imshow('dst_x2 ', dst_x2)
    cv2.imshow('dst_y2 ', dst_y2)
    cv2.imshow('dst_x_Norm', dst_x_Norm)
    cv2.imshow('dst_y_Norm ', dst_y_Norm)

    cv2.waitKey()
    cv2.destroyAllWindows()


from urllib.request import urlopen
from bs4 import BeautifulSoup

def obtain_reqs(URL,list_len,answer_list,list_begin):
    url = URL
    html = urlopen(url).read()
    soup = BeautifulSoup(html)

    for script in soup(["script", "style"]):
        script.decompose()

    strips = list(soup.stripped_strings)

    start_idx = strips.index(list_begin)
    ans = answer_list

    info = {}
    for i in range(1,list_len+1):
        info["Question " +str(i)+ ": " +strips[start_idx+i]] = "Answer " +str(i)+ ": " +ans[i-1]
    return info

def return_info():
    info = obtain_reqs(URL="https://fetch-hiring.s3.amazonaws.com/data-engineer/text-similarity.html",
           list_len=5,
           answer_list=["My application does not count punctuation",
                      "My application removes common stop words",
                      "My application does not care about the ordering of words",
                      "Number of unique matched words divided by total unique words in both samples",
                      "Dictionaries, lists, sets, and tuples are employed. Sets are used for comparing unique words between two samples and are helpful because they are more performant for lookups than lists."],
           list_begin="You will have to make a number of decisions as you develop this solution:")

    return info


#!/usr/bin/env python3
"""
Get page module

Contains get_page function
"""

import redis
import requests

rc = redis.Redis()
count = 0

def get_page(url: str) -> str:
    """ Get the cached values. """
    rc.set("cached:{}".format(url), count)
    resp = requests.get(url)
    rc.incr("count:{}".format(url))
    rc.setex("cached:{}".format(url), 10, rc.get("cached:{}".format(url)))
    return resp.text

if __name__ == "__main__":
    """ Main method. """
    get_page('http://slowwly.robertomurray.co.uk')


from numpy import asarray
from numpy import meshgrid
from numpy import linspace
from numpy import amax
from numpy import amin
from scipy.interpolate import griddata  # type: ignore
import matplotlib.pyplot as plt

def scalarfield_contours_numpy(xy, s, levels=50, density=100):
    r"""Compute the contour lines of a scalarfield.

    Parameters
    ----------
    xy : array-like
        The xy-coordinates at which the scalar field is defined.
    s : array-like
        The values of the scalar field.
    levels : int, optional
        The number of contour lines to compute.
        Default is ``50``.

    Returns
    -------
    tuple
        A tuple of a list of levels and a list of contour geometry.

        The list of levels contains the values of the scalarfield at each of
        the contours. The second item in the tuple is a list of contour lines.
        Each contour line is a list of paths, and each path is a list polygons.

    Notes
    -----
    The computation of the contour lines is based on the `contours function`_
    available through matplotlib.

    Examples
    --------
    .. code-block:: python

        import compas
        from compas.datastructures import Mesh
        from compas.geometry import centroid_points
        from compas.geometry import distance_point_point
        from compas.geometry import scalarfield_contours_numpy

        mesh = Mesh.from_obj(compas.get('faces.obj'))

        points = [mesh.vertex_coordinates(key) for key in mesh.vertices()]
        centroid = centroid_points(points)
        distances = [distance_point_point(point, centroid) for point in points]

        xy = [point[0:2] for point in points]

        levels, contours = scalarfield_contours_numpy(xy, distances)

        for i in range(len(contours)):
            level = levels[i]
            contour = contours[i]
            print(level)
            for path in contour:
                for polygon in path:
                    print(polygon)

    .. _contours function: http://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.contour.html#matplotlib.axes.Axes.contour

    """
    xy = asarray(xy)
    s = asarray(s)
    x = xy[:, 0]
    y = xy[:, 1]
    X, Y = meshgrid(linspace(amin(x), amax(x), 2 * density), linspace(amin(y), amax(y), 2 * density))
    S = griddata((x, y), s, (X, Y), method="cubic")

    fig = plt.figure()
    ax = fig.add_subplot(111, aspect="equal")

    c = ax.contour(X, Y, S, levels)

    contours = [0] * len(c.collections)  # type: ignore
    levels = c.levels  # type: ignore

    for i, coll in enumerate(iter(c.collections)):  # type: ignore
        paths = coll.get_paths()
        contours[i] = [0] * len(paths)  # type: ignore
        for j, path in enumerate(iter(paths)):
            polygons = path.to_polygons()
            contours[i][j] = [0] * len(polygons)  # type: ignore
            for k, polygon in enumerate(iter(polygons)):
                contours[i][j][k] = polygon  # type: ignore

    plt.close(fig)

    return levels, contours


#Python modules
import argparse
import logging
import json
import warnings
import os
import gc

#Pytorch modules
from torch.utils.data import DataLoader
import torch
from torch.autograd import Variable
from torchvision import transforms
import torch.optim as optim

import numpy as np
from datasets import ALOVDataset
import model
import pytorch_utils as util

warnings.filterwarnings("ignore")
logging.getLogger().setLevel(logging.INFO)

transform = transforms.Compose([util.Normalize(), util.ToTensor()])

def train(model, optimizer, loss_fn, dataloader, metrics, params):
    """Train the model on `num_steps` batches
    Args:
        model: (torch.nn.Module) the neural network
        optimizer: (torch.optim) optimizer for parameters of model
        loss_fn: a function that takes batch_output and batch_labels and computes the loss for the batch
        dataloader: (DataLoader) a torch.utils.data.DataLoader object that fetches training data
        metrics: (dict) a dictionary of functions that compute a metric using the output and labels of each batch
        params: (Params) hyperparameters
        num_steps: (int) number of batches to train on, each of size params.batch_size
    """

    # set model to training mode
    model.train()

    # summary for current training loop and a running average object for loss
    summ = []
    loss_avg = util.RunningAverage()

    counter=0
    for i,data in enumerate(dataloader):
        optimizer.zero_grad()

        x1, x2, y = data['previmg'], data['currimg'], data['currbb']
        if params.cuda:
            x1, x2, y = Variable(x1.cuda()), Variable(x2.cuda()), Variable(y.cuda(), requires_grad=False)

        output = model(x1, x2)
        loss = loss_fn(output, y)

        loss.backward(retain_graph=True)

        # performs updates using calculated gradients
        optimizer.step()

        # Evaluate summaries only once in a while
        if i % params.save_summary_steps == 0:
            # extract data from torch Variable, move to cpu, convert to numpy arrays
            output = output.data.cpu().numpy()
            # compute all metrics on this batch
            summary_batch = {}
            summary_batch['loss'] = loss.data[0]
            summ.append(summary_batch)
            logging.info('- Average Loss for iteration {} is {}'.format(i,loss.data[0]/params.batch_size))

        # update the average loss
        loss_avg.update(loss.data[0])
        counter+=1

    print(counter)

        # compute mean of all metrics in summary
    metrics_mean = {metric: np.mean([x[metric] for x in summ]) for metric in summ[0]}
    metrics_string = " ; ".join("{}: {:05.3f}".format(k, v) for k, v in metrics_mean.items())
    logging.info("- Train metrics: " + metrics_string)

def train_and_evaluate(model, train_dataloader, val_dataloader, optimizer, loss_fn, metrics, params, model_dir,
                       restore_file=None):
    """Train the model and evaluate every epoch.
    Args:
        model: (torch.nn.Module) the neural network
        train_dataloader: (DataLoader) a torch.utils.data.DataLoader object that fetches training data
        val_dataloader: (DataLoader) a torch.utils.data.DataLoader object that fetches validation data
        optimizer: (torch.optim) optimizer for parameters of model
        loss_fn: a function that takes batch_output and batch_labels and computes the loss for the batch
        metrics: (dict) a dictionary of functions that compute a metric using the output and labels of each batch
        params: (Params) hyperparameters
        model_dir: (string) directory containing config, weights and log
        restore_file: (string) optional- name of file to restore from (without its extension .pth.tar)
    """

    epoch_start=0

    # reload weights from restore_file if specified
    if restore_file is not None:
        restore_path=''
        if os.path.isabs(args.restore_file):
            restore_path=args.restore_file
        else:
            restore_path = os.path.join(model_dir, args.restore_file)
        logging.info("Restoring parameters from {}".format(restore_path))
        checkpoint=util.load_checkpoint(restore_path, model, optimizer)
        epoch_start=checkpoint['epoch']-1

    best_val_acc = 0.0

    for epoch in range(epoch_start,params.num_epochs):
        # Run one epoch
        logging.info("Epoch {}/{}".format(epoch + 1, params.num_epochs))

        # compute number of batches in one epoch (one full pass over the training set)
        train(model, optimizer, loss_fn, train_dataloader, metrics, params)

        # Evaluate for one epoch on validation set
        val_metrics = evaluate(model, loss_fn, val_dataloader, metrics, params)

        # val_acc = val_metrics['accuracy']
        # is_best = val_acc>=best_val_acc
        #
        # # Save weights
        util.save_checkpoint({'epoch': epoch + 1,
                               'state_dict': model.state_dict(),
                               'optim_dict' : optimizer.state_dict()},
                                is_best=False,
                               checkpoint=model_dir)
        #
        # # If best_eval, best_save_path
        # if is_best:
        #     logging.info("- Found new best accuracy")
        #     best_val_acc = val_acc
        #
        #     # Save best val metrics in a json file in the model directory
        #     best_json_path = os.path.join(model_dir, "metrics_val_best_weights.json")
        #     util.save_dict_to_json(val_metrics, best_json_path)

        # Save latest val metrics in a json file in the model directory
        last_json_path = os.path.join(model_dir, "metrics_val_last_weights.json")
        util.save_dict_to_json(val_metrics, last_json_path)

def evaluate(model, loss_fn, dataloader, metrics, params):
    """Evaluate the model on `num_steps` batches.
    Args:
        model: (torch.nn.Module) the neural network
        loss_fn: a function that takes batch_output and batch_labels and computes the loss for the batch
        dataloader: (DataLoader) a torch.utils.data.DataLoader object that fetches data
        metrics: (dict) a dictionary of functions that compute a metric using the output and labels of each batch
        params: (Params) hyperparameters
        num_steps: (int) number of batches to train on, each of size params.batch_size
    """

    # set model to evaluation mode
    model.eval()

    # summary for current eval loop
    summ = []

    dataset = dataloader.dataset

    total_loss = 0

    # compute metrics over the dataset
    for i in range(64):

        sample = dataset[i]
        sample['currimg'] = sample['currimg'][None, :, :, :]
        sample['previmg'] = sample['previmg'][None, :, :, :]
        x1, x2 = sample['previmg'], sample['currimg']
        y = sample['currbb']

        # move to GPU if available
        if params.cuda:
            x1 = Variable(x1.cuda())
            x2 = Variable(x2.cuda())
            y = Variable(y.cuda(), requires_grad=False)

        # compute model output
        output = model(x1, x2)
        loss = loss_fn(output[0], y)

        # extract data from torch Variable, move to cpu, convert to numpy arrays
        output = output.data.cpu().numpy()

        # compute all metrics on this batch
        summary_batch = dict()
        summary_batch['loss'] = loss.data[0]
        summ.append(summary_batch)

    # compute mean of all metrics in summary
    metrics_mean = {metric: np.mean([x[metric] for x in summ]) for metric in summ[0]}
    metrics_string = " ; ".join("{}: {:05.3f}".format(k, v) for k, v in metrics_mean.items())
    logging.info("- Eval metrics : " + metrics_string)

    return metrics_mean

if __name__ == '__main__':

    default_json = json.dumps([{"learning_rate": 1e-3,
                                "batch_size": 32,
                                "num_epochs": 100,
                                "dropout_rate": 0.8,
                                "num_channels": 32,
                                "save_summary_steps": 100,
                                "num_workers": 4}])

    parser = argparse.ArgumentParser()
    parser.add_argument('--model_dir', default=None, help="Directory containing params.json")
    parser.add_argument('--restore_file', default=None,
                        help="Optional, name of the file in --model_dir containing weights to reload before \
                        training")  # 'best' or 'train'

    args = parser.parse_args()

    params=util.Params(default_json)

    model_dir=0
    if args.model_dir :
        params=util.Params()
        params.update(args.model_dir)
        model_dir=args.model_dir
    else:
        model_dir_path=os.path.join(".","model")
        if  not os.path.isdir(model_dir_path):
            os.mkdir(model_dir_path)
        model_dir=model_dir_path

    params.cuda = torch.cuda.is_available()

    alov = ALOVDataset('/large_storage/imagedata++', '/large_storage/alov300++_rectangleAnnotation_full', transform)

    dataloader = DataLoader(alov, batch_size=params.batch_size)

    use_gpu = torch.cuda.is_available()

    model = model.Re3Net().cuda() if use_gpu else model.Re3Net()
    optimizer = optim.Adam(model.parameters(), lr=params.learning_rate)

    net = 0

    loss_fn=model.loss_fn(params.cuda)

    # Train the model
    logging.info("Starting training for {} epoch(s)".format(params.num_epochs))
    train_and_evaluate(model, dataloader, dataloader, optimizer, loss_fn, 0, params, model_dir,
                       args.restore_file)


# Adrian Potok
# CS4541
# 3/18/2023
# adrian.m.potok@wmich.edu

# Imports
import sys
import argparse

class memory_access():
    def __init__(self, access_mode, tag, set_index, block, print_address_and_size):
        self.access_mode = access_mode
        self.tag = tag
        self.set_index = set_index
        self.block = block
        self.print_address_and_size = print_address_and_size

def main():

    # Parse arguments
    parser = argparse.ArgumentParser(description='Cache Simulator using FIFO replacement strategy')
    parser.add_argument('-v', '--verbose', action='store_true', help='Enable verbose output')
    parser.add_argument('-s', '--sets', type=int, required=True, default=1, help='The number of set index bits')
    parser.add_argument('-E', '--associativity', type=int, required=True, default=1, help='The number of lines per set')
    parser.add_argument('-b', '--blocks', type=int, required=True, default=1, help='The number of block bits')
    parser.add_argument('-t', '--trace', type=argparse.FileType('r'), required=True, help='The trace file to replay')

    if len(sys.argv) == 1:
        parser.print_help(sys.stderr)
        sys.exit(1)

    args = parser.parse_args()

    verbose_flag = args.verbose
    set_index_bits = args.sets
    associativity = args.associativity
    block_bits = args.blocks
    trace_file = args.trace

    # Calculate tag bits
    tag_bits = 64 - (block_bits + set_index_bits)

    # Parse file into array ignoring "I" lines
    try:
        # Read contents from file
        contents = trace_file.read()

        # Create list of lines from contents string
        contents = contents.split("\n")

        # Check the first character of each line to skip
        access_info = []
        for line in contents:
            if len(line) < 2 or line[1] not in ("S","M","L"):
                continue

            # Extract trace info
            parts = line.split()
            access_mode = parts[0]
            print_address_and_size = parts[1].split(",")
            print_address = print_address_and_size[0]
            if len(print_address) > 1:
                print_address_and_size = parts[1].lstrip("0")
            else:
                print_address_and_size = parts[1]

            address = str(bin(int(parts[1].split(",")[0], 16))[2:]).zfill(64)

            # Extract access info
            tag = address[ : tag_bits]
            set_index = address[tag_bits : set_index_bits + tag_bits]
            block = address[tag_bits + set_index_bits : ]
            access = memory_access(access_mode, tag, int(set_index, 2), block, print_address_and_size)
            access_info.append(access)

    finally:
        trace_file.close()

    # Setup simulated cache
    cache = []
    for i in range(2 ** set_index_bits):
        inner_list = []
        for j in range(associativity):
            inner_list.append(None)
        cache.append(inner_list)

    # Setup cache indicies list for FIFO replacement
    cache_indicies = []
    for i in range(2 ** set_index_bits):
        cache_indicies.append(0)

    # Run cache simulation
    hits = 0
    misses = 0
    evictions = 0

    x = 0
    while x < len(access_info):

        # Verbose prints
        if(verbose_flag):
            print(access_info[x].access_mode + " " +  access_info[x].print_address_and_size + " ", end="")

        # y represents what line within the set we are looking at
        y = 0
        while y < associativity:

            # Current set is int representing which set we are looking at
            current_set = access_info[x].set_index

            if access_info[x].access_mode == "M":
                # Cold miss
                if cache[current_set][y] is None:
                    cache[current_set][y] = access_info[x]
                    if(verbose_flag):
                        print("miss hit")
                    hits += 1
                    misses += 1
                    y = associativity

                # Hit twice since access mode is M
                elif cache[current_set][y].tag == access_info[x].tag:
                    cache[current_set][y] = access_info[x]
                    if(verbose_flag):
                        print("hit hit")
                    hits += 2
                    y = associativity

                # Pass to increment line index until its 1 less than associativity
                elif cache[current_set][y].tag != access_info[x].tag and y < len(cache[0]) - 1:
                    pass

                # If no cold misses or hits happen we must evict and replace
                elif cache[current_set][y].tag != access_info[x].tag:
                    # Replace the first access to be placed in the cache
                    cache[current_set][cache_indicies[current_set]%associativity] = access_info[x]
                    cache_indicies[current_set] += 1
                    hits += 1
                    misses += 1
                    evictions += 1
                    if(verbose_flag):
                        print("miss eviction hit")
            else:
                # Cold miss
                if cache[current_set][y] is None:
                    cache[current_set][y] = access_info[x]
                    if(verbose_flag):
                        print("miss")
                    misses += 1
                    y = associativity

                # Hit once if tag is equal
                elif cache[current_set][y].tag == access_info[x].tag:
                    cache[current_set][y] = access_info[x]
                    hits += 1
                    if(verbose_flag):
                        print("hit")
                    y = associativity

                # Pass to increment line index until its 1 less than associativity
                elif cache[current_set][y].tag != access_info[x].tag and y < len(cache[0]) - 1:
                    pass

                # If no cold misses or hits happen we must evict and replace
                elif cache[current_set][y].tag != access_info[x].tag:
                    # Replace the first access to be placed in the cache
                    cache[current_set][cache_indicies[current_set]%associativity] = access_info[x]
                    cache_indicies[current_set] += 1
                    misses += 1
                    evictions += 1
                    if(verbose_flag):
                        print("miss eviction")
            y = y + 1
        x = x + 1

    print(f"hits:{hits} misses:{misses} evictions:{evictions}", end="")

    return

main()


from django.urls import path
from . import views
urlpatterns = [
    path('', views.index, name='index'),
    path('cart/', views.cart, name='cart'),
    path('add-to-cart/<int:id>/', views.add_to_cart, name='addcart'),
    path('item/<int:id>/', views.item, name = 'item'),
    path('remove-from-cart/<int:id>/', views.remove_item, name = 'item'),
    path('comment/<int:id>/', views.rate_item, name='comment-rate'),
    path('create-order/', views.create_order, name = 'create-order'),
    path('orders/', views.view_orders, name = 'list-order'),
    path('order/<int:orderId>/', views.view_order, name = 'view-order'),
    path('report/', views.feedback, name = 'feedback'),
    path('buy-now/<int:id>/', views.buynow, name='buynow'),
    path('noti/<int:id>/', views.change_noti, name="change-notification"),
    path('onoti/<int:id>/', views.change_onoti, name="change-order-notification"),
    path('feedback-order/<int:id>/', views.feedback_order, name="feedback-order"),
    path('detail-feedback/<int:id>/', views.detail_feedback, name="feedback-order"),
]


# -*- coding: utf-8 -*-
from __future__ import absolute_import
import numpy as np
from aiida.parsers.parser import Parser
from aiida.orm.nodes.data.array.xy import XyData
from aiida.orm.nodes.data.dict import Dict
from aiida.common.exceptions import InvalidOperation
from aiida_quantumespresso.parsers import QEOutputParsingError
from aiida_quantumespresso.parsers import parse_raw_out_basic
from aiida_quantumespresso.calculations.dos import DosCalculation
from six.moves import range

class DosParser(Parser):
    """
    This class is the implementation of the Parser class for Dos.
    """
    _dos_name = 'output_dos'
    _units_name = 'output_units'

    def __init__(self, calculation):
        """
        Initialize the instance of DosParser
        """
        # check for valid input
        if not isinstance(calculation, DosCalculation):
            raise QEOutputParsingError("Input calc must be a DosCalculation")

        self._calc = calculation

        super(DosParser, self).__init__(calculation)

    def get_linkname_dos(self):
        """
        Returns the name of the link of dos
        """
        return self._dos_name

    def get_linkname_units(self):
        """
        Returns the name of the link of units
        """
        return self._units_name

    def parse_with_retrieved(self, retrieved):
        """
        Parses the datafolder, stores results.
        Retrieves dos output, and some basic information from the
        out_file, such as warnings and wall_time
        """

        # suppose at the start that the job is successful
        successful = True
        new_nodes_list = []

        try:
            out_folder = self._calc.get_retrieved_node()
        except KeyError:
            self.logger.error("No retrieved folder found")
            return successful, new_nodes_list

        # Read standard out
        try:
            filpath = out_folder.get_abs_path(self._calc._OUTPUT_FILE_NAME)
            with open(filpath, 'r') as fil:
                    out_file = fil.readlines()
        except OSError:
            self.logger.error("Standard output file could not be found.")
            successful = False
            return successful, new_nodes_list

        successful = False
        for i in range(len(out_file)):
            line = out_file[-i]
            if "JOB DONE" in line:
                successful = True
                break
        if not successful:
            self.logger.error("Computation did not finish properly")
            return successful, new_nodes_list

        # check that the dos file is present, if it is, read it
        try:
            dos_path = out_folder.get_abs_path(self._calc._DOS_FILENAME)
            with open(dos_path, 'r') as fil:
                    dos_file = fil.readlines()
        except OSError:
            successful = False
            self.logger.error("Dos output file could not found")
            return successful, new_nodes_list

        # end of initial checks

        array_names = [[], []]
        array_units = [[], []]
        array_names[0] = ['dos_energy', 'dos',
                          'integrated_dos']  # When spin is not displayed
        array_names[1] = ['dos_energy', 'dos_spin_up', 'dos_spin_down',
                          'integrated_dos']  # When spin is displayed
        array_units[0] = ['eV', 'states/eV',
                          'states']  # When spin is not displayed
        array_units[1] = ['eV', 'states/eV', 'states/eV',
                          'states']  # When spin is displayed

        # grabs parsed data from aiida.dos
        array_data, spin = parse_raw_dos(dos_file, array_names, array_units)

        energy_units = 'eV'
        dos_units = 'states/eV'
        int_dos_units = 'states'
        xy_data = XyData()
        xy_data.set_x(array_data["dos_energy"],"dos_energy", energy_units)
        y_arrays = []
        y_names = []
        y_units = []
        y_arrays  += [array_data["integrated_dos"]]
        y_names += ["integrated_dos"]
        y_units += ["states"]
        if spin:
            y_arrays  += [array_data["dos_spin_up"]]
            y_arrays  += [array_data["dos_spin_down"]]
            y_names += ["dos_spin_up"]
            y_names += ["dos_spin_down"]
            y_units += ["states/eV"]*2
        else:
            y_arrays  += [array_data["dos"]]
            y_names += ["dos"]
            y_units += ["states/eV"]
        xy_data.set_y(y_arrays,y_names,y_units)

        # grabs the parsed data from aiida.out
        parsed_data = parse_raw_out_basic(out_file, "DOS")
        output_params = Dict(dict=parsed_data)
        # Adds warnings
        for message in parsed_data['warnings']:
            self.logger.error(message)
        # Create New Nodes List
        new_nodes_list = [(self.get_linkname_outparams(), output_params),
                          (self.get_linkname_dos(), xy_data)]
        return successful,new_nodes_list

def parse_raw_dos(dos_file, array_names, array_units):
    """
    This function takes as input the dos_file as a list of filelines along
    with information on how to give labels and units to the parsed data

    :param dos_file: dos file lines in the form of a list
    :type dos_file: list
    :param array_names: list of all array names, note that array_names[0]
                        is for the case with non spin-polarized calculations
                        and array_names[1] is for the case with spin-polarized
                        calculation
    :type array_names: list
    :param array_units: list of all array units, note that array_units[0] is
                        for the case with non spin-polarized calculations and
                        array_units[1] is for the case with spin-polarized
                        calculation
    :type array_units: list

    :return array_data: narray, a dictionary for ArrayData type, which contains
                        all parsed dos output along with labels and units
    :return spin: boolean, indicates whether the parsed results are spin
                  polarized
    """

    dos_header = dos_file[0]
    try:
        dos_data = np.genfromtxt(dos_file)
    except ValueError:
        raise QEOutputParsingError('dosfile could not be loaded '
        ' using genfromtxt')
    if len(dos_data) == 0:
        raise QEOutputParsingError("Dos file is empty.")
    if np.isnan(dos_data).any():
        raise QEOutputParsingError("Dos file contains non-numeric elements.")

    # Checks the number of columns, essentially to see whether spin was used
    if len(dos_data[0]) == 3:
        # spin is not used
        array_names = array_names[0]
        array_units = array_units[0]
        spin = False
    elif len(dos_data[0]) == 4:
        # spin is used
        array_names = array_names[1]
        array_units = array_units[1]
        spin = True
    else:
        raise QEOutputParsingError("Dos file in format that the parser is not "
                                   "designed to handle.")

    i = 0
    array_data = {}
    array_data['header'] = np.array(dos_header)
    while i < len(array_names):
        array_data[array_names[i]] = dos_data[:, i]
        array_data[array_names[i]+'_units'] = np.array(array_units[i])
        i += 1
    return array_data,spin


# -*- coding:utf-8 -*-
from collections import deque

def bfs() -> list:
    while queue:
        x, y = queue.popleft()

        for i in range(4):
            a = x + dx[i]
            b = y + dy[i]

            if 0<=a<N and 0<=b<M and graph[a][b] == 0:
                queue.append([a, b])
                graph[a][b] = graph[x][y] + 1

    return graph

if __name__ == "__main__":

    # 초기 변수 선언 & 그래프 생성
    M, N = list(map(int, input().split()))
    graph = []
    queue = deque()

    dx = [-1, 0, 1, 0] # 익은 토마토 좌표 기준으로 사방향 드로잉을 위한 x좌표
    dy = [0, -1, 0, 1] # 익은 토마토 좌표 기준으로 사방향 드로잉을 위한 y좌표

    for i in range(N):
        graph.append(list(map(int,input().split())))

    # 익은 토마토 좌표 추출 -> 큐 삽입

    for i in range(N):
        for j in range(M):
            if graph[i][j] == 1:
                queue.append([i, j])

    # 토마토 숙성
    graph = bfs()

    # 결과 출력
    day = 0
    for i in graph:
        for j in i:
            if j == 0:
                print (-1)
                exit(0)
        day = max(day, max(i))

    print (day-1)


import uuid

from celery.signals import worker_process_init

from strongr.core.domain.schedulerdomain import SchedulerDomain
from .wrapper import Command

import strongr.core
from celery import Celery, signals

class RunWorkerCommand(Command):
    """
    Runs a strongr worker.

    worker:run
        {--p|profile=elasticworker : The worker profile to be used}
    """
    def handle(self):
        config = strongr.core.Core.config()
        broker = config.celery.broker
        backend = config.celery.backend

        celery = Celery('strongr', broker=broker, backend=backend)

        scheduler = SchedulerDomain.schedulerService()
        scheduler.getCommandBus() # we need to initiate this as it self-registers it's commands to celery
        scheduler.getQueryBus() # we need to initiate this as it self-registers it's queries to celery

        domains = getattr(config.celery.workers, self.option('profile')).as_dict()

        commands = []
        for domain in domains:
            for command in domains[domain]:
                commands.append('{}.{}'.format(domain, command))

        for command in commands:
            strongr.core.Core.command_router().enable_worker_route_for_command(celery, command)

        workername = '%h@{}'.format(uuid.uuid4())

        argv = [
            'worker',
            '--loglevel=DEBUG',
            '-Q=' + ','.join(commands),
            #'--pool=solo',
            #'--concurrency=1',
            #'--max-tasks-per-child=1',
            '--loglevel=INFO',
            '-n {}'.format(workername)
        ]

        # crude fix for celery daemonized threads causing salt to fail
        # https://github.com/celery/celery/issues/1709
        @worker_process_init.connect
        def fix_multiprocessing(**kwargs):
            # don't be a daemon, so we can create new subprocesses
            from multiprocessing import current_process
            current_process().daemon = False

        @signals.setup_logging.connect
        def setup_celery_logging(**kwargs):
            pass

        celery.worker_main(argv)


from geopy.geocoders import Nominatim
from geopy import Location
from exif import Image
import os
import argparse
import datetime
import shutil
import time

from srt_parser import SrtParser

def get_location_label(location: Location):
    address = location.raw['address']
    label = address.get('city', '')
    label = label if label else address.get('town', '')
    label = label if label else address.get('county', '')
    return label

def prompt_label(day: str):
    return input(f'Label for {day}: ')

parser = argparse.ArgumentParser()
parser.add_argument('-l', '--label', action='store_true', help='request explicit labels')
parser.add_argument('-i', '--input', default='Files', help='input directory')
parser.add_argument('-o', '--output', default='Output', help='output directory')
parser.add_argument('-s', '--sleep', default=1, type=float, help='time between geolocation requests')
parser.add_argument('-d', '--delete', action='store_true', help='delete old files')
parser.add_argument('-v', '--verbose', action='store_true', help='verbose output')
parser.add_argument('-n', '--num', default=float('inf'), type=float, help='number to copy')
parser.add_argument('-e', '--extensions', nargs='*', help='only process files with these extensions')
parser.add_argument('--srt', action='store_true', help='attempt to find an srt file for each mp4')
args = parser.parse_args()

img_types = ['jpg', 'dng']

# Instantiate the label map. Maps day to a specific label. NOTE: videos will use first label for a day
labels = {}

# Instantiate geolocator if necessary
if not args.label or args.srt:
    geolocator = Nominatim(user_agent="geoapiExercises")

# Instantiate srt parser if necessary
if args.srt:
    srt_parser = SrtParser()

# Tidy up extension args
if args.extensions:
    args.extensions = list(map(lambda x: x.lower().strip('.'), args.extensions))

# Get all contents of input directory and sort it. Currently sorts
# based on extension to make sure images are processed first (no geo information on videos)
files = os.listdir(args.input)
files.sort(key=lambda x: x.split('.')[-1])

# Make output directory
if not os.path.isdir(args.output):
    os.mkdir(args.output)

num = 0
for file in files:
    # Skip srt files
    if file.lower().endswith('.srt'):
        if args.verbose:
            print(f'Skipping .srt file {file}')
        continue

    # Only process this file if the extension is currently being processed
    if args.extensions:
        extension = file.split('.')[-1]
        if extension.lower() not in args.extensions:
            print(f'Skipping {file} due to extension')
            continue

    # Make sure the specified number of images hasn't been reached
    num += 1
    if num > args.num:
        break

    # Get path of file
    old_file = os.path.join(args.input, file)

    # Print file name
    print(old_file)

    # Default folder name to blank
    folder = ''
    with open(old_file, 'rb') as f:
        # If the file is an image, get the exif timestamp, otherwise get creation date
        is_image = old_file.lower().split('.')[-1] in img_types
        if is_image:
            image = Image(f)
            date = image.get('datetime')
            parsed_date = datetime.datetime.strptime(date, '%Y:%m:%d %H:%M:%S')
            day = str(parsed_date.date())
        else:
            day = str(datetime.datetime.fromtimestamp(os.path.getctime(old_file)).date())

        label = ''

        # If explicit label is specified, request one for each day
        if args.label and not day in labels:
            label = prompt_label(day)

        # If this is a video and srt is specified
        elif not is_image and args.srt:
            srt_file = ''.join(old_file.split('.')[:-1]) + '.SRT'

            # Make sure the srt file exists before continuing
            if os.path.exists(srt_file):
                record = list(srt_parser.parse(srt_file))[0]
                location = geolocator.reverse(f'{record.latitude},{record.longitude}')
                label = get_location_label(location)
                label = label if label else prompt_label(day)

        # Attempt to geolocate image
        elif is_image:
            # Get longitude/latitude from geotag
            latitude_ref = image.get('gps_latitude_ref')
            latitude = image.get('gps_latitude')
            longitude_ref = image.get('gps_longitude_ref')
            longitude = image.get('gps_longitude')
            city = None

            if latitude is not None and longitude is not None:
                # Calculate longitude/latitude from deg/min/s
                actual_latitude = (latitude[0] + latitude[1] / 60 + latitude[2] / 3600) * (1 if latitude_ref == 'N' else -1)
                actual_longitude = (longitude[0] + longitude[1] / 60 + longitude[2] / 3600) * (1 if longitude_ref == 'E' else -1)

                # Geolocate
                location = geolocator.reverse(f'{actual_latitude},{actual_longitude}')

                # Print location if verbose
                if args.verbose:
                    print(location)

                # Sleep to avoid hitting api limits
                time.sleep(args.sleep)

                # Use the city/town/county as label
                city = get_location_label(location)

            # If a location could be found, set that as the label
            if city:
                label = city
            # If there is already a label for this day, use it
            elif day in labels:
                label = labels[day]
            # Otherwise, request a label
            else:
                label = input(f'Label for {day}: ')

        # If label has not been found, default to first label from this day and prompt for label if not found
        if not label:
            if day in labels:
                label = labels[day]

            label = prompt_label(day)

        # Populate label map if necessary
        if not day in labels:
            labels[day] = label

        # Join day and label to make folder name, create if needed
        folder = os.path.join(args.output, label + ' ' + day)
        if not os.path.isdir(folder):
            os.mkdir(folder)

    try:
        if args.verbose:
            print(f'Moving {old_file} to {folder}')
        # Copy or move the file
        if args.delete:
            shutil.move(old_file, folder)
            if args.srt:
                shutil.move(srt_file, folder)
        else:
            shutil.copy(old_file, folder)
            if args.srt:
                shutil.copy(srt_file, folder)
    except Exception as e:
        print(e)


# Lakeshore 221 Temperature Monitor
# David Christle <christle@uchicago.edu>, December 2013

from instrument import Instrument
import visa
import types
import logging
import math
import time
import pyvisa
import qt

CR = '\r'
LF = '\n'

class Lakeshore_211(Instrument):

    def __init__(self, name, address, reset=False):
        Instrument.__init__(self, name, tags=['physical'])

        self._address = address
        # Device identification
        self.add_parameter('identification',
        flags=Instrument.FLAG_GET)
        # Get temperature in Kelvin
        self.add_parameter('temperature',
            flags=Instrument.FLAG_GET,
            type=types.FloatType,
            units='K')
        # Input type is the type of temperator sensor in the device
        self.add_parameter('intype',
            flags=Instrument.FLAG_GETSET,
            type=types.IntType)
        # Controls whether display is on or off on the module
        self.add_parameter('dispon',
            flags=Instrument.FLAG_GETSET,
            type=types.BooleanType)

        self._open_serial_connection()
        if reset:
            self.reset()
        else:
            self.get_all()

    # Open serial connection
    def _open_serial_connection(self):
        logging.debug(__name__ + ' : Opening serial connection')
        qt.rm.open_resource(self._address)
        self._visa = qt.rm.get_instrument(self._address)
        self._visa.baud_rate = long(9600)
        self._visa.data_bits = 7
        self._visa.stop_bits = 1
        self._visa.read_termination = CR+LF
        self._visa.write_termination = CR+LF
        self._visa.parity = pyvisa.constants.VI_ASRL_PAR_ODD

##        self._visa = pyvisa.visa.SerialInstrument(self._address,
##                baud_rate=9600, data_bits=7, stop_bits=1,
##                parity=pyvisa.visa.odd_parity, term_chars="\r\n",
##                timeout=2)
        # The purpose of the short timeout is so that the buffer_clear()
        # operation that takes place with every command to ensure the proper
        # output doesn't take too long. Each buffer_clear() usually takes one
        # entire timeout period, since most of the time, the buffer is in fact
        # clear.

    # Close serial connection
    def _close_serial_connection(self):
        '''
        Closes the serial connection
        '''
        logging.debug(__name__ + ' : Closing serial connection')
        self._visa.close()

    def buffer_clear(self):
        navail = self._visa.get_visa_attribute(pyvisa.VI_ATTR_ASRL_AVAIL_NUM)
        if navail > 0:
            reply = pyvisa.vpp43.read(self._visa.vi, navail)

    def reset(self):
        self._visa.write('*rst')
        time.sleep(3) # Sleep to avoid trying to talk to the device too quickly

    def get_all(self):
        self.get_identification()
        self.get_intype()
        self.get_temperature()
        self.get_dispon()

    def do_get_identification(self):
        self.buffer_clear()
        return self._visa.ask('*IDN?')

    def do_get_dispon(self):
        logging.debug(__name__ + 'reading temperature')
        self.buffer_clear()
        return self._visa.ask('DISPON?')

    def do_set_dispon(self, dispon):
        logging.debug(__name__ + 'setting input type')
        self.buffer_clear()
        if dispon == True:
            self._visa.write('DISPON 1')
        elif dispon == False:
            self._visa.write('DISPON 0')
        else:
            logging.error(__name__ + 'dispon value received was not a Boolean!')
            return False
        return True

    def do_get_temperature(self):
        logging.debug(__name__ + 'reading temperature')
        self.buffer_clear()
        return self._visa.ask('KRDG?')

    def do_get_intype(self):
        logging.debug(__name__ + 'reading input type')
        self.buffer_clear()
        return float(self._visa.ask('INTYPE?'))

    def do_set_intype(self, intype):
        logging.debug(__name__ + 'setting input type')
        self.buffer_clear()
        self._visa.write('INTYPE %d' % intype)


from selenium.webdriver.common.by import By
import os

from .modules.misc import datetime_formater
from .modules.scrapper_utils import double_element_parser
from .modules.scrapper_base import base_driver, kill_driver

def init_scrapper(endpoint=None, lookup_class=None):
    srvurl = os.environ.get("SELENIUM_URL")
    options = os.environ.get("SELENIUM_BROWSER_OP")
    service_type = os.environ.get("SELENIUM_SRV_TYPE")

    driver = base_driver(srvurl, service_type, options)
    driver.get("".format(os.environ.get("HISTORY_BASE_URL"),endpoint))

    elements = driver.find_elements(By.CLASS_NAME, lookup_class)

    parsed_elements = globals()[endpoint](elements)

    driver.quit()

    return parsed_elements

def doubles(elements):

    last_entrances = []

    for el in elements:
        bet_id = int(el.get_attribute("data-id"))

        el = el.find_element(By.CLASS_NAME, "sm-box")
        el_html = el.get_attribute("data-bs-content")

        entrance = double_element_parser(el_html)
        entrance["b_id"] = bet_id

        last_entrances.append(entrance)

    return last_entrances

def crashes(elements):

    last_entrances = []

    for el in elements:
        crash_el = {}

        status = ((el.get_attribute("class")).split(" "))[1]
        datetime_str = (((el.get_attribute("data-bs-original-title")).split(" "))[0::2])[:-1]

        crash_value = el.get_attribute("innerText")

        crash_el["status"] = status
        crash_el["date"] = datetime_str[0]
        crash_el["datetime"] = " ".join(datetime_str)
        crash_el["timestamp"] = datetime_formater(crash_el["datetime"])
        crash_el["crash"] = float(crash_value.replace("X",""))
        crash_el["b_id"] = "".join([status,str(crash_el["timestamp"]),crash_value])

        last_entrances.append(crash_el)

    return last_entrances


import grpc
import user_service_pb2
import user_service_pb2_grpc
from concurrent import futures  # Import the futures module

class UserService(user_service_pb2_grpc.UserServiceServicer):
    def GetUserByID(self, request, context):
        # Implement logic to fetch user by ID from your list
        user = find_user_by_id(request.user_id)
        if user:
            return user_service_pb2.UserResponse(**user)
        else:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            return user_service_pb2.UserResponse()

    def GetUsersByIDs(self, request, context):
        for user_id in request.user_ids:
            user = find_user_by_id(user_id)
            if user:
                yield user_service_pb2.UserResponse(**user)

def find_user_by_id(user_id):
    # Implement logic to find the user in your data
    # Return the user as a dictionary
    pass

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    user_service_pb2_grpc.add_UserServiceServicer_to_server(UserService(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()

if __name__ == '__main__':
    serve()


# -*- coding: utf-8 -*-
"""
Created on Sun Jun 07 06:58:16 2015

@author: zacha_000
"""
import numpy as np
from pyspark import SparkContext
from datetime import datetime
sc = SparkContext()
from matplotlib import pyplot as plt
from pyspark.sql import SQLContext, Row

sqlContext = SQLContext(sc)
filer = sc.textFile('hdfs://wolf.iems.northwestern.edu/user/huser58/Spark/crime')
file1 = filer.map(lambda x: x.split(','))
header = file1.first()
filer1 = file1.filter(lambda x: x!=header)#strip first row, headers
file2 = filer1.map(lambda x: Row(id=x[0],casenum = x[1], crimedate = datetime.strptime(x[2],'%m/%d/%Y %I:%M:%S %p')))

#create new rdd for each crime month
jancrime = file2.filter(lambda x: x.crimedate.month == 1)
febcrime = file2.filter(lambda x: x.crimedate.month == 2)
marcrime = file2.filter(lambda x: x.crimedate.month == 3)
aprcrime = file2.filter(lambda x: x.crimedate.month == 4)
maycrime = file2.filter(lambda x: x.crimedate.month == 5)
juncrime = file2.filter(lambda x: x.crimedate.month == 6)
julcrime = file2.filter(lambda x: x.crimedate.month == 7)
augcrime = file2.filter(lambda x: x.crimedate.month == 8)
sepcrime = file2.filter(lambda x: x.crimedate.month == 9)
octcrime = file2.filter(lambda x: x.crimedate.month == 10)
novcrime = file2.filter(lambda x: x.crimedate.month == 11)
deccrime = file2.filter(lambda x: x.crimedate.month == 12)

#it would be easier here to just get the counts of each monthcrime, but the assignment says to use SparkSQL
schema_jan = sqlContext.createDataFrame(jancrime)
schema_feb = sqlContext.createDataFrame(febcrime)
schema_mar = sqlContext.createDataFrame(marcrime)
schema_apr = sqlContext.createDataFrame(aprcrime)
schema_may = sqlContext.createDataFrame(maycrime)
schema_jun = sqlContext.createDataFrame(juncrime)
schema_jul = sqlContext.createDataFrame(julcrime)
schema_aug = sqlContext.createDataFrame(augcrime)
schema_sep = sqlContext.createDataFrame(sepcrime)
schema_oct = sqlContext.createDataFrame(octcrime)
schema_nov = sqlContext.createDataFrame(novcrime)
schema_dec = sqlContext.createDataFrame(deccrime)

#create tables
schema_jan.registerTempTable("jantable")
schema_feb.registerTempTable("febtable")
schema_mar.registerTempTable("martable")
schema_apr.registerTempTable("aprtable")
schema_may.registerTempTable("maytable")
schema_jun.registerTempTable("juntable")
schema_jul.registerTempTable("jultable")
schema_aug.registerTempTable("augtable")
schema_sep.registerTempTable("septable")
schema_oct.registerTempTable("octtable")
schema_nov.registerTempTable("novtable")
schema_dec.registerTempTable("dectable")

#get count of each table
jancount = sqlContext.sql("SELECT COUNT(*) FROM jantable")
febcount = sqlContext.sql("SELECT COUNT(*) FROM febtable")
marcount = sqlContext.sql("SELECT COUNT(*) FROM martable")
aprcount = sqlContext.sql("SELECT COUNT(*) FROM aprtable")
maycount = sqlContext.sql("SELECT COUNT(*) FROM maytable")
juncount = sqlContext.sql("SELECT COUNT(*) FROM juntable")
julcount = sqlContext.sql("SELECT COUNT(*) FROM jultable")
augcount = sqlContext.sql("SELECT COUNT(*) FROM augtable")
sepcount = sqlContext.sql("SELECT COUNT(*) FROM septable")
octcount = sqlContext.sql("SELECT COUNT(*) FROM octtable")
novcount = sqlContext.sql("SELECT COUNT(*) FROM novtable")
deccount = sqlContext.sql("SELECT COUNT(*) FROM dectable")

#actual count ints
jantotal = jancount.first()[0]
febtotal = febcount.first()[0]
martotal = marcount.first()[0]
aprtotal = aprcount.first()[0]
maytotal = maycount.first()[0]
juntotal = juncount.first()[0]
jultotal = julcount.first()[0]
augtotal = augcount.first()[0]
septotal = sepcount.first()[0]
octtotal = octcount.first()[0]
novtotal = novcount.first()[0]
dectotal = deccount.first()[0]

#monthly average
janavg = jantotal/15
febavg = febtotal/15
maravg = martotal/15
apravg = aprtotal/15
mayavg = maytotal/15
junavg = juntotal/15
julavg = jultotal/15
augavg = augtotal/15
sepavg = septotal/15
octavg = octtotal/15
novavg = novtotal/15
decavg = dectotal/15
#15 januarys, 15 feb, 15 mar, 15 apr, 15 may, 14 jun, 14 jul, 14 aug, 14 sep, 14 oct, 14 nov, 14 dec

#plot monthly averages
fig = plt.figure()
monthavg = (janavg, febavg, maravg, apravg, mayavg, junavg, julavg, augavg, sepavg, octavg, novavg, decavg)

ind = np.arange(12)
width = 0.35

fig, ax = plt.subplots()
rects1 = ax.bar(ind, monthavg, width, color='r')

ax.set_ylabel('Average crime count')
ax.set_xlabel('Month')
ax.set_title('Average count of crimes by month')
ax.set_xticks(ind+width/2)
ax.set_xticklabels( ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') )

plt.show()


# Biblioteca que cria as APIs e Rotas
from flask import Flask, jsonify
# Biblioteca do Json simples para objetos com varios tipos de elementos (decimal, string, inteiro, etc)
import simplejson as json
# Código Fonte que respode na Rota Default /
from Controller import home
# Código Fonte que respode na Rota Clientes
from Controller import clientes
# Código Fonte que respode na Rota Receitas
from Controller import receita
# Biblioteca que imprime na tela os resultados melhor organizados
from pprint import pprint

app = Flask(__name__)

# Cria a Rota Home
@app.route('/', methods=['GET'])
def index():
    response = home.home()
    return response,200

# Cria Rota CLientes
@app.route('/clientes', methods=['GET'])
def ListaCliente():
    # Busca os CLientes do ERPFlex
    response = clientes.getClientes()
    # Converte o Objeto em Json
    return jsonify(response),200

# Cria Rota das Receitas
@app.route('/receitas', methods=['GET'])
def ListaReceitas():
    # Busca as Receitas no ERPFlex
    response = receita.getReceita()
    # Converte o Objeto em Json
    return jsonify(response),200

# Roda o Server
if __name__ == '__main__':
    app.run(debug=True)


from __future__ import annotations

import base64
from dataclasses import field, dataclass, asdict
import enum
import json
import logging
from typing import Dict, List, ClassVar, Any, Optional
import uuid
import os
import sys

import OpenSSL
import click

from . import Signer
from ..operations.base import SignOperation
from ..operations import ClearSignOperation, ContainerSignOperation
from ..results.signing_results import SigningResults
from ..results import ClearSignResult, ContainerSignResult
from ..results import SignerResults
from ..exceptions import UnsupportedOperation
from ..clients.msg_send_client import SendClient
from ..clients.msg_recv_client import RecvClient
from ..models.msg import MsgMessage
from ..conf.conf import load_config, CONFIG_PATHS
from ..utils import set_log_level, isodate_now, _get_config_file

LOG = logging.getLogger("pubtools.sign.signers.msgsigner")

class SignRequestType(str, enum.Enum):
    """Sign request type enum."""

    CONTAINER = "container_signature"
    CLEARSIGN = "clearsign_signature"

@dataclass()
class MsgSignerResults(SignerResults):
    """MsgSignerResults model."""

    status: str
    error_message: str

    def to_dict(self: SignerResults):
        """Return dict representation of MsgSignerResults model."""
        return {"status": self.status, "error_message": self.error_message}

    @classmethod
    def doc_arguments(cls: SignerResults) -> Dict[str, Any]:
        """Return dictionary with result description of SignerResults."""
        doc_arguments = {
            "signer_result": {
                "type": "dict",
                "description": "Signing result status.",
                "returned": "always",
                "sample": {"status": "ok", "error_message": ""},
            }
        }

        return doc_arguments

@dataclass()
class MsgSigner(Signer):
    """Messaging signer class."""

    messaging_brokers: List[str] = field(
        init=False,
        metadata={
            "description": "List of brokers URLS",
            "sample": [
                "amqps://broker-01:5671",
                "amqps://broker-02:5671",
            ],
        },
    )
    messaging_cert_key: str = field(
        init=False,
        metadata={
            "description": "Client certificate + key for messaging authorization",
            "sample": "~/messaging/cert.pem",
        },
    )
    messaging_ca_cert: str = field(
        init=False,
        metadata={"description": "Messaging CA certificate", "sample": "~/messaging/ca_cert.crt"},
    )
    topic_send_to: str = field(
        init=False,
        metadata={
            "description": "Topic where to send the messages",
            "sample": "topic://Topic.sign",
        },
    )
    topic_listen_to: str = field(
        init=False,
        metadata={
            "description": "Topic where to listen for replies",
            "sample": "queue://Consumer.{{creator}}.{{task_id}}.Topic.sign.{{task_id}}",
        },
    )
    creator: str = field(
        init=False,
        metadata={
            "description": "Identification of creator of signing request",
            "sample": "pubtools-sign",
        },
    )
    environment: str = field(
        init=False,
        metadata={"description": "Environment indetification in sent messages", "sample": "prod"},
    )
    service: str = field(
        init=False, metadata={"description": "Service identificator", "sample": "pubtools-sign"}
    )
    timeout: int = field(
        init=False,
        default=60,
        metadata={"description": "Timeout for messaging sent/receive", "sample": 1},
    )
    retries: int = field(
        init=False,
        default=60,
        metadata={"description": "Retries for messaging sent/receive", "sample": 3},
    )
    message_id_key: str = field(
        init=False,
        metadata={
            "description": "Attribute name in message body which should be used as message id",
            "sample": "123",
        },
    )
    log_level: str = field(init=False, metadata={"description": "Log level", "sample": "debug"})

    SUPPORTED_OPERATIONS: ClassVar[List[SignOperation]] = [
        ContainerSignOperation,
        ClearSignOperation,
    ]

    _signer_config_key: str = "msg_signer"

    def _construct_signing_message(
        self: MsgSigner,
        claim,
        signing_key: str,
        repo: str,
        extra_attrs: Optional[Dict] = None,
        sig_type: SignRequestType = SignRequestType.CONTAINER,
    ):
        data_attr = "claim_file" if sig_type == SignRequestType.CONTAINER else "data"
        _extra_attrs = extra_attrs or {}
        message = {
            "sig_key_id": signing_key,
            data_attr: claim,
            "request_id": str(uuid.uuid4()),
            "created": isodate_now(),
            "requested_by": self.creator,
            "repo": repo,
        }
        message.update(_extra_attrs)
        return message

    def _construct_headers(self: MsgSigner, sig_type, extra_attrs: Optional[Dict] = None):
        headers = {
            "service": self.service,
            "environment": self.environment,
            "owner_id": self.creator,
            "mtype": sig_type.value,
            "source": "metadata",
        }
        if extra_attrs:
            headers.update(extra_attrs)
        return headers

    def _create_msg_message(
        self: MsgSigner, data, operation: SignOperation, sig_type: SignRequestType, extra_attrs=None
    ):
        ret = MsgMessage(
            headers=self._construct_headers(sig_type, extra_attrs=extra_attrs),
            body=self._construct_signing_message(
                data,
                operation.signing_key,
                repo=operation.repo,
                extra_attrs=extra_attrs,
                sig_type=sig_type.value,
            ),
            address=self.topic_send_to.format(
                **dict(list(asdict(self).items()) + list(asdict(operation).items()))
            ),
        )
        LOG.debug(f"Construted message with request_id {ret.body['request_id']}")
        return ret

    def load_config(self: MsgSigner, config_data: Dict[str, Any]) -> None:
        """Load configuration of messaging signer."""
        self.messaging_brokers = config_data["msg_signer"]["messaging_brokers"]
        self.messaging_cert_key = os.path.expanduser(
            config_data["msg_signer"]["messaging_cert_key"]
        )
        self.messaging_ca_cert = os.path.expanduser(config_data["msg_signer"]["messaging_ca_cert"])
        self.topic_send_to = config_data["msg_signer"]["topic_send_to"]
        self.topic_listen_to = config_data["msg_signer"]["topic_listen_to"]
        self.environment = config_data["msg_signer"]["environment"]
        self.service = config_data["msg_signer"]["service"]
        self.message_id_key = config_data["msg_signer"]["message_id_key"]
        self.retries = config_data["msg_signer"]["retries"]
        self.log_level = config_data["msg_signer"]["log_level"]
        self.timeout = config_data["msg_signer"]["timeout"]
        self.creator = self._get_cert_subject_cn()

    def _get_cert_subject_cn(self):
        x509 = OpenSSL.crypto.load_certificate(
            OpenSSL.crypto.FILETYPE_PEM, open(os.path.expanduser(self.messaging_cert_key)).read()
        )
        return x509.get_subject().CN

    def operations(self: MsgSigner) -> List[SignOperation]:
        """Return list of supported operations."""
        return self.SUPPORTED_OPERATIONS

    def sign(self: MsgSigner, operation: SignOperation) -> SigningResults:
        """Run signing operation.

        :param operation: signing operation
        :type operation: SignOperation

        :return: SigningResults
        """
        if isinstance(operation, ClearSignOperation):
            return self.clear_sign(operation)
        elif isinstance(operation, ContainerSignOperation):
            return self.container_sign(operation)
        else:
            raise UnsupportedOperation(operation)

    def clear_sign(self: MsgSigner, operation: ClearSignOperation):
        """Run the clearsign operation.

        :param operation: signing operation
        :type operation: ClearSignOperation

        :return: SigningResults
        """
        set_log_level(LOG, self.log_level)
        messages = []
        message_to_data = {}
        for in_data in operation.inputs:
            message = self._create_msg_message(
                base64.b64encode(in_data.encode("latin1")).decode("latin-1"),
                operation,
                SignRequestType.CLEARSIGN,
                extra_attrs={"pub_task_id": operation.task_id},
            )
            message_to_data[message.body["request_id"]] = message
            messages.append(message)

        signer_results = MsgSignerResults(status="ok", error_message="")
        operation_result = ClearSignResult(
            signing_key=operation.signing_key, outputs=[""] * len(operation.inputs)
        )
        signing_results = SigningResults(
            signer=self,
            operation=operation,
            signer_results=signer_results,
            operation_result=operation_result,
        )
        LOG.debug(f"{len(messages)} messages to send")

        errors = []
        errors = SendClient(
            messages=messages,
            broker_urls=self.messaging_brokers,
            cert=self.messaging_cert_key,
            ca_cert=self.messaging_ca_cert,
            retries=self.retries,
            errors=errors,
        ).run()

        if errors:
            signer_results.status = "error"
            for error in errors:
                signer_results.error_message += f"{error.name} : {error.description}\n"
            return signing_results

        message_ids = [message.body["request_id"] for message in messages]

        recvc = RecvClient(
            message_ids=message_ids,
            topic=self.topic_listen_to.format(
                **dict(list(asdict(self).items()) + list(asdict(operation).items()))
            ),
            id_key=self.message_id_key,
            broker_urls=self.messaging_brokers,
            cert=self.messaging_cert_key,
            ca_cert=self.messaging_ca_cert,
            timeout=self.timeout,
            retries=self.retries,
            errors=errors,
        )
        recvc.run()
        errors = recvc.errors
        if errors:
            signer_results.status = "error"
            for error in errors:
                signer_results.error_message += f"{error.name} : {error.description}\n"
            return signing_results

        operation_result = ClearSignResult(
            signing_key=operation.signing_key, outputs=[""] * len(messages)
        )
        for recv_id, received in recvc.recv.items():
            operation_result.outputs[messages.index(message_to_data[recv_id])] = received
        signing_results.operation_result = operation_result
        return signing_results

    @staticmethod
    def create_manifest_claim_message(signature_key, digest, reference):
        """Create manifest claim for container signing.

        See below for the specification for the manifest claim that is created here
        https://github.com/containers/image/blob/master/docs/atomic-signature.md
        """
        manifest_claim = {
            "critical": {
                "type": "atomic container signature",
                "image": {"docker-manifest-digest": digest},
                "identity": {"docker-reference": reference},
            },
            "optional": {"creator": "pubtools-sign"},
        }
        return base64.b64encode(json.dumps(manifest_claim).encode("latin1")).decode("latin1")

    def container_sign(self: MsgSigner, operation: ContainerSignOperation):
        """Run container signing operation.

        :param operation: signing operation
        :type operation: ContainerSignOperation

        :return: SigningResults
        """
        set_log_level(LOG, self.log_level)
        messages = []
        message_to_data = {}
        if len(operation.digests) != len(operation.references):
            raise ValueError("Digests must pairs with references")

        for digest, reference in zip(operation.digests, operation.references):
            message = self._create_msg_message(
                self.create_manifest_claim_message(
                    operation.signing_key, digest=digest, reference=reference
                ),
                operation,
                SignRequestType.CONTAINER,
                extra_attrs={"pub_task_id": operation.task_id, "manifest_digest": digest},
            )
            message_to_data[message.body["request_id"]] = message
            messages.append(message)

        signer_results = MsgSignerResults(status="ok", error_message="")
        operation_result = ContainerSignResult(
            signing_key=operation.signing_key, results=[""] * len(operation.digests), failed=False
        )
        signing_results = SigningResults(
            signer=self,
            operation=operation,
            signer_results=signer_results,
            operation_result=operation_result,
        )
        LOG.debug(f"{len(messages)} messages to send")

        errors = []
        errors = SendClient(
            messages=messages,
            broker_urls=self.messaging_brokers,
            cert=self.messaging_cert_key,
            ca_cert=self.messaging_ca_cert,
            retries=self.retries,
            errors=errors,
        ).run()

        if errors:
            signer_results.status = "error"
            for error in errors:
                signer_results.error_message += f"{error.name} : {error.description}\n"
            return signing_results

        message_ids = [message.body["request_id"] for message in messages]

        recvc = RecvClient(
            message_ids=message_ids,
            topic=self.topic_listen_to.format(
                **dict(list(asdict(self).items()) + list(asdict(operation).items()))
            ),
            id_key=self.message_id_key,
            broker_urls=self.messaging_brokers,
            cert=self.messaging_cert_key,
            ca_cert=self.messaging_ca_cert,
            timeout=self.timeout,
            retries=self.retries,
            errors=errors,
        )
        recvc.run()
        errors = recvc.errors

        if recvc.errors:
            signer_results.status = "error"
            for error in errors:
                signer_results.error_message += f"{error.name} : {error.description}\n"
            return signing_results

        operation_result = ContainerSignResult(
            signing_key=operation.signing_key, results=[""] * len(messages), failed=False
        )
        for recv_id, received in recvc.recv.items():
            operation_result.failed = True if received[0]["msg"]["errors"] else False
            operation_result.results[messages.index(message_to_data[recv_id])] = received
        signing_results.operation_result = operation_result
        return signing_results

def msg_clear_sign(inputs, signing_key=None, task_id=None, config="", repo=""):
    """Run clearsign operation."""
    msg_signer = MsgSigner()
    config = _get_config_file(config)
    msg_signer.load_config(load_config(os.path.expanduser(config)))

    str_inputs = []
    for input_ in inputs:
        if input_.startswith("@"):
            str_inputs.append(open(input_.lstrip("@")).read())
        else:
            str_inputs.append(input_)
    operation = ClearSignOperation(
        inputs=str_inputs, signing_key=signing_key, task_id=task_id, repo=repo
    )
    signing_result = msg_signer.sign(operation)
    return {
        "signer_result": signing_result.signer_results.to_dict(),
        "operation_results": signing_result.operation_result.outputs,
        "signing_key": signing_result.operation_result.signing_key,
    }

def msg_container_sign(
    signing_key=None, task_id=None, config="", digest=None, reference=None, repo=None
):
    """Run containersign operation with cli arguments."""
    msg_signer = MsgSigner()
    config = _get_config_file(config)
    msg_signer.load_config(load_config(os.path.expanduser(config)))

    operation = ContainerSignOperation(
        digests=digest,
        references=reference,
        signing_key=signing_key,
        task_id=task_id,
        repo=repo,
    )
    signing_result = msg_signer.sign(operation)
    return {
        "signer_result": signing_result.signer_results.to_dict(),
        "operation_results": signing_result.operation_result.results,
        "signing_key": signing_result.operation_result.signing_key,
    }

@click.command()
@click.option(
    "--signing-key",
    required=True,
    help="8 characters key fingerprint of key which should be used for signing",
)
@click.option("--task-id", required=True, help="Task id identifier (usually pub task-id)")
@click.option("--config", default=CONFIG_PATHS[0], help="path to the config file")
@click.option("--raw", default=False, is_flag=True, help="Print raw output instead of json")
@click.option("--repo", help="Repository reference")
@click.argument("inputs", nargs=-1)
def msg_clear_sign_main(inputs, signing_key=None, task_id=None, config=None, raw=None, repo=None):
    """Entry point method for clearsign operation."""
    ret = msg_clear_sign(inputs, signing_key=signing_key, task_id=task_id, repo=repo, config=config)
    if not raw:
        click.echo(json.dumps(ret))
        if ret["signer_result"]["status"] == "error":
            sys.exit(1)
    else:
        if ret["signer_result"]["status"] == "error":
            print(ret["signer_result"]["error_message"], file=sys.stderr)
            sys.exit(1)
        else:
            for claim in ret["operation_results"]:
                if claim[0]["msg"]["errors"]:
                    for error in claim[0]["msg"]["errors"]:
                        print(error, file=sys.stderr)
                    sys.exit(1)
                else:
                    print(claim[0]["msg"]["signed_data"])

@click.command()
@click.option(
    "--signing-key",
    required=True,
    help="8 characters key fingerprint of key which should be used for signing",
)
@click.option("--task-id", required=True, help="Task id identifier (usually pub task-id)")
@click.option("--config", default=CONFIG_PATHS[0], help="path to the config file")
@click.option(
    "--digest",
    required=True,
    multiple=True,
    type=str,
    help="Digests which should be signed.",
)
@click.option(
    "--reference",
    required=True,
    multiple=True,
    type=str,
    help="References which should be signed.",
)
@click.option("--raw", default=False, is_flag=True, help="Print raw output instead of json")
@click.option("--repo", help="Repository reference")
def msg_container_sign_main(
    signing_key=None,
    task_id=None,
    config=None,
    digest=None,
    reference=None,
    raw=None,
    repo=None,
):
    """Entry point method for containersign operation."""
    ret = msg_container_sign(
        signing_key=signing_key,
        task_id=task_id,
        config=config,
        digest=digest,
        reference=reference,
        repo=repo,
    )
    if not raw:
        click.echo(json.dumps(ret))
        if ret["signer_result"]["status"] == "error":
            sys.exit(1)
    else:
        for claim in ret["operation_results"]:
            if claim[0]["msg"]["errors"]:
                for error in claim[0]["msg"]["errors"]:
                    print(error, file=sys.stderr)
                sys.exit(1)
            else:
                print(claim[0]["msg"]["signed_claim"])