import copy
import inspect
import json
from pathlib import Path
from typing import Dict, List

import vcr
from vcr import matchers
from vcr.request import Request

from .constants import FILTER_HEADERS, TEST_CLASSES_FOR_RUN_INTEGRATION_TEST_RECORDING, SanitizedValues
from .processors import (
    AzureMLExperimentIDProcessor,
    AzureOpenAIConnectionProcessor,
    AzureResourceProcessor,
    AzureWorkspaceTriadProcessor,
    DropProcessor,
    EmailProcessor,
    IndexServiceProcessor,
    PFSProcessor,
    RecordingProcessor,
    StorageProcessor,
    UserInfoProcessor,
)
from .utils import (
    is_httpx_response,
    is_json_payload_request,
    is_live,
    is_record,
    is_replay,
    sanitize_pfs_body,
    sanitize_upload_hash,
)
from .variable_recorder import VariableRecorder

class PFAzureIntegrationTestRecording:
    def __init__(self, test_class, test_func_name: str, user_object_id: str, tenant_id: str):
        self.test_class = test_class
        self.test_func_name = test_func_name
        self.user_object_id = user_object_id
        self.tenant_id = tenant_id
        self.recording_file = self._get_recording_file()
        self.recording_processors = self._get_recording_processors()
        self.vcr = self._init_vcr()
        self._cm = None  # context manager from VCR
        self.cassette = None
        self.variable_recorder = VariableRecorder()

    @staticmethod
    def from_test_case(test_class, test_func_name: str, **kwargs) -> "PFAzureIntegrationTestRecording":
        test_class_name = test_class.__name__
        user_object_id = kwargs.get("user_object_id", "")
        tenant_id = kwargs.get("tenant_id", "")
        if test_class_name in TEST_CLASSES_FOR_RUN_INTEGRATION_TEST_RECORDING:
            return PFAzureRunIntegrationTestRecording(
                test_class, test_func_name, user_object_id=user_object_id, tenant_id=tenant_id
            )
        else:
            return PFAzureIntegrationTestRecording(
                test_class, test_func_name, user_object_id=user_object_id, tenant_id=tenant_id
            )

    def _get_recording_file(self) -> Path:
        # recording files are expected to be located at "tests/test_configs/recordings"
        # test file path should locate at "tests/sdk_cli_azure_test/e2etests"
        test_file_path = Path(inspect.getfile(self.test_class)).resolve()
        recording_dir = (test_file_path.parent.parent.parent / "test_configs" / "recordings").resolve()
        recording_dir.mkdir(exist_ok=True)

        test_file_name = test_file_path.stem
        test_class_name = self.test_class.__name__
        if "[" in self.test_func_name:
            # for tests that use pytest.mark.parametrize, there will be "[]" in test function name
            # recording filename pattern:
            # {test_file_name}_{test_class_name}_{test_func_name}/{parameter_id}.yaml
            test_func_name, parameter_id = self.test_func_name.split("[")
            parameter_id = parameter_id.rstrip("]")
            test_func_dir = (recording_dir / f"{test_file_name}_{test_class_name}_{test_func_name}").resolve()
            test_func_dir.mkdir(exist_ok=True)
            recording_file = (test_func_dir / f"{parameter_id}.yaml").resolve()
        else:
            # for most remaining tests
            # recording filename pattern: {test_file_name}_{test_class_name}_{test_func_name}.yaml
            recording_filename = f"{test_file_name}_{test_class_name}_{self.test_func_name}.yaml"
            recording_file = (recording_dir / recording_filename).resolve()
        if is_record() and recording_file.is_file():
            recording_file.unlink()
        return recording_file

    def _init_vcr(self) -> vcr.VCR:
        _vcr = vcr.VCR(
            cassette_library_dir=self.recording_file.parent.as_posix(),
            before_record_request=self._process_request_recording,
            before_record_response=self._process_response_recording,
            decode_compressed_response=True,
            record_mode="none" if is_replay() else "all",
            filter_headers=FILTER_HEADERS,
        )
        _vcr.match_on += ("body",)
        return _vcr

    def enter_vcr(self):
        self._cm = self.vcr.use_cassette(self.recording_file.as_posix())
        self.cassette = self._cm.__enter__()

    def exit_vcr(self):
        if is_record():
            self._postprocess_recording()
        self._cm.__exit__()

    def _process_request_recording(self, request: Request) -> Request:
        if is_live():
            return request

        if is_record():
            for processor in self.recording_processors:
                request = processor.process_request(request)

        return request

    def _process_response_recording(self, response: Dict) -> Dict:
        if is_live():
            return response

        # httpx and non-httpx responses have different structure
        # non-httpx has .body.string, while httpx has .content
        # in our sanitizers (processors) logic, we only handle .body.string
        # so make httpx align non-httpx for less code change
        is_httpx = is_httpx_response(response)
        if is_httpx:
            body_string = response.pop("content")
            response["body"] = {"string": body_string}
        else:
            response["body"]["string"] = response["body"]["string"].decode("utf-8")

        if is_record():
            # lower and filter some headers
            headers = {}
            for k in response["headers"]:
                if k.lower() not in FILTER_HEADERS:
                    headers[k.lower()] = response["headers"][k]
            response["headers"] = headers

            for processor in self.recording_processors:
                response = processor.process_response(response)

        if is_httpx:
            response["content"] = response["body"]["string"]
            if not is_replay():
                response.pop("body")
                if isinstance(response["content"], bytes):
                    response["content"] = response["content"].decode("utf-8")
            else:
                # vcrpy does not handle well with httpx, so we need some transformations
                # otherwise, replay tests will break during init VCR response instance
                response["status"] = {"code": response["status_code"], "message": ""}
                if isinstance(response["body"]["string"], str):
                    response["body"]["string"] = response["body"]["string"].encode("utf-8")
        else:
            response["body"]["string"] = response["body"]["string"].encode("utf-8")

        return response

    def _get_recording_processors(self) -> List[RecordingProcessor]:
        return [
            AzureMLExperimentIDProcessor(),
            AzureOpenAIConnectionProcessor(),
            AzureResourceProcessor(),
            AzureWorkspaceTriadProcessor(),
            DropProcessor(),
            EmailProcessor(),
            IndexServiceProcessor(),
            PFSProcessor(),
            StorageProcessor(),
            UserInfoProcessor(user_object_id=self.user_object_id, tenant_id=self.tenant_id),
        ]

    def get_or_record_variable(self, variable: str, default: str) -> str:
        if not is_replay():
            return self.variable_recorder.get_or_record_variable(variable, default)
        else:
            # return variable when playback, which is expected to be sanitized
            return variable

    def _postprocess_recording(self) -> None:
        self._apply_replacement_for_recordings()
        return

    def _apply_replacement_for_recordings(self) -> None:
        for i in range(len(self.cassette.data)):
            req, resp = self.cassette.data[i]
            req = self.variable_recorder.sanitize_request(req)
            resp = self.variable_recorder.sanitize_response(resp)
            self.cassette.data[i] = (req, resp)
        return

class PFAzureRunIntegrationTestRecording(PFAzureIntegrationTestRecording):
    """Test class for run operations in Prompt Flow Azure.

    Different from other operations, run operations have:

    - duplicate network requests for stream run
    - blob storage requests contain upload hash
    - Submit and get run data API requests are indistinguishable without run name in body

    Use a separate class with more pre/post recording processing method or
    request matchers to handle above cases.
    """

    def _init_vcr(self) -> vcr.VCR:
        _vcr = super(PFAzureRunIntegrationTestRecording, self)._init_vcr()
        _vcr.register_matcher("path", self._custom_request_path_matcher)
        _vcr.register_matcher("body", self._custom_request_body_matcher)
        return _vcr

    def enter_vcr(self):
        self._cm = self.vcr.use_cassette(
            self.recording_file.as_posix(),
            allow_playback_repeats=True,
            filter_query_parameters=["api-version"],
        )
        self.cassette = self._cm.__enter__()

    def _postprocess_recording(self) -> None:
        self._drop_duplicate_recordings()
        super(PFAzureRunIntegrationTestRecording, self)._postprocess_recording()

    def _drop_duplicate_recordings(self) -> None:
        # stream run operation contains two requests:
        # 1. get status; 2. get logs
        # before the run is terminated, there will be many duplicate requests
        # getting status/logs, which leads to infinite loop during replay
        # therefore apply such post process to drop those duplicate recordings
        dropped_recordings = []
        run_data_requests = dict()
        log_content_requests = dict()
        for req, resp in self.cassette.data:
            # run hisotry's rundata API
            if str(req.path).endswith("/rundata"):
                body = req.body.decode("utf-8")
                body_dict = json.loads(body)
                name = body_dict["runId"]
                run_data_requests[name] = (req, resp)
                continue
            if str(req.path).endswith("/logContent"):
                log_content_requests[req.uri] = (req, resp)
                continue
            dropped_recordings.append((req, resp))
        # append rundata recording(s)
        for req, resp in run_data_requests.values():
            dropped_recordings.append((req, resp))
        for req, resp in log_content_requests.values():
            dropped_recordings.append((req, resp))

        self.cassette.data = dropped_recordings
        return

    def _custom_request_path_matcher(self, r1: Request, r2: Request) -> bool:
        # NOTE: orders of below conditions matter, please modify with caution
        # in run download scenario, observed below wired path: https://<xxx>/https://<yyy>/<remaining>
        # as we don't have append/replace logic, it might result from Azure blob client,
        # which is hard to patch; therefore, hack this in matcher (here)
        # https:// should appear in path, so it's safe to use this as a condition
        if "https://" in r1.path:
            _path = str(r1.path)
            endpoint = ".blob.core.windows.net/"
            duplicate_path = _path[_path.index(endpoint) + len(endpoint) :]
            path_for_compare = _path[: _path.index("https://")] + duplicate_path[duplicate_path.index("/") + 1 :]
            return path_for_compare == r2.path
        # for blob storage request, sanitize the upload hash in path
        if r1.host == r2.host and r1.host == SanitizedValues.BLOB_STORAGE_REQUEST_HOST:
            return sanitize_upload_hash(r1.path) == r2.path
        return r1.path == r2.path

    def _custom_request_body_matcher(self, r1: Request, r2: Request) -> bool:
        if is_json_payload_request(r1) and r1.body is not None:
            # note that `sanitize_upload_hash` is not idempotent
            # so we should not modify r1 directly
            # otherwise it will be sanitized multiple times with many zeros
            _r1 = copy.deepcopy(r1)
            body1 = _r1.body.decode("utf-8")
            body1 = sanitize_pfs_body(body1)
            body1 = sanitize_upload_hash(body1)
            _r1.body = body1.encode("utf-8")
            return matchers.body(_r1, r2)
        else:
            return matchers.body(r1, r2)


# Fri 19 Nov 2010 11:50:56 EST
# Set of helper functions to read, write and call David Newman's
# topic model code: http://www.ics.uci.edu/~newman/code/topicmodel/

import sys, os
import logging
import math

import numpy

# from scipy import sparse

# needed?
PROJECT_PATH=os.path.realpath(os.path.join(os.path.dirname(__file__),".."))
PACK_DIR=os.path.realpath(os.path.join(os.path.dirname(__file__),"packs/"))
RUN_ROOT = os.path.join(PROJECT_PATH, "data/runs/")
#RUN_DIR="../data/runs/run2_first_test/"

logger = logging.getLogger("newmanlib")
logger.setLevel(logging.INFO)

# Portions of the code is heavily inspired by:
# Copyright (C) 2010 Radim Rehurek <radimrehurek@seznam.cz>
# Licensed under the GNU LGPL v2.1 - http://www.gnu.org/licenses/lgpl.html

class NewmanWriter(object):
    """
    Store corpus into a file docword.txt in the Dave Newman's sparse matrix format.

    used via static method writeCorpus as follows:
        NewmanWriter.writeCorpus(fname, corpus)
        where fname is either a file-like object or a string containing the filename,
        and corpus is of the type [[(,)]]

    """

    def __init__(self, fname):
        self.fname = fname

        tmp = open(self.fname, 'w') # reset/create the target file
        tmp.close()
        self.fout = open(self.fname, 'rb+') # open for both reading and writing
        self.headersWritten = False

    def writeHeaders(self, numDocs, numTerms, numNnz):
        import string   # needed for padding left to 30 chars
        if numNnz < 0:
            # we don't know the matrix shape/density yet, so only log a general line
            logger.info("saving sparse matrix to %s" % self.fname)
            self.fout.write(' ' * 30 + '\n') # save three newlines for headers
            self.fout.write(' ' * 30 + '\n') #
            self.fout.write(' ' * 30 + '\n') # 30 digits must be enough even for the
                                             #  most avid Megalomane
        else:
            logger.info("saving sparse %sx%s matrix with %i non-zero entries to %s" %
                         (numDocs, numTerms, numNnz, self.fname))
            self.fout.write(string.ljust('%s' % numDocs, 30) +'\n')
            self.fout.write(string.ljust('%s' % numTerms, 30) +'\n')
            self.fout.write(string.ljust('%s' % numNnz, 30) +'\n')

        self.lastDocNo = -1
        self.headersWritten = True

    def realHeaders(self, numDocs, numTerms, numNnz):
        import string   # needed for padding left to 30 chars
        logger.info("writing the real headers now --  sparse %sx%s matrix with %i non-zero entries to %s" %
                         (numDocs, numTerms, numNnz, self.fname))
        self.fout.seek(0)
        self.fout.write(string.ljust('%s' % numDocs, 30) + '\n')
        self.fout.write(string.ljust('%s' % numTerms, 30) + '\n')
        self.fout.write(string.ljust('%s' % numNnz, 30) + '\n')

    def writeVector(self, docNo, vector):
        """
        Write a single sparse vector to the file.

        Sparse vector is any iterable yielding (field id, field value) pairs.
        """
        assert self.headersWritten, "must write Matrix Market file headers before writing data!"
        assert self.lastDocNo < docNo, "documents %i and %i not in sequential order!" % (self.lastDocNo, docNo)
        for termId, weight in sorted(vector): # write term ids in sorted order
            if weight == 0:
                # to ensure len(doc) does what is expected, there must not be any zero elements in the sparse document
                raise ValueError("zero weights not allowed in sparse documents; check your document generator")
            #self.fout.write("%i %i %s\n" % (docNo + 1, termId + 1, weight)) # +1 because MM format starts counting from 1
            # Newman reader function int **read_sparse(char *fname, int *nr_, int *nc_)
            # is looking for a %d in the file so I will coerse to int
            self.fout.write("%i %i %i\n" % (docNo + 1, termId + 1, int(weight))) # +1 because MM format starts counting from 1
        self.lastDocNo = docNo

    @staticmethod
    def writeCorpus(fname, corpus, progressCnt = 10000):
        """
        Save the vector space representation of an entire corpus to disk.

        Note that the documents are processed one at a time, so the whole corpus
        is allowed to be larger than the available RAM.
        """
        mw = NewmanWriter(fname)

        # write empty headers to the file (with enough space to be overwritten later)
        mw.writeHeaders(-1, -1, -1) # will print three rows of 30 spaces each
                                    # need to reserve space for when we have the total NZ count

        # calculate necessary header info (nnz elements, num terms, num docs) while writing out vectors
        numTerms = numNnz = 0
        docNo = -1

        for docNo, bow in enumerate(corpus):
            if docNo % progressCnt == 0:
                logger.info("PROGRESS: saving document #%i" % docNo)
            if len(bow) > 0:
                numTerms = max(numTerms, 1 + max(wordId for wordId, val in bow))
                numNnz += len(bow)
            mw.writeVector(docNo, bow)
        numDocs = docNo + 1

        if numDocs * numTerms != 0:
            logger.info("saved %ix%i matrix, density=%.3f%% (%i/%i)" %
                         (numDocs, numTerms,
                          100.0 * numNnz / (numDocs * numTerms),
                          numNnz,
                          numDocs * numTerms))

        # now write proper headers, by seeking and overwriting a part of the file
        mw.realHeaders(numDocs, numTerms, numNnz)

        mw.close()

    def __del__(self):
        """
        Automatic destructor which closes the underlying file.

        There must be no circular references contained in the object for __del__
        to work! Closing the file explicitly via the close() method is preferred
        and safer.
        """
        self.close() # does nothing if called twice (on an already closed file), so no worries

    def close(self):
        logging.debug("closing %s" % self.fname)
        self.fout.close()
#endclass NewanWriter

class NewmanReader(object):
    """
    Wrap a term-document matrix on disk (in Dave Newman's sparse matrix format), and present it
    as an object which supports iteration over the documents.

    Note that the file is read into memory one document at a time, not the whole
    matrix at once (unlike scipy.io.mmread). This allows for representing corpora
    which are larger than the available RAM.
    """

    def __init__(self, input, transposed=True):

        """
        Initialize the matrix reader.

        `input` is either a string (file path) or a file-like object that supports
        `seek(0)` (e.g. gzip.GzipFile, bz2.BZ2File).
        The contents are expected to be in the following format:

           numDocs
           numTerms
           numElements
           i j count(j in i)
           ...
           ...

        The i index the documents (1 based indexing),
        j stands for the wordid (j=1="aardvark", j=2="abs", ...  j=MaxJ="zulu")
        the third column contains the count of how many times word j appears in document i.

        The number of lines in the file should be numEntries + 3.
        """

        logger.info("initializing Newman reader from %s" % input)

        self.input, self.transposed = input, transposed
        if isinstance(input, basestring):
            input = open(input)

        # get the header information
        self.numDocs = self.numTerms = self.numElements = 0
        MaxI = input.next().strip()
        MaxJ = input.next().strip()
        NumRows = input.next().strip()

        self.numDocs, self.numTerms, self.numElements = map(int, [MaxI,MaxJ,NumRows] )

        if not self.transposed:
            self.numDocs, self.numTerms = self.numTerms, self.numDocs

        logger.info("accepted corpus with %i documents, %i terms, %i non-zero entries" %
                     (self.numDocs, self.numTerms, self.numElements))

    def __len__(self):
        return self.numDocs

    def __str__(self):
        return ("MmCorpus(%i documents, %i features, %i non-zero entries)" %
                (self.numDocs, self.numTerms, self.numElements))

    def __iter__(self):
        """
        Iteratively yield vectors from the underlying file, in the format (rowNo, vector),
        where vector is a list of (colId, value) 2-tuples.

        Note that the total number of vectors returned is always equal to the
        number of rows specified in the header; empty documents are inserted and
        yielded where appropriate, even if they are not explicitly stored in the
        Matrix Market file.
        """
        if isinstance(self.input, basestring):
            fin = open(self.input)
        else:
            fin = self.input
            fin.seek(0)

        # skip 3 lines of headers
        fin.next()
        fin.next()
        fin.next()

        prevId = -1
        for line in fin:
            docId, termId, val = line.split()
            if not self.transposed:
                termId, docId = docId, termId
            docId, termId, val = int(docId) - 1, int(termId) - 1, float(val) # -1 because matrix market indexes are 1-based => convert to 0-based
            assert prevId <= docId, "matrix columns must come in ascending order"
            if docId != prevId:
                # change of document: return the document read so far (its id is prevId)
                if prevId >= 0:
                    yield prevId, document

                # return implicit (empty) documents between previous id and new id
                # too, to keep consistent document numbering and corpus length
                for prevId in xrange(prevId + 1, docId):
                    yield prevId, []

                # from now on start adding fields to a new document, with a new id
                prevId = docId
                document = []

            document.append((termId, val,)) # add another field to the current document

        # handle the last document, as a special case
        if prevId >= 0:
            yield prevId, document
        for prevId in xrange(prevId + 1, self.numDocs):
            yield prevId, []

#endclas NewmanReader

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

class NewmanLdaModel(object):
    """
    This is the the main class for the LDA topic model functionnality

    attrinbutes:
        N           : total number of words in documet collection
        T           : number of topics in model
        documents   : reference to a DocumentColleciton object
        D           : len(documents)
        vocab       : ref to Vacabulary object
        W           : len(vocab)

        phi         : topic-word distribution
                      size: WxT
                      alias: prob_w_given_t
        theta       : topic-document distibution
                      size: TxD
                      alias: prob_t_given_d
        z           : the topic assignment
                      size: ?
        topics      : array of size T with short descriptions for each of the topics
                      ['physics', 'chemistry', ... , 'general science']

    methods:
        __init__ constuctor ... see below
        train(method)
        query(queryDocCol, method)

    """

    def __init__(self): #, documents=None, T=None, vocab=None):
        """
        must give a DocumentCollection object upon creation and T # topics
        """

        self.T=None
        self.documents = None

        # trained / non-trained
        self.is_trained = False

#    def __init__(self,rundir):
#        self.trained = False
#        self.path = '?????'

    def fromDocumentCollection(self, documents=None, T=None, vocab=None):
        pass

    def loadFromPickledDict(self, fileobj):
        """Loads the TopicModel from a cPickle file-like object """
        pass

    def loadFromJson(self):
        """Loads the TopicModel from a json file"""
        pass

    def train(self, method):
        """ run the training method on the TopicModel
            allowed values are:
            NewmanGibbs
            (soon) AndrzejewskiCVB
            """
        pass

def loadsparsemat(filename):
    """ Load a Nweman sparse matrix from file `filename` """
    indata = open(filename).readlines()
    NROWS=int(indata[0].strip() )       # first line is W
    NCOLS=int(indata[1].strip() )       # T
    nCols =int(indata[2].strip() )
    cols = indata[3:]
    assert( len(cols) == nCols)

    wp = numpy.zeros([NROWS,NCOLS])       # undormalized word dopic \beta distr.
    for line in cols:
        if len(line)>0:
            [i,j,d]= line.split()
            wp[int(i)-1,int(j)-1] = d
    return wp

def conv_Ndt_to_theta(input):
    """
    converts the topic counts in documents
    to a probability distibution
      p(t|d)
    rows are documents
    columns are topic proportions
    """

    numDocs,numT = input.shape

    input = numpy.array( input, dtype=numpy.float )

    normalizer = 1.0/numpy.sum(input,1)     # 1 / total num of words in each topic
    for t in numpy.arange(0,numT):
        input[:,t]=input[:,t]*normalizer

    prob_t_given_d = input.transpose()

    # TODO: add alpha ?

    return prob_t_given_d

def conv_Nwt_to_phi(input):
    """
    convers number of words in topic counts
    to a probability distibution
      p(w|t)
    rows are topics
    columns are word likelyhoods
    """

    numTerms,numT = input.shape

    input = numpy.array( input, dtype=numpy.float )

    prob_w_given_t = numpy.dot(input, numpy.diag(1/numpy.sum(input,0))  )

    # TODO: add beta???

    return prob_w_given_t.transpose()

# FIXME: just copied over the old code needs to be fixed...
def calculate_perplexity(d_w_cnt, prob_w_given_t, prob_t_given_d):
    """ guess what it does """
    # compute the perplexity

    # load the docword
    # assume they are all the same :)
    dwpath = RUN_ROOT+"share/"
    d_w_cnt = get_d_w_cnt(dwpath)

    N=float( sum(d_w_cnt,0)[2] )
    inner_sum=0.0

    for [d,w,cnt] in d_w_cnt:
        prelog = dot(prob_w_given_t[w,:], prob_t_given_d[:,d])
        inner_sum = inner_sum + cnt*log(prelog)

    pplex = exp(-1*inner_sum/N)
    return pplex


#!/usr/bin/python3

import os
import sys
import time
import subprocess
import utils
import boto3

s3 = boto3.resource("s3")
ec2 = boto3.resource('ec2')

# Creates a new ec2 instance - ImageId in the Ireland region
# Requires the config file to be set in eu-west-1
def create_instance():
    utils.clear_screen()
    # Get instance info from the user
    instance_name = input("Enter the name of your instance: ")
    key_path = make_key_read_only(utils.get_valid_key("Enter path to your private key: "))
    key_name = utils.get_file_name_from_path(key_path)

    try:
        instance = ec2.create_instances(
            ImageId='ami-acd005d5',
            MinCount=1,
            MaxCount=1,
            InstanceType='t2.micro',
            KeyName=key_name,  # Name of the key to enable ssh
            TagSpecifications=[
                {
                    'ResourceType': 'instance',
                    'Tags': [
                        {
                            'Key': 'Name',
                            'Value': instance_name
                        },
                    ]
                },
            ],
            SecurityGroupIds=[
                utils.get_security_group(),  # call util method to create or get security group id
            ],
            UserData='''#!/bin/bash
                        yum -y update
                        yum install -y python35
                        yum install -y nginx'''
        )
        created_instance = instance[0]
        utils.print_and_log('Created instance Id: ' + created_instance.id)
        instance_public_ip = wait_till_public_ip(created_instance)  # store the instance public ip

        # Ssh related
        check_ssh(instance_public_ip, key_path)
        copy_check_webserver(instance_public_ip, key_path)
    except Exception as error:
        utils.print_and_log('Instance creation failed - exiting')
        utils.print_and_log(error)

# Function to wait till instance get's a public ip and returns the public ip
def wait_till_public_ip(instance):
    utils.print_and_log('Waiting for instance to get a public ip to access later')
    while not instance.public_ip_address:  # loop through till when the instance get's public ip
        try:  # try block as instance may not immediately exist
            instance.reload()  # reload the instance property
            if instance.public_ip_address:  # if the created instance gets an public ip
                public_ip = instance.public_ip_address
                utils.print_and_log('Instance Public IP: ' + public_ip)
                return public_ip
        except Exception as error:
            utils.print_and_log(error)

# Simple check does ssh work by passing pwd to ssh command to instance
def check_ssh(public_ip, key_path):
    exit_loop = 0  # Loop control variable
    while exit_loop <= 10:  # Loop as can take a while for instance to be up after creation
        ssh_check_cmd = construct_ssh(key_path, public_ip, " 'sudo pwd'")
        (status, output) = subprocess.getstatusoutput(ssh_check_cmd)
        if status == 0:  # ssh command ran ok
            utils.print_and_log('Instance is ready to ssh')
            break
        elif 'bad permissions' in output:  # If key is not read only to you
            make_key_read_only(key_path)
        elif exit_loop == 10:  # On condition where loop has reach 10
            utils.print_and_log("Loop 10 reached - instance wasn't ready in time.. exiting loop")
            utils.print_and_log(output)
            break
        else:  # Increase exit_loop by 1 and sleep for 15 seconds before running ssh command again
            utils.print_and_log('Instance is not ready to ssh yet, trying again in 15 seconds '
                                '- loop ' + str(exit_loop) + '/10')
            exit_loop += 1
            time.sleep(15)

# Copy check_webserver.py to instance using scp
def copy_check_webserver(public_ip, key_path):
    scp_cmd = 'scp -i ' + key_path + ' check_webserver.py ec2-user@' + public_ip + ':.'
    utils.print_and_log('Now trying to copy check_webserver to instance')
    (status, output) = subprocess.getstatusoutput(scp_cmd)
    if status == 0:  # if successfully copied, change permissions to make it executable
        utils.print_and_log('Successfully copied check_webserver.py to new instance')
        (status, output) = subprocess.getstatusoutput(
            construct_ssh(key_path, public_ip, " 'chmod 700 ./check_webserver.py'"))
        if status == 0:  # if successful, run check webserver
            utils.print_and_log('Made check_webserver executable on instance')
            run_check_webserver(public_ip, key_path)
        else:
            utils.print_and_log(str('Failed to change persmissions: ' + output))
    else:
        utils.print_and_log('Copy check_webserver.py failed :(')

# Run check_webserver.py on instance
def run_check_webserver(public_ip, key_path):
    utils.print_and_log('\nNow trying to run check_webserver in instance')
    exit_loop = 0  # Loop control variable
    while exit_loop <= 10:  # loop as can take a while for instance to be up and for scp copying
        ssh_run_check_cmd = construct_ssh(key_path, public_ip, " './check_webserver.py'")
        (status, output) = subprocess.getstatusoutput(ssh_run_check_cmd)
        if status == 0:  # Successfully ran ssh command
            utils.print_and_log('Successfully run the check_webserver.py on instance')
            utils.print_and_log(output)
            break
        elif 'Permission denied (publickey)' in output:  # If public key was wrong
            utils.print_and_log('Wrong key to ssh to instance')
            key_path = make_key_read_only(utils.get_valid_key('Re-enter path to key: '))
        elif exit_loop == 10:  # On the 10th loop
            if 'No such file or directory' in output:  # if there was no check_webserver on instance
                utils.print_and_log('check_websever.py doesn\'t seem to be on instance')
                choice = input('Copy check_webserver to instance (y/n): ').lower()
                if choice == 'y':  # copy to instance if y
                    copy_check_webserver(public_ip, key_path)
                else:
                    print('Returning to main menu')
            # if python3 wasn't installed on instance
            elif '/usr/bin/python3: bad interpreter: No such file' in output:
                utils.print_and_log('Python35 doesn\'t seem to on instance')
                install_python35(key_path, public_ip)  # install on instance and run loop again
                utils.print_and_log('Running run_check_webserver again')
                exit_loop = 0
            else:  # Otherwise exit loop
                utils.print_and_log('Exiting due to exit loop limit reached')
                utils.print_and_log(output)
                break
        else:  # increase loop variable by 1 and sleep for 15 seconds
            utils.print_and_log('Run check_webserver.py failed, trying again in 15 seconds - loop '
                                + str(exit_loop) + '/10')
            time.sleep(15)
            exit_loop += 1

# Create a new bucket and ask user do they want to upload file
def create_bucket():
    while True:  # Loop as till break condition as bucket name must be unique
        bucket_name = input("\nBucket name: ").lower()  # bucket name must be all lower case
        try:
            response = s3.create_bucket(
                Bucket=bucket_name,  # create bucket with name and default region in aws config
                CreateBucketConfiguration={'LocationConstraint': utils.default_region()})
            utils.print_and_log(response)
            choice = input("Would you like to upload file to this bucket now (y/n): ")
            if choice == 'y':  # if input is y
                put_file_in_bucket(bucket_name)
                break
            else:  # otherwise break loop
                utils.print_and_log("Returning back to main menu")
                break
        except Exception as error:
            utils.print_and_log(error)

# Puts a file into a bucket
def put_file_in_bucket(bucket_name):
    # get file name to upload to bucket
    file_path = utils.get_abs_file_path('\nPath of file to put into bucket: ')
    try:  # set object name to just the base name as would otherwise create the folders to file.
        # Would have problems, especially when path to object is relative and when getting file link
        response = s3.Object(bucket_name, os.path.basename(file_path)).put(
            ACL='public-read',  # make public readable
            Body=open(file_path, 'rb'))
        utils.print_and_log(response)
        choice = input("Would you like to append file to index html (y/n): ").lower()
        if choice == 'y':
            url = get_file_url(bucket_name, os.path.basename(file_path))
            public_ip = get_instance_ip()
            if public_ip:  # If there is a public ip returned
                while True:
                    try:
                        key_path = make_key_read_only(
                            utils.get_valid_key("Enter path to your private key: "))
                        append_to_index(public_ip, url, key_path)
                        break
                    except Exception as error:
                        print("Error: Not a valid option")

    except Exception as error:
        utils.print_and_log(error)

# Returns the url of a object in a bucket
# https://stackoverflow.com/questions/43973658/how-to-access-image-by-url-on-s3-using-boto3
# http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.generate_presigned_url
def get_file_url(bucket_name, object_name):
    client = boto3.client('s3')
    url = client.generate_presigned_url('get_object',
                                        Params={
                                            'Bucket': bucket_name,
                                            'Key': object_name,
                                        },
                                        ExpiresIn=3600)
    # split url into a list at '?' as the above generates a url link that will be expired
    split = url.split('?')
    utils.print_and_log('Url: ' + split[0])
    return split[0]  # Return the url with no expiry date

# Change the file permission for write access of index.html
# Needed to echo into file for image appending later
def change_index_file_permission(public_ip, key_path):
    ssh_permission_cmd = construct_ssh(
        key_path, public_ip, " 'sudo chmod 646 /usr/share/nginx/html/index.html'")
    utils.print_and_log('Trying to change permission on index.html')
    (status, output) = subprocess.getstatusoutput(ssh_permission_cmd)
    if status == 0:
        utils.print_and_log('Successfully changed the file permission')
    else:
        utils.print_and_log('Failed to change file permission')
        utils.print_and_log(output)

# Append image uploaded to bucket to the end of index.html of nginx
# Use echo to append to the bottom of the index.html
def append_to_index(public_ip, url, key_path):
    # If index.html permissions are not 646 (needed to append url)
    # call change index file permission
    (status, output) = subprocess.getstatusoutput(construct_ssh(key_path, public_ip, " 'sudo stat -c \"%a %n\" /usr/share/nginx/html/index.html'"))
    if '646' not in output:
        change_index_file_permission(public_ip, key_path)

    # if the url is a common image format - enclose url in img tags
    if url.endswith('.png') or url.endswith('.jpg') or url.endswith('.gif'):
        tag_url = '"\"'
    else:  # otherwise encase as a link with the url basename
        tag_url = '"' + os.path.basename(url) + '\"'

    # compose bash command to pass by ssh
    cmd = " 'sudo echo " + tag_url + " >> /usr/share/nginx/html/index.html'"

    ssh_cmd = construct_ssh(key_path, public_ip, cmd)
    utils.print_and_log('\nNow trying to append image url to index html with: ' + ssh_cmd)
    (status, output) = subprocess.getstatusoutput(ssh_cmd)
    if status == 0:
        utils.print_and_log('Successfully appended to index ')
    else:
        utils.print_and_log('Image append failed')
        utils.print_and_log(output)

# Helper to construct ssh command to reduce duplication
def construct_ssh(key_path, public_ip, cmd):
    return "ssh -t -o StrictHostKeyChecking=no -i " + key_path + " ec2-user@" + public_ip + cmd

# List buckets and get file to upload if there are buckets
def list_and_upload_bucket():
    bucket_map = {}  # empty empty that will be used to map value to bucket name
    i = 1  # iterable vale that is used as key to bucket name dictionary value
    print('#', '\tBucket Name')
    for bucket in s3.buckets.all():  # For each bucket the user owns
        bucket_map[str(i)] = bucket.name  # Map current i value as key to bucket name to dictonary
        print(str(i) + "\t" + bucket.name)
        i += 1  # increase i by 1
    if len(bucket_map) == 0:  # If dictionary if empty i.e have no buckets
        print("You have no buckets. Create one at the main menu")
        time.sleep(3)
    else:  # Otherwise loop to get user input for bucket number to get bucket name from dictionary
        while True:
            try:
                choice = input("Enter number of bucket: ")
                put_file_in_bucket(bucket_map[choice])
                break
            except Exception as error:
                print("Error: Not a valid option" + str(error))

# List instances for running check server
def get_instance_ip():
    instance_dict = {}  # Create empty dictionary
    i = 1  # Value to iterate as key for dictionary
    print('\n#', '\tInstance ID', '\t\tPublic IP Adrress')
    for instance in ec2.instances.all():
        if instance.state['Name'] == 'running':  # for only instances that are running
            instance_dict[str(i)] = instance.public_ip_address  # map current value of i as key to public address value
            print(i, '\t' + instance.id, '\t' + instance.public_ip_address)
            i += 1
    if len(instance_dict) == 0:  # if there are no instances running
        print("You have no instances. Create one at the main menu")
        time.sleep(3)
    else:  # if there are running instances, get input from user to get instance public ip
        while True:
            try:
                choice = input("Enter number of instance: ")
                return instance_dict[choice]  # Get's public ip from dictionary and return
            except Exception as error:
                print("Error: Not a valid option" + str(error))

# Method to install python35 on instance on case where it wasn't installed for script to run
def install_python35(key_path, public_ip):
    install_cmd = construct_ssh(key_path, public_ip, " 'sudo yum install -y python35'")
    utils.print_and_log('Installing python35')
    (status, output) = subprocess.getstatusoutput(install_cmd)
    if status == 0:
        utils.print_and_log('Successfully installed python35')
    else:
        utils.print_and_log('Failed to install python35')
        utils.print_and_log(output)

# Get basic instance cpu info from instance
def get_instance_usage(key_path, public_ip):
    usage_cmd = construct_ssh(key_path, public_ip, " 'top -n 1 -b'")
    (status, output) = subprocess.getstatusoutput(usage_cmd)
    if status == 0:
        utils.print_and_log('\n' + output)
        time.sleep(5)
    else:
        utils.print_and_log('\nGet usage failed ' + output)

# Make key read only to you as otherwise would be ignored during ssh
def make_key_read_only(key_path):
    (status, output) = subprocess.getstatusoutput('stat -c "%a %n" ' + key_path)  # get file permission status
    if '600' not in output:  # if not 600, change file permission
        utils.print_and_log('Private key must by read only to you, othwerwise will be ignored')
        (status, output) = subprocess.getstatusoutput("chmod 600 " + key_path)
        if status == 0:
            utils.print_and_log("Changed key to read only by you, to avoid ssh problems")
        else:
            utils.print_and_log("Failed to change key permissions to read only by you " + output)
    return key_path

# Main menu of script
def menu():
    print('''
Welcome
    1. Create instance and bucket
    2. Create instance
    3. Create bucket
    4. Upload to bucket
    5. Run check_server on instance
    6. Print basic cpu usage on instance
    ===================
    0. Exit''')

# Main function
def main():
    while True:
        menu()
        choice = input("\nEnter your choice: ")
        if choice == "1":
            print("Create instance and bucket")
            create_instance()
            create_bucket()
        elif choice == "2":
            print("Create instance")
            create_instance()
        elif choice == "3":
            print("Create bucket")
            create_bucket()
        elif choice == "4":
            print("Upload to bucket")
            list_and_upload_bucket()
        elif choice == "5":
            try:
                public_ip = get_instance_ip()
                if public_ip:
                    key_path = make_key_read_only(utils.get_valid_key("Enter path to your private key: "))
                    run_check_webserver(public_ip, key_path)
            except Exception as error:
                utils.print_and_log("Run Check Server Error: " + str(error))
        elif choice == '6':
            try:
                public_ip = get_instance_ip()
                if public_ip:
                    key_path = make_key_read_only(utils.get_valid_key("Enter path to your private key: "))
                    get_instance_usage(key_path, public_ip)
            except Exception as error:
                utils.print_and_log("Get Instance Usage Error: " + str(error))
        elif choice == "0":
            print("Exiting")
            sys.exit(0)
        else:
            print("Not a valid choice")

# This is the standard boilerplate that calls the main() function.
if __name__ == "__main__":
    main()


# Проект содержит решение 6-го задания по курсу "Основы Python"
# Студент: Алексей Пискунов

# Вопросы преподавателю:
# Возможно, что в первой задаче ожидалась другая реализация (типа ручного переключения),
# но мне показалось страным делать ручное там, где можно сразу сделать автомат.
# Если же я принципиально сделал в первой задаче что-то не то, прошу разъяснить, что именно требовалось :).

import time
import datetime

task = int(input('Введите номер задачи: '))

if task == 1:
    # В исходном задании совершенно не понял идею контроля последовательности переключений:
    # зачем это делать, если можно сразу реализовать правильную последовательность?
    # Поэтому в качестве дополнения сделал второй светофор с другим режимом переключений
    # И заодно немного познакомился с функциями дат и времени

    #создаем класс для эмуляции работы светофора в режиме, заданном в задании
    class TrafficLight(object):
        def __init__(self):
            self.__color = ""
            self.colors_regime = {"red": 7, "yellow": 2, "green": 5}   #режим работы светофора (оставляем публичным, чтобы иметь возможность переопределить)
            self.switches = 6         #количество переключений до запроса на прерывание (оставляем публичным)

        def running(self):
            i = 0
            while(True):
                if i // self.switches > 0 and i % self.switches == 0:
                    c = (input("Продолжить (да/нет)? - ")).upper()
                    while(c != "ДА" and c != "НЕТ"):
                        c = (input("Продолжить (да/нет)? - ")).upper()
                    if c == "НЕТ":
                        break

                colors = list(self.colors_regime.keys())
                self.__color = colors[i % 3]
                print(f'    {self.__color}, время включения: {datetime.datetime.today().strftime("%d.%m.%Y %H:%M:%S")}')
                time.sleep(float(self.colors_regime.get(self.__color)))
                i += 1

    # создадим класс с другим режимом работы светофора на основе класса TrafficLight
    class TrafficLightNew(TrafficLight):
        def __init__(self):
            self.colors_regime = {"red": 3, "yellow": 2, "green": 4}   #режим работы светофора
            self.switches = 9         #количество переключений до запроса на прерывание

    #Создаем объект класса TrafficLight и запускаем метод, эмулирующий переключения светофора в исходном режиме
    light = TrafficLight()
    print("Светофор 1:")
    light.running()

    #Создаем объект класса TrafficLightNew и запускаем метод, эмулирующий переключения светофора в новом режиме
    light_new = TrafficLightNew()
    print("Светофор 2:")
    light_new.running()

if task == 2:

    class Road(object):
        def __init__(self, length, width, thickness = 5):
            self._length = length
            self._width = width
            self.__outlay = 25              # кг/кв.м
            self.thickness = thickness      # толщина покрытия в см

        def get_mass(self):
            return self._length * self._width * self.__outlay * self.thickness / 1000
    l = float(input("Введите длину дороги: "))
    w = float(input("Введите ширину дороги: "))
    s_order = Road(l, w, 10)
    print(f"На строительство дороги нужно {s_order.get_mass()} тонн асфальта")

if task == 3:

    class Worker(object):
        def __init__(self, name, surname, position, wage, bonus):
            self.name = name
            self.surname = surname
            self.position = position
            self._income = {"wage": wage, "bonus": bonus}

    class Position(Worker):
        def __init__(self, name, surname, position, wage, bonus):
            super().__init__(name, surname, position, wage, bonus)

        def get_full_name(self):
            return self.name + ' ' + self.surname

        def get_total_income(self):
            return self._income.get("wage") + self._income.get("bonus")

    worker_one = Position("Иван", "Иванов", "Директор", 150000, 100000)
    print(worker_one.name)
    print(worker_one.surname)
    print(worker_one.position)
    print(worker_one._income)
    print(worker_one.get_full_name())
    print(worker_one.get_total_income())

if task == 4:

    class Car(object):
        def __init__(self, speed, color, name, is_police = False):
            self.speed = speed
            self.color = color
            self.name = name
            self.is_police = is_police

        def go(self):
            print(f"Автомобиль {self.color.title()} {self.name} поехал")

        def stop(self):
            print(f"Автомобиль {self.color.title()} {self.name} остановился")

        def turn(self, direction):
            print(f"Автомобиль {self.color.title()} {self.name} повернул {direction}")

        def show_speed(self):
            print(f"Автомобиль {self.color.title()} {self.name}. Скорость движения: {self.speed} км/ч")

    class TownCar(Car):
        def __init__(self, speed, color, name, is_police = False):
            super().__init__(speed, color, name, is_police = False)

        def show_speed(self):
            if self.speed > 60 :
                print(f"{self.color.title()} {self.name}, вы превысили скорость!!!")
            else:
                print(f"{self.color.title()} {self.name}, скорость движения: {self.speed} км/ч")

    class WorkCar(Car):
        def __init__(self, speed, color, name, is_police=False):
            super().__init__(speed, color, name, is_police=False)

        def show_speed(self):
            if self.speed > 40:
                print("Вы превысили ограничение скорости для рабочего автомобиля!")
            else:
                print(f"Скорость движения: {self.speed} км/ч")

    class SportCar(Car):
        def __init__(self, speed, color, name, is_police=False):
            super().__init__(speed, color, name, is_police=False)

    class PoliceCar(Car):
        def __init__(self, speed, color, name, is_police=True):
            super().__init__(speed, color, name, is_police)

    t_one = TownCar(60,"красный","Citroen")
    print(f"Автомобиль: {t_one.color}, {t_one.name}, {t_one.speed} км/ч, полиция = {t_one.is_police}")

    t_two = TownCar(80,"черный","Volvo")
    print(f"Автомобиль: {t_two.color}, {t_two.name}, {t_two.speed} км/ч, полиция = {t_two.is_police}")

    w = WorkCar(50,"оранжевый","КамАЗ")
    print(f"Автомобиль: {w.color}, {w.name}, {w.speed} км/ч, полиция = {w.is_police}")

    s = SportCar(250,"красно-желтый","Porche")
    print(f"Автомобиль: {s.color}, {s.name}, {s.speed} км/ч, полиция = {s.is_police}")

    p = PoliceCar(90,"бело-голубой","BMW")
    print(f"Автомобиль: {p.color}, {p.name}, {p.speed} км/ч, полиция = {p.is_police}")

    #Все тронулись
    t_one.go()
    t_two.go()
    w.go()
    s.go()
    p.go()

    #смотрим скорость
    t_one.show_speed()
    t_two.show_speed()
    w.show_speed()
    s.show_speed()
    p.show_speed()

    #кто-то поворачивает
    t_one.turn("направо")
    t_two.turn("налево")
    p.turn("налево")

    #полиция останавливает одного из нарушителей :)
    t_two.stop()
    p.stop()

if task == 5:

    class Stationary(object):
        def __init__(self, title):
            self.title = title

        def draw(self):
            print("Запуск отрисовки")

    class Pen(Stationary):
        def __init__(self):
            self.title = "Pen"

        def draw(self):
            print(f"Запуск отрисовки объекта {self.title}")

    class Pencil(Stationary):
        def __init__(self):
            self.title = "Pencil"

        def draw(self):
            print(f"Запуск отрисовки объекта {self.title}")

    class Handle(Stationary):
        def __init__(self):
            self.title = "Handle"

        def draw(self):
            print(f"Запуск отрисовки объекта {self.title}")

    s = Stationary("Степлер")
    pn = Pen()
    pl = Pencil()
    h = Handle()

    s.draw()
    pn.draw()
    pl.draw()
    h.draw()

if task < 1 or task > 5:
    print("Номер задачи должен быть от 1 до 5")


"""Installation script for docinstance module."""
import setuptools

with open("README.md", "r") as fh:
    # pylint: disable=C0103
    long_description = fh.read()

setuptools.setup(
    name="docinstance",
    version="0.0.1",
    author="Taewon D. Kim",
    author_email="david.kim.91@gmail.com",
    description="Docstring using flexible objects rather than strings.",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/kimt33/docinstance",
    packages=setuptools.find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
        "Operating System :: OS Independent",
    ],
)


from django import forms
from django.contrib.auth.forms import UserCreationForm
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Fieldset
from crispy_bootstrap5.bootstrap5 import FloatingField

from core.utils import crispy_save_or_go_back

from .models import User

class EditUserForm(forms.ModelForm):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.layout = Layout(
            Fieldset("Profile edit",
                Div(
                    Div(FloatingField('first_name'), css_class="col"),
                    Div(FloatingField('last_name'), css_class="col"),
                    Div(FloatingField('pronouns'), css_class="col"),
                    css_class="row",
                ),
                FloatingField('description'),
                'image',
                'tz',
            ),
            crispy_save_or_go_back(),
        )

    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'pronouns', 'description', 'image', 'tz')

class CreateUserForm(UserCreationForm):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.layout = Layout(
            Fieldset("Create user",
                'username',
                Div(
                    Div(FloatingField('first_name'), css_class="col"),
                    Div(FloatingField('last_name'), css_class="col"),
                    css_class="row",
                ),
                'password1',
                'password2',
            ),
            crispy_save_or_go_back('Sign in!'),
        )

    class Meta:
        model = User
        fields = UserCreationForm.Meta.fields + ('first_name', 'last_name')
        field_classes = UserCreationForm.Meta.field_classes


import aiohttp
from discord.ext import commands
import json
from bs4 import BeautifulSoup
from urllib import parse

class Wolfram(commands.Cog):
    """Wolfram Alpha related commands"""

    def __init__(self, bot):
        self.bot = bot
        self.json_file = 'data/wolfram.json'
        self.session = aiohttp.ClientSession()

    @commands.command()
    async def wolfram(self,  ctx, *, query: str):
        """
        gives a wolfram query result
        :param query: the query you want to search use 'image' as first keywoard to get your result as image
        """
        with open(self.json_file) as f:
            api_key = json.load(f)['api_key']

        url = 'http://api.wolframalpha.com/v2/query'
        want_image = query.split(' ')[0] == 'image'
        if not want_image:
            params = {'appid': api_key, 'input': query, 'format': 'plaintext'}
            async with ctx.typing():
                async with self.session.get(url=url, params=params) as response:
                    if response.status == 200:
                        html = await response.text()
                        soup = BeautifulSoup(html, 'html.parser')
                        success = soup.find('queryresult')['success']
                        if success == 'true':
                            query_input = soup.find('plaintext').contents
                            full_response = '<http://www.wolframalpha.com/input/?i={}>'.format(parse.quote_plus(query))
                            message = '**Full Response:** {} \n'.format(full_response)
                            message += '**Input:** {} \n'.format(query_input[0])
                            message += '**Result:** \n' \
                                       '```\n'
                            for elem in soup.find_all('plaintext')[1:6]:
                                if len(elem) > 0:
                                    message += elem.contents[0] + '\n'
                            message += '```'

                            await ctx.send(message)
                        else:
                            await ctx.send('Query was unsuccessful please try something else')
        else:
            re_query = query.split(' ')[1:]
            re_query = ' '.join(re_query)
            params = {'appid': api_key, 'input': re_query, 'format': 'plaintext,image'}
            async with ctx.typing():
                async with self.session.get(url=url, params=params) as response:
                    if response.status == 200:
                        soup = BeautifulSoup(await response.text(), 'html.parser')
                        success = soup.find('queryresult')['success']
                        if success == 'true':
                            query_input = soup.find('plaintext').contents
                            full_response = '<http://www.wolframalpha.com/input/?i={}>'.format(parse.quote_plus(re_query))
                            message = '**Full Response:** {} \n'.format(full_response)
                            message += '**Input:** {} \n'.format(query_input[0])
                            message += '**Result:** \n'
                            await ctx.send(message)
                            for elem in soup.find_all('img')[1:5]:
                                await ctx.send(elem['src'])
                        else:
                            await ctx.send('Query was unsuccessful please try something else')

    def cog_unload(self):
        self.bot.loop.create_task(self.session.close())

def setup(bot):
    bot.add_cog(Wolfram(bot))


import numpy as np
import cv2
import sys
sys.path.append('..')
from utils.LogitechWebcam import LogitechWebcam
from IPython import embed

if __name__ == '__main__':
    refFileName = "./images/left_screen_rect.png"
    refImage = cv2.imread(refFileName)
    subImage = cv2.imread("./images/sub_image.jpg")
    gray = cv2.cvtColor(refImage, cv2.COLOR_BGR2GRAY)
    fourcc = cv2.VideoWriter_fourcc(*'DIVX')
    VOut = cv2.VideoWriter('Tak_2_second.avi', fourcc, 3.0, (640, 480))

    orb = cv2.ORB_create()
    kp1, des1 = orb.detectAndCompute(gray, None)
    # surf = cv2.xfeatures2d_SURF.create(400)
    # keyPoints, descriptors = surf.detectAndCompute(gray, None)

    camera = LogitechWebcam()
    # matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    index_params = dict(algorithm=6,
                        table_number=6,
                        key_size=12,
                        multi_probe_level=2)
    search_params = {}
    matcher = cv2.FlannBasedMatcher(index_params, search_params)

    while True:
        frame = camera.get_image()
        frameGray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        kp2, des2 = orb.detectAndCompute(frameGray, None)
        # frameKeyPoints, frameDescriptors = surf.detectAndCompute(
        #     frameGray, None)

        # matches = matcher.match(des1, des2)

        # matches = sorted(matches, key=lambda x: x.distance)
        # goodMatch = matches[:100]

        matches = matcher.knnMatch(des1, des2, k=2)

        goodMatch = []
        for m, n in matches:
            if m.distance < 0.75 * n.distance:
                goodMatch.append(m)

        minMatches = 20
        image_out = frame

        if len(goodMatch) > minMatches:
            srcPts = np.float32([kp1[m.queryIdx].pt
                                 for m in goodMatch]).reshape(-1, 1, 2)
            dstPts = np.float32([kp2[m.trainIdx].pt
                                 for m in goodMatch]).reshape(-1, 1, 2)

            M, mask = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)
            # matchesMask = mask.ravel().tolist()

            h, w, _ = frame.shape

            warp = cv2.warpPerspective(subImage, M, frameGray.shape[0:2][::-1])
            contPix = np.where(((warp[:, :, 0] == 0) + (warp[:, :, 0] == 1) +
                                (warp[:, :, 2] == 0)) == False)

            image_out[contPix[0], contPix[1], :] = warp[contPix[0],
                                                        contPix[1], :]

            # cv2.imshow("Warped", warp)

        cv2.imshow("Frame", image_out)
        VOut.write(image_out)
        if cv2.waitKey(30) != -1:
            break

    VOut.release()
    cv2.destroyAllWindows()


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

# In[1]:

import pandas as pd
import scrapy
from scrapy.crawler import CrawlerProcess
finalnames=[]
finalsectors=[]
finalopen=[]
finalclose=[]

# In[2]:

class StockSpy(scrapy.Spider):
    name='StockSpyder'

    def start_requests(self):
        url= 'https://www.moneycontrol.com/india/stockpricequote'
        yield scrapy.Request(url=url, callback=self.findstock)

    def findstock(self, response):
        stocklink=[]
        links=response.xpath('//div[@class="PT15"]//td/a/@href').extract()
        for link in links:
            stocklink.append(link)
        for link in stocklink:
            yield response.follow(url=link, callback= self.getprice)

    def getprice(self, response):
        name=response.xpath('//div[@id="stockName"]/h1/text()').extract()
        cleanname=[n.strip() for n in name]
        for i in cleanname:
            finalnames.append(i)

        sector=response.xpath('//div[@id="stockName"]//strong/a/text()').extract()
        cleansector=[s.strip() for s in sector]
        for i in cleansector:
            finalsectors.append(i)

        open_p=response.xpath('//div[@class="nsestock_overview bsestock_overview"]//td[@class="nseopn bseopn"]/text()').extract()
        cleanopen=[o.strip() for o in open_p]
        for i in cleanopen:
            finalopen.append(i)

        close_p=response.xpath('//div[@class="nsestock_overview bsestock_overview"]//td[@class="nseprvclose bseprvclose"]/text()').extract()
        cleanclose=[c.strip() for c in close_p]
        for i in cleanclose:
            finalclose.append(i)

process= CrawlerProcess()
process.crawl(StockSpy)
process.start()

StockData=pd.DataFrame()
StockData['StockName']=finalnames
StockData['Sector']=finalsectors
StockData['OpenPrice']=finalopen
StockData['PrevClose']=finalclose
StockData.to_excel('MoneyControl.xlsx', sheet_name='NSE_Stocks')

# In[ ]:

# In[ ]:

# In[ ]:

# In[ ]:

# In[ ]:


import sys
from resource_management.libraries.script.script import Script
from resource_management.libraries.functions.format import format
from resource_management.libraries.functions.check_process_status import check_process_status
from resource_management.libraries.functions.security_commons import build_expectations, \
  cached_kinit_executor, get_params_from_filesystem, validate_security_config_properties, \
  FILE_TYPE_XML
from hbase import hbase
from hbase_service import hbase_service
from hbase_decommission import hbase_decommission
import upgrade
from setup_ranger_hbase import setup_ranger_hbase
from ambari_commons import OSCheck, OSConst
from ambari_commons.os_family_impl import OsFamilyImpl
import os
from resource_management.libraries.functions.setup_atlas_hook import has_atlas_in_cluster, setup_atlas_hook
from ambari_commons.constants import SERVICE
from resource_management.core.logger import Logger

class HbaseMaster(Script):
  def configure(self, env):
    import params
    env.set_params(params)
    hbase(name='master')

  def install(self, env):
    import params
    env.set_params(params)
    self.install_packages(env)

  def decommission(self, env):
    import params
    env.set_params(params)
    hbase_decommission(env)

@OsFamilyImpl(os_family=OSConst.WINSRV_FAMILY)
class HbaseMasterWindows(HbaseMaster):
  def start(self, env):
    import status_params
    self.configure(env)
    Service(status_params.hbase_master_win_service_name, action="start")

  def stop(self, env):
    import status_params
    env.set_params(status_params)
    Service(status_params.hbase_master_win_service_name, action="stop")

  def status(self, env):
    import status_params
    env.set_params(status_params)
    check_windows_service_status(status_params.hbase_master_win_service_name)

@OsFamilyImpl(os_family=OsFamilyImpl.DEFAULT)
class HbaseMasterDefault(HbaseMaster):
  def pre_upgrade_restart(self, env, upgrade_type=None):
    import params
    env.set_params(params)
    upgrade.prestart(env)

  def start(self, env, upgrade_type=None):
    import params
    env.set_params(params)
    self.configure(env) # for security
    setup_ranger_hbase(upgrade_type=upgrade_type, service_name="hbase-master")
    if params.enable_hbase_atlas_hook:
      Logger.info("Hbase Atlas hook is enabled, configuring Atlas HBase Hook.")
      hbase_atlas_hook_file_path = os.path.join(params.hbase_conf_dir,params.atlas_hook_filename)
      setup_atlas_hook(SERVICE.HBASE,params.hbase_atlas_hook_properties,hbase_atlas_hook_file_path,params.hbase_user,params.user_group)
    else:
      Logger.info("Hbase Atlas hook is disabled, skippking Atlas configurations.")
    hbase_service('master', action = 'start')

  def stop(self, env, upgrade_type=None):
    import params
    env.set_params(params)
    hbase_service('master', action = 'stop')

  def status(self, env):
    import status_params
    env.set_params(status_params)

    check_process_status(status_params.hbase_master_pid_file)

  def security_status(self, env):
    import status_params

    env.set_params(status_params)
    if status_params.security_enabled:
      props_value_check = {"hbase.security.authentication" : "kerberos",
                           "hbase.security.authorization": "true"}
      props_empty_check = ['hbase.master.keytab.file',
                           'hbase.master.kerberos.principal']
      props_read_check = ['hbase.master.keytab.file']
      hbase_site_expectations = build_expectations('hbase-site', props_value_check, props_empty_check,
                                                  props_read_check)

      hbase_expectations = {}
      hbase_expectations.update(hbase_site_expectations)

      security_params = get_params_from_filesystem(status_params.hbase_conf_dir,
                                                   {'hbase-site.xml': FILE_TYPE_XML})
      result_issues = validate_security_config_properties(security_params, hbase_expectations)
      if not result_issues:  # If all validations passed successfully
        try:
          # Double check the dict before calling execute
          if ( 'hbase-site' not in security_params
               or 'hbase.master.keytab.file' not in security_params['hbase-site']
               or 'hbase.master.kerberos.principal' not in security_params['hbase-site']):
            self.put_structured_out({"securityState": "UNSECURED"})
            self.put_structured_out(
              {"securityIssuesFound": "Keytab file or principal are not set property."})
            return

          cached_kinit_executor(status_params.kinit_path_local,
                                status_params.hbase_user,
                                security_params['hbase-site']['hbase.master.keytab.file'],
                                security_params['hbase-site']['hbase.master.kerberos.principal'],
                                status_params.hostname,
                                status_params.tmp_dir)
          self.put_structured_out({"securityState": "SECURED_KERBEROS"})
        except Exception as e:
          self.put_structured_out({"securityState": "ERROR"})
          self.put_structured_out({"securityStateErrorInfo": str(e)})
      else:
        issues = []
        for cf in result_issues:
          issues.append("Configuration file %s did not pass the validation. Reason: %s" % (cf, result_issues[cf]))
        self.put_structured_out({"securityIssuesFound": ". ".join(issues)})
        self.put_structured_out({"securityState": "UNSECURED"})
    else:
      self.put_structured_out({"securityState": "UNSECURED"})

  def get_log_folder(self):
    import params
    return params.log_dir

  def get_user(self):
    import params
    return params.hbase_user

  def get_pid_files(self):
    import status_params
    return [status_params.hbase_master_pid_file]

if __name__ == "__main__":
  HbaseMaster().execute()


import dataset

a = dataset.main()
power = 0
test_subset = [
    "00100",
    "11110",
    "10110",
    "10111",
    "10101",
    "01111",
    "00111",
    "11100",
    "10000",
    "11001",
    "00010",
    "01010",
]

# GAmma is worked out by common bit of each index of input
# Epsilon rate is least common bit, or opposite of gamma
def PartA():
    arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    print(arr[1])
    for item in a:
        for i, char in enumerate(item):

            if char is "1":
                arr[i] = arr[i] + 1
            else:
                arr[i] -= 1

    gamma = ""
    for num in arr:
        if num > 0:
            gamma = gamma + "1"
        elif num < 0:
            gamma = gamma + "0"

    epsilon = ""
    for item in gamma:
        if item is "1":
            epsilon += "0"
        else:
            epsilon += "1"

    print(gamma)
    print(epsilon)
    power = int(gamma, 2) * int(epsilon, 2)
    print(power)

# PART 2
def PartB():
    life_sup = 0
    # Making These strings as we manipulate the binary
    # Only keep numbers matching and stop when we have 1 left
    #oxygen = a
    #co2 = a
    oxygen = a
    co2 = a
    # For each bit array in list
    # Shortcut, we are assuming all binary numbers are same length

    oxygen = FindOxygen(oxygen)
    co2 = FindCO2(co2)
    print(f'Oxygen: {oxygen}, CO2: {co2}')
    life_sup = int(oxygen[0], 2) * int(co2[0], 2)
    print(life_sup)

def FindOxygen(oxygen):
    # TODO: FIX THIS RANGE
    for i in range(len(oxygen[0])):
        counter = 0
        temp = []
        for item in oxygen:
            counter += CommonBit(item[i])
        for item in oxygen:
            if counter > 0 and item[i] == "1":
                temp.append(item)
            elif counter == 0 and item[i] == "1":
                temp.append(item)
            elif counter < 0 and item[i] == "0":
                temp.append(item)
        oxygen = temp
    return oxygen

def FindCO2(co2):
    for i in range(len(co2[0])):
        # While we have more than 1 item in co2
        print("\n")
        print(f'Iteration {i + 1}')
        print(f'List: {co2}')
        counter = 0
        temp = []
        print(f'Length of co2: {len(co2)}')
        for item in co2:
            counter += CommonBit(item[i])
            # Lets inverse the counter
            # This now shows least common bit
        counter = counter * -1
        print(f'Least common bit: {counter}')
        for item in co2:
            if counter < 0 and item[i] == "0":
                temp.append(item)
            elif counter > 0 and item[i] == "1":
                temp.append(item)
            elif counter == 0 and item[i] == "0":
                print("HERE?")
                temp.append(item)
        print(temp)
        if len(co2) > 1:
            co2 = temp
    return co2

def FindMostCommonBitArr(arr):
    # Return a number to represent common bit
    # x > 0, 1 is commmon
    # x = 0, Even 1 and 0
    # x < 0, 0 is common bit
    counter = 0
    for item in arr:
        if item == "1":
            counter += 1
        else:
            counter -= 1

def CommonBit(int):
    if int == "1":
        print(1)
        return 1
    else:
        print(-1)
        return -1

# FindMostCommonBit(["1", "1", "0"])
PartB()


#!/usr/bin/python

import csv, re

with open('data.csv', 'rb') as f:
	reader = csv.reader(f)
	fi = open('data2.csv', 'w')
	fi.write("First,M.I.,Last,Number\n")
	for row in reader:
		if len(row[1]) < 10:
			continue
		words = row[0].split()
		if len(words) == 2:
			regex = r"([a-zA-Z]+)\D+?([a-zA-Z]+)"
			if words[0][-1] == ',':
				#last name is first
				fi.write(re.sub(regex, r"\2,,\1,", row[0]))
			else:
				#first name is first
				fi.write(re.sub(regex, r"\1,,\2,", row[0]))
		else:
			regex = r"([a-zA-Z]+)\D+?([a-zA-Z]+)\D?\D?([a-zA-Z]+)\D?"
			if words[0][-1] == ',':
				#last first middle
				fi.write(re.sub(regex, r"\2,\3.,\1,", row[0]))
			else:
				#first middle last
				fi.write(re.sub(regex, r"\1,\2.,\3,", row[0]))
		#regex for numbers
		regex = r"(\d-)?\(?([0-9]{3})\D?([0-9]{3})\D?([0-9]{4})"
		fi.write(re.sub(regex, r"(\2) \3-\4", row[1])+"\n")
	f.close()
	fi.close()


from secrets import *
print ("secure random generator, a 506independent program")
#makes the variables
canc = False
high = 2
num = 0
while canc == False:
    choice = input("what do you want to generate? a single random number"
                   " in the range you choose (s), as many"
                   "separate secure random numbers as you want, in a"
                   " range you choose (3), make a hex with as many bytes "
                   "as you choose(h)"
                   "or generate a token with as many bytes as you"
                   " choose (t). you can also see about, (a). maybe you"
                   " want to enter the DICE LOOP (dl)")
    #ensures your choice is processed
    if choice == "s":
        high = int(input("what will be the highest number?"))
        num = randbelow (high)
        print (num)
    if choice == "t":
        high = int(input("how many bytes is your token?"))
        num = token_bytes (high)
        print (num)
    if choice == "h":
        high = int(input("how many bytes is your hex?"))
        num = token_hex(high)
        print (num)
    if choice == "3":
        rang = int(input("how many random numbers do YOU want to"
                         " GENERATE?"))
        choice = input("do you want to choose the cap for all the "
                       "numbers at once(a), or meet them induvidually(i)?")
        if choice == "a":
            high = int(input(" what is the cap?"))
        for i in range(rang):
            if choice == "i":
                high = int(input("what is the cap for this number?"))
                num = randbelow (high)
                print (num)
            else:
                num = randbelow (high)
                print (num)
                #changing the choice is essantial, otherwise it will play the about page
                choice = "d"
    if choice == "a":
        print ("this dice was designed as a secure dice, for when you need secure random generation.")
        print ("imagine this. you're playing a board game, and someone decided to bring a cheat dice. you then lose.")
    if choice == "dl":
        #makes the variables befor they are used
        mode = "fill"
        enter = "fill"
        mode = int(input(" what mode do you want? 10, 8, 6, 5, 2 or choose(1)?"))
        enter = input("you have decided to enter the DICE LOOP. to enter, just enter the word in, and you are in. otherwise,"
                      "you will be kicked out")
        if enter == "in":
            print ("you poor soul, you ahve entered the loop! e to exit if you got here by accident!")
            if mode == 10:
                while not enter == "e":
                    num = randbelow (10)
                    print (num)
                    enter = input("press enter when you are ready to re-roll")
            if mode == 8:
                while not enter == "e":
                    num = randbelow (8)
                    print (num)
                    enter = input("press enter when you are ready to re-roll")
            if mode == 6:
                while not enter == "e":
                    num = randbelow (6)
                    print (num)
                    enter = input("press enter when you are ready to re-roll")
            if mode == 5:
                while not enter == "e":
                    num = randbelow (5)
                    print (num)
                    enter = input("press enter when you are ready to re-roll")
            if mode == 2:
                while not enter == "e":
                    num = randbelow (2)
                    print (num)
                    enter = input("press enter when you are ready to re-roll")
            if mode == 1:
                high = int(input("what is the cap number?"))
                while not enter == "e":
                    num = randbelow (high)
                    print (num)
                    enter = input("press enter when you are ready to re-roll")
        else:
            pass
    #turns the canc into python readable Trues and Falses.
    canc = input("again(y/n)")
    if canc == "y":
        canc = False
#hundredth line?!
    if canc == "Y":
        can = False
    if canc == "n":
        canc = True
    if canc == "N":
        canc = True
#when you use the python runthing, then this wont close the runthing instantly. stops when you hit enter.
input("thanks for trying my second dice!")


from textblob import TextBlob
import spacy

text = "Compatibility of systems of linear constraints over the set of natural numbers. Criteria of compatibility of a system of linear Diophantine equations, strict inequations, and nonstrict inequations are considered."

blob = TextBlob(text)

for sent in blob.sentences:
    print(sent)
    print(sent.tags)

nlp = spacy.load('en')
doc = nlp(text)

for sent in doc.sents:
    print(sent)
    print(type(sent))
    print(repr(sent))

    print(sent.start, sent.end, len(sent))

    #for word in nlp(repr(sent)):
    #for word in sent.__iter__:
    for i in range(len(sent)):
        word = sent[i]
        print(word.text, word.lemma, word.lemma_, word.tag, word.tag_, word.pos, word.pos_)

for np in doc.noun_chunks:
    print(np.text)

print("---")
from spacy.symbols import *

np_labels = set([nsubj, nsubjpass, dobj, iobj, pobj]) # Probably others too

def iter_nps(doc):
    for word in doc:
        if word.dep in np_labels:
            yield word.subtree

for np in iter_nps(doc):
    print(list(np))


n  = int(input())
tmp = list(map(int, input().split()))
score = 0
tmpscore = 0
for i in range(n) :
    if tmp[i] == 1:
        tmpscore += 1
        score += tmpscore
    elif tmp[i] == 0 :
        tmpscore = 0

print(score)