"""Selector and proactor event loops for Windows."""

import _overlapped
import _winapi
import errno
import math
import msvcrt
import socket
import struct
import time
import weakref

from . import events
from . import base_subprocess
from . import futures
from . import exceptions
from . import proactor_events
from . import selector_events
from . import tasks
from . import windows_utils
from .log import logger

__all__ = (
    'SelectorEventLoop', 'ProactorEventLoop', 'IocpProactor',
    'DefaultEventLoopPolicy', 'WindowsSelectorEventLoopPolicy',
    'WindowsProactorEventLoopPolicy',
)

NULL = 0
INFINITE = 0xffffffff
ERROR_CONNECTION_REFUSED = 1225
ERROR_CONNECTION_ABORTED = 1236

# Initial delay in seconds for connect_pipe() before retrying to connect
CONNECT_PIPE_INIT_DELAY = 0.001

# Maximum delay in seconds for connect_pipe() before retrying to connect
CONNECT_PIPE_MAX_DELAY = 0.100

class _OverlappedFuture(futures.Future):
    """Subclass of Future which represents an overlapped operation.

    Cancelling it will immediately cancel the overlapped operation.
    """

    def __init__(self, ov, *, loop=None):
        super().__init__(loop=loop)
        if self._source_traceback:
            del self._source_traceback[-1]
        self._ov = ov

    def _repr_info(self):
        info = super()._repr_info()
        if self._ov is not None:
            state = 'pending' if self._ov.pending else 'completed'
            info.insert(1, f'overlapped=<{state}, {self._ov.address:#x}>')
        return info

    def _cancel_overlapped(self):
        if self._ov is None:
            return
        try:
            self._ov.cancel()
        except OSError as exc:
            context = {
                'message': 'Cancelling an overlapped future failed',
                'exception': exc,
                'future': self,
            }
            if self._source_traceback:
                context['source_traceback'] = self._source_traceback
            self._loop.call_exception_handler(context)
        self._ov = None

    def cancel(self, msg=None):
        self._cancel_overlapped()
        return super().cancel(msg=msg)

    def set_exception(self, exception):
        super().set_exception(exception)
        self._cancel_overlapped()

    def set_result(self, result):
        super().set_result(result)
        self._ov = None

class _BaseWaitHandleFuture(futures.Future):
    """Subclass of Future which represents a wait handle."""

    def __init__(self, ov, handle, wait_handle, *, loop=None):
        super().__init__(loop=loop)
        if self._source_traceback:
            del self._source_traceback[-1]
        # Keep a reference to the Overlapped object to keep it alive until the
        # wait is unregistered
        self._ov = ov
        self._handle = handle
        self._wait_handle = wait_handle

        # Should we call UnregisterWaitEx() if the wait completes
        # or is cancelled?
        self._registered = True

    def _poll(self):
        # non-blocking wait: use a timeout of 0 millisecond
        return (_winapi.WaitForSingleObject(self._handle, 0) ==
                _winapi.WAIT_OBJECT_0)

    def _repr_info(self):
        info = super()._repr_info()
        info.append(f'handle={self._handle:#x}')
        if self._handle is not None:
            state = 'signaled' if self._poll() else 'waiting'
            info.append(state)
        if self._wait_handle is not None:
            info.append(f'wait_handle={self._wait_handle:#x}')
        return info

    def _unregister_wait_cb(self, fut):
        # The wait was unregistered: it's not safe to destroy the Overlapped
        # object
        self._ov = None

    def _unregister_wait(self):
        if not self._registered:
            return
        self._registered = False

        wait_handle = self._wait_handle
        self._wait_handle = None
        try:
            _overlapped.UnregisterWait(wait_handle)
        except OSError as exc:
            if exc.winerror != _overlapped.ERROR_IO_PENDING:
                context = {
                    'message': 'Failed to unregister the wait handle',
                    'exception': exc,
                    'future': self,
                }
                if self._source_traceback:
                    context['source_traceback'] = self._source_traceback
                self._loop.call_exception_handler(context)
                return
            # ERROR_IO_PENDING means that the unregister is pending

        self._unregister_wait_cb(None)

    def cancel(self, msg=None):
        self._unregister_wait()
        return super().cancel(msg=msg)

    def set_exception(self, exception):
        self._unregister_wait()
        super().set_exception(exception)

    def set_result(self, result):
        self._unregister_wait()
        super().set_result(result)

class _WaitCancelFuture(_BaseWaitHandleFuture):
    """Subclass of Future which represents a wait for the cancellation of a
    _WaitHandleFuture using an event.
    """

    def __init__(self, ov, event, wait_handle, *, loop=None):
        super().__init__(ov, event, wait_handle, loop=loop)

        self._done_callback = None

    def cancel(self):
        raise RuntimeError("_WaitCancelFuture must not be cancelled")

    def set_result(self, result):
        super().set_result(result)
        if self._done_callback is not None:
            self._done_callback(self)

    def set_exception(self, exception):
        super().set_exception(exception)
        if self._done_callback is not None:
            self._done_callback(self)

class _WaitHandleFuture(_BaseWaitHandleFuture):
    def __init__(self, ov, handle, wait_handle, proactor, *, loop=None):
        super().__init__(ov, handle, wait_handle, loop=loop)
        self._proactor = proactor
        self._unregister_proactor = True
        self._event = _overlapped.CreateEvent(None, True, False, None)
        self._event_fut = None

    def _unregister_wait_cb(self, fut):
        if self._event is not None:
            _winapi.CloseHandle(self._event)
            self._event = None
            self._event_fut = None

        # If the wait was cancelled, the wait may never be signalled, so
        # it's required to unregister it. Otherwise, IocpProactor.close() will
        # wait forever for an event which will never come.
        #
        # If the IocpProactor already received the event, it's safe to call
        # _unregister() because we kept a reference to the Overlapped object
        # which is used as a unique key.
        self._proactor._unregister(self._ov)
        self._proactor = None

        super()._unregister_wait_cb(fut)

    def _unregister_wait(self):
        if not self._registered:
            return
        self._registered = False

        wait_handle = self._wait_handle
        self._wait_handle = None
        try:
            _overlapped.UnregisterWaitEx(wait_handle, self._event)
        except OSError as exc:
            if exc.winerror != _overlapped.ERROR_IO_PENDING:
                context = {
                    'message': 'Failed to unregister the wait handle',
                    'exception': exc,
                    'future': self,
                }
                if self._source_traceback:
                    context['source_traceback'] = self._source_traceback
                self._loop.call_exception_handler(context)
                return
            # ERROR_IO_PENDING is not an error, the wait was unregistered

        self._event_fut = self._proactor._wait_cancel(self._event,
                                                      self._unregister_wait_cb)

class PipeServer(object):
    """Class representing a pipe server.

    This is much like a bound, listening socket.
    """
    def __init__(self, address):
        self._address = address
        self._free_instances = weakref.WeakSet()
        # initialize the pipe attribute before calling _server_pipe_handle()
        # because this function can raise an exception and the destructor calls
        # the close() method
        self._pipe = None
        self._accept_pipe_future = None
        self._pipe = self._server_pipe_handle(True)

    def _get_unconnected_pipe(self):
        # Create new instance and return previous one.  This ensures
        # that (until the server is closed) there is always at least
        # one pipe handle for address.  Therefore if a client attempt
        # to connect it will not fail with FileNotFoundError.
        tmp, self._pipe = self._pipe, self._server_pipe_handle(False)
        return tmp

    def _server_pipe_handle(self, first):
        # Return a wrapper for a new pipe handle.
        if self.closed():
            return None
        flags = _winapi.PIPE_ACCESS_DUPLEX | _winapi.FILE_FLAG_OVERLAPPED
        if first:
            flags |= _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE
        h = _winapi.CreateNamedPipe(
            self._address, flags,
            _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE |
            _winapi.PIPE_WAIT,
            _winapi.PIPE_UNLIMITED_INSTANCES,
            windows_utils.BUFSIZE, windows_utils.BUFSIZE,
            _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
        pipe = windows_utils.PipeHandle(h)
        self._free_instances.add(pipe)
        return pipe

    def closed(self):
        return (self._address is None)

    def close(self):
        if self._accept_pipe_future is not None:
            self._accept_pipe_future.cancel()
            self._accept_pipe_future = None
        # Close all instances which have not been connected to by a client.
        if self._address is not None:
            for pipe in self._free_instances:
                pipe.close()
            self._pipe = None
            self._address = None
            self._free_instances.clear()

    __del__ = close

class _WindowsSelectorEventLoop(selector_events.BaseSelectorEventLoop):
    """Windows version of selector event loop."""

class ProactorEventLoop(proactor_events.BaseProactorEventLoop):
    """Windows version of proactor event loop using IOCP."""

    def __init__(self, proactor=None):
        if proactor is None:
            proactor = IocpProactor()
        super().__init__(proactor)

    def run_forever(self):
        try:
            assert self._self_reading_future is None
            self.call_soon(self._loop_self_reading)
            super().run_forever()
        finally:
            if self._self_reading_future is not None:
                ov = self._self_reading_future._ov
                self._self_reading_future.cancel()
                # self_reading_future was just cancelled so if it hasn't been
                # finished yet, it never will be (it's possible that it has
                # already finished and its callback is waiting in the queue,
                # where it could still happen if the event loop is restarted).
                # Unregister it otherwise IocpProactor.close will wait for it
                # forever
                if ov is not None:
                    self._proactor._unregister(ov)
                self._self_reading_future = None

    async def create_pipe_connection(self, protocol_factory, address):
        f = self._proactor.connect_pipe(address)
        pipe = await f
        protocol = protocol_factory()
        trans = self._make_duplex_pipe_transport(pipe, protocol,
                                                 extra={'addr': address})
        return trans, protocol

    async def start_serving_pipe(self, protocol_factory, address):
        server = PipeServer(address)

        def loop_accept_pipe(f=None):
            pipe = None
            try:
                if f:
                    pipe = f.result()
                    server._free_instances.discard(pipe)

                    if server.closed():
                        # A client connected before the server was closed:
                        # drop the client (close the pipe) and exit
                        pipe.close()
                        return

                    protocol = protocol_factory()
                    self._make_duplex_pipe_transport(
                        pipe, protocol, extra={'addr': address})

                pipe = server._get_unconnected_pipe()
                if pipe is None:
                    return

                f = self._proactor.accept_pipe(pipe)
            except OSError as exc:
                if pipe and pipe.fileno() != -1:
                    self.call_exception_handler({
                        'message': 'Pipe accept failed',
                        'exception': exc,
                        'pipe': pipe,
                    })
                    pipe.close()
                elif self._debug:
                    logger.warning("Accept pipe failed on pipe %r",
                                   pipe, exc_info=True)
            except exceptions.CancelledError:
                if pipe:
                    pipe.close()
            else:
                server._accept_pipe_future = f
                f.add_done_callback(loop_accept_pipe)

        self.call_soon(loop_accept_pipe)
        return [server]

    async def _make_subprocess_transport(self, protocol, args, shell,
                                         stdin, stdout, stderr, bufsize,
                                         extra=None, **kwargs):
        waiter = self.create_future()
        transp = _WindowsSubprocessTransport(self, protocol, args, shell,
                                             stdin, stdout, stderr, bufsize,
                                             waiter=waiter, extra=extra,
                                             **kwargs)
        try:
            await waiter
        except (SystemExit, KeyboardInterrupt):
            raise
        except BaseException:
            transp.close()
            await transp._wait()
            raise

        return transp

class IocpProactor:
    """Proactor implementation using IOCP."""

    def __init__(self, concurrency=0xffffffff):
        self._loop = None
        self._results = []
        self._iocp = _overlapped.CreateIoCompletionPort(
            _overlapped.INVALID_HANDLE_VALUE, NULL, 0, concurrency)
        self._cache = {}
        self._registered = weakref.WeakSet()
        self._unregistered = []
        self._stopped_serving = weakref.WeakSet()

    def _check_closed(self):
        if self._iocp is None:
            raise RuntimeError('IocpProactor is closed')

    def __repr__(self):
        info = ['overlapped#=%s' % len(self._cache),
                'result#=%s' % len(self._results)]
        if self._iocp is None:
            info.append('closed')
        return '<%s %s>' % (self.__class__.__name__, " ".join(info))

    def set_loop(self, loop):
        self._loop = loop

    def select(self, timeout=None):
        if not self._results:
            self._poll(timeout)
        tmp = self._results
        self._results = []
        return tmp

    def _result(self, value):
        fut = self._loop.create_future()
        fut.set_result(value)
        return fut

    def recv(self, conn, nbytes, flags=0):
        self._register_with_iocp(conn)
        ov = _overlapped.Overlapped(NULL)
        try:
            if isinstance(conn, socket.socket):
                ov.WSARecv(conn.fileno(), nbytes, flags)
            else:
                ov.ReadFile(conn.fileno(), nbytes)
        except BrokenPipeError:
            return self._result(b'')

        def finish_recv(trans, key, ov):
            try:
                return ov.getresult()
            except OSError as exc:
                if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
                                    _overlapped.ERROR_OPERATION_ABORTED):
                    raise ConnectionResetError(*exc.args)
                else:
                    raise

        return self._register(ov, conn, finish_recv)

    def recv_into(self, conn, buf, flags=0):
        self._register_with_iocp(conn)
        ov = _overlapped.Overlapped(NULL)
        try:
            if isinstance(conn, socket.socket):
                ov.WSARecvInto(conn.fileno(), buf, flags)
            else:
                ov.ReadFileInto(conn.fileno(), buf)
        except BrokenPipeError:
            return self._result(0)

        def finish_recv(trans, key, ov):
            try:
                return ov.getresult()
            except OSError as exc:
                if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
                                    _overlapped.ERROR_OPERATION_ABORTED):
                    raise ConnectionResetError(*exc.args)
                else:
                    raise

        return self._register(ov, conn, finish_recv)

    def recvfrom(self, conn, nbytes, flags=0):
        self._register_with_iocp(conn)
        ov = _overlapped.Overlapped(NULL)
        try:
            ov.WSARecvFrom(conn.fileno(), nbytes, flags)
        except BrokenPipeError:
            return self._result((b'', None))

        def finish_recv(trans, key, ov):
            try:
                return ov.getresult()
            except OSError as exc:
                if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
                                    _overlapped.ERROR_OPERATION_ABORTED):
                    raise ConnectionResetError(*exc.args)
                else:
                    raise

        return self._register(ov, conn, finish_recv)

    def sendto(self, conn, buf, flags=0, addr=None):
        self._register_with_iocp(conn)
        ov = _overlapped.Overlapped(NULL)

        ov.WSASendTo(conn.fileno(), buf, flags, addr)

        def finish_send(trans, key, ov):
            try:
                return ov.getresult()
            except OSError as exc:
                if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
                                    _overlapped.ERROR_OPERATION_ABORTED):
                    raise ConnectionResetError(*exc.args)
                else:
                    raise

        return self._register(ov, conn, finish_send)

    def send(self, conn, buf, flags=0):
        self._register_with_iocp(conn)
        ov = _overlapped.Overlapped(NULL)
        if isinstance(conn, socket.socket):
            ov.WSASend(conn.fileno(), buf, flags)
        else:
            ov.WriteFile(conn.fileno(), buf)

        def finish_send(trans, key, ov):
            try:
                return ov.getresult()
            except OSError as exc:
                if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
                                    _overlapped.ERROR_OPERATION_ABORTED):
                    raise ConnectionResetError(*exc.args)
                else:
                    raise

        return self._register(ov, conn, finish_send)

    def accept(self, listener):
        self._register_with_iocp(listener)
        conn = self._get_accept_socket(listener.family)
        ov = _overlapped.Overlapped(NULL)
        ov.AcceptEx(listener.fileno(), conn.fileno())

        def finish_accept(trans, key, ov):
            ov.getresult()
            # Use SO_UPDATE_ACCEPT_CONTEXT so getsockname() etc work.
            buf = struct.pack('@P', listener.fileno())
            conn.setsockopt(socket.SOL_SOCKET,
                            _overlapped.SO_UPDATE_ACCEPT_CONTEXT, buf)
            conn.settimeout(listener.gettimeout())
            return conn, conn.getpeername()

        async def accept_coro(future, conn):
            # Coroutine closing the accept socket if the future is cancelled
            try:
                await future
            except exceptions.CancelledError:
                conn.close()
                raise

        future = self._register(ov, listener, finish_accept)
        coro = accept_coro(future, conn)
        tasks.ensure_future(coro, loop=self._loop)
        return future

    def connect(self, conn, address):
        if conn.type == socket.SOCK_DGRAM:
            # WSAConnect will complete immediately for UDP sockets so we don't
            # need to register any IOCP operation
            _overlapped.WSAConnect(conn.fileno(), address)
            fut = self._loop.create_future()
            fut.set_result(None)
            return fut

        self._register_with_iocp(conn)
        # The socket needs to be locally bound before we call ConnectEx().
        try:
            _overlapped.BindLocal(conn.fileno(), conn.family)
        except OSError as e:
            if e.winerror != errno.WSAEINVAL:
                raise
            # Probably already locally bound; check using getsockname().
            if conn.getsockname()[1] == 0:
                raise
        ov = _overlapped.Overlapped(NULL)
        ov.ConnectEx(conn.fileno(), address)

        def finish_connect(trans, key, ov):
            ov.getresult()
            # Use SO_UPDATE_CONNECT_CONTEXT so getsockname() etc work.
            conn.setsockopt(socket.SOL_SOCKET,
                            _overlapped.SO_UPDATE_CONNECT_CONTEXT, 0)
            return conn

        return self._register(ov, conn, finish_connect)

    def sendfile(self, sock, file, offset, count):
        self._register_with_iocp(sock)
        ov = _overlapped.Overlapped(NULL)
        offset_low = offset & 0xffff_ffff
        offset_high = (offset >> 32) & 0xffff_ffff
        ov.TransmitFile(sock.fileno(),
                        msvcrt.get_osfhandle(file.fileno()),
                        offset_low, offset_high,
                        count, 0, 0)

        def finish_sendfile(trans, key, ov):
            try:
                return ov.getresult()
            except OSError as exc:
                if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
                                    _overlapped.ERROR_OPERATION_ABORTED):
                    raise ConnectionResetError(*exc.args)
                else:
                    raise
        return self._register(ov, sock, finish_sendfile)

    def accept_pipe(self, pipe):
        self._register_with_iocp(pipe)
        ov = _overlapped.Overlapped(NULL)
        connected = ov.ConnectNamedPipe(pipe.fileno())

        if connected:
            # ConnectNamePipe() failed with ERROR_PIPE_CONNECTED which means
            # that the pipe is connected. There is no need to wait for the
            # completion of the connection.
            return self._result(pipe)

        def finish_accept_pipe(trans, key, ov):
            ov.getresult()
            return pipe

        return self._register(ov, pipe, finish_accept_pipe)

    async def connect_pipe(self, address):
        delay = CONNECT_PIPE_INIT_DELAY
        while True:
            # Unfortunately there is no way to do an overlapped connect to
            # a pipe.  Call CreateFile() in a loop until it doesn't fail with
            # ERROR_PIPE_BUSY.
            try:
                handle = _overlapped.ConnectPipe(address)
                break
            except OSError as exc:
                if exc.winerror != _overlapped.ERROR_PIPE_BUSY:
                    raise

            # ConnectPipe() failed with ERROR_PIPE_BUSY: retry later
            delay = min(delay * 2, CONNECT_PIPE_MAX_DELAY)
            await tasks.sleep(delay)

        return windows_utils.PipeHandle(handle)

    def wait_for_handle(self, handle, timeout=None):
        """Wait for a handle.

        Return a Future object. The result of the future is True if the wait
        completed, or False if the wait did not complete (on timeout).
        """
        return self._wait_for_handle(handle, timeout, False)

    def _wait_cancel(self, event, done_callback):
        fut = self._wait_for_handle(event, None, True)
        # add_done_callback() cannot be used because the wait may only complete
        # in IocpProactor.close(), while the event loop is not running.
        fut._done_callback = done_callback
        return fut

    def _wait_for_handle(self, handle, timeout, _is_cancel):
        self._check_closed()

        if timeout is None:
            ms = _winapi.INFINITE
        else:
            # RegisterWaitForSingleObject() has a resolution of 1 millisecond,
            # round away from zero to wait *at least* timeout seconds.
            ms = math.ceil(timeout * 1e3)

        # We only create ov so we can use ov.address as a key for the cache.
        ov = _overlapped.Overlapped(NULL)
        wait_handle = _overlapped.RegisterWaitWithQueue(
            handle, self._iocp, ov.address, ms)
        if _is_cancel:
            f = _WaitCancelFuture(ov, handle, wait_handle, loop=self._loop)
        else:
            f = _WaitHandleFuture(ov, handle, wait_handle, self,
                                  loop=self._loop)
        if f._source_traceback:
            del f._source_traceback[-1]

        def finish_wait_for_handle(trans, key, ov):
            # Note that this second wait means that we should only use
            # this with handles types where a successful wait has no
            # effect.  So events or processes are all right, but locks
            # or semaphores are not.  Also note if the handle is
            # signalled and then quickly reset, then we may return
            # False even though we have not timed out.
            return f._poll()

        self._cache[ov.address] = (f, ov, 0, finish_wait_for_handle)
        return f

    def _register_with_iocp(self, obj):
        # To get notifications of finished ops on this objects sent to the
        # completion port, were must register the handle.
        if obj not in self._registered:
            self._registered.add(obj)
            _overlapped.CreateIoCompletionPort(obj.fileno(), self._iocp, 0, 0)
            # XXX We could also use SetFileCompletionNotificationModes()
            # to avoid sending notifications to completion port of ops
            # that succeed immediately.

    def _register(self, ov, obj, callback):
        self._check_closed()

        # Return a future which will be set with the result of the
        # operation when it completes.  The future's value is actually
        # the value returned by callback().
        f = _OverlappedFuture(ov, loop=self._loop)
        if f._source_traceback:
            del f._source_traceback[-1]
        if not ov.pending:
            # The operation has completed, so no need to postpone the
            # work.  We cannot take this short cut if we need the
            # NumberOfBytes, CompletionKey values returned by
            # PostQueuedCompletionStatus().
            try:
                value = callback(None, None, ov)
            except OSError as e:
                f.set_exception(e)
            else:
                f.set_result(value)
            # Even if GetOverlappedResult() was called, we have to wait for the
            # notification of the completion in GetQueuedCompletionStatus().
            # Register the overlapped operation to keep a reference to the
            # OVERLAPPED object, otherwise the memory is freed and Windows may
            # read uninitialized memory.

        # Register the overlapped operation for later.  Note that
        # we only store obj to prevent it from being garbage
        # collected too early.
        self._cache[ov.address] = (f, ov, obj, callback)
        return f

    def _unregister(self, ov):
        """Unregister an overlapped object.

        Call this method when its future has been cancelled. The event can
        already be signalled (pending in the proactor event queue). It is also
        safe if the event is never signalled (because it was cancelled).
        """
        self._check_closed()
        self._unregistered.append(ov)

    def _get_accept_socket(self, family):
        s = socket.socket(family)
        s.settimeout(0)
        return s

    def _poll(self, timeout=None):
        if timeout is None:
            ms = INFINITE
        elif timeout < 0:
            raise ValueError("negative timeout")
        else:
            # GetQueuedCompletionStatus() has a resolution of 1 millisecond,
            # round away from zero to wait *at least* timeout seconds.
            ms = math.ceil(timeout * 1e3)
            if ms >= INFINITE:
                raise ValueError("timeout too big")

        while True:
            status = _overlapped.GetQueuedCompletionStatus(self._iocp, ms)
            if status is None:
                break
            ms = 0

            err, transferred, key, address = status
            try:
                f, ov, obj, callback = self._cache.pop(address)
            except KeyError:
                if self._loop.get_debug():
                    self._loop.call_exception_handler({
                        'message': ('GetQueuedCompletionStatus() returned an '
                                    'unexpected event'),
                        'status': ('err=%s transferred=%s key=%#x address=%#x'
                                   % (err, transferred, key, address)),
                    })

                # key is either zero, or it is used to return a pipe
                # handle which should be closed to avoid a leak.
                if key not in (0, _overlapped.INVALID_HANDLE_VALUE):
                    _winapi.CloseHandle(key)
                continue

            if obj in self._stopped_serving:
                f.cancel()
            # Don't call the callback if _register() already read the result or
            # if the overlapped has been cancelled
            elif not f.done():
                try:
                    value = callback(transferred, key, ov)
                except OSError as e:
                    f.set_exception(e)
                    self._results.append(f)
                else:
                    f.set_result(value)
                    self._results.append(f)

        # Remove unregistered futures
        for ov in self._unregistered:
            self._cache.pop(ov.address, None)
        self._unregistered.clear()

    def _stop_serving(self, obj):
        # obj is a socket or pipe handle.  It will be closed in
        # BaseProactorEventLoop._stop_serving() which will make any
        # pending operations fail quickly.
        self._stopped_serving.add(obj)

    def close(self):
        if self._iocp is None:
            # already closed
            return

        # Cancel remaining registered operations.
        for address, (fut, ov, obj, callback) in list(self._cache.items()):
            if fut.cancelled():
                # Nothing to do with cancelled futures
                pass
            elif isinstance(fut, _WaitCancelFuture):
                # _WaitCancelFuture must not be cancelled
                pass
            else:
                try:
                    fut.cancel()
                except OSError as exc:
                    if self._loop is not None:
                        context = {
                            'message': 'Cancelling a future failed',
                            'exception': exc,
                            'future': fut,
                        }
                        if fut._source_traceback:
                            context['source_traceback'] = fut._source_traceback
                        self._loop.call_exception_handler(context)

        # Wait until all cancelled overlapped complete: don't exit with running
        # overlapped to prevent a crash. Display progress every second if the
        # loop is still running.
        msg_update = 1.0
        start_time = time.monotonic()
        next_msg = start_time + msg_update
        while self._cache:
            if next_msg <= time.monotonic():
                logger.debug('%r is running after closing for %.1f seconds',
                             self, time.monotonic() - start_time)
                next_msg = time.monotonic() + msg_update

            # handle a few events, or timeout
            self._poll(msg_update)

        self._results = []

        _winapi.CloseHandle(self._iocp)
        self._iocp = None

    def __del__(self):
        self.close()

class _WindowsSubprocessTransport(base_subprocess.BaseSubprocessTransport):

    def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
        self._proc = windows_utils.Popen(
            args, shell=shell, stdin=stdin, stdout=stdout, stderr=stderr,
            bufsize=bufsize, **kwargs)

        def callback(f):
            returncode = self._proc.poll()
            self._process_exited(returncode)

        f = self._loop._proactor.wait_for_handle(int(self._proc._handle))
        f.add_done_callback(callback)

SelectorEventLoop = _WindowsSelectorEventLoop

class WindowsSelectorEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
    _loop_factory = SelectorEventLoop

class WindowsProactorEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
    _loop_factory = ProactorEventLoop

DefaultEventLoopPolicy = WindowsProactorEventLoopPolicy


from django.urls import path, include

from comment.api.views import CommentCreateApiView, CommentListApiView, CommentValidateApiView

app_name = "comment"

urlpatterns = [
    path('create/', CommentCreateApiView.as_view(), name='create'),
    path('list/', CommentListApiView.as_view(), name='list'),
    path('validate/<pk>', CommentValidateApiView.as_view(), name='validate'),

]


def readline(f, newline):
    buf = ""
    while True:
        while newline in buf:
            pos = buf.index(newline)
            yield buf[:pos]
            buf = buf[pos + len(newline):]
        chunk = f.read(4096 * 10)
        if not chunk:
            yield buf
            break
        buf += chunk

with open("index.txt") as f:
    for line in readline(f, "{|}"):
        print(line)


# Generated by Django 3.0 on 2021-01-05 14:01

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion

class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Action',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('verb', models.CharField(max_length=255)),
                ('created', models.DateTimeField(auto_now_add=True, db_index=True)),
                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='actions', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'ordering': ('-created',),
            },
        ),
    ]


"""The module defines the abstract interface for resolving container images for tool execution."""
from abc import (
    ABCMeta,
    abstractmethod,
    abstractproperty,
)

from galaxy.util.bunch import Bunch
from galaxy.util.dictifiable import Dictifiable

class ResolutionCache(Bunch):
    """Simple cache for duplicated computation created once per set of requests (likely web request in Galaxy context).

    This should not be assumed to be thread safe - resolution using a given cache should all occur
    one resolution at a time in a single thread.
    """

    mulled_resolution_cache = None

class ContainerResolver(Dictifiable, metaclass=ABCMeta):
    """Description of a technique for resolving container images for tool execution."""

    # Keys for dictification.
    dict_collection_visible_keys = ["resolver_type", "can_uninstall_dependencies", "builds_on_resolution"]
    can_uninstall_dependencies = False
    builds_on_resolution = False
    read_only = True  # not used for containers, but set for when they are used like dependency resolvers

    def __init__(self, app_info=None, **kwds):
        """Default initializer for ``ContainerResolver`` subclasses."""
        self.app_info = app_info
        self.resolver_kwds = kwds

    def _get_config_option(self, key, default=None):
        """Look in resolver-specific settings for option and then fallback to
        global settings.
        """
        if self.app_info and hasattr(self.app_info, key):
            return getattr(self.app_info, key)
        else:
            return default

    @abstractmethod
    def resolve(self, enabled_container_types, tool_info, resolution_cache=None, **kwds):
        """Find a container matching all supplied requirements for tool.

        The supplied argument is a :class:`galaxy.tool_util.deps.containers.ToolInfo` description
        of the tool and its requirements.
        """

    @abstractproperty
    def resolver_type(self):
        """Short label for the type of container resolution."""

    def _container_type_enabled(self, container_description, enabled_container_types):
        """Return a boolean indicating if the specified container type is enabled."""
        return container_description.type in enabled_container_types

    def __str__(self):
        return f"{self.__class__.__name__}[]"


import warnings
from itertools import islice
from types import GeneratorType
from typing import (
    TYPE_CHECKING,
    AbstractSet,
    Any,
    Callable,
    Dict,
    Generator,
    Iterator,
    List,
    Optional,
    Set,
    Tuple,
    Type,
    TypeVar,
    Union,
    no_type_check,
)

from .typing import AnyType, display_as_type
from .version import version_info

if TYPE_CHECKING:
    from inspect import Signature
    from .main import BaseModel, BaseConfig  # noqa: F401
    from .typing import AbstractSetIntStr, DictIntStrAny, IntStr, MappingIntStrAny, ReprArgs  # noqa: F401
    from .fields import ModelField  # noqa: F401
    from .dataclasses import DataclassType  # noqa: F401

__all__ = (
    'import_string',
    'sequence_like',
    'validate_field_name',
    'lenient_issubclass',
    'in_ipython',
    'deep_update',
    'update_not_none',
    'almost_equal_floats',
    'get_model',
    'to_camel',
    'PyObjectStr',
    'Representation',
    'GetterDict',
    'ValueItems',
    'version_info',  # required here to match behaviour in v1.3
)

def import_string(dotted_path: str) -> Any:
    """
    Stolen approximately from django. Import a dotted module path and return the attribute/class designated by the
    last name in the path. Raise ImportError if the import fails.
    """
    from importlib import import_module

    try:
        module_path, class_name = dotted_path.strip(' ').rsplit('.', 1)
    except ValueError as e:
        raise ImportError(f'"{dotted_path}" doesn\'t look like a module path') from e

    module = import_module(module_path)
    try:
        return getattr(module, class_name)
    except AttributeError as e:
        raise ImportError(f'Module "{module_path}" does not define a "{class_name}" attribute') from e

def truncate(v: Union[str], *, max_len: int = 80) -> str:
    """
    Truncate a value and add a unicode ellipsis (three dots) to the end if it was too long
    """
    warnings.warn('`truncate` is no-longer used by pydantic and is deprecated', DeprecationWarning)
    if isinstance(v, str) and len(v) > (max_len - 2):
        # -3 so quote + string + … + quote has correct length
        return (v[: (max_len - 3)] + '…').__repr__()
    try:
        v = v.__repr__()
    except TypeError:
        v = v.__class__.__repr__(v)  # in case v is a type
    if len(v) > max_len:
        v = v[: max_len - 1] + '…'
    return v

def sequence_like(v: AnyType) -> bool:
    return isinstance(v, (list, tuple, set, frozenset, GeneratorType))

def validate_field_name(bases: List[Type['BaseModel']], field_name: str) -> None:
    """
    Ensure that the field's name does not shadow an existing attribute of the model.
    """
    for base in bases:
        if getattr(base, field_name, None):
            raise NameError(
                f'Field name "{field_name}" shadows a BaseModel attribute; '
                f'use a different field name with "alias=\'{field_name}\'".'
            )

def lenient_issubclass(cls: Any, class_or_tuple: Union[AnyType, Tuple[AnyType, ...]]) -> bool:
    return isinstance(cls, type) and issubclass(cls, class_or_tuple)

def in_ipython() -> bool:
    """
    Check whether we're in an ipython environment, including jupyter notebooks.
    """
    try:
        eval('__IPYTHON__')
    except NameError:
        return False
    else:  # pragma: no cover
        return True

KeyType = TypeVar('KeyType')

def deep_update(mapping: Dict[KeyType, Any], updating_mapping: Dict[KeyType, Any]) -> Dict[KeyType, Any]:
    updated_mapping = mapping.copy()
    for k, v in updating_mapping.items():
        if k in mapping and isinstance(mapping[k], dict) and isinstance(v, dict):
            updated_mapping[k] = deep_update(mapping[k], v)
        else:
            updated_mapping[k] = v
    return updated_mapping

def update_not_none(mapping: Dict[Any, Any], **update: Any) -> None:
    mapping.update({k: v for k, v in update.items() if v is not None})

def almost_equal_floats(value_1: float, value_2: float, *, delta: float = 1e-8) -> bool:
    """
    Return True if two floats are almost equal
    """
    return abs(value_1 - value_2) <= delta

def generate_model_signature(
    init: Callable[..., None], fields: Dict[str, 'ModelField'], config: Type['BaseConfig']
) -> 'Signature':
    """
    Generate signature for model based on its fields
    """
    from inspect import Parameter, Signature, signature

    present_params = signature(init).parameters.values()
    merged_params: Dict[str, Parameter] = {}
    var_kw = None
    use_var_kw = False

    for param in islice(present_params, 1, None):  # skip self arg
        if param.kind is param.VAR_KEYWORD:
            var_kw = param
            continue
        merged_params[param.name] = param

    if var_kw:  # if custom init has no var_kw, fields which are not declared in it cannot be passed through
        allow_names = config.allow_population_by_field_name
        for field_name, field in fields.items():
            param_name = field.alias
            if field_name in merged_params or param_name in merged_params:
                continue
            elif not param_name.isidentifier():
                if allow_names and field_name.isidentifier():
                    param_name = field_name
                else:
                    use_var_kw = True
                    continue

            # TODO: replace annotation with actual expected types once #1055 solved
            kwargs = {'default': field.default} if not field.required else {}
            merged_params[param_name] = Parameter(
                param_name, Parameter.KEYWORD_ONLY, annotation=field.outer_type_, **kwargs
            )

    if config.extra is config.extra.allow:
        use_var_kw = True

    if var_kw and use_var_kw:
        # Make sure the parameter for extra kwargs
        # does not have the same name as a field
        default_model_signature = [
            ('__pydantic_self__', Parameter.POSITIONAL_OR_KEYWORD),
            ('data', Parameter.VAR_KEYWORD),
        ]
        if [(p.name, p.kind) for p in present_params] == default_model_signature:
            # if this is the standard model signature, use extra_data as the extra args name
            var_kw_name = 'extra_data'
        else:
            # else start from var_kw
            var_kw_name = var_kw.name

        # generate a name that's definitely unique
        while var_kw_name in fields:
            var_kw_name += '_'
        merged_params[var_kw_name] = var_kw.replace(name=var_kw_name)

    return Signature(parameters=list(merged_params.values()), return_annotation=None)

def get_model(obj: Union[Type['BaseModel'], Type['DataclassType']]) -> Type['BaseModel']:
    from .main import BaseModel  # noqa: F811

    try:
        model_cls = obj.__pydantic_model__  # type: ignore
    except AttributeError:
        model_cls = obj

    if not issubclass(model_cls, BaseModel):
        raise TypeError('Unsupported type, must be either BaseModel or dataclass')
    return model_cls

def to_camel(string: str) -> str:
    return ''.join(word.capitalize() for word in string.split('_'))

class PyObjectStr(str):
    """
    String class where repr doesn't include quotes. Useful with Representation when you want to return a string
    representation of something that valid (or pseudo-valid) python.
    """

    def __repr__(self) -> str:
        return str(self)

class Representation:
    """
    Mixin to provide __str__, __repr__, and __pretty__ methods. See #884 for more details.

    __pretty__ is used by [devtools](https://python-devtools.helpmanual.io/) to provide human readable representations
    of objects.
    """

    __slots__: Tuple[str, ...] = tuple()

    def __repr_args__(self) -> 'ReprArgs':
        """
        Returns the attributes to show in __str__, __repr__, and __pretty__ this is generally overridden.

        Can either return:
        * name - value pairs, e.g.: `[('foo_name', 'foo'), ('bar_name', ['b', 'a', 'r'])]`
        * or, just values, e.g.: `[(None, 'foo'), (None, ['b', 'a', 'r'])]`
        """
        attrs = ((s, getattr(self, s)) for s in self.__slots__)
        return [(a, v) for a, v in attrs if v is not None]

    def __repr_name__(self) -> str:
        """
        Name of the instance's class, used in __repr__.
        """
        return self.__class__.__name__

    def __repr_str__(self, join_str: str) -> str:
        return join_str.join(repr(v) if a is None else f'{a}={v!r}' for a, v in self.__repr_args__())

    def __pretty__(self, fmt: Callable[[Any], Any], **kwargs: Any) -> Generator[Any, None, None]:
        """
        Used by devtools (https://python-devtools.helpmanual.io/) to provide a human readable representations of objects
        """
        yield self.__repr_name__() + '('
        yield 1
        for name, value in self.__repr_args__():
            if name is not None:
                yield name + '='
            yield fmt(value)
            yield ','
            yield 0
        yield -1
        yield ')'

    def __str__(self) -> str:
        return self.__repr_str__(' ')

    def __repr__(self) -> str:
        return f'{self.__repr_name__()}({self.__repr_str__(", ")})'

class GetterDict(Representation):
    """
    Hack to make object's smell just enough like dicts for validate_model.

    We can't inherit from Mapping[str, Any] because it upsets cython so we have to implement all methods ourselves.
    """

    __slots__ = ('_obj',)

    def __init__(self, obj: Any):
        self._obj = obj

    def __getitem__(self, key: str) -> Any:
        try:
            return getattr(self._obj, key)
        except AttributeError as e:
            raise KeyError(key) from e

    def get(self, key: Any, default: Any = None) -> Any:
        return getattr(self._obj, key, default)

    def extra_keys(self) -> Set[Any]:
        """
        We don't want to get any other attributes of obj if the model didn't explicitly ask for them
        """
        return set()

    def keys(self) -> List[Any]:
        """
        Keys of the pseudo dictionary, uses a list not set so order information can be maintained like python
        dictionaries.
        """
        return list(self)

    def values(self) -> List[Any]:
        return [self[k] for k in self]

    def items(self) -> Iterator[Tuple[str, Any]]:
        for k in self:
            yield k, self.get(k)

    def __iter__(self) -> Iterator[str]:
        for name in dir(self._obj):
            if not name.startswith('_'):
                yield name

    def __len__(self) -> int:
        return sum(1 for _ in self)

    def __contains__(self, item: Any) -> bool:
        return item in self.keys()

    def __eq__(self, other: Any) -> bool:
        return dict(self) == dict(other.items())  # type: ignore

    def __repr_args__(self) -> 'ReprArgs':
        return [(None, dict(self))]  # type: ignore

    def __repr_name__(self) -> str:
        return f'GetterDict[{display_as_type(self._obj)}]'

class ValueItems(Representation):
    """
    Class for more convenient calculation of excluded or included fields on values.
    """

    __slots__ = ('_items', '_type')

    def __init__(self, value: Any, items: Union['AbstractSetIntStr', 'MappingIntStrAny']) -> None:
        if TYPE_CHECKING:
            self._items: Union['AbstractSetIntStr', 'MappingIntStrAny']
            self._type: Type[Union[set, dict]]  # type: ignore

        # For further type checks speed-up
        if isinstance(items, dict):
            self._type = dict
        elif isinstance(items, AbstractSet):
            self._type = set
        else:
            raise TypeError(f'Unexpected type of exclude value {items.__class__}')

        if isinstance(value, (list, tuple)):
            try:
                items = self._normalize_indexes(items, len(value))
            except TypeError as e:
                raise TypeError(
                    'Excluding fields from a sequence of sub-models or dicts must be performed index-wise: '
                    'expected integer keys or keyword "__all__"'
                ) from e

        self._items = items

    @no_type_check
    def is_excluded(self, item: Any) -> bool:
        """
        Check if item is fully excluded
        (value considered excluded if self._type is set and item contained in self._items
         or self._type is dict and self._items.get(item) is ...

        :param item: key or index of a value
        """
        if self._type is set:
            return item in self._items
        return self._items.get(item) is ...

    @no_type_check
    def is_included(self, item: Any) -> bool:
        """
        Check if value is contained in self._items

        :param item: key or index of value
        """
        return item in self._items

    @no_type_check
    def for_element(self, e: 'IntStr') -> Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']]:
        """
        :param e: key or index of element on value
        :return: raw values for elemet if self._items is dict and contain needed element
        """

        if self._type is dict:
            item = self._items.get(e)
            return item if item is not ... else None
        return None

    @no_type_check
    def _normalize_indexes(
        self, items: Union['AbstractSetIntStr', 'MappingIntStrAny'], v_length: int
    ) -> Union['AbstractSetIntStr', 'DictIntStrAny']:
        """
        :param items: dict or set of indexes which will be normalized
        :param v_length: length of sequence indexes of which will be

        >>> self._normalize_indexes({0, -2, -1}, 4)
        {0, 2, 3}
        >>> self._normalize_indexes({'__all__'}, 4)
        {0, 1, 2, 3}
        """
        if self._type is set:
            if '__all__' in items:
                if items != {'__all__'}:
                    raise ValueError('set with keyword "__all__" must not contain other elements')
                return {i for i in range(v_length)}
            return {v_length + i if i < 0 else i for i in items}
        else:
            normalized_items = {v_length + i if i < 0 else i: v for i, v in items.items() if i != '__all__'}
            all_set = items.get('__all__')
            if all_set:
                for i in range(v_length):
                    normalized_items.setdefault(i, set()).update(all_set)

            return normalized_items

    def __repr_args__(self) -> 'ReprArgs':
        return [(None, self._items)]


#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
from flask import Blueprint, render_template

about_blueprint = Blueprint('about', __name__)

@about_blueprint.route("/catalog/about")
def about():
    """Show about page."""
    return render_template("about.html")


#    _____           ______  _____
#  / ____/    /\    |  ____ |  __ \
# | |        /  \   | |__   | |__) | Caer - Modern Computer Vision
# | |       / /\ \  |  __|  |  _  /  Languages: Python, C, C++, Cuda
# | |___   / ____ \ | |____ | | \ \  http://github.com/jasmcaus/caer
#  \_____\/_/    \_ \______ |_|  \_\

# Licensed under the MIT License <http://opensource.org/licenses/MIT>
# SPDX-License-Identifier: MIT
# Copyright (c) 2020-2021 The Caer Authors <http://github.com/jasmcaus>

from threading import Thread
import time
import math
from queue import Queue
import cv2 as cv

from .constants import FRAME_COUNT, FPS

__all__ = [
    'GPUFileStream'
]

class GPUFileStream:
    r"""
        This is an auxiliary class that enables Video Streaming using the GPU for caer with minimalistic latency, and at the expense of little to no additional computational requirements.

        The basic idea behind it is to tracks and save the salient feature array for the given number of frames and then uses these anchor point to cancel out all perturbations relative to it for the incoming frames in the queue. This class relies heavily on **Threaded Queue mode** for error-free & ultra-fast frame handling.

    Args:
        source (int, str): Source path for the video. If ``source=0``, the default camera device is used. For
            multiple external camera devices, use incremented values. For eg: ``source=1`` represents the second camera device on your system.
        qsize (int): Default queue size for handling the video streams. Default: 128.
    """

    def __init__(self, source, qsize=128):
        """
            Source must be a path to a video file
            Utilizes your system's GPU to process the stream
        """

        if not isinstance(source, str):
            raise ValueError(f'Expected either a filepath. Got {type(source)}. Consider using VideoStream which supports both live video as well as pre-existing videos')

        # initialize the file video stream along with the boolean
        # used to indicate if the thread should be stopped or not
        self.stream = cv.VideoCapture(source)
        self.kill_stream = False
        self.count = 0

        # initialize the queue to store frames
        self.Q = Queue(maxsize=qsize)

        self.width = int(self.stream.get(cv.CAP_PROP_FRAME_WIDTH))
        self.height = int(self.stream.get(cv.CAP_PROP_FRAME_HEIGHT))
        self.res = (self.width, self.height)

        self.fps = math.ceil(self.stream.get(FPS))
        self.frames = int(self.stream.get(FRAME_COUNT))

        # since we use UMat to store the images to
        # we need to initialize them beforehand
        self.qframes = [0] * qsize
        for ii in range(qsize):
            self.qframes[ii] = cv.UMat(self.height, self.width, cv.CV_8UC3)

    def begin_stream(self):
        # start a thread to read frames from the file video stream
        t = Thread(target=self.update, args=())
        t.daemon = True
        t.start()
        return self

    def update(self):
        # keep looping infinitely
        while True:
            if self.kill_stream:
                return

            # otherwise, ensure the queue has room in it
            if not self.Q.full():
                self.count += 1
                target = (self.count-1) % self.Q.maxsize
                ret = self.stream.grab()

                if not ret:
                    self.release()
                    return

                self.stream.retrieve(self.qframes[target])

                # add the frame to the queue
                self.Q.put(target)

    def read(self):
        while (not self.more() and self.kill_stream):
            time.sleep(0.1)
        # return next frame in the queue
        return self.qframes[self.Q.get()]

    def more(self):
        # return True if there are still frames in the queue
        return self.Q.qsize() > 0

    def release(self):
        self.kill_stream = True
        # wait until stream resources are released
        self.thread.join()

    # Gets frame count
    def count_frames(self):
        if not self.kill_stream and not self.live_video:
            return self.frames
            # if get_opencv_version() == '2':
            #     return int(self.stream.get(FRAME_COUNT_DEPR))
            # else:
            #     return int(self.stream.get(FRAME_COUNT))

        if self.live_video:
            print('[WARNING] Frames cannot be computed on live streams')
            return -1

    # Gets FPS count
    def get_fps(self):
        if not self.kill_stream:
            return self.fps

    # Get frame dimensions
    def get_res(self):
        return self.res


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('api', '0007_apirequest_extra'),
    ]

    operations = [
        migrations.AddField(
            model_name='apirequest',
            name='api_client',
            field=models.CharField(null=True, editable=False, max_length=50),
            preserve_default=True,
        ),
    ]


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

import pytest

import random
import string
import itertools as itt
import collections

import spiceminer as sm
import spiceminer.kernel.lowlevel as lowlevel

### Helpers ###
def rstrings(max_size):
    while True:
        yield ''.join(random.sample(string.lowercase, random.randint(1, max_size)))

class FakeKernel(object):
    def __init__(self, path):
        self.path = path
        self.loaded = True

    def _unload(self):
        self.loaded = False

@pytest.fixture(scope='function')
def fake_LOADED(kernelfiles, monkeypatch):
    available = random.sample(kernelfiles, random.randint(0, len(kernelfiles)))
    substitute = {FakeKernel(path) for path in available}
    monkeypatch.setattr(lowlevel, 'LOADED_KERNELS', substitute)
    return substitute

@pytest.fixture(scope='function')
def fake_loaders(monkeypatch):
    '''Patch lowlevel loader functions to rerturn dummy results.'''
    def fake_loader(path):
        windows = {'ABC': 'Test'}
        return windows
    for func in ('_load_sp', '_load_pc', '_load_c', '_load_f'):
        monkeypatch.setattr(lowlevel, func, fake_loader)

@pytest.fixture(scope='function')
def fake_furnsh(monkeypatch):
    monkeypatch.setattr(lowlevel.spice, 'furnsh', lambda x: None)
    monkeypatch.setattr(lowlevel.spice, 'unload', lambda x: None)

### Tests ###
class TestKernelProperties(object):
    def test_kp_good(self, kernelfile):
        kprops = lowlevel.kernel_properties(kernelfile)
        assert kprops.path == kernelfile
        assert kprops.arch in lowlevel.ARCH
        assert kprops.type in lowlevel.KTYPE

    def test_kp_bad(self, nonkernelfile):
        with pytest.raises((ValueError, sm.SpiceError)):
            kprops = lowlevel.kernel_properties(nonkernelfile)

@pytest.mark.parametrize('ktype', list(lowlevel.KTYPE) + list(
    set(itt.islice(rstrings(10), 5)) - lowlevel.KTYPE
))
def test_info_type(ktype):
    info = lowlevel._info_type(ktype)
    if ktype in lowlevel.KTYPE:
        assert info in ('pos', 'rot', 'none')
    else:
        assert info == None

xValueError = pytest.mark.xfail(raises=ValueError)
@pytest.mark.parametrize('arch', list(lowlevel.ARCH) + [xValueError('?')])
@pytest.mark.parametrize('ktype', list(lowlevel.KTYPE) + [
    xValueError(next(rstrings(10)))
])
def test_validate(arch, ktype):
    lowlevel._validate('Test', arch, ktype)

@pytest.mark.parametrize('recursive', [True, False])
def test_icollect_kprops(datadir, kernelfiles, recursive):
    paths = set(kp.path for kp in lowlevel.icollect_kprops(datadir, recursive, False))
    if not recursive:
        assert len(paths) < len(kernelfiles)
    assert paths - set(kernelfiles) == set()

def test_ifilter_kprops(kernelfiles, fake_LOADED):
    kp = collections.namedtuple('KernelPath', 'path')
    result = lowlevel.ifilter_kprops(kp(path) for path in kernelfiles)
    result_paths = set(kprops.path for kprops in result)
    fake_paths = set(k.path for k in fake_LOADED)
    assert result_paths.symmetric_difference(fake_paths) == set(kernelfiles)

def test_iunload_kprops(kernelfiles, fake_LOADED):
    kp = collections.namedtuple('KernelPath', 'path')
    result = lowlevel.iunload_kprops(kp(path) for path in kernelfiles)
    result_paths = set(kprops.path for kprops in result)
    assert result_paths == set(kernelfiles)
    unloaded_paths = {k.path for k in fake_LOADED if not k.loaded}
    assert len(unloaded_paths) == len(fake_LOADED)

@pytest.mark.parametrize('types', [
    [random.choice(list(lowlevel.KTYPE)) for i in range(10)]
])
def test_split_kprops(types):
    kt = collections.namedtuple('KernelType', 'type')
    kpmisc, kpbody = lowlevel.split_kprops(kt(t) for t in types)
    body_types = {kt.type for kt in kpbody}
    misc_types = {kt.type for kt in kpmisc}
    assert body_types.union(lowlevel.KTYPE_BODY) == lowlevel.KTYPE_BODY
    assert misc_types.intersection(lowlevel.KTYPE_BODY) == set()
    assert body_types.union(misc_types) == set(types)

@pytest.mark.usefixtures('fake_loaders', 'fake_furnsh')
def test_load_any(kernelfile):
    kp = collections.namedtuple('KernelProperties', ['path', 'type'])
    kprops = kp(kernelfile, random.choice(list(lowlevel.KTYPE)))
    time_window_map = lowlevel.load_any(kprops)
    if kprops.type in lowlevel.KTYPE_BODY:
        assert time_window_map == {'ABC': 'Test'}
    else:
        assert time_window_map == {}

def test_unload_any():
    pass

@pytest.mark.parametrize('path', ['.'])
def test_load_dummy(path):
    assert lowlevel._load_dummy(path) == {}

@pytest.mark.usefixtures('with_leapseconds')
def test_load_sp(spfile):
    time_window_map = lowlevel._load_sp(spfile)
    assert time_window_map != {}

@pytest.mark.usefixtures('with_leapseconds', 'with_spacecraftclock')
def test_load_c(cfile):
    time_window_map = lowlevel._load_c(cfile)
    assert time_window_map != {}

@pytest.mark.usefixtures('with_leapseconds')
def test_load_pc(pcfile):
    time_window_map = lowlevel._load_pc(pcfile)
    assert time_window_map != {}

@pytest.mark.usefixtures('with_leapseconds')
def test_load_f(ffile):
    time_window_map = lowlevel._load_f(ffile)
    assert time_window_map != {}


def myprint():

    print('myprint: ' + s)

s = 'I am global variable'
print(s)
myprint()


from typing import Any, Dict

from dbt.contracts.connection import HasCredentials

from dbt.context.base import (
    BaseContext, contextproperty
)

class TargetContext(BaseContext):
    # subclass is ConfiguredContext
    def __init__(self, config: HasCredentials, cli_vars: Dict[str, Any]):
        super().__init__(cli_vars=cli_vars)
        self.config = config

    @contextproperty
    def target(self) -> Dict[str, Any]:
        """`target` contains information about your connection to the warehouse
        (specified in profiles.yml). Some configs are shared between all
        adapters, while others are adapter-specific.

        Common:

            |----------|-----------|------------------------------------------|
            | Variable |  Example  |                Description               |
            |----------|-----------|------------------------------------------|
            |   name   |    dev    | Name of the active target                |
            |----------|-----------|------------------------------------------|
            |  schema  | dbt_alice | Name of the dbt schema (or, dataset on   |
            |          |           | BigQuery)                                |
            |----------|-----------|------------------------------------------|
            |   type   |  postgres | The active adapter being used.           |
            |----------|-----------|------------------------------------------|
            | threads  |    4      | The number of threads in use by dbt      |
            |----------|-----------|------------------------------------------|

        Snowflake:

            |----------|-----------|------------------------------------------|
            | Variable |  Example  |                Description               |
            |----------|-----------|------------------------------------------|
            | database |    RAW    | The active target's database.            |
            |----------|-----------|------------------------------------------|
            | warehouse| TRANSFORM | The active target's warehouse.           |
            |----------|-----------|------------------------------------------|
            |   user   |  USERNAME | The active target's user                 |
            |----------|-----------|------------------------------------------|
            | role     |  ROLENAME | The active target's role                 |
            |----------|-----------|------------------------------------------|
            | account  |  abc123   | The active target's account              |
            |----------|-----------|------------------------------------------|

        Postgres/Redshift:

            |----------|-------------------|----------------------------------|
            | Variable |  Example          |        Description               |
            |----------|-------------------|----------------------------------|
            |  dbname  | analytics         | The active target's database.    |
            |----------|-------------------|----------------------------------|
            |  host    | abc123.us-west-2. | The active target's host.        |
            |          | redshift.amazonaws|                                  |
            |          |  .com             |                                  |
            |----------|-------------------|----------------------------------|
            |   user   |  dbt_user         |  The active target's user        |
            |----------|-------------------|----------------------------------|
            |   port   |    5439           | The active target's port         |
            |----------|-------------------|----------------------------------|

        BigQuery:

            |----------|-----------|------------------------------------------|
            | Variable |  Example  |                Description               |
            |----------|-----------|------------------------------------------|
            | project  |  abc-123  | The active target's project.             |
            |----------|-----------|------------------------------------------|

        """
        return self.config.to_target_dict()

def generate_target_context(
    config: HasCredentials, cli_vars: Dict[str, Any]
) -> Dict[str, Any]:
    ctx = TargetContext(config, cli_vars)
    return ctx.to_dict()


import json
import datetime
from django.utils import timezone
from django.core.exceptions import PermissionDenied
from rest_framework import permissions, generics
from resources.models import Unit, Reservation, Resource, ResourceType
from hmlvaraus.models.hml_reservation import HMLReservation
from hmlvaraus.models.berth import Berth
from django.contrib.gis.geos import GEOSGeometry
from rest_framework import status
from rest_framework.response import Response

from django.utils.dateparse import parse_datetime
import pytz

class ImporterView(generics.CreateAPIView):
    base_name = 'importer'
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        request_user = request.user

        if not request_user.is_staff:
            raise PermissionDenied()

        uploaded_file = request.data['file']
        data = uploaded_file.read().decode("utf-8")

        data_rows = data.split('\n')

        # Kohteet
        if data_rows[0][0] == '1':
            del data_rows[1]
            del data_rows[0]
            for row in data_rows:
                fields = row.split(';')

                try:
                    print('Kohdedataa')
                    a = fields[5]
                except:
                    continue

                location = None
                if fields[5] and fields[5] != '':
                    location = fields[5].split(',')
                    coordinates = []
                    for coord in location:
                        coord = coord.strip()
                        coord = float(coord)
                        coordinates = [coord] + coordinates

                    location = GEOSGeometry(json.dumps({'type': 'Point', 'coordinates': coordinates}))
                Unit.objects.get_or_create(name=fields[0], street_address=fields[1], address_zip=fields[2], email=fields[3], phone=fields[4], location=location, description=fields[6])

        # Venepaikat
        if data_rows[0][0] == '2':
            del data_rows[1]
            del data_rows[0]
            for row in data_rows:
                fields = row.split(';')

                try:
                    print('Venepaikkadataa, Kohde:', fields[0])
                    unit = Unit.objects.get(name=fields[0]);
                except:
                    continue

                resource_types = ResourceType.objects.all();
                for resource_type in resource_types:
                    if 'vene' in resource_type.name.lower() or 'boat' in resource_type.name.lower():
                        type_instance = resource_type

                resource = Resource.objects.get_or_create(unit=unit, name=fields[1], description=fields[2], type=type_instance, reservable=True)[0]
                is_disabled = False
                if fields[3] == 'kyllä':
                    is_disabled = True
                price = 0
                if fields[4]:
                    price = fields[4].replace(',', '.')
                    price = float(price)

                type_mapping = {
                    'numero': 'number',
                    'laituri': 'dock',
                    'poletti': 'ground'
                }
                length = 0
                width = 0
                depth = 0
                if fields[5] and fields[5] != '':
                    length = int(fields[5])
                if fields[6] and fields[6] != '':
                    width = int(fields[6])
                if fields[7] and fields[7] != '':
                    depth = int(fields[7])

                berth_type = type_mapping.get(fields[8].lower(), None)
                Berth.objects.get_or_create(resource=resource, is_disabled=is_disabled, price=price, length_cm=length, width_cm=width, depth_cm=depth, type=berth_type)

        # Varaukset
        if data_rows[0][0] == '3':
            del data_rows[1]
            del data_rows[0]
            for i, row in enumerate(data_rows):
                fields = row.split(';')
                try:
                    print(i, 'Varausdataa, Kohde:', fields[1])
                    unit = Unit.objects.get(name=fields[1])
                    resource = Resource.objects.get(unit=unit, name=str(fields[0]), description=str(fields[4]))
                except:
                    continue

                resource.reservable = False

                berth = Berth.objects.get(resource=resource)
                begin = parse_datetime(str(fields[2]) + ' 00:00:00')
                begin = pytz.timezone("Europe/Helsinki").localize(begin, is_dst=None)
                end = parse_datetime(str(fields[3]) + ' 00:00:00')
                end = pytz.timezone("Europe/Helsinki").localize(end, is_dst=None)

                state = 'confirmed'
                state_updated_at = timezone.now()
                is_paid = False
                is_paid_at = None
                if fields[5] and fields[5].strip() != '':
                    state_updated_at = datetime.datetime.strptime(fields[5], "%d.%m.%Y %H:%M")
                    state = 'cancelled'

                if fields[6] and fields[6].strip() != '':
                    is_paid_at = datetime.datetime.strptime(fields[6], "%d.%m.%Y %H:%M")
                    is_paid = True

                reservation = Reservation.objects.create(
                    resource=resource,
                    begin=begin,
                    end=end,
                    event_description=fields[4] or '',
                    state=state,
                    reserver_name=fields[7] or '',
                    reserver_email_address=fields[8] or '',
                    reserver_phone_number=fields[9] or '',
                    reserver_address_street=fields[10] or '',
                    reserver_address_city=fields[11] or '',
                    reserver_address_zip=fields[12] or '',
                )

                HMLReservation.objects.get_or_create(reservation=reservation, berth=berth, state_updated_at=state_updated_at, is_paid_at=is_paid_at, is_paid=is_paid)
                resource.save()

        return Response(
            status=status.HTTP_201_CREATED
        )


#!/usr/bin/env python3
from training import *
from datasets import load_mnist_data as load_data

def make_tiny_model (input_shape, **kwds):
    return tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(6, (3, 3), input_shape = input_shape),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(32),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Dense(10),
        tf.keras.layers.Activation('softmax'),
    ], **kwds)

def make_small_model (input_shape, **kwds):
    return tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(8, (3, 3), input_shape = input_shape),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(42),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Dense(10),
        tf.keras.layers.Activation('softmax'),
    ], **kwds)

def make_small_maxp_model (input_shape, **kwds):
    return tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(8, (3, 3), input_shape = input_shape),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.MaxPooling2D(),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(42),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Dense(10),
        tf.keras.layers.Activation('softmax'),
    ], **kwds)

def make_medium_model (input_shape, **kwds):
    return tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(5, (3, 3), input_shape = input_shape),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Conv2D(5, (5, 5)),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Conv2D(3, (7, 7)),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(128),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Dense(64),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Dense(10),
        tf.keras.layers.Activation('softmax'),
    ], **kwds)

def make_large_model (input_shape, **kwds):
    return tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(32, (3, 3), input_shape = input_shape),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Conv2D(16, (5, 5)),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Conv2D(8, (7, 7)),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(256),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Dense(64),
        tf.keras.layers.Activation('relu'),
        tf.keras.layers.Dense(10),
        tf.keras.layers.Activation('softmax'),
    ], **kwds)

# classifier (load_data, make_tiny_model,
#             model_name = 'mnist_tiny',
#             epochs = 20)

# classifier (load_data, make_small_model,
#             model_name = 'mnist_small',
#             epochs = 20)

# classifier (load_data, make_small_model,
#             model_name = 'mnist_small_overfitting',
#             early_stopping = False,
#             epochs = 50)

classifier (load_data, make_small_maxp_model,
            model_name = 'mnist_small_maxp',
            epochs = 20)

# classifier (load_data, make_medium_model,
#             model_name = 'mnist_medium',
#             epochs = 20)

# classifier (load_data, make_large_model,
#             model_name = 'mnist_overfitting',
#             early_stopping = False,
#             epochs = 20)


"""Gaussian MLP Policy.

A policy represented by a Gaussian distribution
which is parameterized by a multilayer perceptron (MLP).
"""
# pylint: disable=wrong-import-order
import akro
import numpy as np
import tensorflow as tf

from garage.tf.models import GaussianMLPModel
from garage.tf.policies.policy import StochasticPolicy

class GaussianMLPPolicy(StochasticPolicy):
    """Gaussian MLP Policy.

    A policy represented by a Gaussian distribution
    which is parameterized by a multilayer perceptron (MLP).

    Args:
        env_spec (garage.envs.env_spec.EnvSpec): Environment specification.
        name (str): Model name, also the variable scope.
        hidden_sizes (list[int]): Output dimension of dense layer(s) for
            the MLP for mean. For example, (32, 32) means the MLP consists
            of two hidden layers, each with 32 hidden units.
        hidden_nonlinearity (callable): Activation function for intermediate
            dense layer(s). It should return a tf.Tensor. Set it to
            None to maintain a linear activation.
        hidden_w_init (callable): Initializer function for the weight
            of intermediate dense layer(s). The function should return a
            tf.Tensor.
        hidden_b_init (callable): Initializer function for the bias
            of intermediate dense layer(s). The function should return a
            tf.Tensor.
        output_nonlinearity (callable): Activation function for output dense
            layer. It should return a tf.Tensor. Set it to None to
            maintain a linear activation.
        output_w_init (callable): Initializer function for the weight
            of output dense layer(s). The function should return a
            tf.Tensor.
        output_b_init (callable): Initializer function for the bias
            of output dense layer(s). The function should return a
            tf.Tensor.
        learn_std (bool): Is std trainable.
        adaptive_std (bool): Is std a neural network. If False, it will be a
            parameter.
        std_share_network (bool): Boolean for whether mean and std share
            the same network.
        init_std (float): Initial value for std.
        std_hidden_sizes (list[int]): Output dimension of dense layer(s) for
            the MLP for std. For example, (32, 32) means the MLP consists
            of two hidden layers, each with 32 hidden units.
        min_std (float): If not None, the std is at least the value of min_std,
            to avoid numerical issues.
        max_std (float): If not None, the std is at most the value of max_std,
            to avoid numerical issues.
        std_hidden_nonlinearity (callable): Nonlinearity for each hidden layer
            in the std network. The function should return a tf.Tensor.
        std_output_nonlinearity (callable): Nonlinearity for output layer in
            the std network. The function should return a
            tf.Tensor.
        std_parameterization (str): How the std should be parametrized. There
            are a few options:
        - exp: the logarithm of the std will be stored, and applied a
            exponential transformation
        - softplus: the std will be computed as log(1+exp(x))
        layer_normalization (bool): Bool for using layer normalization or not.

    """

    def __init__(self,
                 env_spec,
                 name='GaussianMLPPolicy',
                 hidden_sizes=(32, 32),
                 hidden_nonlinearity=tf.nn.tanh,
                 hidden_w_init=tf.initializers.glorot_uniform(),
                 hidden_b_init=tf.zeros_initializer(),
                 output_nonlinearity=None,
                 output_w_init=tf.initializers.glorot_uniform(),
                 output_b_init=tf.zeros_initializer(),
                 learn_std=True,
                 adaptive_std=False,
                 std_share_network=False,
                 init_std=1.0,
                 min_std=1e-6,
                 max_std=None,
                 std_hidden_sizes=(32, 32),
                 std_hidden_nonlinearity=tf.nn.tanh,
                 std_output_nonlinearity=None,
                 std_parameterization='exp',
                 layer_normalization=False):
        if not isinstance(env_spec.action_space, akro.Box):
            raise ValueError('GaussianMLPPolicy only works with '
                             'akro.Box action space, but not {}'.format(
                                 env_spec.action_space))
        super().__init__(name, env_spec)
        self._obs_dim = env_spec.observation_space.flat_dim
        self._action_dim = env_spec.action_space.flat_dim

        self._hidden_sizes = hidden_sizes
        self._hidden_nonlinearity = hidden_nonlinearity
        self._hidden_w_init = hidden_w_init
        self._hidden_b_init = hidden_b_init
        self._output_nonlinearity = output_nonlinearity
        self._output_w_init = output_w_init
        self._output_b_init = output_b_init
        self._learn_std = learn_std
        self._adaptive_std = adaptive_std
        self._std_share_network = std_share_network
        self._init_std = init_std
        self._min_std = min_std
        self._max_std = max_std
        self._std_hidden_sizes = std_hidden_sizes
        self._std_hidden_nonlinearity = std_hidden_nonlinearity
        self._std_output_nonlinearity = std_output_nonlinearity
        self._std_parameterization = std_parameterization
        self._layer_normalization = layer_normalization

        self._f_dist = None
        self._dist = None

        self.model = GaussianMLPModel(
            output_dim=self._action_dim,
            hidden_sizes=hidden_sizes,
            hidden_nonlinearity=hidden_nonlinearity,
            hidden_w_init=hidden_w_init,
            hidden_b_init=hidden_b_init,
            output_nonlinearity=output_nonlinearity,
            output_w_init=output_w_init,
            output_b_init=output_b_init,
            learn_std=learn_std,
            adaptive_std=adaptive_std,
            std_share_network=std_share_network,
            init_std=init_std,
            min_std=min_std,
            max_std=max_std,
            std_hidden_sizes=std_hidden_sizes,
            std_hidden_nonlinearity=std_hidden_nonlinearity,
            std_output_nonlinearity=std_output_nonlinearity,
            std_parameterization=std_parameterization,
            layer_normalization=layer_normalization,
            name='GaussianMLPModel')

        self._initialize()

    def _initialize(self):
        """Initialize policy."""
        with tf.compat.v1.variable_scope(self.name) as vs:
            self._variable_scope = vs
            state_input = tf.compat.v1.placeholder(tf.float32,
                                                   shape=(None, None,
                                                          self._obs_dim))
            self._dist, mean, log_std = self.model.build(state_input).outputs
            self._f_dist = tf.compat.v1.get_default_session().make_callable(
                [self._dist.sample(), mean, log_std], feed_list=[state_input])

    @property
    def input_dim(self):
        """int: Dimension of the policy input."""
        return self._obs_dim

    def build(self, state_input, name=None):
        """Build policy.

        Args:
            state_input (tf.Tensor) : State input.
            name (str): Name of the policy, which is also the name scope.

        Returns:
            tfp.distributions.MultivariateNormalDiag: Distribution.
            tf.tensor: Mean.
            tf.Tensor: Log of standard deviation.

        """
        with tf.compat.v1.variable_scope(self._variable_scope):
            return self.model.build(state_input, name=name)

    @property
    def vectorized(self):
        """Vectorized or not.

        Returns:
            Bool: True if primitive supports vectorized operations.

        """
        return True

    def get_action(self, observation):
        """Get single action from this policy for the input observation.

        Args:
            observation (numpy.ndarray): Observation from environment.

        Returns:
            numpy.ndarray: Actions
            dict: Predicted action and agent information.

        Note:
            It returns an action and a dict, with keys
            - mean (numpy.ndarray): Mean of the distribution.
            - log_std (numpy.ndarray): Log standard deviation of the
                distribution.

        """
        sample, mean, log_std = self._f_dist(np.expand_dims([observation], 1))
        sample = self.action_space.unflatten(np.squeeze(sample, 1)[0])
        mean = self.action_space.unflatten(np.squeeze(mean, 1)[0])
        log_std = self.action_space.unflatten(np.squeeze(log_std, 1)[0])
        return sample, dict(mean=mean, log_std=log_std)

    def get_actions(self, observations):
        """Get multiple actions from this policy for the input observations.

        Args:
            observations (numpy.ndarray): Observations from environment.

        Returns:
            numpy.ndarray: Actions
            dict: Predicted action and agent information.

        Note:
            It returns actions and a dict, with keys
            - mean (numpy.ndarray): Means of the distribution.
            - log_std (numpy.ndarray): Log standard deviations of the
                distribution.

        """
        samples, means, log_stds = self._f_dist(np.expand_dims(
            observations, 1))
        samples = self.action_space.unflatten_n(np.squeeze(samples, 1))
        means = self.action_space.unflatten_n(np.squeeze(means, 1))
        log_stds = self.action_space.unflatten_n(np.squeeze(log_stds, 1))
        return samples, dict(mean=means, log_std=log_stds)

    @property
    def distribution(self):
        """Policy distribution.

        Returns:
            tfp.Distribution.MultivariateNormalDiag: Policy distribution.

        """
        return self._dist

    def clone(self, name):
        """Return a clone of the policy.

        It only copies the configuration of the primitive,
        not the parameters.

        Args:
            name (str): Name of the newly created policy. It has to be
                different from source policy if cloned under the same
                computational graph.

        Returns:
            garage.tf.policies.GaussianMLPPolicy: Newly cloned policy.

        """
        return self.__class__(
            name=name,
            env_spec=self._env_spec,
            hidden_sizes=self._hidden_sizes,
            hidden_nonlinearity=self._hidden_nonlinearity,
            hidden_w_init=self._hidden_w_init,
            hidden_b_init=self._hidden_b_init,
            output_nonlinearity=self._output_nonlinearity,
            output_w_init=self._output_w_init,
            output_b_init=self._output_b_init,
            learn_std=self._learn_std,
            adaptive_std=self._adaptive_std,
            std_share_network=self._std_share_network,
            init_std=self._init_std,
            min_std=self._min_std,
            max_std=self._max_std,
            std_hidden_sizes=self._std_hidden_sizes,
            std_hidden_nonlinearity=self._std_hidden_nonlinearity,
            std_output_nonlinearity=self._std_output_nonlinearity,
            std_parameterization=self._std_parameterization,
            layer_normalization=self._layer_normalization)

    def __getstate__(self):
        """Object.__getstate__.

        Returns:
            dict: the state to be pickled for the instance.

        """
        new_dict = super().__getstate__()
        del new_dict['_f_dist']
        del new_dict['_dist']
        return new_dict

    def __setstate__(self, state):
        """Object.__setstate__.

        Args:
            state (dict): Unpickled state.

        """
        super().__setstate__(state)
        self._initialize()


# never name this package "types", or mypy will crash in ugly ways
from hologram import (
    FieldEncoder, JsonSchemaMixin, JsonDict, ValidationError
)

from datetime import timedelta
from typing import NewType

Port = NewType('Port', int)

class PortEncoder(FieldEncoder):
    @property
    def json_schema(self):
        return {'type': 'integer', 'minimum': 0, 'maximum': 65535}

class TimeDeltaFieldEncoder(FieldEncoder[timedelta]):
    """Encodes timedeltas to dictionaries"""

    def to_wire(self, value: timedelta) -> float:
        return value.total_seconds()

    def to_python(self, value) -> timedelta:
        if isinstance(value, timedelta):
            return value
        try:
            return timedelta(seconds=value)
        except TypeError:
            raise ValidationError(
                'cannot encode {} into timedelta'.format(value)
            ) from None

    @property
    def json_schema(self) -> JsonDict:
        return {'type': 'number'}

JsonSchemaMixin.register_field_encoders({
    Port: PortEncoder(),
    timedelta: TimeDeltaFieldEncoder()
})


# Copyright (C) 2019 The Raphielscape Company LLC.
#
# Licensed under the Raphielscape Public License, Version 1.d (the "License");
# you may not use this file except in compliance with the License.
#

# Original source for the deepfrying code (used under the following
# license): https://github.com/Ovyerus/deeppyer

# MIT License
#
# Copyright (c) 2017 Ovyerus
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Ported from Xtra-telegram by @heyworld

# KING USERBOT

import os
from telethon.errors.rpcerrorlist import YouBlockedUserError

from userbot.events import register
from userbot import bot, TEMP_DOWNLOAD_DIRECTORY, CMD_HELP

@register(outgoing=True, pattern=r'^.kekuatan(:? |$)([1-8])?')
async def _(fry):
    await fry.edit("`King Mengaktifkan Kekuatan Telegram...⚡`")
    level = fry.pattern_match.group(2)
    if fry.fwd_from:
        return
    if not fry.reply_to_msg_id:
        await fry.edit("`Mohon Balas Di Sticker King`")
        return
    reply_message = await fry.get_reply_message()
    if not reply_message.media:
        await fry.edit("`Gambar tidak di dukung`")
        return
    if reply_message.sender.bot:
        await fry.edit("`Mohon Balas Di Sticker King`")
        return
    chat = "@image_deepfrybot"
    message_id_to_reply = fry.message.reply_to_msg_id
    async with fry.client.conversation(chat) as conv:
        try:
            msg = await conv.send_message(reply_message)
            if level:
                m = f"/deepfry {level}"
                msg_level = await conv.send_message(
                    m,
                    reply_to=msg.id)
                r = await conv.get_response()
                response = await conv.get_response()
            else:
                response = await conv.get_response()
            """ - don't spam notif - """
            await bot.send_read_acknowledge(conv.chat_id)
        except YouBlockedUserError:
            await fry.reply("`King Mohon Unblock` @image_deepfrybot`...`")
            return
        if response.text.startswith("Forward"):
            await fry.edit("`King Mohon Matikan Setelan Forward Privasi...`")
        else:
            downloaded_file_name = await fry.client.download_media(
                response.media,
                TEMP_DOWNLOAD_DIRECTORY
            )
            await fry.client.send_file(
                fry.chat_id,
                downloaded_file_name,
                force_document=False,
                reply_to=message_id_to_reply
            )
            """ - cleanup chat after completed - """
            try:
                msg_level
            except NameError:
                await fry.client.delete_messages(conv.chat_id,
                                                 [msg.id, response.id])
            else:
                await fry.client.delete_messages(
                    conv.chat_id,
                    [msg.id, response.id, r.id, msg_level.id])
    await fry.delete()
    return os.remove(downloaded_file_name)

@register(outgoing=True, pattern=r'^.df(:? |$)([1-8])?')
async def _(fry):
    await fry.edit("`Sedang Dalam Proses......`")
    level = fry.pattern_match.group(2)
    if fry.fwd_from:
        return
    if not fry.reply_to_msg_id:
        await fry.edit("`Mohon Balas Di Sticker King`")
        return
    reply_message = await fry.get_reply_message()
    if not reply_message.media:
        await fry.edit("`Mohon Balas Di Sticker King`")
        return
    if reply_message.sender.bot:
        await fry.edit("`Mohon Balas Di Sticker King`")
        return
    chat = "@image_deepfrybot"
    message_id_to_reply = fry.message.reply_to_msg_id
    async with fry.client.conversation(chat) as conv:
        try:
            msg = await conv.send_message(reply_message)
            if level:
                m = f"/deepfry {level}"
                msg_level = await conv.send_message(
                    m,
                    reply_to=msg.id)
                r = await conv.get_response()
                response = await conv.get_response()
            else:
                response = await conv.get_response()
            """ - don't spam notif - """
            await bot.send_read_acknowledge(conv.chat_id)
        except YouBlockedUserError:
            await fry.reply("`King Mohon Unblock` @image_deepfrybot`...`")
            return
        if response.text.startswith("Forward"):
            await fry.edit("`King Mohon Matikan Setelan Privasi Forward...`")
        else:
            downloaded_file_name = await fry.client.download_media(
                response.media,
                TEMP_DOWNLOAD_DIRECTORY
            )
            await fry.client.send_file(
                fry.chat_id,
                downloaded_file_name,
                force_document=False,
                reply_to=message_id_to_reply
            )
            """ - cleanup chat after completed - """
            try:
                msg_level
            except NameError:
                await fry.client.delete_messages(conv.chat_id,
                                                 [msg.id, response.id])
            else:
                await fry.client.delete_messages(
                    conv.chat_id,
                    [msg.id, response.id, r.id, msg_level.id])
    await fry.delete()
    return os.remove(downloaded_file_name)

CMD_HELP.update({
    "kekuatan":
    "**Modules: __Kekuatan__\n\n⚡𝘾𝙈𝘿⚡: `.kekuatan` / `.kekuatan [level(1-8)]`"
    "\n**Penjelasan:** untuk mengubah foto/sticker."
})


from collections import Counter
class Solution:
    def removeDuplicateLetters(self, s: str) -> str:
        counter = Counter(s)
        seen = set()
        stack = []

        for letter in s:
            counter[letter] -= 1

            if letter in seen:
                continue

            while stack and stack[-1] > letter and counter[stack[-1]] > 0:
                seen.remove(stack.pop())

            stack.append(letter)
            seen.add(letter)

        return "".join(stack)