#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-
###############################################################################
#
# This module contains implementation of an RPC interface and resource, built
# on top of TcpInterface/TcpResource. Pythomnic3k RPC is based on the following
# principles:
#
# 1. Automatic discovery of a target cage. Whenever some cage executes
#    pmnc("othercage").module.method(...)
#    the location of othercage is discovered automatically and transparently
#    by sending out UDP broadcasts to which (either copy of) othercage presumably
#    responds. The received response contains the listening address of the
#    responded cage and TCP/SSL connection can be initiated.
#    Target cage addresses can be configured separately, if necessary,
#    for example if UDP broadcasts can't go freely between the cages.
#    Therefore a network of cages can well exist without broadcasts,
#    but that would require a lot of manual configuration.
#
# 2. Multiple cages with the same name can be running on different servers,
#    they all respond to the discovery requests. One of the responses to arrive
#    first is chosen, and responses from different cages may cause connections
#    to different copies of the target cage to exist at the same time.
#
# 3. Hence this - in Pythomnic3k there is no difference between copies of
#    identically named cages - they are supposed to be freely interchangeable.
#    This fact is stressed by using SSL certificates to authenticate cages
#    to each other - each "cage" presumably owns a certificate which has common
#    name of "cage". This allows cages to trust each other at least by name.
#
# 4. RPC implemented here is synchronous and plays by Pythomnic3k rules of non-
#    blocking and timing out within deadline. Execution of the call on the target
#    cage inherits the original timeout, therefore the original request is logically
#    "extended" to the target cage and impersonated for the course of RPC execution.
#
# 5. Each cage advertises its location by periodically sending out broadast
#    requests. The received locations of other cages are kept on record and
#    can be accessed by get_cages and get_nodes methods of the rpc interface,
#    this is used by the health_monitor cage to locate active cages. Typically
#    a cage broadcasts its own presence but it is technically possible for one
#    cage (a sort of registry perhaps) to broadcast the locations of other cages.
#
# There is just one RPC interface and RPC resource required for a cage to be
# able to exchange RPC calls with other cages.
#
# Sample RPC interface configuration (config_interface_rpc.py):
#
# config = dict \
# (
# protocol = "rpc",                                        # meta
# request_timeout = None,                                  # meta, optional
# random_port = -63000,                                    # tcp, negative means "in range 63000..63999"
# max_connections = 100,                                   # tcp
# broadcast_address = ("1.2.3.4/1.2.3.255", 12480),        # rpc, "interface address/broadcast address", port
# flock_id = "DEFAULT",                                    # rpc, arbitrary cage group identifier
# )
#
# Sample RPC resource configuration (config_resource_rpc.py)
#
# config = dict \
# (
# protocol = "rpc",                                        # meta
# broadcast_address = ("1.2.3.4/1.2.3.255", 12480),        # rpc, "interface address/broadcast address", port
# discovery_timeout = 3.0,                                 # rpc + tcp (discovery + connect timeout)
# multiple_timeout_allowance = 0.5,                        # rpc, in range 0.0..1.0
# flock_id = "DEFAULT",                                    # rpc, arbitrary cage group identifier
# exact_locations = { "SomeCage": "ssl://1.2.3.5:63842" }, # rpc, maps cage names to their fixed locations
# )

# Pythomnic3k project
# (c) 2005-2010, Dmitry Dvoinikov <dmitry@targeted.org>
# Distributed under BSD license
#
###############################################################################

__all__ = [ "Interface", "Resource", "Handler" ]

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

import os; from os import urandom, SEEK_SET, SEEK_CUR, SEEK_END, path as os_path
import time; from time import time
import binascii; from binascii import b2a_hex
import select; from select import select
import io; from io import BytesIO
import hashlib; from hashlib import sha1
import threading; from threading import current_thread, Lock
import pickle; from pickle import load as unpickle, dumps as pickles
import random; from random import randint
import ssl; from ssl import CERT_REQUIRED
import socket; from socket import socket, AF_INET, SOCK_DGRAM, SOL_SOCKET, \
                                  SO_BROADCAST, SO_REUSEADDR, error as socket_error
try:
    from socket import SO_REUSEPORT
except ImportError:
    have_reuse_port = False
else:
    have_reuse_port = True

if __name__ == "__main__": # add pythomnic/lib to sys.path
    import os; import sys
    main_module_dir = os.path.dirname(sys.modules["__main__"].__file__) or os.getcwd()
    sys.path.insert(0, os.path.normpath(os.path.join(main_module_dir, "..", "..", "lib")))

import exc_string; from exc_string import exc_string
import typecheck; from typecheck import typecheck, optional, by_regex, dict_of
import pmnc.resource_pool; from pmnc.resource_pool import TransactionalResource, \
                                                          ResourceError, RPCError
import pmnc.timeout; from pmnc.timeout import Timeout
import pmnc.threads; from pmnc.threads import HeavyThread

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

valid_cage_name = by_regex("^[A-Za-z0-9_-]{1,32}$")
valid_node_name = by_regex("^[A-Za-z0-9_-]{1,32}$")
valid_flock_id = by_regex("^[A-Za-z0-9_-]+$")
valid_location = by_regex("^(ssl|tcp)://([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|\\*):[0-9]{1,5}/$")
valid_exact_location = by_regex("^(ssl|tcp)://[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}:[0-9]{1,5}/$")

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

def _get_peer_name(ssl_socket):
    for f in ssl_socket.getpeercert()["subject"]:
        if f[0][0] == "commonName":
            return f[0][1]
    else:
        return None

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

def _create_sending_broadcast_socket(addr: str) -> socket:
    bc_socket = socket(AF_INET, SOCK_DGRAM)
    try:
        bc_socket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
        bc_socket.bind((addr, 0))
    except:
        bc_socket.close()
        raise
    else:
        return bc_socket

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

def _create_receiving_broadcast_socket(port: int) -> socket:
    bc_socket = socket(AF_INET, SOCK_DGRAM)
    try:
        bc_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        if have_reuse_port:
            bc_socket.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
        bc_socket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
        bc_socket.bind(("0.0.0.0", port))
    except:
        bc_socket.close()
        raise
    else:
        return bc_socket

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

# key files required to establish SSL connection
# may reside in current cage or in .shared

def _locate_key_file(filename: str) -> optional(os_path.isfile):

    s = os_path.join(__cage_dir__, "ssl_keys", filename)
    if os_path.isfile(s):
        return s

    s = os_path.normpath(os_path.join(__cage_dir__, "..", ".shared", "ssl_keys", filename))
    if os_path.isfile(s):
        return s

    return None

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

class RpcPacket():

    def __init__(self, max_size: optional(int) = None):
        self._max_size = max_size
        self._stream = BytesIO()
        self._length = None
        self._expected_hash = None
        self._hash = None
        self._method = None

    @staticmethod
    def marshal(data):
        return b"PKL3" + pickles(data)

    def _unmarshal(self):
        if self._method == "PKL3":
            self._stream.seek(52, SEEK_SET)
            return unpickle(self._stream)
        else:
            raise Exception("unsupported marshaling method: "
                            "{0:s}".format(self._method))

    def write(self, data: bytes):

        self._stream.write(data)
        if self._max_size and self._stream.tell() > self._max_size:
            raise Exception("packet size exceeded")

        if self._length is None and self._stream.tell() >= 8:
            self._stream.seek(0, SEEK_SET)
            self._length = int(self._stream.read(8).decode("ascii"), 16) + 48
            if self._max_size and self._length > self._max_size:
                raise Exception("request size exceeded")
            self._stream.seek(0, SEEK_END)

        if self._expected_hash is None and self._stream.tell() >= 48:
            self._stream.seek(8, SEEK_SET)
            self._expected_hash = self._stream.read(40).decode("ascii")
            self._hash = sha1(self._stream.read())
        elif self._hash is not None:
            self._hash.update(data)

        if self._method is None and self._stream.tell() >= 52:
            self._stream.seek(48, SEEK_SET)
            self._method = self._stream.read(4).decode("ascii")
            self._stream.seek(0, SEEK_END)

        if self._stream.tell() == self._length:
            if self._hash.hexdigest().upper() != self._expected_hash:
                raise Exception("request hash mismatch")
            return self._unmarshal()
        else:
            return None

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

class Interface: # RPC interface

    @typecheck
    def __init__(self, name: str, *,
                 random_port: lambda i: isinstance(i, int) and (-65500 <= i <= 65535),
                 max_connections: int,
                 broadcast_address: (str, int),
                 flock_id: valid_flock_id,
                 separate_thread_pool: optional(bool) = False,
                 disable_broadcast: optional(bool) = False,
                 request_timeout: optional(float) = None,
                 **kwargs):

        self._name = name
        broadcast_address, self._broadcast_port = broadcast_address
        self._bind_address, self._broadcast_address = broadcast_address.split("/")
        self._disable_broadcast = disable_broadcast
        self._request_prefix = "PYTHOMNIC3K-REQUEST:{0:s}:".format(flock_id)
        self._response_prefix = "PYTHOMNIC3K-RESPONSE:{0:s}:".format(flock_id)
        self._known_cages = {} # { cage: { node: { location: ..., expires_at: ... } } }
        self._known_cages_lock = Lock()
        self._ad_period_idx = 0

        ssl_key_cert_file = _locate_key_file("key_cert.pem")
        ssl_ca_cert_file = _locate_key_file("ca_cert.pem")

        if pmnc.request.self_test == __name__: # self-test
            self.process_rpc_request = kwargs["process_rpc_request"]
            self._cage_name = kwargs["cage_name"]
            if "ad_periods" in kwargs:
                self._ad_periods = kwargs["ad_periods"]
        else:
            self._cage_name = __cage__

        # having handler factory create handlers through a pmnc call
        # allows online modifications to this module, after it is reloaded

        handler_factory = lambda prev_handler: \
            pmnc.protocol_rpc.Handler(self.process_rpc_request, self._cage_name)

        # create an instance of underlying TCP interface, note that in case
        # of SSL we require the client (source cage) to present a certificate

        request_timeout = request_timeout or \
                          pmnc.config_interfaces.get("request_timeout") # this is now static

        self._tcp_interface = \
            pmnc.protocol_tcp.TcpInterface(name, handler_factory, request_timeout,
                                           listener_address = (self._bind_address, random_port),
                                           max_connections = max_connections,
                                           ssl_key_cert_file = ssl_key_cert_file,
                                           ssl_ca_cert_file = ssl_ca_cert_file,
                                           required_auth_level = CERT_REQUIRED)

        # RPC interface is special in that it can be configured to enqueue
        # its requests to a separate private thread pool instead of using
        # the thread pool shared with all other interfaces

        if separate_thread_pool:
            self._thread_pool = pmnc.shared_pools.get_private_thread_pool()
            self._tcp_interface._enqueue_request = self._enqueue_request

    name = property(lambda self: self._tcp_interface.name)
    listener_address = property(lambda self: self._tcp_interface.listener_address)

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

    def start(self):
        self._tcp_interface.start()
        if not self._disable_broadcast: # create and start broadcaster thread
            self._broadcaster = HeavyThread(target = self._broadcaster_proc,
                                            name = "{0:s}:brc".format(self._name))
            self._broadcaster.start()

    def cease(self):
        if not self._disable_broadcast:
            self._broadcaster.stop()
        self._tcp_interface.cease()

    def stop(self):
        self._tcp_interface.stop()

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

    def _broadcaster_proc(self):
        try:

            # the listening socket must be bound to the configured port

            self._bc_socket = _create_receiving_broadcast_socket(self._broadcast_port)
            try:

                ad_timeout = self._next_advertisement_timeout()

                while not current_thread().stopped(): # lifetime loop
                    try:

                        # receive incoming broadcast packets

                        receive_timeout = Timeout(1.0)
                        while not receive_timeout.expired and select([self._bc_socket], [], [], receive_timeout.remain)[0]:
                            try:
                                try:
                                    packet, (client_addr, client_port) = self._bc_socket.recvfrom(57344)
                                except socket_error as e:
                                    if e.args[0] == 10054: # workaround for this issue: http://support.microsoft.com/kb/263823
                                        continue
                                    else:
                                        raise
                                try:
                                    packet = packet.decode("ascii")
                                except UnicodeDecodeError:
                                    continue
                                self._handle_received_packet(packet, client_addr, client_port)
                            except:
                                pmnc.log.error(exc_string()) # log and ignore

                        # send self-advertisement once in a while

                        if ad_timeout.expired:
                            try:
                                self._purge_known_cages()
                                self._broadcast_advertisement()
                            finally:
                                ad_timeout = self._next_advertisement_timeout()

                    except:
                        pmnc.log.error(exc_string()) # log and ignore

            finally:
                self._bc_socket.close()

        except:
            pmnc.log.error(exc_string()) # log and ignore

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

    # this method overrides identical method from TcpInterface
    # if the interface is configured to use private thread pool

    def _enqueue_request(self, *args, **kwargs):
        self._thread_pool.enqueue(*args, **kwargs)

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

    def get_cages(self):
        with self._known_cages_lock:
            return set(self._known_cages.keys())

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

    @typecheck
    def get_nodes(self, cage: valid_cage_name):
        with self._known_cages_lock:
            nodes = self._known_cages.get(cage, {})
            return { node: cage_info["location"]
                     for node, cage_info in nodes.items() }

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

    def _discovery_response(self, request_id: str) -> bytes:
        return "{0:s}{1:s}:{2:s}://*:{3:d}/".\
               format(self._response_prefix, request_id,
                      self._tcp_interface.encrypted and "ssl" or "tcp",
                      self._tcp_interface.listener_address[1]).\
               encode("ascii")

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

    # each cage broadcasts its presence, issuing increasing timeouts
    # between the broadcasts, so that all the other cages know soon,
    # but do not receive excessive flood afterwards

    _ad_periods = (10.0, 20.0, 30.0, 60.0, 180.0, 300.0, 600.0) # in seconds, the last one is repeated

    def _next_advertisement_timeout(self) -> Timeout:
        ad_period = self._ad_periods[self._ad_period_idx]
        if self._ad_period_idx < len(self._ad_periods) - 1:
            self._ad_period_idx += 1
        return Timeout(ad_period)

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

    def _advertisement_packet(self) -> bytes:

        request_id = b2a_hex(urandom(8)).decode("ascii").upper()
        return "{0:s}{1:s}:ADVERTISE-CAGE:{2:s}:{3:s}:{4:d}:{5:s}://*:{6:d}/".\
               format(self._request_prefix, request_id, __node__,
                      self._cage_name, int(self._ad_periods[self._ad_period_idx]),
                      self._tcp_interface.encrypted and "ssl" or "tcp",
                      self._tcp_interface.listener_address[1]).\
               encode("ascii")

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

    def _broadcast_advertisement(self):

        bc_socket = _create_sending_broadcast_socket(self._bind_address)
        try:
            pmnc.log.debug("broadcasting cage advertisement: {0:s}.{1:s} is at "
                           "{2:s}://*:{3:d}/".format(__node__, self._cage_name,
                           self._tcp_interface.encrypted and "ssl" or "tcp",
                           self._tcp_interface.listener_address[1]))
            bc_socket.sendto(self._advertisement_packet(),
                             (self._broadcast_address, self._broadcast_port))
        finally:
            bc_socket.close()

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

    def _handle_received_packet(self, packet: str, client_addr: str, client_port: int):

        if not packet.startswith(self._request_prefix):
            return

        request_id, request, request_params = \
            packet[len(self._request_prefix):].split(":", 2)

        if request == "DISCOVER-CAGE": # received discovery request from another cage

            if request_params == self._cage_name:
                discovery_response = self._discovery_response(request_id)
                pmnc.log.debug("sending response to discovery request "
                               "from {0:s}".format(client_addr))
                self._bc_socket.sendto(discovery_response, (client_addr, client_port))

        elif request == "ADVERTISE-CAGE": # received other cage's presence broadcast

            node, cage, period, advertised_location = request_params.split(":", 3)
            try:
                period = int(period)
            except ValueError:
                period = 0

            if valid_cage_name(cage) and valid_node_name(node) and \
               1 <= period <= 3600 and valid_location(advertised_location):

                # the advertisement should contain the URL to the cage,
                # for example ssl://1.2.3.4:5678/ or ssl://*:5678/ the latter
                # form meaning the address from which it has been sent

                cage_addr, cage_port = advertised_location[6:-1].split(":")
                if cage_addr == "*": cage_addr = client_addr
                location = "{0:s}{1:s}:{2:s}/".format(advertised_location[:6],
                                                      cage_addr, cage_port)

                # record the received advertisement, keeping track of time,
                # so that the record expires and disappears without receiving
                # more advertisements

                with self._known_cages_lock:
                    nodes = self._known_cages.setdefault(cage, {})
                    if nodes.get(node, {}).get("location") != location:
                        pmnc.log.debug("received cage advertisement: {0:s}.{1:s} "
                                       "is at {2:s}".format(node, cage, location))
                    nodes[node] = dict(location = location, expires_at = time() + period * 2)

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

    def _purge_known_cages(self):

        purge_time = time()
        with self._known_cages_lock:
            for cage, nodes in self._known_cages.items():
                expired_nodes = [ node for node, cage_info in nodes.items()
                                  if cage_info["expires_at"]  < purge_time ]
                for expired_node in expired_nodes:
                    del nodes[expired_node]

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

    def process_rpc_request(self, module, method, args, kwargs):
        return pmnc.__getattr__(module).__getattr__(method)(*args, **kwargs)

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

class Handler: # this class is instantiated from interface_tcp

    protocol = "rpc"

    _max_request_size = 1048576

    idle_timeout = 86400.0 # server side of an RPC connection will be kept until
                           # the client closes it, either as idle or expired

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

    def __init__(self, process_rpc_request, cage_name):
        self._process_rpc_request = process_rpc_request
        self._cage_name = cage_name
        self._rpc_packet = RpcPacket(self._max_request_size)

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

    @typecheck
    def consume(self, data: bytes) -> bool:
        rpc_request = self._rpc_packet.write(data)
        if rpc_request is not None:
            self._rpc_request = rpc_request # the packet has been received and parsed
            return True
        else:
            return False

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

    # this method is executed by one of the interface pool threads and performs
    # the actual processing of a previously read and parsed request

    def process_tcp_request(self):

        rpc_request = self._rpc_request

        # extract call information from the dict contained
        # in the received request

        assert rpc_request["target_cage"] == self._cage_name, \
               "expected call to this cage"

        source_cage = rpc_request["source_cage"]
        module = rpc_request["module"]
        method = rpc_request["method"]
        module_method = "{0:s}.{1:s}".format(module, method)
        args = rpc_request["args"]
        kwargs = rpc_request["kwargs"]

        # extract the original request, note that its remaining time
        # is decreased if the current RPC request has less time left

        request_dict = rpc_request["request"]

        request_dict.setdefault("interface", "rpc") # backwards compatibility section
        request_dict.setdefault("protocol", "rpc")
        request_dict["parameters"].setdefault("auth_tokens", {}).\
                                   setdefault("source_cage", source_cage)

        request = pmnc.request.from_dict(request_dict, timeout = pmnc.request.remain)

        # if the connection arrived over SSL, we verify source
        # cage name against the peer's SSL certificate

        auth_tokens = pmnc.request.parameters["auth_tokens"]

        if auth_tokens["encrypted"] and \
           not by_regex("^{0:s}$".format(auth_tokens["peer_cn"]))(source_cage):
            raise Exception("source cage name does not match its SSL certificate")

        # now we know more about the request, it is still the current
        # RPC request, we haven't impersonated the received request yet

        pmnc.request.describe("RPC call {0:s} from {1:s} at {2:s}".\
                              format(module_method, source_cage, auth_tokens["peer_ip"]))
        try:
            pmnc.log.debug("impersonating request {0:s}".format(request.description))
            original_request = current_thread()._request
            current_thread()._request = request
            try:
                result = self._process_rpc_request(module, method, args, kwargs)
            finally:
                current_thread()._request = original_request
        except:
            error = exc_string()
            pmnc.log.error("incoming RPC call failed: {0:s}".format(error))
            rpc_response = dict(exception = error)
            deliver_message = "RPC error"
        else:
            rpc_response = dict(result = result)
            deliver_message = "RPC response, {0:d} byte(s)"

        # marshal the response and prepare for delivery, note that
        # the delivery is done on behalf and within the local request

        response_bytes = RpcPacket.marshal(rpc_response)
        response_hash = sha1(response_bytes).hexdigest().upper()
        response_packet = "{0:08X}{1:s}".\
                          format(len(response_bytes), response_hash).\
                          encode("ascii") + response_bytes
        self._response = BytesIO(response_packet)

        pmnc.log.debug("returning {0:s}".format(
                       deliver_message.format(len(response_packet))))

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

    @typecheck
    def produce(self, n: int) -> bytes:
        return self._response.read(n)

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

    @typecheck
    def retract(self, n: int):
        self._response.seek(-n, SEEK_CUR)

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

class Resource(TransactionalResource): # RPC resource

    @typecheck
    def __init__(self, name, *,
                 broadcast_address: (str, int),
                 discovery_timeout: float,
                 multiple_timeout_allowance: float,
                 flock_id: valid_flock_id,
                 exact_locations: dict_of(valid_cage_name, valid_exact_location),
                 pool__resource_name: valid_cage_name):

        TransactionalResource.__init__(self, name)

        self._cage_name = pool__resource_name
        self._exact_location = exact_locations.get(self._cage_name)
        self._connect_timeout = discovery_timeout

        if self._exact_location is None:
            broadcast_address, self._broadcast_port = broadcast_address
            self._bind_address, self._broadcast_address = broadcast_address.split("/")
            self._multiple_timeout_allowance = min(multiple_timeout_allowance, 1.0)
            self._request_prefix = "PYTHOMNIC3K-REQUEST:{0:s}:".format(flock_id)
            self._response_prefix = "PYTHOMNIC3K-RESPONSE:{0:s}:".format(flock_id)

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

    def connect(self):

        TransactionalResource.connect(self)

        # discover and establish connection

        connect_timeout = Timeout(min(self._connect_timeout, pmnc.request.remain))
        if self._exact_location is None:
            self._tcp_resource = self._discover(connect_timeout)
        else:
            self._tcp_resource = self._create_tcp_resource(connect_timeout, self._exact_location)
        self._tcp_resource.connect()

        # if the connection was established over SSL, we verify
        # target cage name against the peer's SSL certificate

        if self._tcp_resource.encrypted and \
           not by_regex("^{0:s}$".format(self._tcp_resource.peer_cn))(self._cage_name):
            raise Exception("target cage name does not match its SSL certificate")

        # reset collected module/method attributes

        self._attrs = []

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

    def __getattr__(self, name):
        self._attrs.append(name)
        return self

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

    def __call__(self, *args, **kwargs):

        try:

            attrs, self._attrs = self._attrs, []
            assert len(attrs) == 2, "expected module.method RPC syntax"
            module, method = attrs

            assert not self.resource_args and not self.resource_kwargs, \
                   "synchronous remote calls have no options"

            # wrap up an RPC call and assemble a byte stream

            request_dict = pmnc.request.to_dict()

            # remove request parameters that must not cross the RPC border

            request_dict["parameters"].pop("retry", None)

            # wrap all the call parameters in a plain dict

            request = dict(source_cage = __cage__,
                           target_cage = self._cage_name,
                           module = module, method = method,
                           args = args, kwargs = kwargs,
                           request = request_dict)

            # marshal the call into a packet of bytes

            request_bytes = RpcPacket.marshal(request)
            request_hash = sha1(request_bytes).hexdigest().upper()
            request_packet = "{0:08X}{1:s}".\
                             format(len(request_bytes), request_hash).\
                             encode("ascii") + request_bytes

            self._response = RpcPacket()

            request_description = \
                "RPC request {0:s}.{1:s} to {2:s}, {3:d} byte(s)".\
                format(module, method, self._tcp_resource.server_info,
                       len(request_packet))

            service_request = module == "remote_call" and method == "accept"

        except:
            ResourceError.rethrow(recoverable = True, terminal = False)

        if not service_request: pmnc.log.info("sending {0:s}".format(request_description))
        try:

            response = self._tcp_resource.send_request(request_packet, self.response_handler)
            try:
                result = response["result"]
            except KeyError:
                raise RPCError(description = response["exception"], terminal = False)

        except RPCError as e:
            pmnc.log.warning("{0:s} returned error: {1:s}".\
                             format(request_description, e.description))
            raise
        except:
            pmnc.log.warning("{0:s} failed: {1:s}".\
                             format(request_description, exc_string()))
            raise
        else:
            if not service_request: pmnc.log.info("RPC request returned successfully")
            return result

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

    def response_handler(self, data: bytes) -> optional(dict):
        return self._response.write(data)

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

    def disconnect(self):
        try:
            self._tcp_resource.disconnect()
        finally:
            TransactionalResource.disconnect(self)

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

    def _create_discovery_request(self) -> (bytes, bytes):

        request_id = b2a_hex(urandom(8)).decode("ascii").upper()
        discovery_request = "{0:s}{1:s}:DISCOVER-CAGE:{2:s}".\
                            format(self._request_prefix, request_id, self._cage_name)
        discovery_response_prefix = "{0:s}{1:s}:".format(self._response_prefix, request_id)

        return discovery_request.encode("ascii"), \
               discovery_response_prefix.encode("ascii")

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

    @typecheck
    def _create_tcp_resource(self, timeout: Timeout, discovered_location: valid_location,
                             remote_addr: optional(str) = None):

        if discovered_location[:6] in ("ssl://", "tcp://") and discovered_location[-1] == "/":
            cage_addr, cage_port = discovered_location[6:-1].split(":")
            if cage_addr == "*":
                assert remote_addr is not None
                cage_addr = remote_addr
        else:
            raise Exception("unsupported RPC protocol")

        if discovered_location.startswith("ssl://"):
            ssl_key_cert_file = _locate_key_file("key_cert.pem")
            ssl_ca_cert_file = _locate_key_file("ca_cert.pem")
        elif discovered_location.startswith("tcp://"):
            ssl_key_cert_file = None
            ssl_ca_cert_file = None

        return pmnc.protocol_tcp.TcpResource(self._cage_name,
                                             server_address = (cage_addr, int(cage_port)),
                                             connect_timeout = timeout.remain,
                                             ssl_key_cert_file = ssl_key_cert_file,
                                             ssl_ca_cert_file = ssl_ca_cert_file)

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

    def _estimate_node_count(self) -> int:
        rpc_interface = pmnc.interfaces.get_interface("rpc")
        return rpc_interface and len(rpc_interface.get_nodes(self._cage_name)) or 0

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

    def _discover(self, timeout: Timeout):

        # during discovery we expect to receive as many responses as
        # there are cage instances currently known through advertising

        expected_responses = self._estimate_node_count()

        pmnc.log.debug("discovering cage {0:s}, advertised from {1:d} node(s)".\
                       format(self._cage_name, expected_responses))
        try:

            # if more than one cage is expected to respond, we allow slightly longer
            # initial waiting for responses, controlled by multiple_timeout_allowance

            if expected_responses > 1:
                multiple_timeout_allowance = Timeout(self._multiple_timeout_allowance)

            discovery_request, discovery_response_prefix = self._create_discovery_request()
            received_responses = {}

            # the one-time broadcasting socket must be bound to a random port

            bc_socket = _create_sending_broadcast_socket(self._bind_address)
            try:

                resend_timeout = Timeout(1.0) # broadcast once a second

                while not timeout.expired and not received_responses: # until target cage is discovered or timeout expires

                    # broadcast discovery request

                    bc_socket.sendto(discovery_request, (self._broadcast_address, self._broadcast_port))
                    resend_timeout.reset()

                    # wait for a matching response (there could be more than one)

                    while select([bc_socket], [], [], min(timeout.remain, resend_timeout.remain))[0]:
                        try:

                            packet, (remote_addr, remote_port) = bc_socket.recvfrom(57344)

                            # note that the received packet does not necessarily
                            # contain the discovery response we wait for

                            if remote_port == self._broadcast_port and \
                               packet.startswith(discovery_response_prefix): # but this one is ours

                                # parse the response and append channel instance to the list of discovered

                                discovered_location = packet[len(discovery_response_prefix):].decode("ascii")
                                pmnc.log.debug("received discovery response from {0:s}, cage {1:s} is at {2:s}".\
                                               format(remote_addr, self._cage_name, discovered_location))

                                received_responses[remote_addr] = discovered_location
                                if len(received_responses) >= expected_responses:
                                    break # while select

                            # if some cage instance(s) have already responded, but there are still
                            # more responses to expect, keep waiting within allowance time

                            if received_responses and \
                               (multiple_timeout_allowance.expired or
                                not select([bc_socket], [], [],
                                           min(timeout.remain, resend_timeout.remain,
                                               multiple_timeout_allowance.remain))[0]):
                                break # while select

                        except:
                            pmnc.log.error(exc_string()) # log and ignore

            finally:
                bc_socket.close()

            # if more than one cage instance has been discovered,
            # pick one at random to improve load balancing

            if received_responses:
                remote_addrs = list(received_responses.keys())
                remote_addr = remote_addrs[randint(0, len(remote_addrs) - 1)]
                discovered_location = received_responses[remote_addr]
                tcp_resource = self._create_tcp_resource(timeout, discovered_location, remote_addr)
            else:
                raise Exception("no discovery response from cage {0:s} in {1:.01f} second(s)".\
                                format(self._cage_name, timeout.timeout))

        except:
            pmnc.log.warning("discovery attempt failed: {0:s}".format(exc_string()))
            raise
        else:
            pmnc.log.debug("discovered {0:s}".format(tcp_resource.server_info))
            return tcp_resource

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

def self_test():

    from pmnc.request import fake_request
    from time import sleep
    from pmnc.self_test import active_interface
    from pmnc.resource_pool import TransactionExecutionError

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

    test_interface_config = dict \
    (
    protocol = "rpc",
    random_port = -63000,
    max_connections = 100,
    broadcast_address = ("0.0.0.0/255.255.255.255", 12481),
    flock_id = "SELF_TEST",
    )

    def interface_config(**kwargs):
        result = test_interface_config.copy()
        result.update(kwargs)
        return result

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

    local_addresses, broadcast_port = test_interface_config["broadcast_address"]
    bind_address, broadcast_address = local_addresses.split("/")

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

    def test_create_broadcast_socket():

        s1 = _create_receiving_broadcast_socket(broadcast_port)
        s2 = _create_receiving_broadcast_socket(broadcast_port)
        s = _create_sending_broadcast_socket(bind_address)

        p = urandom(64)
        s.sendto(p, (broadcast_address, broadcast_port))

        assert select([s1], [], [], 3.0)[0] == [s1]
        packet = s1.recvfrom(57344)[0]
        assert packet == p

        assert select([s2], [], [], 3.0)[0] == [s2]
        packet = s2.recvfrom(57344)[0]
        assert packet == p

    test_create_broadcast_socket()

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

    def test_start_stop_interface():

        def process_rpc_request(module, method, args, kwargs):
            pass

        with active_interface("rpc", cage_name = "cage_start_stop", **interface_config(process_rpc_request = process_rpc_request)) as ifc:
            assert ifc.listener_address[0] == bind_address
            assert 63000 <= ifc.listener_address[1] < 64000
            assert ifc._broadcast_port == 12481

    test_start_stop_interface()

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

    def test_create_discovery_request():

        params = pmnc.config_resource_rpc.copy()
        del params["protocol"]           # normally resource.py does this
        del params["pool__idle_timeout"] # normally transaction.py does this
        del params["pool__max_age"]
        r = Resource("test", pool__resource_name = "cage123", **params)

        rq, rsp = r._create_discovery_request()
        rq = rq.decode("ascii"); rsp = rsp.decode("ascii")
        assert by_regex("^PYTHOMNIC3K-REQUEST:SELF_TEST:[0-9A-F]{16}:DISCOVER-CAGE:cage123$")(rq)
        rid = rq.split(":", 4)[2]
        assert rsp == "PYTHOMNIC3K-RESPONSE:SELF_TEST:{0:s}:".format(rid)

    test_create_discovery_request()

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

    def test_discover_once():

        def process_rpc_request(module, method, args, kwargs):
            pass

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_discover_once")) as ifc:

            s = _create_sending_broadcast_socket(bind_address)

            request_id = b2a_hex(urandom(8)).decode("ascii").upper()
            request = "PYTHOMNIC3K-REQUEST:SELF_TEST:{0:s}:DISCOVER-CAGE:{1:s}".\
                      format(request_id, "cage_discover_once").encode("ascii")
            response = "PYTHOMNIC3K-RESPONSE:SELF_TEST:{0:s}:ssl://*:{1:d}/".\
                       format(request_id, ifc.listener_address[1]).encode("ascii")

            for i in range(3):
                s.sendto(request, (broadcast_address, ifc._broadcast_port))
                sleep(0.5)

            t = Timeout(3.0)
            while not t.expired and select([s], [], [], t.remain)[0]:
                packet = s.recvfrom(57344)[0]
                if packet == response:
                    break
            else:
                raise Exception("no discovery response")

    test_discover_once()

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

    def test_advertisement():

        def process_rpc_request(module, method, args, kwargs):
            pass

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_advertisement", ad_periods = (1.0, ))) as ifc:

            assert not ifc.get_cages()
            assert ifc.get_nodes("cage_advertisement") == {}

            timeout = Timeout(5.0)
            while not timeout.expired:
                nodes = ifc.get_nodes("cage_advertisement")
                if nodes:
                    assert len(nodes) == 1
                    loc = nodes["self_test"]
                    assert valid_location(loc)
                    assert loc.endswith(":{0:d}/".format(ifc.listener_address[1]))
                    break
                sleep(1.0)
            else:
                assert False, "should have advertised itself"

        sleep(3.0)
        ifc._purge_known_cages()
        assert ifc.get_cages() == { "cage_advertisement" }
        assert ifc.get_nodes("cage_advertisement") == {}

    test_advertisement()

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

    def test_exact_location():

        def process_rpc_request(module, method, args, kwargs):
            return "been there"

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_exact_location", ad_periods = (1.0, ))) as ifc:

            fake_request(10.0)

            # wait for the cage to be advertised

            nodes = ifc.get_nodes("cage_exact_location")
            while not nodes and not pmnc.request.expired:
                sleep(1.0)
                nodes = ifc.get_nodes("cage_exact_location")
            assert nodes, "should have advertised itself"

            # then initiate connection to the now known exact address

            exact_locations = { "cage_exact_location": nodes["self_test"] }

            resource = pmnc.protocol_rpc.Resource("self_test.cage_exact_location",
                                                  broadcast_address = ("UNUSED/UNUSED", 0),
                                                  discovery_timeout = 3.0,
                                                  multiple_timeout_allowance = 0.0,
                                                  flock_id = "UNUSED",
                                                  exact_locations = exact_locations, # same as in config file
                                                  pool__resource_name = "cage_exact_location")
            resource.connect()
            try:
                resource.begin_transaction("xid", source_module_name = __name__,
                                           transaction_options = {}, resource_args = (),
                                           resource_kwargs = {})
                try:
                    result = resource.module.method()
                except:
                    resource.rollback()
                    raise
                else:
                    resource.commit()
            finally:
                resource.disconnect()

            assert result == "been there"

    test_exact_location()

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

    def test_resource_success():

        def process_rpc_request(module, method, args, kwargs):
            return eval(args[0])

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_resource_success")) as ifc:

            fake_request(10.0)
            pmnc.request.describe("it's my request all right")

            xa = pmnc.transaction.create()
            xa.rpc__cage_resource_success.foo.bar("module, method, args, kwargs", "param", a = "b")
            xa.rpc__cage_resource_success.biz.baz("pmnc.request.to_dict()")
            r1, r2 = xa.execute()

            assert r1 == ("foo", "bar", ("module, method, args, kwargs", "param"), { "a": "b" })

            deadline = r2.pop("deadline")
            assert abs(deadline - (time() + pmnc.request.remain)) < 0.01

            assert r2 == dict(protocol = pmnc.request.protocol,
                              description = "it's my request all right",
                              parameters = dict(auth_tokens = { "source_cage": __cage__ }),
                              interface = pmnc.request.interface,
                              unique_id = pmnc.request.unique_id)

    test_resource_success()

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

    def test_resource_failure():

        def process_rpc_request(module, method, args, kwargs):
            1 / 0

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_resource_failure")) as ifc:

            fake_request(10.0)

            xa = pmnc.transaction.create()
            xa.rpc__cage_resource_failure.foo.bar()
            try:
                xa.execute()
            except RPCError as e:
                assert e.description.startswith("ZeroDivisionError")
            else:
                assert False

    test_resource_failure()

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

    def test_resource_local_timeout():

        def process_rpc_request(module, method, args, kwargs):
            assert 1.5 < pmnc.request.remain < 2.5 # interface timeout takes over the received request timeout
            sleep(3.0)

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_resource_local_timeout", request_timeout = 2.0)) as ifc:

            fake_request(5.0)

            xa = pmnc.transaction.create()
            xa.rpc__cage_resource_local_timeout.foo.bar()
            try:
                xa.execute()
            except ResourceError as e:
                assert str(e).startswith("unexpected eof reading data from cage_resource_local_timeout") # as interface drops the connection
            else:
                assert False

    test_resource_local_timeout()

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

    def test_resource_remote_timeout():

        def process_rpc_request(module, method, args, kwargs):
            assert 2.5 < pmnc.request.remain < 3.5 # inherited remote timeout
            sleep(4.0)

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_resource_remote_timeout")) as ifc:

            fake_request(5.0)
            sleep(2.0)

            xa = pmnc.transaction.create()
            xa.rpc__cage_resource_remote_timeout.foo.bar()
            try:
                xa.execute()
            except (ResourceError, TransactionExecutionError) as e:
                assert str(e).startswith("request deadline reading data from cage_resource_remote_timeout") or \
                       str(e).startswith("request deadline waiting for intermediate result from resource rpc__cage_resource_remote_timeout")
            else:
                assert False

    test_resource_remote_timeout()

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

    def test_pmnc_discovery():

        fake_request(5.0)

        try:
            pmnc("never_existed").foo.bar()
        except ResourceError as e:
            assert str(e) == "no discovery response from cage never_existed in 3.0 second(s)"
            assert e.recoverable and e.terminal
        else:
            assert False

    test_pmnc_discovery()

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

    def test_pmnc_success():

        def process_rpc_request(module, method, args, kwargs):
            return module, method, args, kwargs, pmnc.request.to_dict()

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_pmnc_success")) as ifc:
            fake_request(5.0)
            pmnc.request.describe("yes it is")
            result = pmnc("cage_pmnc_success").foo.bar(1, "foo", biz = "baz")

        module, method, args, kwargs, request = result
        assert module == "foo" and method == "bar" and args == (1, "foo") and kwargs == { "biz": "baz" }

        deadline = request.pop("deadline")
        assert abs(deadline - (time() + pmnc.request.remain)) < 0.01

        assert request == dict \
                          (
                              protocol = pmnc.request.protocol,
                              description = "yes it is",
                              parameters = dict(auth_tokens = { "source_cage": __cage__ }),
                              interface = pmnc.request.interface,
                              unique_id = pmnc.request.unique_id,
                          )

    test_pmnc_success()

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

    def test_pmnc_failure():

        def process_rpc_request(module, method, args, kwargs):
            {}["not-there"]

        with active_interface("rpc", **interface_config(process_rpc_request = process_rpc_request,
                              cage_name = "cage_pmnc_failure")) as ifc:
            fake_request(5.0)
            try:
                pmnc("cage_pmnc_failure").foo.bar()
            except RPCError as e:
                assert e.description.startswith("KeyError(\"'not-there'\") in process_rpc_request()")
                assert not e.recoverable and not e.terminal
            else:
                assert False

    test_pmnc_failure()

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

    def test_two_calls():

        def process_rpc_request1(module, method, args, kwargs):
            assert pmnc.request.parameters["auth_tokens"]["source_cage"] == __cage__
            pmnc.request.parameters["auth_tokens"]["source_cage"] = "set once"
            return pmnc("cage_second").module.second()

        def process_rpc_request2(module, method, args, kwargs):
            return pmnc.request.to_dict()

        with active_interface("rpc1", **interface_config(process_rpc_request = process_rpc_request1,
                              cage_name = "cage_first")) as ifc1:
            with active_interface("rpc2", **interface_config(process_rpc_request = process_rpc_request2,
                                  cage_name = "cage_second")) as ifc2:
                fake_request(10.0)
                result = pmnc("cage_first").foo.bar()

        deadline = result.pop("deadline")
        assert abs(deadline - (time() + pmnc.request.remain)) < 0.01

        assert result == dict(protocol = pmnc.request.protocol,
                              description = None,
                              parameters = dict(auth_tokens = { "source_cage": "set once" }),
                              interface = pmnc.request.interface,
                              unique_id = pmnc.request.unique_id)

    test_two_calls()

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

if __name__ == "__main__": import pmnc.self_test; pmnc.self_test.run()

###############################################################################
# EOF


#!/bin/python3
import random

# Ejercicio de la ruleta

fichas_recuperadas = 0

plata_ganada = 0

fichas_ganadas = 0

fichas = 6 # Fichas iniciales

negros = [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35]

rojos = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34 ,36]

impares = list(range(1,36,2))

pares = list(range(2,37,2))

falta = list(range(1,19,1))

pasa = list(range(19,37,1))

docena_uno = list(range(1,13,1))

docena_dos = list(range(13,25,1))

docena_tres = list(range(25,37,1))

columna_uno = list(range(1,37,3))

columna_dos = list(range(2,37,3))

columna_tres = list(range(3,37,3))

print(" La apuesta en cada momento sera de 1 ficha")

print("\n")

print(" Le apostara al rojo(1) o al negro(2)?")
apuesta_uno = int(input())

print("\n Le apostara a par(1) o impar(2)?")
apuesta_dos = int(input())

print("\n Apostara a que pasa(1) o falta(2)?")
apuesta_tres = int(input())

print("\n A que docena le apostara? 1, 2, o 3?")
apuesta_cuatro = int(input())

print("\n A que columna apostara? 1, 2, o 3?")
apuesta_cinco = int(input())

print("\n A que numero, entre el 0 al 36, apostara?")
apuesta_seis = int(input())

print("\n")

num = random.randint(0,36) # Se elige un numero al azar entre o y 36.

print("El numero que toco es" ,num, "\n") # Se printea la variale que recibio el valor aleatorio.

if num == 0 or apuesta_seis == 0:
    print("\n Esta apuesta se salteara")
elif apuesta_uno == 1 and num in rojos:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta de colores fue acertada")
elif apuesta_uno == 2 and num in negros:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta de colores fue acertada")
else:
    print("\n La apuesta del color no ha sido acertada")

if num == 0 or apuesta_seis == 0:
    print("\n Esta apuesta se salteara")
else:
    if apuesta_dos == 1 and num in pares:
        fichas_ganadas += 1
        fichas_recuperadas += 1
        print("\n La apuesta de par fue acertada")
    elif apuesta_dos == 2 and num in impares:
        fichas_ganadas += 1
        fichas_recuperadas += 1
        print("\n La apuesta de impar fue acertada")
    else:
        print("\n La apuesta de par o impar no fue acertada")

if num == 0 or apuesta_seis == 0:
    print("\n Esta apuesta se salteara")
elif apuesta_tres == 1 and num in pasa:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta de pasa fue acertada")
elif apuesta_tres == 2 and num in falta:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta de falta fue acertada")
else:
    print("\n La apuesta de falta o pasa no fue acertada")

if num == 0 or apuesta_seis == 0:
    print("\n Esta apuesta se salteara")
elif apuesta_cuatro == 1 and num in docena_uno:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta a la docena uno fue acertada")
elif apuesta_cuatro == 2 and num in docena_dos:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta a la docena dos fue acertada")
elif apuesta_cuatro == 3 and num in docena_tres:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta a la docena tres fue acertada")
else:
    print("\n La apuesta de docenas no fue acertada")

if num == 0 or apuesta_seis == 0:
    print("\n Esta apuesta se salteara")
elif apuesta_cinco == 1 and num in columna_uno:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta a la columna uno fue acertada")
elif apuesta_cinco == 2 and num in columna_dos:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta a la columna dos fue acertada")
elif apuesta_cinco == 3 and num in columna_tres:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta a la columna tres fue acertada")
else:
    print("\n La apuesta de la columna no fue acertada")

if num == apuesta_seis:
    fichas_ganadas += 1
    fichas_recuperadas += 1
    print("\n La apuesta del numero pleno fue acertada")
else:
    print("\n La apuesta del numero pleno no fue acertada")

plata_ganada = (fichas_ganadas + fichas_recuperadas) * 100 * 0.95

print("\nSe han recuperado" ,fichas_recuperadas, "fichas. Y se han ganado" ,fichas_ganadas, "fichas.")
print("\nEl valor total de sus fichas descontando el %5 del valor es de $" ,plata_ganada)


import numpy as np
from datetime import datetime

# Function to take raw input
def raw_input_tensor():
    input_data = {
        "VehicleType": input("Vehicle Type : "),
        "Model": input("Model : "),
        "Kilometer": int(input("Kilometer : ")),
        "NotRepaired": input("NotRepaired :"),
        "NumberOfPictures": int(input("Number of Picture :")),
        "FuelType": input("Fuel type : "),
        "RegistrationYear": int(input("Registration Year : ")),
        "RegistrationMonth": int(input("Registration Month : ")),
        "Gearbox": input("Gearbox : "),
        "Brand": input("Brand : "),
        "PostalCode": int(input("Postal Code : ")),
        "Power": int(input("Power : ")),
        "DateCrawled": input("Date Crawled : "),
        "DateCreated": input("Date Created : "),
        "LastSeen": input("Last Seen : ")
    }
    return input_data

# Function to transform the input_tensor into numeric type for prediction
def transform_input_tensor(input_data,encoders):
    date_created_str = input_data['DateCreated']
    date_created_obj = datetime.strptime(date_created_str, '%Y-%m-%d %H:%M:%S')
    input_data['DateCreated_month'] = int(date_created_obj.month)
    input_data['DateCreated_hour'] = int(date_created_obj.hour)
    input_data['DateCreated_day'] = int(date_created_obj.day)
    date_LastSeen_str = input_data['LastSeen']
    date_LastSeen_obj = datetime.strptime(date_LastSeen_str, '%Y-%m-%d %H:%M:%S')
    input_data['LastSeen_hour'] = int(date_LastSeen_obj.hour)
    input_data['LastSeen_month'] = int(date_LastSeen_obj.month)
    input_data['LastSeen_day'] = int(date_LastSeen_obj.day)
    date_DateCrawled_str = input_data['DateCrawled']
    date_DateCrawled_obj = datetime.strptime(date_DateCrawled_str, '%Y-%m-%d %H:%M:%S')
    input_data['DateCrawled_hour'] = int(date_DateCrawled_obj.hour)
    input_data['DateCrawled_day'] = int(date_DateCrawled_obj.day)
    input_data['DateCrawled_month'] = int(date_DateCrawled_obj.month)

    model_encoder = encoders['Model']
    input_data['Model'] = model_encoder.transform([input_data['Model']])

    fueltype_encoder = encoders['FuelType']
    input_data['FuelType'] = fueltype_encoder.transform([input_data['FuelType']])

    brand_encoder = encoders['Brand']
    input_data['Brand'] = brand_encoder.transform([input_data['Brand']])

    vehicletype_encoder = encoders['VehicleType']
    input_data['VehicleType'] = vehicletype_encoder.transform([input_data['VehicleType']])

    if(input_data['NotRepaired']=='yes'):
        input_data['NotRepaired']=1
    else:
        input_data['NotRepaired'] = 0

    if(input_data['Gearbox']=='auto'):
        input_data['Gearbox']=1
    else:
        input_data['Gearbox']=0
    # Deleting the Keys
    del input_data['DateCreated']
    del input_data['LastSeen']
    del input_data['DateCrawled']
    return input_data

def give_input_tensor(features,input_data):
    input_tensor = []
    for f in features:
        input_tensor.append(input_data[f])
    return np.array(input_tensor)


from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

from insta_parser.models import *
from insta_parser.serializers import (
    IgtvHashtagsSerializer,
    HighlightSerializer,
    StoryHashtagsSerializer,
    UserInstagramSerializer,
    StorySerializer,
    IgtvSerializer,
)
from main.models import MusicOneUser

class InstagramDataView(APIView):

    def get(self, request):
        igtv_hashtags_queryset = IgtvHashtag.objects.all()
        highlight_queryset = Highlight.objects.all()
        story_hashtags_queryset = StoryHashtag.objects.all()
        users_queryset = MusicOneUser.objects.all()
        users_serializer = UserInstagramSerializer(users_queryset, many=True)
        igtv_hashtags_serializer = IgtvHashtagsSerializer(igtv_hashtags_queryset, many=True)
        highlight_serializer = HighlightSerializer(highlight_queryset, many=True)
        story_hashtags_serializer = StoryHashtagsSerializer(story_hashtags_queryset, many=True)
        return Response({
            'highlights': highlight_serializer.data,
            'users': users_serializer.data,
            'igtv_hashtags': igtv_hashtags_serializer.data,
            'story_hashtags': story_hashtags_serializer.data,
        })

    def post(self, request):
        input_data = request.data
        igtvs = input_data['igtvs']
        stories = input_data['stories']
        igtv_serializer = IgtvSerializer(data=igtvs, many=True)
        story_serializer = StorySerializer(data=stories, many=True)
        if igtv_serializer.is_valid():
            igtv_serializer.save()
        else:
            return Response(igtv_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        if story_serializer.is_valid():
            story_serializer.save()
        else:
            return Response(story_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        return Response({}, status=status.HTTP_201_CREATED)


import os
import re

studenti={}
bodovi={}
rezultat={}
maxlab=0

with open('studenti.txt','r') as dat:
    for line in dat:
        temp=line.rstrip().split(" ")
        studenti[temp[0]]=[temp[1],temp[2]]

files=os.listdir(".")
for fileName in files:
    match = re.match(r'^Lab_([\d]{2})_g([\d]{2})',fileName)
    if match:
        lab,grupa=int(match.group(1)),int(match.group(2))
        if maxlab < lab: maxlab=lab
        with open(fileName,'r') as f:
            # print("Labos: {} Grupa: {}".format(lab,grupa))
            for line in f:
                temp=line.rstrip().split(" ")
                if temp[0] not in bodovi:
                    bodovi[temp[0]]={} #inicijalizacija
                bodovi[temp[0]][lab]=temp[1]
                # print("{} {} {}".format(temp[0],lab,temp[1]))

s="{0:10} {1:18}".format("JMBAG","Prezime, Ime")
for i in range(1,5):
    s+= "L{0:4}".format(str(i))
print(s)

for jmbag,v in studenti.items():
    pi=v[0]+", "+v[1]
    s="{0:10} {1:18}".format(jmbag,pi)
    for i in range(1,maxlab+1):
        try:
            bod=bodovi[jmbag][i]
            s += "{0:4} ".format(bod)
        except:
            s += "{0:4}".format(" ")
    print(s)


#Create input and output arrays of training patches

#input_arrayfin, output_arrayfin,  bandsin, bandsout are explained in training_preprocessing.py

import math
import numpy as np

def create_patches(output_arrayfin, input_arrayfin, patch_size, bandsin, bandsout):

     #calculate size of padded image (it should be divided with the patch_size without remainder)

     rows=output_arrayfin.shape[0]
     cols=output_arrayfin.shape[1]

     y_size=(math.floor(rows/patch_size) + 1) * patch_size
     x_size=(math.floor(cols/patch_size) + 1) * patch_size

     y_pad= int(y_size - rows)
     x_pad= int(x_size - cols)

     #create padded  input and output images
     input_arraypad=np.float16(np.zeros((rows+y_pad, cols+x_pad, bandsin)))
     input_arraypad[0:rows,0:cols,:]=input_arrayfin

     output_arraypad=np.float16(np.zeros((rows+y_pad, cols+x_pad, bandsout)))
     output_arraypad[0:rows,0:cols,:]=output_arrayfin

     #create input and output training patches
     input_list_patches=[]
     output_list_patches=[]

     for i in range(0, y_size-patch_size, 4): #~50% overlap
        for j in range(0, x_size-patch_size, 4):
            input_list_patches.append(input_arraypad[i:i+patch_size, j:j+patch_size,:])
            output_list_patches.append(output_arraypad[i:i+patch_size, j:j+patch_size,:])

     input_patches=np.zeros((len(input_list_patches),patch_size,patch_size,bandsin))
     output_patches=np.zeros((len(output_list_patches),patch_size,patch_size,bandsout))

     for i in range (len(input_list_patches)):
        input_patches[i,:,:,:] = input_list_patches[i]
        output_patches[i,:,:,:] = output_list_patches[i]

     return input_patches, output_patches


def factorial(n):
    r = 1
    for i in range(2, n + 1):
        r *= i
    return r

ans = 0
N_fac = factorial(int(input()))
for i in str(N_fac)[::-1]:
    if i != '0':
        break
    ans += 1
print(ans)


import argparse
import redis
import time
import random
import string

parser = argparse.ArgumentParser()
parser.add_argument("-i", "--id", help = "App ID. Mandatory (int).")
parser.add_argument("-k", "--key", help = "Key for get it value. Default: value = 'foo'")
parser.add_argument("-t", "--ttl", help = "TTL seconds. Default: value = 60.")
parser.add_argument("-s", "--sleep", help = "Sleep timeout for show refresh cache. Default: value = 5.")
args = parser.parse_args()
id = int(args.id) if args.id else None
if id is None:
    raise Exception("Please set mandatory argument --id. For more details see 'python app.py --help'")
key = args.key if args.key else 'foo'
ttl = int(args.ttl) if args.ttl else 60
sleep = float(args.sleep) if args.sleep else 5.0

ttl_refresh_cache = 0.1 * ttl
ttl_refresh_decision = ttl_refresh_cache / 2

r = redis.Redis(host='localhost', port=6379)

while True:
    ttl_last = r.ttl(name=key)
    print(f"ID: {id}. TTL last: {ttl_last} seconds")
    if ttl_last > ttl_refresh_cache:
        print(f"ID: {id}. Used cache.")
        print(f"ID: {id}. Value: '{r.get(name=key)}'")
    elif ttl_last < 0:
        print(f"ID: {id}. Key '{key}' missed in cache.")
        print(f"ID: {id}. Get value from source.")
        value = ''.join(random.choices(string.ascii_uppercase + string.digits, k=20))
        print(f"ID: {id}. Value: '{value}'")
        r.set(name=key, value=value, ex=ttl)
    else:
        p = (random.randrange((ttl_refresh_cache - ttl_last)*100, ttl_refresh_cache*100, 1) / 100)
        print(f"ID: {id}. Probability: {p}. Decision: value > {ttl_refresh_decision}.")
        #if (random.randrange((ttl_refresh_cache - ttl_last)*100, ttl_refresh_cache*100, 1) / 100) >= ttl_refresh_decision:
        if p >= ttl_refresh_decision:
            print(f"ID: {id}. Used probabilistic cache.")
            print(f"ID: {id}. Get value from source.")
            value = ''.join(random.choices(string.ascii_uppercase + string.digits, k=20))
            print(f"ID: {id}. Value: '{value}'")
            r.set(name=key, value=value, ex=ttl)
        else:
            print(f"ID: {id}. Used cache.")
            print(f"ID: {id}. Value: '{r.get(name=key)}'")
    print('****************************************')
    time.sleep(sleep)


import json
from urllib.error import HTTPError

from lakefs_sdk.exceptions import ApiException

from lakefs_spec.errors import translate_lakefs_error

def test_error_translation() -> None:
    rpath = "repo/ref/ohno.txt"

    # first case: lakeFS API error, 401 unauthorized
    e = ApiException(status=401, reason="unauthorized")
    e.body = json.dumps({"message": "unauthorized"})

    translated_err = translate_lakefs_error(e, rpath=rpath)
    assert isinstance(translated_err, PermissionError)
    assert f"unauthorized: {rpath!r}" in str(translated_err)

    # second case: urllib 403 unauthorized (blockstore put)
    e = HTTPError("any", 403, "forbidden", None, None)  # type: ignore
    translated_err = translate_lakefs_error(e, rpath=rpath)
    assert isinstance(translated_err, PermissionError)
    assert f"forbidden: {rpath!r}" in str(translated_err)

    # third case: lakeFS API error 420 (corresponds to partial IOError)
    e = ApiException(status=420, reason="too many requests")
    e.body = json.dumps({"message": "too many requests"})
    translated_err = translate_lakefs_error(e, rpath=rpath)
    assert isinstance(translated_err, OSError)
    assert f"too many requests: {rpath!r}" in str(translated_err)

    # fourth case: lakeFS API error 400 with a custom message.
    e = ApiException(status=400, reason="bad request")
    e.body = json.dumps({"message": "bad request"})
    message = "oh no!"
    translated_err = translate_lakefs_error(e, message=message)
    assert isinstance(translated_err, OSError)
    assert str(translated_err).endswith(message)


from flask import Flask, request, jsonify
from flask_cors import CORS

from paddle_tokenizer.server import server

app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False
app.config["DEBUG"] = False
CORS(app)

@app.route("/single_tokenizer", methods=["GET"])
def single_tokenizer():
    message = request.args.get("message")

    segment_result = server(message)

    return jsonify(segment_result)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)


from itertools import product
import json
from PyQt5.QtCore import QVariant

from qgis.core import (QgsPointXY,
                       QgsGeometry,
                       QgsFeature,
                       QgsFields,
                       QgsField)

from ..utils import convert

def get_request_point_features(route_dict, row_by_row):
    """
    Processes input point features depending on the layer to layer relation in directions settings

    :param route_dict: all coordinates and ID field values of start and end point layers
    :type route_dict: dict

    :param row_by_row: Specifies whether row-by-row relation or all-by-all has been used.
    :type row_by_row: str

    :returns: tuple of coordinates and ID field value for each routing feature in route_dict
    :rtype: tuple of QgsPointXY and others
    """

    locations_list = list(product(route_dict['start']['geometries'],
                                  route_dict['end']['geometries']))
    values_list = list(product(route_dict['start']['values'],
                               route_dict['end']['values']))

    # If row-by-row in two-layer mode, then only zip the locations
    if row_by_row == 'Row-by-Row':
        locations_list = list(zip(route_dict['start']['geometries'],
                                  route_dict['end']['geometries']))

        values_list = list(zip(route_dict['start']['values'],
                               route_dict['end']['values']))

    for properties in zip(locations_list, values_list):
        # Skip if first and last location are the same
        if properties[0][0] == properties[0][-1]:
            continue

        coordinates = [QgsPointXY(x, y) for x, y in properties[0]]
        values = properties[1]

        yield (coordinates, values)

def get_fields(from_type=QVariant.String, to_type=QVariant.String, from_name="FROM_ID", to_name="TO_ID", line=False):
    """
    Builds output fields for directions response layer.

    :param from_type: field type for 'FROM_ID' field
    :type from_type: QVariant enum

    :param to_type: field type for 'TO_ID' field
    :type to_type: QVariant enum

    :param from_name: field name for 'FROM_ID' field
    :type from_name: str

    :param to_name: field name for 'TO_ID' field
    :type to_name: field name for 'TO_ID' field

    :param line: Specifies whether the output feature is a line or a point
    :type line: boolean

    :returns: fields object to set attributes of output layer
    :rtype: QgsFields
    """

    fields = QgsFields()
    fields.append(QgsField("DIST_KM", QVariant.Double))
    fields.append(QgsField("DURATION_H", QVariant.Double))
    fields.append(QgsField("PROFILE", QVariant.String))
    fields.append(QgsField("OPTIONS", QVariant.String))
    fields.append(QgsField(from_name, from_type))
    if not line:
        fields.append(QgsField(to_name, to_type))

    return fields

def get_output_feature_directions(response, profile, options=None, from_value=None, to_value=None):
    """
    Build output feature based on response attributes for directions endpoint.

    :param response: API response object
    :type response: dict

    :param profile: Transportation mode being used
    :type profile: str

    :param options: Costing option being used.
    :type options: dict

    :param from_value: value of 'FROM_ID' field
    :type from_value: any

    :param to_value: value of 'TO_ID' field
    :type to_value: any

    :returns: Ouput feature with attributes and geometry set.
    :rtype: QgsFeature
    """
    response_mini = response['trip']
    feat = QgsFeature()
    coordinates, distance, duration = [], 0, 0
    for leg in response_mini['legs']:
            coordinates.extend([
                list(reversed(coord))
                for coord in convert.decode_polyline6(leg['shape'])
            ])
            duration += round(leg['summary']['time'] / 3600, 3)
            distance += round(leg['summary']['length'], 3)

    qgis_coords = [QgsPointXY(x, y) for x, y in coordinates]
    feat.setGeometry(QgsGeometry.fromPolylineXY(qgis_coords))
    feat.setAttributes([distance,
                        duration,
                        profile,
                        json.dumps(options),
                        from_value,
                        to_value
                        ])

    return feat


from fastapi import Depends, APIRouter, Request, Response, HTTPException
from fastapi.templating import Jinja2Templates

templates = Jinja2Templates(directory="static")
router = APIRouter()

# catch all get request in path "/app/***" ----------------------------------------------------
@router.get("/app/{rest_of_path:path}")
async def serve_my_app(request: Request, rest_of_path: str):
    return templates.TemplateResponse("index.html", {"request": request, "msg": "Dont send request via addressbar"})

# -----------------------------------------------------------------------------

@router.get("/app")
async def serve_my_app(request: Request):
    return templates.TemplateResponse("index.html", {"request": request, "msg": "Dont send request via addressbar"})


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

@author: enes doruk
"""

n = int(input(' n sayisini gir:  '))

a = []

for i in range(1,n,1):
    a.append(i)

enb = a[1]
enk = a[1]
enbyer =1
enkyer =1

for i in range(2,n,1):

    if a[i]>enb:
        enb = a[i]
        enbyer = i
    if a[i]<enk:
        enk = a[i]
        enk = i

print('enb {}, enbyer {}, enk {}, enkyer {} '.format(enb,enbyer,enk,enkyer))


#Code written in C
#// Conditionals, Boolean expressions, relational operators
#
#include <cs50.h>
#include <stdio.h>
#
#int main(void)
#{
#    // Prompt user for integers
#    int x = get_int("What's x? ");
#    int y = get_int("What's y? ");
#
#    // Compare integers
#    if (x < y)
#    {
#        printf("x is less than y\n");
#    }
#    else if (x > y)
#    {
#        printf("x is greater than y\n");
#    }
#    else
#    {
#        printf("x is equal to y\n");
#    }
#}
#How the same thing is written in Python
# Conditionals, Boolean expressions, relational operators

from cs50 import get_int

# Prompt user for integers
x = get_int("What's x? ")
y = get_int("What's y? ")

# Compare integers
if x < y:
    print("x is less than y")
elif x > y:
    print("x is greater than y")
else:
    print("x is equal to y")

#Code written in C
#// Logical operators
#
#include <cs50.h>
#include <stdio.h>
#
#int main(void)
#{
#    // Prompt user to agree
#    char c = get_char("Do you agree? ");
#
#    // Check whether agreed
#    if (c == 'Y' || c == 'y')
#    {
#        printf("Agreed.\n");
#    }
#    else if (c == 'N' || c == 'n')
#    {
#        printf("Not agreed.\n");
#    }
#}
#Same thing written in Python
# Logical operators
#
#from cs50 import get_string
#
# Prompt user to agree
#s = get_string("Do you agree? ")
#
# Check whether agreed
#if s == "Y" or s == "y":
#    print("Agreed.")
#elif s == "N" or s == "n":
#    print("Not agreed.")
# Logical operators, using lists

from cs50 import get_string

# Prompt user to agree
s = get_string("Do you agree? ")

# Check whether agreed
if s in ["y", "yes"]:
    print("Agreed.")
elif s in ["n", "no"]:
    print("Not agreed.")


from cement import Controller
from cement.utils.version import get_version_banner
from ..core.version import get_version

VERSION_BANNER = """
Add Dependencies and Extensions for Hashicorp Packer %s
%s
""" % (get_version(), get_version_banner())

class Base(Controller):
    class Meta:
        label = 'base'
        description = 'Add Dependencies and Extensions for Hashicorp Packer'
        arguments = [
            (['-v', '--version'],
             {'action': 'version',
              'version': VERSION_BANNER}),
        ]

    def _default(self):
        """Default action if no sub-command is passed."""

        self.app.args.print_help()


from random import*
print("야구게임 입니다.")
print(" 각기 다른 세 정수를 입력하세요.")
try:
    FirstNumber = input("첫 번째 숫자를 입력하세요")
    SecondNumber = input("두 번째 숫자를 입력하세요")
    ThirdNumber = input("세 번째 숫자를 입력하세요")
    int(FirstNumber)
    int(SecondNumber)
    int(ThirdNumber)
    print("{0}, {1}, {2} 을(를) 입력하셨습니다.".format(FirstNumber,SecondNumber,ThirdNumber))
    if FirstNumber == SecondNumber or SecondNumber == ThirdNumber or ThirdNumber == FirstNumber:
        print()
        print()
        print("세 정수가 모두 달라야 합니다!")
except:
    print("정수를 입력하세요!")
group = [int(FirstNumber), int(SecondNumber), int(ThirdNumber)]
# club = [1,2,3,4,5,6,7,8,9]
# a = choice(club)
# b = choice(club)
# c = choice(club)

# if b == a or b == c:
#     b = choice(club)
# if b == a or b == c:
#     b = choice(club)
# if b == a or b == c:
#     b = choice(club)
# if b == a or b == c:
#     b = choice(club)
# if c == a or c == b:
#     c = choice(club)
# if c == a or c == b:
#     c = choice(club)
# if c == a or c == b:
#     c = choice(club)
# if c == a or c == b:
#     c = choice(club)
# if c == a or c == b:
#     c = choice(club)

a,b,c = 2,6,9

def note(a,b,c):
    output = 0
    for i in group:
        if i == a:
            output += 1
        elif i == b:
            output += 1
        elif i == c:
            output += 1
        else:
            pass
    return output

output = note(a,b,c)

if output == 0:
    print("세 수가 모두 같지 않습니다.")
elif output == 1:
    print("하나의 수가 같습니다.")
elif output == 2:
    print("두 수가 같습니다.")
else:
    print("세 수가 모두 같습니다.")


def add_suffix(txt, suffix):
    """add the given to every element in given comma separated list.
    adds suffix before -.

    Example:
    add_suffix("hello,john", "ga:") -> "ga:hello,ga:john"
    """

    if txt is None:
        return None

    elements = txt.split(",")
    elements = ["-" + suffix + e[1:] if e[0] == "-"
            else suffix + e for e in elements]

    return ",".join(elements)


from unittest import TestCase
from unittest.mock import patch, Mock

from samcli.commands.traces.trace_console_consumers import XRayTraceConsoleConsumer

class TestTraceConsoleConsumers(TestCase):
    @patch("samcli.commands.traces.trace_console_consumers.click")
    def test_console_consumer(self, patched_click):
        event = Mock()
        consumer = XRayTraceConsoleConsumer()
        consumer.consume(event)

        patched_click.echo.assert_called_with(event.message)


# -*- coding: utf-8 -*-
"""
Created on Fri Oct 25 11:42:32 2019

@author: dexter
"""
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import glob as glob

class Raman_Spot:
    """An class to store SERS data and analyze it """
    def __init__(self, filename): #initalizes a Raman object from a text file
        #initilize atributes
        self.files_location = "C:/Users/dexte/Box/Kulkarni/Raman/data/Raman_Spectra_Clinical_Samples/Raman_Spectra_Clinical_Samples/20181115-22/"
        self.metadata_values = {}
        self.data_list = []
        self.filename_string = filename
        self.average_spectra = np.zeros((1024,2),dtype=float)

        with open(self.filename_string) as infile: #opens file and then stores
            self.metadata_values = self.get_metadata(infile)
            self.data_list = self.get_file_spectra(infile)

        self.average_spectra = self.get_average()

    def get_metadata(self,file_iterator):
        metadata_values = {} #creates dictionary to return
        for line in file_iterator:
            if(line=="\n"): #determines when metadata ends and spectra data begins
                return metadata_values
            data_name = []
            data_values = []
            colon_encountered = False
            iterline = iter(line)
            for c in iterline:
                if(not colon_encountered and c==":"):
                    colon_encountered = True
                    c = next(iterline)
                    while(c==" "):
                        c = next(iterline) #iterates through all whitespace between key and date
                if (not colon_encountered): #if you are iterating through the key
                    data_name.append(c)
                    continue
                else:
                    if(c=="\n"): #skip newline characters
                        continue
                    data_values.append(c)
                    continue

            metadata_values["".join(data_name)]="".join(data_values) #adds name and value to a dictionary
        print("something is wrong with get_metadata")
        return metadata_values

    def get_file_spectra(self,file_iterator):
        i =0
        data_list = []
        data_array = np.zeros((1024,2),dtype=float) #this is for storing the data

        for line in file_iterator:
            if(line=="\n"): #skips new line characters at the begining of the file
                continue
            splt_line = line.split("	")
            if(len(splt_line) != 3): #skips nondata
                print("I am called")
                print(line)
                continue
            #if you go through one whole dataset  if(len(wavelength_list)!=0 and wavelength<wavelength_list[-1]): #if the wavelengths go back to the start point, restart things
            if(i>=1024):
                data_list.append(data_array)
                data_array = np.zeros((1024,2),dtype=float) #clears data array for next round
                i = 0
            wavelength = float(splt_line[0])
            intensity = float(splt_line[1])
            data_array[i,0] = wavelength
            data_array[i,1] = intensity

            i += 1
        return data_list
    def get_average(self):
        average_data_array = np.zeros((1024,2),dtype=float)
        for arr in self.data_list:
            average_data_array += arr
        average_data_array = average_data_array/len(self.data_list)
        return average_data_array
    def plot_average(self,fig_number=1):
        plt.figure(num=fig_number, figsize=(10, 7.5), dpi=80, facecolor='w', edgecolor='k')
        x = self.average_spectra[:,0]
        y = self.average_spectra[:,1]
        plt.plot(x,y,'-',linewidth=2.0,color='k')
    def plot_all(self):
        plt.figure(num=2, figsize=(10, 7.5), dpi=80, facecolor='w', edgecolor='k')
        x = self.average_spectra[:,0]
        y = self.average_spectra[:,1]
        i = 0
        for d in self.data_list:
           i += 1
           plt.plot(d[:,0],d[:,1],label=i)
        plt.plot(x,y,'-',linewidth=7.0,color='k',label="average")
        plt.legend()

class Raman_Folder:
    def __init__(self,root_location,folder_name):
        self.folder_name = folder_name
        glob_cmd = root_location+folder_name+"*.txt"
        self.file_list = glob.glob(glob_cmd)
        self.raman_spot_dict = {}
        for filename in self.file_list:
            spot_index = filename.find("SPOT",0,len(filename))
            key = filename[spot_index+4:spot_index+7]
            self.raman_spot_dict[key] = Raman_Spot(filename)
    def plot_everything(self):
        avearge_list = []
        name_list = []
        plt.figure(num=None, figsize=(10, 7.5), dpi=80, facecolor='w', edgecolor='k')
        for key, raman_spot in self.raman_spot_dict.items():
            avearge_list.append(raman_spot.get_average())
            name_list.append(key)
        i = 0
        for avg in avearge_list:
            plt.plot(avg[:,0],avg[:,1]+i*100,'-',label=name_list[i]) #offset for visualization
            i+= 1
        plt.legend()
        plt.title(self.folder_name)
    def plot_specific_spot(self,key):
        self.raman_spot_dict[key].plot_average()
        #print(file_list)

#location = "C:/Users/dexte/Box/Kulkarni/Raman/data/Raman_Spectra_Clinical_Samples/Raman_Spectra_Clinical_Samples/20181115-22/"
#file_name = "20191015_SebStripe_20181115-22_trypsin_100x_dilution_on_20mM_Cysteamine_Wash_WetState_60X_4mW_SPOT1_2.txt"
#filename_list= [location,file_name]
#filename_string = "".join(filename_list)
##test = Raman_Spot(filename_string)
#
##testing raman folder class
#
#root_location = location = "C:/Users/dexte/Box/Kulkarni/Raman/data/Raman_Spectra_Clinical_Samples/Raman_Spectra_Clinical_Samples/"
#folder_name = "20181115-22/"
#
#Folder_test = Raman_Folder(root_location,folder_name)
#Folder_test.plot_everything()
#
###spot_index = name.find("SPOT",0,len(name))
##print(name[spot_index+4:spot_index+7])
#test = Raman_Spot(name)

#plt.figure(num=2, figsize=(10, 7.5), dpi=80, facecolor='w', edgecolor='k')
#avgxy = test.get_average()
#i = 0
#for d in test.data_list:
#   i += 1
#   plt.plot(d[:,0],d[:,1],label=i)
#plt.legend()
#plt.plot(avgxy[:,0],avgxy[:,1],'-',linewidth=7.0,color='k')
#
#

#plt.plot(test.wavelength_list,test.intensity_list,'-')
#for i in range(0,len())


#Simple methods to find prime numbers
from math import *

def prime_finder(n):
#Determine whether a number is prime.

    #Check whether proper input type
	if type(n) != int:
		return 'input must be an integer'
	if n < 2:
		return 'input must be greater than or equal to 2'

    #Make initial list of possible divisors from 2 to the square root of n
    #Note that a number greater than the square root of n must be multiplied by a number less than the square root of n to get the product n
	max_divisor = int(sqrt(n))
	divisors = list(range(2,max_divisor+1))

    #Check if the minimum number in the list is a divisor of n, and if so, return "not prime"
    #If not a divisor of n, remove every factor of that divisor from the list and repeat
    #Note that if n is indivisible by that number, n will also be indivisible by every factor of that number
	while len(divisors) > 0:
		first = divisors[0]
		if n%first == 0:
			return 'not prime'
		divisors = [e for e in divisors if e%first != 0]

    #If divisor list emptied without returning "not prime," n is prime
	return 'prime'

def primes_to_n(n):
#Return all primes less than or equal to n.

    #Check whether proper input type
	if type(n) != int:
		return 'input must be an integer'
	if n < 2:
		return 'input must be greater than or equal to 2'

    #Make a list of all integers from 2 to n and an empty list to store prime numbers
	nums = list(range(2,n+1))
	primes = []

    #Cycle through the list by taking the first (minimum) number in it and removing every factor of it from the list
    #After each cycle, the first (minimum) number remaining is prime because it is not a factor of (i.e. is not divisible by) any lower integer
	while len(nums) > 0:
		first = nums[0]
		primes.append(first)
		nums = [e for e in nums if e%first != 0]

	return primes


from unicodedata import normalize

from ._snowball import _Snowball

__all__ = ['SnowballSwedish']

class SnowballSwedish(_Snowball):
    """Snowball Swedish stemmer.

    The Snowball Swedish stemmer is defined at:
    http://snowball.tartarus.org/algorithms/swedish/stemmer.html

    .. versionadded:: 0.3.6
    """

    _vowels = {'a', 'e', 'i', 'o', 'u', 'y', 'ä', 'å', 'ö'}
    _s_endings = {
        'b',
        'c',
        'd',
        'f',
        'g',
        'h',
        'j',
        'k',
        'l',
        'm',
        'n',
        'o',
        'p',
        'r',
        't',
        'v',
        'y',
    }

    def stem(self, word: str) -> str:
        """Return Snowball Swedish stem.

        Parameters
        ----------
        word : str
            The word to stem

        Returns
        -------
        str
            Word stem

        Examples
        --------
        >>> stmr = SnowballSwedish()
        >>> stmr.stem('undervisa')
        'undervis'
        >>> stmr.stem('suspension')
        'suspension'
        >>> stmr.stem('visshet')
        'viss'

        .. versionadded:: 0.1.0
        .. versionchanged:: 0.3.6
            Encapsulated in class

        """
        # lowercase, normalize, and compose
        word = normalize('NFC', word.lower())

        r1_start = min(max(3, self._sb_r1(word)), len(word))

        # Step 1
        _r1 = word[r1_start:]
        if _r1[-7:] == 'heterna':
            word = word[:-7]
        elif _r1[-6:] == 'hetens':
            word = word[:-6]
        elif _r1[-5:] in {
            'anden',
            'heten',
            'heter',
            'arnas',
            'ernas',
            'ornas',
            'andes',
            'arens',
            'andet',
        }:
            word = word[:-5]
        elif _r1[-4:] in {
            'arna',
            'erna',
            'orna',
            'ande',
            'arne',
            'aste',
            'aren',
            'ades',
            'erns',
        }:
            word = word[:-4]
        elif _r1[-3:] in {'ade', 'are', 'ern', 'ens', 'het', 'ast'}:
            word = word[:-3]
        elif _r1[-2:] in {'ad', 'en', 'ar', 'er', 'or', 'as', 'es', 'at'}:
            word = word[:-2]
        elif _r1[-1:] in {'a', 'e'}:
            word = word[:-1]
        elif _r1[-1:] == 's':
            if len(word) > 1 and word[-2] in self._s_endings:
                word = word[:-1]

        # Step 2
        if word[r1_start:][-2:] in {'dd', 'gd', 'nn', 'dt', 'gt', 'kt', 'tt'}:
            word = word[:-1]

        # Step 3
        _r1 = word[r1_start:]
        if _r1[-5:] == 'fullt':
            word = word[:-1]
        elif _r1[-4:] == 'löst':
            word = word[:-1]
        elif _r1[-3:] in {'lig', 'els'}:
            word = word[:-3]
        elif _r1[-2:] == 'ig':
            word = word[:-2]

        return word

if __name__ == '__main__':
    import doctest

    doctest.testmod()


import re
import unittest

import pytest
from cognite.client.data_classes import ContextualizationJob
from cognite.client.exceptions import ModelFailedException

from cognite.experimental import CogniteClient
from cognite.experimental.data_classes import PNIDDetectionList, PNIDDetectResults
from tests.utils import jsgz_load

COGNITE_CLIENT = CogniteClient()
PNIDAPI = COGNITE_CLIENT.pnid_parsing

@pytest.fixture
def mock_detect(rsps):
    response_body = {"jobId": 789, "status": "Queued"}
    rsps.add(
        rsps.POST,
        PNIDAPI._get_base_url_with_base_path() + PNIDAPI._RESOURCE_PATH + "/detect",
        status=200,
        json=response_body,
    )
    yield rsps

@pytest.fixture
def mock_extract_pattern(rsps):
    response_body = {"jobId": 456, "status": "Queued"}
    rsps.add(
        rsps.POST,
        PNIDAPI._get_base_url_with_base_path() + PNIDAPI._RESOURCE_PATH + "/extractpattern",
        status=200,
        json=response_body,
    )
    yield rsps

@pytest.fixture
def mock_convert(rsps):
    response_body = {"jobId": 345, "status": "Queued"}
    rsps.add(
        rsps.POST,
        PNIDAPI._get_base_url_with_base_path() + PNIDAPI._RESOURCE_PATH + "/convert",
        status=200,
        json=response_body,
    )
    yield rsps

@pytest.fixture
def mock_status_detect_ok(rsps):
    response_body = {
        "jobId": 123,
        "status": "Completed",
        "items": [
            {"text": "a", "boundingBox": {"xMin": 0, "xMax": 1, "yMin": 0, "yMax": 1}, "entities": [{"name": "a"}]}
        ],
        "fileId": 123432423,
        "fileExternalId": "123432423",
    }
    rsps.add(
        rsps.GET,
        re.compile(PNIDAPI._get_base_url_with_base_path() + PNIDAPI._RESOURCE_PATH + "/detect" + "/\\d+"),
        status=200,
        json=response_body,
    )
    yield rsps

@pytest.fixture
def mock_status_pattern_ok(rsps):
    response_body = {
        "jobId": 456,
        "status": "Completed",
        "items": [],
        "fileId": 123432423,
        "fileExternalId": "123432423",
    }
    rsps.add(
        rsps.GET,
        re.compile(PNIDAPI._get_base_url_with_base_path() + PNIDAPI._RESOURCE_PATH + "/extractpattern" + "/\\d+"),
        status=200,
        json=response_body,
    )
    yield rsps

@pytest.fixture
def mock_status_convert_ok(rsps):
    response_body = {
        "jobId": 123,
        "status": "Completed",
        "svgUrl": "svg.url.com",
        "pngUrl": "png.url.com",
        "fileId": 123432423,
        "fileExternalId": "123432423",
    }
    rsps.add(
        rsps.GET,
        re.compile(PNIDAPI._get_base_url_with_base_path() + PNIDAPI._RESOURCE_PATH + "/convert" + "/\\d+"),
        status=200,
        json=response_body,
    )
    yield rsps

@pytest.fixture
def mock_status_failed(rsps):
    response_body = {"jobId": 123, "status": "Failed", "errorMessage": "error message"}
    rsps.add(
        rsps.GET,
        re.compile(PNIDAPI._get_base_url_with_base_path() + PNIDAPI._RESOURCE_PATH + "/\\d+"),
        status=200,
        json=response_body,
    )
    yield rsps

class TestPNIDParsing:
    def test_detect_entities_str(self, mock_detect, mock_status_detect_ok):
        entities = ["a", "b"]
        file_id = 123432423
        job = PNIDAPI.detect(
            file_id=file_id, entities=entities, name_mapping={"a": "c"}, partial_match=False, min_tokens=3
        )
        assert isinstance(job, ContextualizationJob)
        assert "items" in job.result
        assert 789 == job.job_id
        assert "Completed" == job.status

        n_detect_calls = 0
        n_status_calls = 0
        for call in mock_detect.calls[1:]:
            if "detect" in call.request.url and call.request.method == "POST":
                n_detect_calls += 1
                assert {
                    "entities": entities,
                    "fileId": file_id,
                    "nameMapping": {"a": "c"},
                    "partialMatch": False,
                    "minTokens": 3,
                    "searchField": "name",
                } == jsgz_load(call.request.body)
            else:
                n_status_calls += 1
                assert "/789" in call.request.url
        assert 1 == n_detect_calls
        assert 1 == n_status_calls

    def test_detect_entities_dict(self, mock_detect, mock_status_detect_ok):
        entities = [{"name": "a"}, {"name": "b"}]
        file_id = 123432423
        job = PNIDAPI.detect(
            file_id=file_id, entities=entities, name_mapping={"a": "c"}, partial_match=False, min_tokens=3
        )
        assert isinstance(job, ContextualizationJob)
        assert "items" in job.result
        assert 789 == job.job_id
        assert "Completed" == job.status

        assert 1 == len(job.matches)
        assert [{"name": "a"}] == job.matches[0].entities
        assert "a" == job.matches[0].text

        n_detect_calls = 0
        n_status_calls = 0
        for call in mock_detect.calls:
            if "detect" in call.request.url and call.request.method == "POST":
                n_detect_calls += 1
                assert {
                    "entities": [{"name": "a"}, {"name": "b"}],
                    "fileId": file_id,
                    "nameMapping": {"a": "c"},
                    "partialMatch": False,
                    "minTokens": 3,
                    "searchField": "name",
                } == jsgz_load(call.request.body)
            else:
                n_status_calls += 1
                assert "/789" in call.request.url
        assert 1 == n_detect_calls
        assert 1 == n_status_calls

    def test_extract_pattern(self, mock_extract_pattern, mock_status_pattern_ok):
        patterns = ["ab{1,2}"]
        file_id = 123432423
        job = PNIDAPI.extract_pattern(file_id=file_id, patterns=patterns)
        assert isinstance(job, ContextualizationJob)
        assert "Queued" == job.status
        assert "items" in job.result
        assert "Completed" == job.status
        assert 456 == job.job_id

        n_extract_pattern_calls = 0
        n_status_calls = 0
        for call in mock_extract_pattern.calls:
            if "extractpattern" in call.request.url and call.request.method == "POST":
                n_extract_pattern_calls += 1
                assert {"patterns": patterns, "fileId": file_id} == jsgz_load(call.request.body)
            else:
                n_status_calls += 1
                assert "/456" in call.request.url
        assert 1 == n_extract_pattern_calls
        assert 1 == n_status_calls

    def test_convert(self, mock_convert, mock_status_convert_ok):
        items = [
            {
                "text": "21-PT-1019",
                "boundingBox": {
                    "xMax": 0.5895183277794608,
                    "xMin": 0.573159648591336,
                    "yMax": 0.3737254901960784,
                    "yMin": 0.3611764705882352,
                },
            }
        ]
        file_id = 123432423
        job = PNIDAPI.convert(file_id=file_id, items=items, grayscale=True)
        assert isinstance(job, ContextualizationJob)
        assert "Queued" == job.status
        assert "svgUrl" in job.result
        assert "Completed" == job.status
        assert 345 == job.job_id

        n_convert_calls = 0
        n_status_calls = 0
        for call in mock_convert.calls:
            if "convert" in call.request.url and call.request.method == "POST":
                n_convert_calls += 1
                assert {
                    "fileId": file_id,
                    "items": items,
                    "grayscale": True,
                } == jsgz_load(call.request.body)
            else:
                n_status_calls += 1
                assert "/345" in call.request.url
        assert 1 == n_convert_calls
        assert 1 == n_status_calls

    def test_file_external_id(self, mock_detect, mock_status_detect_ok):
        entities = [{"name": "a"}, {"name": "b"}]
        file_external_id = "123432423"
        job = PNIDAPI.detect(
            file_external_id=file_external_id,
            entities=entities,
            name_mapping={"a": "c"},
            partial_match=False,
            min_tokens=3,
        )
        assert isinstance(job, PNIDDetectResults)
        assert isinstance(job._repr_html_(), str)
        assert "fileId" in job.result
        assert "fileExternalId" in job.result
        assert file_external_id == job.file_external_id
        assert isinstance(job.matches, PNIDDetectionList)
        assert "Completed" == job.status