import contextlib
import dataclasses
import functools
import inspect
import typing
import weakref

from torchgen.model import FunctionSchema, OperatorName, SchemaKind

import torch
import torch._C as _C
import torch.library as library

from .autograd import autograd_kernel_indirection, construct_autograd_kernel

"""
There are various APIs for defining custom-operator-like things in PyTorch:
- [user-facing] autograd.Function (Python)
- [user-facing] custom_op (Python)
- [for power users] torch.library (Python)
- [for power users] TORCH_LIBRARY (C++)

This file contains the implementation for a Simple Custom Operator API (CustomOp).
Using CustomOp, you are able to define a custom operator and implement interactions
between the CustomOp and various PyTorch subsystems, including all the subsystems
that are necessary for a custom operator to work with torch.compile (i.e.,
autograd, FakeTensor, functionalization).

CustomOp is positioned as being safer and easier to use than
torch.library/TORCH_LIBRARY, which require deep understanding of PyTorch internals.
In additional, it supports torch.compile better than and is in general more
comprehensive than autograd.Function, which only supports implementing gradient
computation and vmap rules.
"""

__all__ = ["custom_op", "CustomOp", "get_ctx", "AbstractImplCtx"]

SUPPORTED_DEVICE_TYPE_TO_KEY = {
    "cpu": "CPU",
    "cuda": "CUDA",
}

# We will not let users register CustomOps with anything that could look like
# PyTorch internals to avoid confusion.
RESERVED_NS = {
    "prim",
    "prims",
    "aten",
    "at",
    "torch",
    "pytorch",
}

def custom_op(
    qualname: str, manual_schema: typing.Optional[str] = None
) -> typing.Callable:
    r"""Creates a new CustomOp object.

    In PyTorch, defining an op (short for "operator") is a two step-process:
    - we need to define (create) the op
    - we need to implement behavior for how the operator interacts with
      various PyTorch subsystems, like CPU/CUDA Tensors, Autograd, etc.

    This entrypoint defines the CustomOp object (the first step);
    you must then perform the second step by calling various methods on
    the CustomOp object.

    This API is used as a decorator (see examples).

    Arguments:
        qualname (str): Should be a string that looks like
            "namespace::operator_name". Operators in PyTorch need a namespace to
            avoid name collisions; a given operator may only be created once.
            If you are writing a Python library, we recommend the namespace to
            be the name of your top-level module. The operator_name must be
            the same as the name of the function you pass to custom_op
            (see examples).
        manual_schema (Optional[str]): Each PyTorch operator needs a schema that
            tells PyTorch the types of the inputs/outputs. If None (default),
            we will infer the schema from the type annotations on the function
            (see examples). Otherwise, if you don't want to use type annotations,
            you may provide us the schema string.

    Example::
        >>> import numpy as np
        >>> from torch import Tensor
        >>>
        >>> # Step 1: define the CustomOp.
        >>> # We need to provide the decorator a "prototype function"
        >>> # (a function with Python ellipses as the body).
        >>> @custom_op("mylibrary::numpy_sin")
        >>> def numpy_sin(x: Tensor) -> Tensor:
        >>>     ...
        >>>
        >>> # numpy_sin is now an instance of class CustomOp
        >>> print(type(numpy_sin))
        >>>
        >>> # Step 2: Register an implementation for various PyTorch subsystems
        >>>
        >>> # Register an implementation for CPU tensors
        >>> @numpy_sin.impl('cpu'):
        >>> def numpy_sin_impl_cpu(x):
        >>>     return torch.from_numpy(np.sin(x.numpy()))
        >>>
        >>> # Register an implementation for CUDA tensors
        >>> @numpy_sin.impl('cuda'):
        >>> def numpy_sin_impl_cuda(x):
        >>>     return torch.from_numpy(np.sin(x.cpu().numpy())).to(x.device)
        >>>
        >>> x = torch.randn(3)
        >>> numpy_sin(x)  # calls numpy_sin_impl_cpu
        >>>
        >>> x_cuda = x.cuda()
        >>> numpy_sin(x)  # calls numpy_sin_impl_cuda

    """

    def inner(func):
        if not inspect.isfunction(func):
            raise ValueError(
                f"custom_op(...)(func): Expected `func` to be a Python "
                f"function, got: {type(func)}"
            )

        ns, name = parse_namespace(qualname)
        validate_namespace(ns)
        if func.__name__ != name:
            raise ValueError(
                f"custom_op(qualname='{qualname}', ...)(func): expected `func` "
                f"to have name '{name}' but got '{func.__name__}'. "
                f"Please either change the name of `func` or the qualname that "
                f"is passed to `custom_op`"
            )

        schema = infer_schema(func) if manual_schema is None else manual_schema
        schema_str = f"{name}{schema}"
        function_schema = FunctionSchema.parse(schema_str)
        validate_schema(function_schema)
        if manual_schema is not None:
            validate_function_matches_schema(function_schema, func)

        lib = library.Library(ns, "FRAGMENT")
        lib.define(schema_str)
        ophandle = find_ophandle_or_throw(ns, function_schema.name)
        result = CustomOp(lib, ns, function_schema, function_schema.name, ophandle, _private_access=True)

        result.__name__ = func.__name__
        result.__module__ = func.__module__
        result.__doc__ = func.__doc__

        library.impl(lib, result._opname, "Autograd")(
            autograd_kernel_indirection(weakref.proxy(result))
        )

        torch._C._dispatch_set_report_error_callback(
            ophandle, functools.partial(report_error_callback, weakref.proxy(result))
        )

        return result

    return inner

# Global dictionary holding references to all CustomOp objects
# Yes, it keeps all CustomOps alive (see NOTE [CustomOp lifetime])
# Used to query the CustomOp associated with a specific C++ dispatcher operator.
# An example usage is FakeTensor: FakeTensor checks if a specific operator
# has an implementation registered via the CustomOp API.
# Indexed by qualname (e.g. aten::foo)
global_registry: typing.Dict[str, "CustomOp"] = {}

class CustomOp:
    r"""Class for custom operators in PyTorch.

    Use the CustomOp API to create user-defined custom operators that behave
    just like regular PyTorch operators (e.g. torch.sin, torch.mm) when it
    comes to various PyTorch subsystems (like torch.compile).

    To construct a `CustomOp`, use `custom_op`.
    """

    def __init__(self, lib, cpp_ns, schema, operator_name, ophandle, *, _private_access=False):
        super(CustomOp, self).__init__()
        if not _private_access:
            raise RuntimeError(
                "The CustomOp constructor is private and we do not guarantee "
                "BC for it. Please use custom_op(...) to create a CustomOp object"
            )
        name = f"{cpp_ns}::{str(operator_name.name)}"
        self._schema = schema
        self._cpp_ns = cpp_ns
        self._lib: library.Library = lib
        self._ophandle: _C._DispatchOperatorHandle = ophandle
        # Has the name of the op, e.g. "foo". We cache here for convenience.
        self._opname: str = str(operator_name)
        # this is _opname but with namespace. e.g. "custom::foo"
        self._qualname: str = name
        self.__name__ = None  # mypy requires this
        # NB: Some of these impls are registered as kernels to DispatchKeys.
        # Modifying the _impls dict directly won't do anything in that case.
        self._impls: typing.Dict[str, typing.Optional[FuncAndLocation]] = {}

        global_registry[self._qualname] = self

    # Records the impl and the source location in self._impls
    # Note that this doesn't cause torch.library to use the impl, that
    # needs to be done in a separate self._lib.impl call.
    def _register_impl(self, kind, func, stacklevel=2):
        if self._has_impl(kind):
            func_and_location = self._impls[kind]
            assert func_and_location is not None  # Pacify mypy
            location = func_and_location.location
            raise RuntimeError(
                f"Attempting to register a {kind} impl for operator {self._qualname} "
                f"that already has a {kind} impl registered from Python at "
                f"{location}. This is not supported."
            )
        frame = inspect.stack()[stacklevel]
        location = f"{frame.filename}:{frame.lineno}"
        self._impls[kind] = FuncAndLocation(func, location)

    def _get_impl(self, kind):
        return self._impls[kind]

    def _has_impl(self, kind):
        return kind in self._impls

    def _destroy(self):
        # NOTE: [CustomOp lifetime]
        # A CustomOp, once created, lives forever. The mechanism is that the
        # global registry holds a reference to it. However, to make testing
        # easier, we want to be able to destroy CustomOp objects.
        # CustomOp._destroy does the job, though it leaves the CustomOp
        # in a garbage state.
        del self._lib

        opnamespace = getattr(torch.ops, self._cpp_ns)
        if hasattr(opnamespace, self._opname):
            delattr(opnamespace, self._opname)

        del global_registry[self._qualname]

    def __repr__(self):
        return f'<CustomOp(op="{self._qualname}")>'

    def __call__(self, *args, **kwargs):
        # Bypass torch.ops.* and directly do OperatorHandle::callBoxed.
        # Using torch.ops.* is a bit of a pain (it can be slow and it has lifetime
        # issues from caching operators that make testing CustomOp difficult).
        result = _C._dispatch_call_boxed(self._ophandle, *args, **kwargs)
        return result

    def impl(
        self, device_types: typing.Union[str, typing.Iterable[str]]
    ) -> typing.Callable:
        r"""Register an implementation for a device type for this CustomOp object.

        If the CustomOp is passed multiple Tensor inputs with different device
        types, it will dispatch to the registered implementation for the highest
        priority device type among those present.
        The supported device types, in order of priority, are {'cuda', 'cpu'}.

        This API is used as a decorator (see examples).

        Arguments:
            device_types (str or Iterable[str]): the device type(s) to register the function for.

        Examples::
            >>> import numpy as np
            >>> from torch import Tensor
            >>>
            >>> @custom_op("mylibrary::numpy_sin")
            >>> def numpy_sin(x: Tensor) -> Tensor:
            >>>     ...
            >>>
            >>> # Register an implementation for CPU Tensors
            >>> @numpy_sin.impl('cpu'):
            >>> def numpy_sin_impl_cpu(x):
            >>>     return torch.from_numpy(np.sin(x.numpy()))
            >>>
            >>> # Register an implementation for CUDA Tensors
            >>> @numpy_sin.impl('cuda'):
            >>> def numpy_sin_impl_cuda(x):
            >>>     return torch.from_numpy(np.sin(x.cpu().numpy())).to(x.device)
            >>>
            >>> x = torch.randn(3)
            >>> numpy_sin(x)  # calls numpy_sin_impl_cpu
            >>>
            >>> x_cuda = x.cuda()
            >>> numpy_sin(x)  # calls numpy_sin_impl_cuda

        """
        if isinstance(device_types, str):
            device_types = [device_types]
        for device_type in device_types:
            validate_device_type(device_type)

        def inner(f):
            for device_type in set(device_types):
                self._register_impl(device_type, f)
                dispatch_key = SUPPORTED_DEVICE_TYPE_TO_KEY[device_type]
                library.impl(self._lib, self._opname, dispatch_key)(f)
            return f

        return inner

    def impl_factory(self) -> typing.Callable:
        r"""Register an implementation for a factory function."""

        def inner(f):
            self._register_impl("factory", f)
            library.impl(self._lib, self._opname, "BackendSelect")(f)
            return f

        return inner

    def impl_abstract(self) -> typing.Callable:
        r"""Register an abstract implementation for this operator.

        An "abstract implementation" specifies the behavior of this operator on
        Tensors that carry no data. Given some input Tensors with certain properties
        (sizes/strides/storage_offset/device), it specifies what the properties of
        the output Tensors are.

        The abstract implementation has the same signature as the operator.
        It is run for both FakeTensors and meta tensors. To write an abstract
        implementation, assume that all Tensor inputs to the operator are
        regular CPU/CUDA/Meta tensors, but they do not have storage, and
        you are trying to return regular CPU/CUDA/Meta tensor(s) as output.
        The abstract implementation must consist of only PyTorch operations
        (and may not directly access the storage or data of any input or
        intermediate Tensors).

        This API is used as a decorator (see examples).

        Examples::
            >>> import numpy as np
            >>> from torch import Tensor
            >>>
            >>> # Example 1: an operator without data-dependent output shape
            >>> @custom_op('mylibrary::custom_linear')
            >>> def custom_linear(x: Tensor, weight: Tensor, bias: Tensor):
            >>>     ...
            >>>
            >>> @custom_linear.impl_abstract():
            >>> def custom_linear_abstract(x, weight):
            >>>     assert x.dim() == 2
            >>>     assert weight.dim() == 2
            >>>     assert bias.dim() == 1
            >>>     assert x.shape[1] == weight.shape[1]
            >>>     assert weight.shape[0] == bias.shape[0]
            >>>     assert x.device == weight.device
            >>>
            >>>     return (x @ weight.t()) + bias
            >>>
            >>> # Example 2: an operator with data-dependent output shape
            >>> @custom_op('mylibrary::custom_nonzero')
            >>> def custom_nonzero(x: Tensor) -> Tensor:
            >>>     ...
            >>>
            >>> @custom_nonzero.impl_abstract():
            >>> def custom_nonzero_abstract(x):
            >>>     # Number of nonzero-elements is data-dependent.
            >>>     # Since we cannot peek at the data in an abstract impl,
            >>>     # we use the ctx object to construct a new symint that
            >>>     # represents the data-dependent size.
            >>>     ctx = torch._custom_op.get_ctx()
            >>>     nnz = ctx.create_unbacked_symint()
            >>>     shape = [x.dim(), nnz]
            >>>     result = x.new_empty(shape, dtype=torch.long)
            >>>     return result
            >>>
            >>> @numpy_nonzero.impl(['cpu', 'cuda'])
            >>> def custom_nonzero_impl(x):
            >>>     x_np = to_numpy(x)
            >>>     res = np.stack(np.nonzero(x_np), axis=1)
            >>>     # unbacked symbolic ints in PyTorch must be >= 2, so we
            >>>     # constrain the range to at least 2
            >>>     if res.shape[0] <= 1:
            >>>         raise RuntimeError("not supported")
            >>>     return torch.tensor(res, device=x.device)

        """

        def inner(f):
            frame = inspect.stack()[1]
            self._register_impl("abstract", f)
            location = self._get_impl("abstract").location

            qualname = self._qualname

            # Handle DispatchKey.Meta registration
            @functools.wraps(f)
            def f_with_ctx(*args, **kwargs):
                def error_on_ctx():
                    raise RuntimeError(
                        f"Attempted to call get_ctx() for the meta implementation "
                        f"for {qualname}."
                        f"You have presumably called get_ctx() because the operator "
                        f"has a data-dependent output shape; if so, there is no "
                        f"such meta implementation and this error is the correct "
                        f"behavior. Otherwise, please remove the call to get_ctx() "
                        f"in the implementation registered with impl_abstract "
                        f"at {location}"
                    )

                with set_ctx_getter(error_on_ctx):
                    return f(*args, **kwargs)

            self._lib.impl(self._opname, f_with_ctx, "Meta")
            return f

        return inner

    # NOTE ["backward", "save_for_backward", and "autograd"]
    # As a part of the explicit autograd API, a user must provide us
    # a "save_for_backward" function and a "backward" function.
    # When both of these have been provided, then we automatically
    # construct the "autograd" kernel.
    def _register_autograd_kernel(self):
        assert self._has_impl("backward")
        assert self._has_impl("save_for_backward")
        kernel = construct_autograd_kernel(
            self._schema,
            self._output_differentiability,
            self,
            self._get_impl("save_for_backward").func,
            self._get_impl("backward").func)
        self._register_impl("autograd", kernel)

    def impl_save_for_backward(self):
        r"""Register a function that tells us what to save for backward.

        Please see impl_backward for more details.
        """
        def inner(f):
            self._register_impl("save_for_backward", f)
            if self._has_impl("backward"):
                self._register_autograd_kernel()
        return inner

    def impl_backward(self, output_differentiability=None):
        r"""Registers a backward formula.

        In order for the CustomOp to work with autograd, you need to register
        a backward formula. There are two pieces to this:
        1. You must give us a function to specify what to save for backward.
           Call this the "save for backward" function.
        2. You must give us a function that computes gradients. Call this the
           "backward" function.

        Use `impl_save_for_backward` to define a "save for backward" function
        that specifies what gets saved for backward. The function should accept
        two arguments ``(inputs, output)`` and return the quantities to be saved
        for backward.

        During runtime, when you call the CustomOp, PyTorch will invoke the
        "save for backward" function with the inputs and output of the CustomOp.

        Use `impl_backward` to define the "backward" function. The backward
        function must accept ``(ctx, saved, *grads)``:
        - ``ctx`` is a context object where we may provide information
        - ``saved`` is exactly what gets returned from the "save for backward"
          function
        - ``grads`` is one or more gradients. The number of gradients matches
          the number of outputs of the CustomOp.

        The backward function must return a dict that maps the name of
        an input to the CustomOp to its corresponding gradient. All inputs that
        were declared to be Tensors in the CustomOp definition must be accounted
        for in the dict. The gradient may be a Tensor or None.

        TODO(rzou): Add example when this PR is closer to landing.

        """
        if output_differentiability is not None:
            def yell():
                raise RuntimeError(
                    f"impl_backward(output_differentiability): expected "
                    f"output_differentiability to be a list of bools with "
                    f"length equal to the number of outputs of this CustomOp "
                    f"got: {output_differentiability}")

            if not isinstance(output_differentiability, list):
                yell()
            for diff in output_differentiability:
                if not isinstance(diff, bool):
                    yell()
            if len(self._schema.returns) != len(output_differentiability):
                yell()

        def inner(f):
            self._register_impl("backward", f)
            self._output_differentiability = output_differentiability
            if self._has_impl("save_for_backward"):
                self._register_autograd_kernel()
        return inner

@dataclasses.dataclass
class FuncAndLocation:
    func: typing.Callable
    location: str

def find_ophandle_or_throw(cpp_ns: str, operator_name: OperatorName):
    overload_name = (
        "" if operator_name.overload_name is None else operator_name.overload_name
    )
    return _C._dispatch_find_schema_or_throw(
        f"{cpp_ns}::{str(operator_name.name)}", overload_name
    )

def validate_namespace(ns: str) -> None:
    if "." in ns:
        raise ValueError(
            f'custom_op(..., ns="{ns}"): expected ns to not contain any . (and be a '
            f"valid variable name)"
        )
    if ns in RESERVED_NS:
        raise ValueError(
            f"custom_op(..., ns='{ns}'): '{ns}' is a reserved namespace, "
            f"please choose something else. "
        )

def validate_schema(schema: FunctionSchema) -> None:
    # Coming in the future. Requires us to have correct logic for
    # the ADInplaceOrView key
    if schema.kind() != SchemaKind.functional:
        raise ValueError(
            f"custom_op does not support non-functional function schema. Got: {schema}"
        )

    rets = schema.returns
    is_non_mutating_view = len(rets) > 0 and any(
        r.annotation is not None and not r.annotation.is_write for r in rets
    )
    if is_non_mutating_view:
        raise ValueError(f"custom_op does not support view functions. Got: {schema}")

    # Just seems weird so banning for now
    if not schema.returns:
        raise ValueError(
            f"custom_op does not support function schema with no outputs. Got: {schema}"
        )

    # For simplicity: don't allow self arguments
    if schema.arguments.self_arg is not None:
        raise ValueError(
            f"custom_op does not support arguments named 'self'. Please "
            f"rename your argument. Got: {schema}"
        )

def parse_namespace(namespaced_entity: str) -> typing.Tuple[str, str]:
    names = namespaced_entity.split("::", 1)
    if len(names) != 2:
        raise ValueError(f"Expected there to be a namespace in {namespaced_entity}.")
    return names[0], names[1]

def validate_device_type(device_type: str) -> None:
    if device_type not in SUPPORTED_DEVICE_TYPE_TO_KEY:
        raise ValueError(
            f"CustomOp.impl(device_types=[{device_type}, ...]): we only support device_type "
            f"in {SUPPORTED_DEVICE_TYPE_TO_KEY.keys()}."
        )

def supported_param(param: inspect.Parameter) -> bool:
    return param.kind in (
        inspect.Parameter.POSITIONAL_OR_KEYWORD,
        inspect.Parameter.KEYWORD_ONLY,
    )

def validate_function_matches_schema(
    schema: FunctionSchema, func: typing.Callable
) -> None:
    sig = inspect.signature(func)

    if not all(supported_param(p) for _, p in sig.parameters.items()):
        raise ValueError(
            f"custom_op(..., manual_schema)(func): positional-only args, "
            f"varargs, and kwargs are not supported. Please rewrite `func` "
            f"to not have them. Got `func` with signature: {sig}"
        )

    if (
        any(
            p.annotation is not inspect.Parameter.empty
            for _, p in sig.parameters.items()
        )
        or sig.return_annotation is not inspect.Signature.empty
    ):
        raise ValueError(
            f"custom_op(..., manual_schema)(func): When passing in a manual "
            f"schema, we expect `func` to have no type annotations to avoid "
            f"ambiguity. Got `func` with signature: {sig}"
        )

    positional = [
        (name, param)
        for name, param in sig.parameters.items()
        if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
    ]
    kwargonly = [
        (name, param)
        for name, param in sig.parameters.items()
        if param.kind == inspect.Parameter.KEYWORD_ONLY
    ]

    def error():
        raise ValueError(
            f"custom_op(..., manual_schema)(func): When passing in a manual "
            f"schema, we expect `func`'s signature to match `manual_schema` "
            f"(aside from type annotations). "
            f"func's signature: {sig}, manual_schema: {schema}"
        )

    def error_default_args():
        raise ValueError(
            f"custom_op(..., manual_schema)(func): "
            f"neither func nor manual_schema should have default "
            f"arguments. Got "
            f"func's signature: {sig}, manual_schema: {schema}"
        )

    def compare(sig_args, schema_args):
        if len(sig_args) != len(schema_args):
            error()
        for (name, param), arg in zip(sig_args, schema_args):
            if name != arg.name:
                error()
            if param.default is not inspect.Parameter.empty or arg.default is not None:
                error_default_args()

    compare(positional, schema.arguments.flat_positional)
    compare(kwargonly, schema.arguments.flat_kwarg_only)

def get_none():
    return None

global_ctx_getter: typing.Callable = get_none

# NOTE [ctx inside the fake implementation]
# If a user has an operator with data-dependent output shape, then when writing
# a fake implementation they must query the current ctx and use methods on the
# ctx to construct a new unbacked symint.
#
# This is done via us setting the global_ctx_getter function every time a fake
# implementation is invoked.
def get_ctx() -> "AbstractImplCtx":
    """get_ctx() returns the current AbstractImplCtx object.

    Calling ``get_ctx()`` is only valid inside of an abstract implementation.
    """
    return global_ctx_getter()

@contextlib.contextmanager
def set_ctx_getter(ctx_getter):
    global global_ctx_getter
    prev = global_ctx_getter
    try:
        global_ctx_getter = ctx_getter
        yield
    finally:
        global_ctx_getter = prev

class AbstractImplCtx:
    """
    Context object for writing abstract implementations for custom operators.
    """

    def __init__(self, _shape_env, _op):
        self._shape_env = _shape_env
        self._op = _op

    def create_unbacked_symint(self, *, min=2, max=None) -> torch.SymInt:
        """Constructs a new symint (symbolic int) representing a data-dependent value.

        This is useful for writing the abstract implementation (which is necessary
        for torch.compile) for a CustomOp where an output Tensor has a size
        that depends on the data of the input Tensors.

        Args:
            min (int): A statically known inclusive lower bound for this symint.
                min must be at least 2 due to implementation details of
                torch.compile. Default: 2.
            max (Optional[int]): A statically known inclusive upper bound for this
                symint. Default: None

        .. warning:

            It is important that the ``min`` and ``max`` (if not None) values are set
            correctly, otherwise, there will be undefined behavior under
            torch.compile. The default value of ``min`` is 2 due to torch.compile
            specializing on 0/1 sizes.

            You must also verify that your implementation on concrete Tensors
            (e.g. CPU/CUDA) only returns Tensors where the size that corresponds
            to the symint also has respects these constraint.
            The easiest way to do this is to add an assertion in the CPU/CUDA/etc
            implementation that the size follows these bounds.

        Example::

            >>> # an operator with data-dependent output shape
            >>> @custom_op("mylibrary::custom_nonzero")
            >>> def custom_nonzero(x: Tensor) -> Tensor:
            >>>     ...
            >>>
            >>> @custom_nonzero.impl_abstract():
            >>> def custom_nonzero_abstract(x):
            >>>     # Number of nonzero-elements is data-dependent
            >>>     ctx = torch._custom_op.get_ctx()
            >>>     nnz = ctx.create_unbacked_symint()
            >>>     shape = [x.dim(), nnz]
            >>>     result = x.new_empty(shape, dtype=torch.long)
            >>>     return result
            >>>
            >>> @numpy_nonzero.impl(['cpu', 'cuda'])
            >>> def custom_nonzero_impl(x):
            >>>     x_np = to_numpy(x)
            >>>     res = np.stack(np.nonzero(x_np), axis=1)
            >>>     # the size associated with ctx.create_unbacked_symint()
            >>>     # must be constrained in the same way, so we add an assertion here.
            >>>     if res.shape[0] < 2 or res.shape[0] > x.numel():
            >>>         raise RuntimeError("not supported")
            >>>     return torch.tensor(res, device=x.device)

        """
        if (
            self._shape_env is None
            or not self._shape_env.allow_dynamic_output_shape_ops
        ):
            raise torch._subclasses.fake_tensor.DynamicOutputShapeException(self._op)

        if isinstance(min, torch.SymInt) or isinstance(max, torch.SymInt):
            raise ValueError(
                f"ctx.create_unbacked_symint(min={min}, max={max}): expected "
                f"min and max to be statically known ints but got SymInt. "
                f"This is not supported."
            )

        if min < 2:
            raise ValueError(
                f"ctx.create_unbacked_symint(min={min}, ...): expected min to be "
                f"greater than or equal to 2. PyTorch only supports new "
                f"data-dependent sizes of >= 2"
            )

        result = self._shape_env.create_unbacked_symint()
        torch.fx.experimental.symbolic_shapes.constrain_range(result, min=2, max=max)
        return result

def infer_schema(prototype_function: typing.Callable) -> str:
    sig = inspect.signature(prototype_function)

    def error_fn(what):
        raise ValueError(
            f"custom_op(...)(func): {what} " f"Got func with signature {sig})"
        )

    params = [
        parse_param(name, param, error_fn) for name, param in sig.parameters.items()
    ]
    ret = parse_return(sig.return_annotation, error_fn)
    return f"({', '.join(params)}) -> {ret}"

def parse_param(name, param, error_fn):
    if not supported_param(param):
        error_fn("We do not support positional-only args, varargs, or varkwargs.")

    if param.annotation is inspect.Parameter.empty:
        error_fn(f"Parameter {name} must have a type annotation.")

    if param.annotation not in SUPPORTED_PARAM_TYPES.keys():
        error_fn(
            f"Parameter {name} has unsupported type {param.annotation}. "
            f"The valid types are: {SUPPORTED_PARAM_TYPES.keys()}."
        )

    if param.default is not inspect.Parameter.empty:
        error_fn(
            f"Parameter {name} has a default value; this is not supported. "
            f"If you want to use default values then create a function with "
            f"default values that calls the CustomOp"
        )

    return f"{SUPPORTED_PARAM_TYPES[param.annotation]} {name}"

def derived_types(
    base_type, cpp_type, list_base, optional_base_list, optional_list_base
):
    result = [
        (base_type, cpp_type),
        (typing.Optional[base_type], f"{cpp_type}?"),
    ]
    if list_base:
        result.append((typing.Sequence[base_type], f"{cpp_type}[]"))  # type: ignore[valid-type]
    if optional_base_list:
        result.append((typing.Sequence[typing.Optional[base_type]], f"{cpp_type}?[]"))  # type: ignore[valid-type]
    if optional_list_base:
        result.append((typing.Optional[typing.Sequence[base_type]], f"{cpp_type}[]?"))  # type: ignore[valid-type]
    return result

def get_supported_param_types():
    data = [
        # (python type, schema type, type[] variant, type?[] variant, type[]? variant
        (torch.Tensor, "Tensor", True, True, False),
        (int, "SymInt", True, False, True),
        (float, "float", True, False, True),
        (bool, "bool", True, False, True),
        (str, "str", False, False, False),
        (torch.types.Number, "Scalar", True, False, False),
        (torch.dtype, "ScalarType", False, False, False),
        (torch.device, "Device", False, False, False),
    ]
    result = []
    for line in data:
        result.extend(derived_types(*line))
    return dict(result)

def parse_return(annotation, error_fn):
    if annotation is torch.Tensor:
        return "Tensor"
    origin = typing.get_origin(annotation)
    if origin is not tuple:
        error_fn(
            "Expected output of func to be type annotated as either Tensor "
            "or a Tuple of known size of one or more tensors"
        )
    args = typing.get_args(annotation)
    for arg in args:
        if arg is not torch.Tensor:
            error_fn(
                "Expected output of func to be type annotated as either Tensor "
                "or a Tuple of known size of one or more tensors"
            )
    return "(" + ", ".join(["Tensor"] * len(args)) + ")"

SUPPORTED_PARAM_TYPES = get_supported_param_types()

def report_error_callback(custom_op: typing.Any, key: str) -> None:
    if key == "Undefined":
        raise NotImplementedError(
            f"{custom_op}: There were no Tensor inputs to this operator "
            f"(e.g. you passed an empty list of Tensors). If your operator is a "
            f"factory function (that is, it takes no Tensors and constructs "
            f"a new one), then please use CustomOp.impl_factory to register "
            f"an implementation for it"
        )
    if key == "Meta":
        raise NotImplementedError(
            f"{custom_op}: when running with device='Meta' tensors: there is no "
            f"abstract impl registered for this CustomOp. Please register one via "
            f"CustomOp.impl_abstract to get this CustomOp to work with Meta tensors"
        )
    if key in ("CPU", "CUDA"):
        device = key.lower()
        raise NotImplementedError(
            f"{custom_op}: when running with device='{device}' tensors: there is no "
            f"{device} impl registered for this CustomOp. Please register one via "
            f"CustomOp.impl(device_type='{device}')"
        )
    raise NotImplementedError(
        f"{custom_op}: No implementation for dispatch key {key}. It is likely "
        f"that we have not added this functionality yet, please either open an "
        f"issue or if you're feeling adventurous, use the low-level "
        f"torch.library API"
    )


from turtle import Screen
from paddle import Paddle
from ball import Ball
from scoreboard import Scoreboard
import time

SCREEN_HEIGHT = 600
SCREEN_WIDTH = 800
LEFT_PADDLE_X_COORD = -350
RIGHT_PADDLE_X_COORD = 350
PADDLE_Y_COORD = 0
FRONT_OF_LEFT_PADDLE_X_COORD = -330
FRONT_OF_RIGHT_PADDLE_X_COORD = 330
SCREEN_UPPER_BOUND = 280
SCREEN_LOWER_BOUND = -280
LEFT_SIDE_BOUNDARY = -352
RIGHT_SIDE_BOUNDARY = 352
LEFT_SCOREBOARD_COORD = (-100, 260)
RIGHT_SCOREBOARD_COORD = (100, 260)
GAME_ENDING_SCORE = 5
SECONDS_DELAY_AFTER_POINT = 0.5
DISTANCE_FROM_PADDLE_FOR_PADDLE_BOUNCE = 50

screen = Screen()
screen.tracer(0)
screen.bgcolor("black")
screen.setup(width=SCREEN_WIDTH, height=SCREEN_HEIGHT)
screen.title("PONG")

left_paddle = Paddle(LEFT_PADDLE_X_COORD, PADDLE_Y_COORD)
right_paddle = Paddle(RIGHT_PADDLE_X_COORD, PADDLE_Y_COORD)

ball = Ball()

left_score = Scoreboard(LEFT_SCOREBOARD_COORD)
right_score = Scoreboard(RIGHT_SCOREBOARD_COORD)

screen.listen()
screen.onkey(left_paddle.move_up, "w")
screen.onkey(left_paddle.move_down, "s")
screen.onkey(right_paddle.move_up, "o")
screen.onkey(right_paddle.move_down, "l")

game_is_running = True
while game_is_running:
    screen.update()
    time.sleep(ball.move_speed)
    ball.move()
    if ball.ycor() >= SCREEN_UPPER_BOUND or ball.ycor() <= SCREEN_LOWER_BOUND:
        ball.y_direction_reversal()
    if ball.xcor() >= FRONT_OF_RIGHT_PADDLE_X_COORD:
        if right_paddle.distance(ball) <= DISTANCE_FROM_PADDLE_FOR_PADDLE_BOUNCE and ball.direction == "right":
            ball.direction = "left"
            ball.x_direction_reversal()
            ball.increase_speed()
        elif ball.xcor() >= RIGHT_SIDE_BOUNDARY:
            ball.reset_position()
            left_score.add_point()
            time.sleep(SECONDS_DELAY_AFTER_POINT)
    if ball.xcor() <= FRONT_OF_LEFT_PADDLE_X_COORD:
        if left_paddle.distance(ball) <= DISTANCE_FROM_PADDLE_FOR_PADDLE_BOUNCE and ball.direction == "left":
            ball.direction = "right"
            ball.x_direction_reversal()
            ball.increase_speed()
        elif ball.xcor() <= LEFT_SIDE_BOUNDARY:
            ball.reset_position()
            right_score.add_point()
            time.sleep(SECONDS_DELAY_AFTER_POINT)
    if left_score.score == GAME_ENDING_SCORE:
        game_is_running = False
        left_score.game_over("left")
    elif right_score.score == GAME_ENDING_SCORE:
        game_is_running = False
        right_score.game_over("right")

screen.exitonclick()


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from two_dim_funcs import *
from Utility import *
from optimizers import *

func_name = "eggholder"
x_range = np.array(domain_range[func_name])
x_opt = np.array(opt_solutions[func_name][0])

xmin = x_range[:,0]
xmax = x_range[:,1]
num_grids = 100
x1 = np.linspace(xmin[0], xmax[0], num_grids)
x2 = np.linspace(xmin[1], xmax[1], num_grids)
X1, X2 = np.meshgrid(x1, x2)
features = np.c_[X1.ravel(), X2.ravel()]
init_func = pick_function(func_name) # pick the initial function w.r.t. the function name
features = torch.tensor(features, requires_grad=True, dtype=torch.float32)
u0 = torch.tensor(init_func(X1.ravel().reshape(-1,1),X2.ravel().reshape(-1,1)), requires_grad=False, dtype=torch.float32)

print("avg u0:",torch.mean(u0))
print("max u0:",torch.max(u0))
print("min u0:",torch.min(u0))
print("std u0:",torch.std(u0))
print(np.sort(u0.numpy(),axis=None)[:5000])
# fig = plt.figure()
# ax = plt.axes(projection='3d')
# ax.plot_surface(X2,X1,u0.reshape(100,100),rstride=1, cstride=1,
#                 cmap='viridis', edgecolor='none')
# ax.set_ylim(x_range[0][0],x_range[0][1])
# ax.set_xlim(x_range[1][1],x_range[1][0])
# ax.set_title("Initial Function")
# ax.set_xlabel("x2")
# ax.set_ylabel("x1")
# plt.show()


import MetaTrader5 as mt5

mt5.initialize()

forex = ['EUR', 'GBP', 'AUD', 'NZD', 'USD', 'CHF', 'CAD', 'SGD', 'NOK', 'SEK']

commodity = ['XAU', 'XPD', 'XPT', 'XNG', 'XTI', 'XBR', 'DXY']

positions = mt5.positions_get(symbol='AUDJPY')
# print(positions)

def volAdjust(vol, asset):

    if asset[0:3] in forex:
        return vol * 100000
    elif asset[0:3] in commodity:
        return vol * 100
    elif asset[0:3] == 'XAG':
        return vol * 1000
    else:
        return vol

def volume(positions):

    if len(positions) == 1:         #For one trade/asset
        if positions[0].type == 0:
            lot = positions[0].volume
        else:
            lot = -(positions[0].volume)
        return volAdjust(lot, positions[0].symbol)
    else:                           #For more than one trades
        volume_ = 0
        for i in positions:
            if i.type == 0:         #for a long position
                volume_ += i.volume
            else:                   #For a short position
                volume_ -= i.volume
        return volAdjust(volume_, positions[0].symbol)

def exposure(positions):

    exposure_ = 0
    if len(positions) == 1:
        exposure_ = volume(positions) * positions[0].price_open
        return exposure_
    else:
        exposure_ = 0
        for i in positions:
            if i.type == 0:
                exposure_ += volAdjust(i.volume, i.symbol) * i.price_open
            else:
                exposure_ -= volAdjust(i.volume, i.symbol) * i.price_open
            return exposure_

print(f"Volumes: {volume(positions)}")
print(f"Exposure: {exposure(positions)}")

mt5.shutdown()


from math import sqrt

# Create a list with the first ten triangular numbers
# (see https://oeis.org/A000217)

L = [i*(1+1)/2 for i in range(10)]

# Create a function to test if a number is prime
def is_prime(n):
    """
    Test if ``n`` is a prime.
    """
    if n < 2:
        return False
    for i in range(2, int(sqrt(n)) + 1):
        if n%i == 0:
            return False
    return True

# Tests
# is_prime(2033) == False
# is_prime(2039) == True

# Create a function which returns a list of the first ten prime numbers
# greater than or equal to n

def next_ten_primes(n):
    """
    Return the list of the first ten prime numbers greate than or equal to n.
    """
    L = []
    while len(L) < 10:
        if is_prime(n):
            L.append(n)
        n += 1
    return L

# Tests
# next_ten_primes(2033) == [2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111]
# next_ten_primes(2039) == [2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111]


import pandas as pd
import random
from names import names
stories = pd.read_csv("/Users/andrewdownie/Documents/Graduate Studies/Courses/CS680/Project/Datasets/2018/cloze_test_val__spring2016 - cloze_test_ALL_val.csv")
print(stories)
print(stories.columns)
cols = ['InputSentence1', 'InputSentence2', 'InputSentence3',
       'InputSentence4', 'RandomFifthSentenceQuiz1',
       'RandomFifthSentenceQuiz2']

precentage = 0.01
repeat = 100
n_samples = len(stories)
sample_points = random.sample(list(range(n_samples)),int(precentage*n_samples))
print(len( stories))
new_stories = stories.copy()
for i in range(repeat):
    new_stories = pd.concat([new_stories,stories.iloc[sample_points,:]],ignore_index=True)

#ew_stories = pd.concat([stories,stories.iloc[sample_points,:]],ignore_index=True)
print(len(new_stories))
new_stories.to_csv("redundant_data_set_1_100.csv")


import boto3

session = boto3.Session(region_name='us-east-1')
client = session.client(service_name='ec2')
all_regions = client.describe_regions()

region_list = ['us-east-1', ]
list_of_regions = []
for each_reg in all_regions['Regions']:
    list_of_regions.append(each_reg['RegionName'])
print(list_of_regions)

for each_reg in list_of_regions:
    session = boto3.Session(region_name=each_reg)
    resource = session.resource(service_name='ec2')
    if each_reg in region_list:
        print("List of services: ", each_reg)
        for each_in_vpc in resource.vpcs.all():
            print(client.describe_vpcs(VpcIds=[each_in_vpc.id]))
        print('-------------------------------------------------------------------')
        for each_in_subnet in resource.subnets.all():
            print(client.describe_subnets(SubnetIds=[each_in_subnet.id]))
        print('-------------------------------------------------------------------')
        for each_in_IGW in resource.internet_gateways.all():
            print(client.describe_internet_gateways(InternetGatewayIds=[each_in_IGW.id]))
        print('-------------------------------------------------------------------')
        for each_in_sg in resource.security_groups.all():
            print(client.describe_security_groups(GroupIds=[each_in_sg.id]))


#!/usr/bin/env python3

import sys
import re
import datetime
from optparse import OptionParser

class Info(object):
    def __init__(self, name, summary=None, description=None, synopsis=None, copyright=None, options=None):
        self.name = name
        self.summary = summary
        self.description = description
        self.synopsis = synopsis
        self.copyright = copyright
        self.options = options  # list of dictionaries with keys ["long_name", "short_name", "description", "arg_description"]

    def gen_rst(self):
        rst  = ".. -*- coding: utf-8 -*-\n\n"
        rst += "%s\n" % ("=" * len(self.name),)
        rst += "%s\n" % self.name
        rst += "%s\n\n" % ("=" * len(self.name),)

        # Add summary
        if self.summary:
            rst += "%s\n" % ("-" * len(self.summary))
            rst += "%s\n" % self.summary
            rst += "%s\n" % ("-" * len(self.summary))
            rst += "\n"

        # Add copyright
        if self.copyright:
            rst += ":Copyright: %s\n" % self.copyright

        # Add manual page section
        rst += ":Manual section: 8\n"

        # Add date
        rst += ":Date: $Date: %s $\n\n" % datetime.datetime.strftime(datetime.datetime.utcnow(), format="%F %X")

        # Add synopsis
        if self.synopsis:
            rst += "SYNOPSIS\n"
            rst += "========\n\n"
            for line in self.synopsis:
                rst += "%s\n\n" % line
            rst += "\n"

        # Add description
        if self.description:
            rst += "DESCRIPTION\n"
            rst += "===========\n\n"
            for line in self.description:
                rst += "%s\n\n" % line
            rst += "\n"

        # Add options
        rst += "OPTIONS\n"
        rst += "=======\n"

        for command in self.options:
            cmd  = ""
            if command["short_name"]:
                cmd += "-%s " % command["short_name"]
            cmd += "--%s" % command["long_name"]
            if command["arg_description"]:
                cmd += " %s" % command["arg_description"]

            rst += "%s\n" % cmd
            rst += "%s\n" % ("-" * len(cmd))
            rst += "%s\n" % command["description"]

            rst += "\n"

        return rst

def parse_arguments_from_c_file(filename):
    args = []

    try:
        content = open(filename, "r").read()
    except IOError:
        print("Error: Cannot open file %s" % filename)
        return args

    re_cmd_entries = re.compile(r"\s*(static|const)[ ]+GOptionEntry[^{]*{(?P<entries>.*)\s*NULL\s*}[,]?\s*};", re.MULTILINE|re.DOTALL)
    match = re_cmd_entries.search(content)
    if not match:
        print("Warning: Cannot find GOptionEntry section in %s" % filename)
        return args

    re_single_entry = re.compile(r"""{\s*"(?P<long_name>[^"]*)"\s*,        # long name
                                     \s*'?(?P<short_name>[^',]*)'?\s*,     # short name
                                     \s*[^,]*\s*,                          # flags
                                     \s*[^,]*\s*,                          # arg type
                                     \s*[^,]*\s*,                          # arg data pointer
                                     \s*("(?P<description>.*?)")\s*,       # description
                                     \s*"?(?P<arg_description>[^"}]*)"?    # arg description
                                  \s*},""", re.MULTILINE|re.DOTALL|re.VERBOSE)
    raw_entries_str = match.group("entries")

    start = 0
    entry_match = re_single_entry.search(raw_entries_str)
    i = 1
    while entry_match:
        long_name = entry_match.group("long_name").strip()
        short_name = entry_match.group("short_name").strip()
        description = entry_match.group("description").strip()
        arg_description = entry_match.group("arg_description").strip()

        # Normalize short name
        if short_name in ("NULL", "0", "\\0"):
            short_name = None

        # Normalize description
        description = description.replace('\\"', "\\\\'")
        description = description.replace("\\\\'", '"')
        description = description.replace('"', "")
        description = description.replace('\n', '')
        description = description.replace('\t', '')

        # Remove multiple whitespaces from description
        while True:
            new_description = description.replace("  ", " ")
            if new_description == description:
                break
            description = new_description
        description = description.strip()

        # Normalize arg_description
        if arg_description and (arg_description == "NULL" or arg_description == "0"):
            arg_description = None

        # Store option into list
        args.append({'long_name': long_name,
                     'short_name': short_name,
                     'description': description,
                     'arg_description': arg_description
                     })

        # Continue to next option
        i += 1
        start += entry_match.end(0)
        entry_match = re_single_entry.search(raw_entries_str[start:])
    # End while

    print("Loaded %2d arguments" % (i,), file=sys.stderr)
    return args

if __name__ == "__main__":
    parser = OptionParser('usage: %prog [options] <filename> [--mergerepo|--modifyrepo|--sqliterepo]')
    parser.add_option('-m', '--mergerepo', action="store_true", help="Gen rst for mergerepo")
    parser.add_option('-r', '--modifyrepo', action="store_true", help="Gen rst for modifyrepo")
    parser.add_option('-s', '--sqliterepo', action="store_true", help="Gen rst for sqliterepo")
    options, args = parser.parse_args()

    if len(args) < 1:
        print("Error: Must specify a input filename. (Example: ../src/cmd_parser.c)", file=sys.stderr)
        sys.exit(1)

    args = parse_arguments_from_c_file(args[0])

    if options.mergerepo:
        NAME = "mergerepo_c"
        info = Info(NAME,
                summary="Merge multiple rpm-md format repositories together",
                synopsis=["%s [options] --repo repo1 --repo repo2" % (NAME,)],
                options=args)
    elif options.modifyrepo:
        NAME = "modifyrepo_c"
        info = Info(NAME,
                summary="Modify a repomd.xml of rpm-md format repository",
                synopsis=["%s [options] <input metadata> <output repodata>" % (NAME,),
                          "%s --remove <metadata type> <output repodata>" % (NAME,),
                          "%s [options] --batchfile <batch file> <output repodata>" % (NAME,) ],
                options=args)
    elif options.sqliterepo:
        NAME = "sqliterepo_c"
        info = Info(NAME,
                summary="Generate sqlite db files for a repository in rpm-md format",
                synopsis=["%s [options] <repo_directory>" % (NAME,) ],
                options=args)
    else:
        NAME = "createrepo_c"
        info = Info(NAME,
                summary="Create rpm-md format (xml-rpm-metadata) repository",
                synopsis=["%s [options] <directory>" % (NAME,)],
                description=["Uses rpm packages from <directory> to create repodata.",
                             "If compiled with libmodulemd support modular metadata inside <directory> identified by the patterns below are automatically collected, merged and added to the repodata.",
                             "The patterns are:",
                             " - \*.modulemd.yaml (recommended file name: N:S:V:C:A.modulemd.yaml)",
                             " - \*.modulemd-defaults.yaml (recommended file name: N.modulemd-defaults.yaml)",
                             " - modules.yaml (recommended way of importing multiple documents at once)"],
                options=args)

    ret = info.gen_rst()
    if not ret:
        print("Error: Rst has not been generated", file=sys.stderr)
        sys.exit(1)

    print(ret)


# Test on new pics

import torch
from torchvision import models, datasets, transforms
#import argparse
import torchvision.transforms.functional as func
import torchvision.utils as utils
from PIL import Image
from data_loader import ClassLoader

'''
parser = argparse.ArgumentParser()
parser.add_argument('--loadfrom', default='', help='The model to load')
parser.add_argument('--image', default='', help='The image to classify')
parser.add_argument('--folder', default='', help='A whole folder of images to classify')
opt = parser.parse_args()

network = models.alexnet(pretrained=False, num_classes=185)
network.load_state_dict(torch.load(opt.loadfrom))
network.eval()
'''

class CustomImageFolder(datasets.ImageFolder):
    def __init__(self, location, transform=None):
        super(CustomImageFolder,self).__init__(location, transform=transform)

    def __getitem__(self, index):
        x, y = super(CustomImageFolder, self).__getitem__(index)
        return {'image':x, 'class':y, 'file':self.imgs[index][0]}

def test_on_new(network, opt):
    folder = opt['folder']
    image = opt['image']
    classes = ClassLoader()

    if folder != '':
        dset = CustomImageFolder(folder, transform=transforms.Compose([transforms.Resize((224,224)),transforms.ToTensor()]))
        loader = torch.utils.data.DataLoader(dset, batch_size=1, shuffle=False, num_workers=1)
    #   iterator=loader.__iter__()
    #   sample = iterator.next()
    #   print(sample)
        allIms = []
        for i, data in enumerate(loader):
            image = data['image']
            allIms.append(image)
            file = data['file'][0]
    #       func.to_pil_image(image.squeeze()).show(title=file) #visualize the image #title doesn't work
            result = network(image).squeeze()
            _, arg = torch.max(result,0)
            arg = arg.item()
            print("File: {0}, Index: {1}, Classification: {2}".format(file, arg, classes.ind2str(arg).replace('_',' ')))
        imBatch = torch.cat(allIms)
        printIms = utils.make_grid(imBatch)
        utils.save_image(printIms, './collected_images.png')

    elif image != '':
        image = Image.open(image)
        image = func.resize(image, (224,224))
        image.show()
        image = func.to_tensor(image).unsqueeze(0)

        result = network(image).squeeze()

        _, arg = torch.max(result,0)
        arg = arg.item()

        print("Index: {0}, Classification: {1}".format(arg,classes.ind2str(arg).replace('_',' ')))

    else:
        print("Invalid image or folder")


from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index),
    url(r'^users$', views.users),
    url(r'^process$', views.process),
    url(r'^user_interests/(?P<user_id>\d+)$', views.user_interests)

]


from tkinter import *
from tkinter import ttk
import numpy as np
from algorithms.bubbleSort import bubble_sort
from algorithms.quickSort import quick_sort
from algorithms.mergeSort import merge_sort

# Initialising Tkinter
root = Tk()
root.title('Sort Visualizer')
root.maxsize(700, 600)
root.config(bg='lightblue')

# Variables
selected_alg = StringVar()
data = []

# Functions
# Given the data list and correspoding color list, plots bar graph on canvas
def plot_data(data, colorArray):
    canvas.delete("all")
    c_height = 380
    c_width = 600
    x_width = c_width / (len(data) + 1)
    offset = 30
    spacing = 10
    normalizedData = [i / max(data) for i in data]
    for i, height in enumerate(normalizedData):
        x0 = i * x_width + offset + spacing
        y0 = c_height - height * 340
        x1 = (i + 1) * x_width + offset
        y1 = c_height
        canvas.create_rectangle(x0, y0, x1, y1, fill=colorArray[i])
        canvas.create_text(x0+2, y0, anchor=SW, text=str(data[i]))
    root.update_idletasks()

# Based on the user values for min, max and size; creates a list of random values
def generate():
    global data
    minVal = int(min_scale.get())
    maxVal = int(max_scale.get())
    size = int(size_scale.get())
    if(minVal > maxVal):
        minVal, maxVal = maxVal, minVal
    data = list(np.random.randint(minVal, maxVal, size))
    plot_data(data, ['salmon' for x in range(len(data))])

def start_sort():
    global data
    if not data:
        return
    s = menu.get()
    if s == 'Quick Sort':
        quick_sort(data, 0, len(data)-1, plot_data, speed_scale.get())
    elif s == 'Bubble Sort':
        bubble_sort(data, plot_data, speed_scale.get())
    elif s == 'Merge Sort':
        merge_sort(data, plot_data, speed_scale.get())
    plot_data(data, ['green' for x in range(len(data))])

# Base Layout
interface = Frame(
    root,
    width=600,
    height=200,
    bg='lightblue'
)
interface.grid(row=0, column=0, padx=10, pady=10)

canvas = Canvas(
    root,
    width=600,
    height=380,
    bg='lightblue'
)
canvas.grid(row=1, column=0, padx=10, pady=10)

# Algorithm Selection Label
Label(
    interface,
    text="Select Algorithm: ",
    bg='lightblue'
).grid(row=0, column=0, padx=5, pady=5, sticky=W)

# Algorithm Selection Dropdown
menu = ttk.Combobox(
    interface,
    textvariable=selected_alg,
    values=[
        'Bubble Sort',
        'Merge Sort',
        'Quick Sort'
    ]
)
# Sets the default value to the first Dropdown value
menu.current(0)
menu.grid(row=0, column=1, padx=5, pady=5)

# Dataset Size Scaler
size_scale = Scale(
    interface,
    from_=3,
    to=10,
    resolution=1,
    orient=HORIZONTAL,
    label="Dataset Size",
    bg='salmon'
)
size_scale.grid(row=0, column=2, padx=5, pady=5)

# Speed Value Scaler
speed_scale = Scale(
    interface,
    from_=0.1,
    to=3.0,
    length=100,
    digits=2,
    resolution=0.2,
    orient=HORIZONTAL,
    label="Speed Selector",
    bg='salmon'
)
speed_scale.grid(row=1, column=0, padx=5, pady=5)

# Minimum Value Scaler
min_scale = Scale(
    interface,
    from_=0,
    to=100,
    resolution=1,
    orient=HORIZONTAL,
    label="Minimum Value",
    bg='salmon'
)
min_scale.grid(row=1, column=1, padx=5, pady=5)

# Maximum Value Scaler
max_scale = Scale(
    interface,
    from_=10,
    to=100,
    resolution=1,
    orient=HORIZONTAL,
    label="Maximum Value",
    bg='salmon'
)
max_scale.grid(row=1, column=2, padx=5, pady=5)

# Start Button
Button(
    interface,
    text="   Start   ",
    command=start_sort,
    bg='salmon'
).grid(row=0, column=3, padx=5, pady=5)

# Generate Button
Button(
    interface,
    text="Generate",
    command=generate,
    bg='salmon'
).grid(row=1, column=3, padx=5, pady=5)

root.mainloop()


import contextlib
import io
import os
import shutil
import tempfile
import textwrap
import tokenize
import unittest
import unittest.mock as mock

from traits.api import HasTraits, Int
from traits.testing.optional_dependencies import sphinx, requires_sphinx

if sphinx is not None:
    from sphinx.ext.autodoc import Options
    from sphinx.ext.autodoc.directive import DocumenterBridge
    from sphinx.testing.path import path
    from sphinx.testing.util import SphinxTestApp
    from sphinx.util.docutils import LoggingReporter

    from traits.util.trait_documenter import (
        _get_definition_tokens,
        TraitDocumenter,
    )

class MyTestClass(HasTraits):
    """
    Class-level docstring.
    """
    #: I'm a troublesome trait with a long definition.
    bar = Int(42, desc=""" First line

        The answer to
        Life,
        the Universe,

        and Everything.
    """)

@requires_sphinx
class TestTraitDocumenter(unittest.TestCase):
    """ Tests for the trait documenter. """

    def setUp(self):
        self.source = """
    depth_interval = Property(Tuple(Float, Float),
                              depends_on="_depth_interval")
"""
        string_io = io.StringIO(self.source)
        tokens = tokenize.generate_tokens(string_io.readline)
        self.tokens = tokens

    def test_get_definition_tokens(self):
        src = textwrap.dedent(
            """\
        depth_interval = Property(Tuple(Float, Float),
                                  depends_on="_depth_interval")
        """
        )
        string_io = io.StringIO(src)
        tokens = tokenize.generate_tokens(string_io.readline)

        definition_tokens = _get_definition_tokens(tokens)

        # Check if they are correctly untokenized. This should not raise.
        string = tokenize.untokenize(definition_tokens)

        self.assertEqual(src.rstrip(), string)

    def test_add_line(self):

        src = textwrap.dedent(
            """\
        class Fake(HasTraits):

            #: Test attribute
            test = Property(Bool, label="ミスあり")
        """
        )
        mocked_directive = mock.MagicMock()

        documenter = TraitDocumenter(mocked_directive, "test", "   ")
        documenter.object_name = "Property"

        with mock.patch(
            "traits.util.trait_documenter.inspect.getsource", return_value=src
        ):
            with mock.patch(
                (
                    "traits.util.trait_documenter.ClassLevelDocumenter"
                    ".add_directive_header"
                )
            ):
                documenter.add_directive_header("")

        self.assertEqual(
            len(documenter.directive.result.append.mock_calls), 1)

    def test_abbreviated_annotations(self):
        # Regression test for enthought/traits#493.
        with self.create_directive() as directive:
            documenter = TraitDocumenter(
                directive, __name__ + ".MyTestClass.bar")
            documenter.generate(all_members=True)
            result = directive.result

        # Find annotations line.
        for item in result:
            if item.lstrip().startswith(":annotation:"):
                break
        else:
            self.fail("Didn't find the expected trait :annotation:")

        # Annotation should be a single line.
        self.assertIn("First line", item)
        self.assertNotIn("\n", item)

    @contextlib.contextmanager
    def create_directive(self):
        """
        Helper function to create a a "directive" suitable
        for instantiating the TraitDocumenter with, along with resources
        to support that directive, and clean up the resources afterwards.

        Returns
        -------
        contextmanager
            A context manager that returns a DocumenterBridge instance.
        """
        with self.tmpdir() as tmpdir:
            # The configuration file must exist, but it's okay if it's empty.
            conf_file = os.path.join(tmpdir, "conf.py")
            with io.open(conf_file, "w", encoding="utf-8"):
                pass

            app = SphinxTestApp(srcdir=path(tmpdir))
            app.builder.env.app = app
            app.builder.env.temp_data["docname"] = "dummy"

            # Backwards compatibility hack: for now, we need to be compatible
            # with both Sphinx < 2.1 (whose DocumenterBridge doesn't take
            # a state argument) and Sphinx >= 2.3 (which warns if the state
            # isn't passed). Eventually we should be able to drop support
            # for Sphinx < 2.1.
            kwds = {}
            if sphinx.version_info >= (2, 1):
                state = mock.Mock()
                state.document.settings.tab_width = 8
                kwds["state"] = state
            yield DocumenterBridge(
                app.env, LoggingReporter(''), Options(), 1, **kwds)

    @contextlib.contextmanager
    def tmpdir(self):
        """
        Helper function to create a temporary directory.

        Returns
        -------
        contextmanager
            Context manager that returns the path to a temporary directory.
        """
        tmpdir = tempfile.mkdtemp()
        try:
            yield tmpdir
        finally:
            shutil.rmtree(tmpdir)


# -*- coding: utf-8 -*-
"""
Created on Thu May 23 15:31:52 2019

@author: David
"""

#import mysql.connector
import requests
from bs4 import BeautifulSoup
import pandas as pd
import re

def convert_dms_to_decimal(dms):
    decimal = (((int(dms[2]) /60) + int(dms[1]))/60 + int(dms[0]))
    return decimal

url = 'https://de.wikipedia.org/wiki/Liste_der_Berliner_U-Bahnh%C3%B6fe'
resp = requests.get(url)
soup = BeautifulSoup(resp.text, 'lxml')

stationTable = soup.findAll('table',{"class":"wikitable sortable"})[1]
stationTable_rows = stationTable.find_all('tr')

stations_data = []

stationTable_rows = stationTable_rows[1:]

for num, element in enumerate(stationTable_rows, start =0):

    station_data = []
    td = stationTable_rows[num].find_all('td')

    for num, element in enumerate(td[0].find_all('a'), start=0):
        if num == 1:
            geodata = element.getText()
            geodata_split = geodata.split(',')
            geodata_split[0]
            latitude_dms = re.findall("[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?", geodata_split[0])
            latitude = convert_dms_to_decimal(latitude_dms)
            longitude_dms = re.findall("[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?", geodata_split[1])
            longitude = convert_dms_to_decimal(longitude_dms)
            station_data.append(latitude)
            station_data.append(longitude)
        else:
            station_name = element.getText()
            station_name = re.sub(r'\([^)]*\)', '', station_name)
            station_data.append(station_name.rstrip())

    #station_data.append(td[1]['data-sort-value'])
    station_data.append(td[4].getText())
    station_data.append('https://de.wikipedia.org' + td[0].find('a')['href'])
    stations_data.append(station_data)

#df=pd.DataFrame(stations_data ,columns=['station_name','latitude','longitude','line_name','district_name', 'station_link'])
df_allStations=pd.DataFrame(stations_data ,columns=['station_name','latitude','longitude','district_name', 'station_link'])
df_allStations = df_allStations.dropna()
df_allStations.drop_duplicates(subset ="station_name", keep = 'first', inplace = True)

df_allStations.to_csv ('C:/Users/David/Desktop/station_data.csv', index = None, header=True)


#Compares the value of two numbers, whether one is greater or equal than other.

username_1 = (input('¿Cuál es tu nombre? '))
userage_1 = int(input('¿Cuál es tu edad? '))
username_2 = (input('¿Cuál es tu nombre? '))
userage_2 = int(input('¿Cuál es tu edad? '))

def run():
    if userage_1 > userage_2:
        print(f'{username_1} es mayor que {username_2}')
    elif userage_1 < userage_2:
        print(f'{username_1} es menor que {username_2}')
    else:
        print(f'{username_1} es igual a {username_2}')

if __name__ == "__main__":
    run()


import setuptools

with open('README.md', 'r') as fh:
    long_description = fh.read()

setuptools.setup(
    name='res2desc',  # Replace with your own username
    version='0.1.0',
    author='Bonan Zhu',
    author_email='zhubonan@outlook.com',
    description=
    'Commandline interface for computing descriptors for AIRSS search results',
    long_description=long_description,
    long_description_content_type='text/markdown',
    url='https://github.com/zhubonan/res2desc',
    packages=setuptools.find_packages(),
    classifiers=[
        'Programming Language :: Python :: 3',
        'License :: OSI Approved :: MIT License',
        'Operating System :: OS Independent',
    ],
    install_requires=['dscribe>=0.3.5', 'click>=7.0', 'tabulate', 'pandas'],
    extras_require={'testing': ['pytest>=5.0']},
    python_requires='>=3.6',
    entry_points='''
        [console_scripts]
        res2desc=res2desc.cli:cli
    ''')


import math

alphabet = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ '")

test_cases = int(input())

for i in range(test_cases):
    aphorism = input()
    n = len(aphorism)
    diameter = 60
    circumference = 2 * math.pi * diameter / 2
    distance_between_2_signs = circumference / 28

    def minimal_distance(index_1, index_2):
        distance_a = (index_1 - index_2) % len(alphabet)
        distance_b = (index_2 - index_1) % len(alphabet)
        return min(distance_a, distance_b) * distance_between_2_signs

    total_distance = 0

    for i in range(n - 1):
        index_1 = alphabet.index(aphorism[i])
        index_2 = alphabet.index(aphorism[i + 1])
        distance = minimal_distance(index_1, index_2)
        total_distance += distance

    print(total_distance / 15 + len(aphorism))


import lxml.etree as ET
import os
from textwrap import dedent

# run from top-level uwlswd folder
# changes DOIs in UWLSWD resource rdf:Description @rdf:about attributes to lowercase

def process_file(filepath):
    edited = False
    tree = ET.parse(filepath)
    root = tree.getroot()

    for child in root:
        if child.tag == '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description':
            if '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about' in child.attrib:
                if "https://doi.org/" in child.attrib['{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about']:
                    old_doi = child.attrib['{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about']
                    if '#' in old_doi:
                        lc_doi = old_doi.split('#')
                        if lc_doi[0].islower() == False:
                            lc_doi[0] = lc_doi[0].lower()
                            final_doi = lc_doi[0] + '#' + lc_doi[1]
                            child.attrib['{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about'] = final_doi
                            edited = True
                    else:
                        if old_doi.islower() == False:
                            final_doi = old_doi.lower()
                            child.attrib['{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about'] = final_doi
                            edited = True
    if edited == True:
        tree.write(filepath, xml_declaration=True, encoding="UTF-8")
        print("DOI changed to lowercase")

# get file path
def prompt_user():
    file_prompt = dedent("""Enter the path of the folder or file relative to the working directory.
    The file must have the extenstion ".rdf",
    if entering the path of a folder, each '.rdf' file within the directory will be serialized
    For example: ../uwlswd_vocabs or ../uwlswd_vocabs/linked_data_platforms.rdf
> """)
    file_path = input(file_prompt)

    if os.path.exists(file_path):
        return file_path

    else:
        print(dedent("\nError: file could not be found. Please re-enter file name or press CTRL+C to cancel.\n"))
        return prompt_user()

file_path = prompt_user()
if os.path.isfile(file_path):
    if file_path.endswith('.rdf'):
        print("\nprocessing " + file_path)
        process_file(file_path)
    else:
        print("Input must be an rdf file or a directory containing rdf files")
        exit()

elif os.path.isdir(file_path):
    complete_files = []

    for root, dir_names, file_names in os.walk(file_path):
        for f in file_names:
            if f.endswith('.rdf'):
                complete_files.append(os.path.join(root, f))

    for f in complete_files:
        print("\nprocessing " + f)
        process_file(f)


"""upgrade table for s3

Revision ID: 7d02396887fb
Revises: 397763fb176d
Create Date: 2023-04-26 08:37:28.381065

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '7d02396887fb'
down_revision = '397763fb176d'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('images', schema=None) as batch_op:
        batch_op.add_column(sa.Column('original_filename', sa.String(length=100), nullable=True))
        batch_op.add_column(sa.Column('filename', sa.String(length=100), nullable=True))
        batch_op.add_column(sa.Column('bucket', sa.String(length=100), nullable=True))
        batch_op.add_column(sa.Column('region', sa.String(length=100), nullable=True))
        batch_op.drop_constraint('images_img_key', type_='unique')
        batch_op.drop_column('name')
        batch_op.drop_column('mimetype')
        batch_op.drop_column('img')

    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('images', schema=None) as batch_op:
        batch_op.add_column(sa.Column('img', sa.VARCHAR(), autoincrement=False, nullable=False))
        batch_op.add_column(sa.Column('mimetype', sa.VARCHAR(), autoincrement=False, nullable=False))
        batch_op.add_column(sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=False))
        batch_op.create_unique_constraint('images_img_key', ['img'])
        batch_op.drop_column('region')
        batch_op.drop_column('bucket')
        batch_op.drop_column('filename')
        batch_op.drop_column('original_filename')

    # ### end Alembic commands ###


D = {'A':'T','C':'G','G':'C','T':'A'}

rc = lambda x: ''.join([D[B] for B in x[::-1]])
comp = lambda x:''.join([D[B] for B in x])

reverse_complement = lambda x: ''.join([{'A':'T','C':'G','G':'C','T':'A', 'N':'N'}[B] for B in x][::-1])

rc2 = lambda x: ''.join([{'A':'T','C':'G','G':'C','T':'A', 'N':'N'}[B] for B in x][::-1])

import time
a=time.time()
for i in range(100000):
   r=comp('ACAAAAAAAAAAAAAAAAAAAAAAAAAGACCGGATCAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC')
b = time.time()
print(b-a)

a=time.time()
for i in range(100000):
   r=rc('ACAAAAAAAAAAAAAAAAAAAAAAAAAAGACCGGATCAACCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC')
b = time.time()
print(b-a)


from environment import Environment

env = Environment(p1=1, p2=0)
state = (0, 0)
while True:
    moves = input()
    move = ''
    if moves == 'w':
        move = 'up'
    elif moves == 'a':
        move = 'left'
    elif moves == 'd':
        move = 'right'
    elif moves == 's':
        move = 'down'
    response = env.agent_makes_decision(move, state)
    row, col = response['location']
    state = response['location']
    for x in range(9, -1, -1):
        for y in range(10):
            if row == x and col == y:
                print('*', end='')
            else:
                print('-', end='')
        print('')


# -*- coding: utf-8 -*-
"""
DSC 430 Assignment 0401

Scott Elmore
10/15/19

 “I have not given or received any
unauthorized assistance on this assignment”

YouTube Link : https://www.youtube.com/watch?v=-X_ucqpjzkY
"""
import random

def binSearch(sorted_nums, n, index):
    '''binary seach algoritm in O(log n) complexity.
    Seraches the list sorted_nums for the number n and
    makes sure it's not the same number from the index
    passed in. Return True if found, False otherwise.'''
    # set first and last parameters, last is length of list
    first = 0
    last = len(sorted_nums) - 1

    # found parameter for loop exit condition
    found = False

    # continue to loop until found or end of search
    while(first <= last and not found):
        # set mid to floor of midpoint
        mid = (first + last)//2

        # if number found and not the same as the given index, return True
        if sorted_nums[mid] == n and mid != index:
            found = True
        else:
            # continue to iterate with new first and last parameters
            if n < sorted_nums[mid]:
                last = mid - 1
            else:
                first = mid + 1
    # return whether or not number is found
    return found

def iterList(sorted_nums, n):
    '''iterate through the list of sorted nums; O(n) complexity.
    For each number run binSearch() to check for the corresponding
    number that will sum to n (n - num). Make sure binSearch is not
    returning own number by iterating with index.'''
    # iterate numbers in sorted_nums, get index with enumerate
    for i, num in enumerate(sorted_nums):
        # if correct number if found; stop iterating
        if binSearch(sorted_nums, n - num, i):
            # return the first number of the sum for print purposes
            return num
    # return None for print purposes
    return None

def toSortedList(i):
    '''create a sorted list of length i of random numbers 0 through 100.'''
    # initialize empty randoms list
    randoms = []
    for x in range(i):
        # add a random integer 0-100 to list
        randoms.append(random.randint(0, 100))

    # use python list sort for sorted list; O(n log n) complexity
    randoms.sort()
    return randoms

def getFromUser():
    '''prompt and return both the size of the random list of integers, i, and the number
    n of which to check if two numbers in the list sum to that number n.'''

    i = eval(input(
        'How many numbers between 0 to 100 would you like to check? Must be greater than 1: '))
    n = eval(input('What number would you like to sum to? '))
    return i, n

def Main():
    '''Main program for Goldbach Deuce. Get parameters from user, make a random list of integers
    and then use Binary Search to check if there are two integers which add to a number n.'''

    i, n = getFromUser()
    # random, sorted list of integers 0-100
    sorted_nums = toSortedList(i)

    # first_num is first number in addition, therefore n-first_num is second
    first_num = iterList(sorted_nums, n)
    if first_num is not None:
        print('\nThe randomly generted list has two numbers that sum to ' + str(n)
              + ':\n\t' + str(first_num) + ' + ' + str(n-first_num) + ' = ' + str(n))
    else:
        # number was not found
        print(
            '\nThe randomly generated list does not contain numbers that sum to ' + str(n))

Main()


import numpy as np
from numpy.random import default_rng
from ..dynamics import recover_dynamics_scvelo

# Make random subsets of scRNAseq data with or without replacement
# Make the list of cell indices
def subsampling(data, num_subsamples=5, subsample_size_ratio=0.8, bootstrap=False, random_state=0, copy=False):

    adata = data.copy() if copy else data

    # Set seed fo reproducibility
    rng = default_rng(random_state)

    # sub-sample size; subsample_size_ratio only relevant for sampling without replacement
    adata_shape = adata.shape[0]
    if not bootstrap:
        subsample_size = int(adata_shape*subsample_size_ratio)
        subsample_index_array = np.empty((num_subsamples, subsample_size), dtype=int)
        for i in range(num_subsamples):
            subsample_index_array[i] = rng.choice(adata_shape, size=subsample_size, replace=False)
    else:
        subsample_size = adata_shape
        subsample_index_array = rng.choice(adata_shape, size=(num_subsamples, subsample_size), replace=True)

    if 'subsampling' not in adata.uns.keys():
        adata.uns['subsampling'] = {}

    adata.uns['subsampling']['params'] = {'subsample_size': subsample_size,
                                       'subsample_size_ratio': subsample_size_ratio,
                                       'bootstrap': bootstrap,
                                       'random_state': random_state
                                      }
    adata.uns['subsampling']['index_array'] = subsample_index_array

    if copy: return adata

# Generate subsamples
def generate_subsample(adata, return_dynamics=True):

    try: isinstance(adata.uns['subsampling']['index_array'], np.ndarray)
    except: raise ValueError('Run subsampling first.')

    num_subsamples = adata.uns['subsampling']['index_array'].shape[0]
    for i in range(num_subsamples):
        current_state = i
        adata_ = adata[adata.uns['subsampling']['index_array'][i]].copy()
        try:
            if return_dynamics:
                adata_.var = adata.uns['subsampling']['parameter_sets'][i]
                adata_.layers['fit_t'] = adata.uns['subsampling']['gene_latent_times'][i]
        except: pass
        yield adata_

# Return a singular subsample
def return_subsample(adata, i, return_dynamics=True):

    try: isinstance(adata.uns['subsampling']['index_array'], np.ndarray)
    except: raise ValueError('Run subsampling first.')

    adata_ = adata[adata.uns['subsampling']['index_array'][i]].copy()
    try:
        if return_dynamics:
            adata_.var = adata.uns['subsampling']['parameter_sets'][i]
            adata_.layers['fit_t'] = adata.uns['subsampling']['gene_latent_times'][i]
    except: pass

    return adata_

# Recover dynamics for subsamples
def infer_subsample_dynamics(adata, method='scvelo', **kwargs):

    if method=='scvelo':
        parameter_sets = []
        gene_latent_times = []
        for adata_ in generate_subsample(adata, return_dynamics=False):
            var, fit_t = recover_dynamics_scvelo(adata_, **kwargs)
            parameter_sets.append(var)
            gene_latent_times.append(fit_t)

    adata.uns['subsampling']['parameter_sets'] = parameter_sets
    adata.uns['subsampling']['gene_latent_times'] = gene_latent_times


import calendar
import datetime

import httpx
from loguru import logger

from lnbits.core.services import fee_reserve, get_wallet

async def check_balance(data) -> bool:
    # check if we can pay the invoice before we create the actual swap on boltz
    amount_msat = data.amount * 1000
    fee_reserve_msat = fee_reserve(amount_msat)
    wallet = await get_wallet(data.wallet)
    assert wallet
    if wallet.balance_msat - fee_reserve_msat < amount_msat:
        return False
    return True

def get_timestamp():
    date = datetime.datetime.utcnow()
    return calendar.timegm(date.utctimetuple())

def req_wrap(funcname, *args, **kwargs):
    try:
        try:
            func = getattr(httpx, funcname)
        except AttributeError:
            logger.error('httpx function not found "%s"' % funcname)
        else:
            res = func(*args, timeout=30, **kwargs)
        res.raise_for_status()
        return res
    except httpx.RequestError as exc:
        msg = f"Unreachable: {exc.request.url!r}."
        logger.error(msg)
        raise
    except httpx.HTTPStatusError as exc:
        msg = f"HTTP Status Error: {exc.response.status_code} while requesting {exc.request.url!r}."
        logger.error(msg)
        logger.error(exc.response.json()["error"])
        raise


def listnumber(stocklist):
    lookinglist = {
        "stock":1,
        "Low":2,
        "S1":3,
        "Mode":4,
        "S2":5,
        "Mode":6,
        "S3":7,
        "Mode":8,
        "R1":9,
        "Mode":10,
        "R2":11,
        "Mode":12,
        "R3":13,
        "Mode":14,
        "R4":15,
        "Mode":16,
        "R5":17,
        "Mode":18,
        "LastPrice":19,
        "BreakS1":20,
        "BreakS2":21,
        "BreakS3":22,
        "BreakR1":23,
        "BreakR2":24,
        "BreakR3":25,
        "BreakR4":26,
        "BreakR5":27,
        "Entry":28,
        "Reward":29,
        "Risk":30,
        "RR":31,
        "Entry":32,
        "Reward":33,
        "Risk":34,
        "RR":35,
        }
    stocklistnumber = lookinglist[stocklist]
    return stocklistnumber


import random
from colorama import Fore
n=1
class batsman:
    def __init__(self,name,nick,hand,score,balls_faced,status):
        self.name=name
        self.nick=nick
        self.hand=hand
        self.score=score
        self.balls_faced=balls_faced
        self.status=status

    def bat(self):
        list1=[1,1,1,1,2,1,1,1,1,1,2,2,2,2,3,4,6,0]
        n = random.choice(list1)
        self.score=self.score+n
        self.balls_faced=self.balls_faced+1
        #print(f"You got {n} runs")
        return n

class bowler:
    def __int__(self,name,hand,wickets,balls_bowled):
        self.name=name
        self.hand=hand
        self.wickets=wickets
        self.balls_bowled=balls_bowled

sanath=batsman ("Sanath Jayasooriya","sanath","left",0,0,"Not Out")
kalu=batsman ("Romesh Kaluwitharana","kalu","right",0,0,"Not Out")
gura=batsman ("Asanka Gurusinghe","gura","left",0,0,"Not Out")
ara=batsman ("Aravinda de Silva","ara","right",0,0,"Not Out")
hashan=batsman ("Hashan Thilakarathne","hashan","left",0,0,"Not Out")
vass=batsman ("Chaminda Vass","vass","left",0,0,"Not Out")

pool_of_players=[sanath,kalu,gura,ara,hashan,vass]

def add_player():
    pool_of_players2=[]
    name= input("Please Enter Name of the Player :")
    nick_name=input("Please Enter Nick Name of the Player: ")
    nick_name2=nick_name
    hand=input("Left hand or Right hand: ")

    for yy in pool_of_players:
        pool_of_players2.append(yy.nick)
    if nick_name not in pool_of_players2:
        globals()[nick_name] = batsman(name,nick_name2,hand,0,0,"Not Out")
        pool_of_players.append(globals()[nick_name])
    else:
        print("The Player Already in the Pool")

i=0
no_of_batters=6
list_nick=[]

def bat_order():
    bat_order = []
    list_nick = []
    for za in pool_of_players:
        list_nick.append(za.nick)
    print(Fore.WHITE,f"the available players are\n  {list_nick}")
    for batting_position in range (0,no_of_batters):

        batter_name=input(f"Enter the name of Batting Position {batting_position+1} :")

        while batter_name not in list_nick:
            print("Your player is not in the pool or already allocated")
            print(f"the available players are\n  {list_nick}")
            batter_name = input(f"Enter the name of Batting Position {batting_position + 1} :")
        for z in pool_of_players:
            if z.nick==batter_name:
                bat_order.append(z)
                pool_of_players.remove(z)
        list_nick=[]
        for za in pool_of_players:
            list_nick.append(za.nick)
        print(f"The available players are {list_nick}")

    return bat_order

def playmatch (no_of_balls,bat_order):
    i=0
    for x in range(0, no_of_balls):
        score=bat_order[i].bat()
        if score==0:
            bat_order[i].status="Out"
            i=i+1
        if i==len(bat_order):
            print ("-----------------------ALL OUT-------------------")
            print(f"No of balls faced {x+1}")
            break

tot=0
def print_scorecard():
    print("--------------------------------------------------------------------------------------------------")
    print("--------------------------------------------------------------------------------------------------")
    print(Fore.GREEN, f"{batt_order[0].name}              {batt_order[0].score}     ({batt_order[0].balls_faced})   {batt_order[0].status}")
    print(Fore.GREEN, f"{batt_order[1].name}              {batt_order[1].score}     ({batt_order[1].balls_faced})   {batt_order[1].status}")
    print(Fore.GREEN, f"{batt_order[2].name}              {batt_order[2].score}     ({batt_order[2].balls_faced})  {batt_order[2].status}")
    print(Fore.GREEN, f"{batt_order[3].name}              {batt_order[3].score}     ({batt_order[3].balls_faced})  {batt_order[3].status}")
    print(Fore.GREEN, f"{batt_order[4].name}              {batt_order[4].score}     ({batt_order[4].balls_faced})   {batt_order[4].status}")
    print(Fore.GREEN, f"{batt_order[5].name}              {batt_order[5].score}     ({batt_order[5].balls_faced})   {batt_order[5].status}")
    #print("--------------------------------------------------------------------------------------------------")
    print("--------------------------------------------------------------------------------------------------")
    print(Fore.BLUE,f"-----Team Total is {batt_order[0].score+ batt_order[1].score+batt_order[2].score+batt_order[3].score+batt_order[4].score+batt_order[5].score}--------")
    print("--------------------------------------------------------------------------------------------------")
    #print("--------------------------------------------------------------------------------------------------")
def print_pool(pool_of_players):
    for ii in pool_of_players:
        print(Fore.BLUE,ii.name)
def print_bat_order(pool_of_players):
    jj=1
    for ii in pool_of_players:
        print(f"{jj}.{ii.name}")
        jj=jj+1

#------------------------------------------Game Starts--------------------------------------------

print("We are going to Play a lovely game of cricket.......")
print(f"These are the current players in the squad....")
print_pool(pool_of_players)

user_in=input("Do you want to add any player:")
while user_in=="y":
    add_player()
    print(f"These are the current players in the squad....")
    print_pool(pool_of_players)
    user_in = input("Do you want to add any player:")

batt_order=bat_order()
print("This is the batting Order")
print_bat_order(batt_order)
no_of_balls1 = input("Please enter the no of Balls per match: ")
while no_of_balls1.isnumeric()==False:
    print("Entry not Valid, Enter a Valid number")
    no_of_balls1 = input("Please enter the no of Balls per match: ")

no_of_balls=int(no_of_balls1)
playmatch(no_of_balls,batt_order)
print_scorecard()


"""taskapplication URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from task.views import IndexView,LoginView,RegisterView,AddTaskView, TaskDetailView,TaskListView,TaskDeleteView,RegistrationView,LoginnView
from task import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    # path("home/",IndexView.as_view()),
    # path("login/",LoginView.as_view()),
    # path("register/",RegisterView.as_view()),
    path("task/add",views.AddTaskView.as_view(),name="todo-add"),
    path("todos/all",views.TaskListView.as_view(),name="todo-all"),
    path("todos/<int:id>",views.TaskDetailView.as_view(),name="todo-detail"),
    path("todos/<int:id>/remove",views.TaskDeleteView.as_view(),name="todo-delete"),
    path("accounts/register",views.RegistrationView.as_view(),name="register"),
    path("",views.LoginnView.as_view(),name="signin"),
    path("accounts/logout",views.signout_view,name="signout"),
    path("todos/changes/<int:id>",views.TaskUpdateView.as_view(),name="todo-update")
]


from pyPS4Controller.controller import Controller
from paho.mqtt import client as mqtt_client
import random
import logging
import json

broker = 'test.mosquitto.org'
port = 1883
topic = "python/mqtt/ds4msg"
client_id = f'python-mqtt-{random.randint(0, 1000)}'
username = ''
password = ''

logging.basicConfig(
    format='[ds4MQTT][%(asctime)s]\t[%(levelname)s]\t%(message)s',
    level=logging.DEBUG
)

class MyController(Controller):

    def __init__(self, **kwargs):
        Controller.__init__(self, **kwargs)

    def on_x_press(self):
        msg = "Custom x press message"
        logging.debug(msg)
        publish(client, msg)

def on_message(client, userdata, message):
    logging.info("Message received: "  + str(message.payload))

def connect_mqtt():
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            logging.info("Connected to MQTT Broker!")
        else:
            logging.warn("Failed to connect, return code %d\n", rc)
    # Set Connecting Client ID
    client = mqtt_client.Client(client_id)
    client.username_pw_set(username, password)
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(broker, port)
    return client

def publish(client, msg="<empty message>"):
    result = client.publish(topic, msg)
    status = result[0]
    if status == 0:
        logging.info(f"Sent `{msg}` to topic `{topic}`")
    else:
        logging.warn(f"Failed to send message to topic {topic}")

controller = MyController(interface="/dev/input/js0", connecting_using_ds4drv=False)

client = connect_mqtt()
def run():
    client.loop_start()
    client.subscribe(topic)
    publish(client)
    controller.listen()

if __name__ == '__main__':
    run()


#Manuel Ortiz at 2022
#Extracted from: https://leetcode.com/problems/search-in-a-binary-search-tree/

from node import Node, in_order_traversal

def rec_find_node(node, val):
    if not node:
        return None
    if node.data == val:
        return node
    if val < node.data:
        return rec_find_node(node.left, val)
    return rec_find_node(node.right,val)

def find_node(node,val):
    while node:
        if val < node.data:
            node = node.left
        elif val > node.data:
            node = node.right
        else:
            return node

    return None

root = Node(2, Node(7, Node(12), Node(6)), Node(5, Node(8), Node(9)))
node_rec = rec_find_node(root, 5)
node = find_node(root, 5)
print(in_order_traversal(node_rec, []))
print('----')
print(in_order_traversal(node, []))


import os
import osmium
import numpy as np
import alphashape
from shapely.geometry import MultiPolygon
import yaml
import json
import re
from polycache import PolyCache
from web_server import start_web_server
import concurrent.futures
from gen_postal_codes import gen_postal_codes

polycache = PolyCache("data/polycache.json",'coordinates')
pointcache = PolyCache("data/pointcache.json", 'points')

def key(postal_code):
    return f"{postal_code['start']}-{postal_code['end']}"

class PostalCodeHandler(osmium.SimpleHandler):
    def __init__(self, postal_code_ranges):
        super(PostalCodeHandler, self).__init__()
        self.postal_code_ranges = postal_code_ranges

    def node(self, n):
        if postal_code_tag in n.tags and self._is_valid_postal_code(n.tags[postal_code_tag]):
            postal_code = int(n.tags[postal_code_tag][:4])  # Extract first four digits of postal code
            for pcr in self.postal_code_ranges:
                if int(pcr['start']) <= postal_code <= int(pcr['end']):
                    if 'points' not in pcr:
                        pcr['points'] = []
                    pcr['points'].append((n.location.lon, n.location.lat))
                    break

    def _is_valid_postal_code(self, postal_code):
        pattern = r"[0-9]{4} ?[A-Za-z]{2}"
        return re.match(pattern, postal_code) is not None

def extract_points(xml_file, postal_code_ranges):
    cached, uncached = pointcache.get_cached(postal_code_ranges)
    print(f"{len(cached)} cached pointclouds reused, {len(uncached)} uncached")

    if len(uncached) > 0:
        handler = PostalCodeHandler(uncached)
        handler.apply_file(xml_file)

        pointcache.update_all(handler.postal_code_ranges)

        return handler.postal_code_ranges + cached

    return cached

def calculate_boundary(cloud):
        points_array = np.array(cloud.pop('points',[]))
        alpha = 55
        hull = alphashape.alphashape(points_array, alpha)
        while type(hull) is MultiPolygon and alpha > 10:
            alpha = alpha - 2
            hull = alphashape.alphashape(points_array, alpha)
        print(f"Ended with alpha at {alpha}")
        cloud['coordinates'] = [np.array(list(hull.exterior.coords)).tolist()]

        return cloud

def calculate_outer_boundaries(point_clouds):

    if not point_clouds:
        raise ValueError("No point clouds found for the given postal code ranges.")

    point_clouds = [c for c in point_clouds if 'points' in c]
    point_clouds = [c for c in point_clouds if len(c['points']) > 0]

    with concurrent.futures.ProcessPoolExecutor() as executor:
        futures = [executor.submit(calculate_boundary, i) for i in point_clouds]

        results = []

        i = 0
        for future in futures:
            i = i + 1
            result = future.result()
            results.append(result)
            polycache.update(result)
            print(f"Progress: {i} / {len(futures)}")

    return results

def generate_geojson(polygons, geojson_file):
    features = []
    for item in polygons:
        feature = {
            "type": "Feature",
            "properties": {
                "start": item['start'],
                "end": item['end'],
                "tooltip": f"{item['start']} - {item['end']}
{item['name']}
{item['other_therapist']}",
                "colour": item['colour']
            },
            "geometry": {
                "type": "Polygon",
                "coordinates": item['coordinates']
            }
        }
        features.append(feature)

    data = {
        "type": "FeatureCollection",
        "features": features
    }

    with open(geojson_file, "w") as file:
        json.dump(data, file)

if __name__ == '__main__':
    with open('config.yaml') as file:
        config = yaml.load(file, Loader=yaml.FullLoader)

    gen_postal_codes()
    with open('data/postal_codes.yaml') as file:
        postal_code_ranges = yaml.load(file, Loader=yaml.FullLoader)['postal_codes']

    xml_file = config['xml_file']
    postal_code_tag = config['postal_code_tag']
    point_clouds_file = "data/point_clouds.json"
    geojson_file = "polygons.geojson"
    web_server_port = 8800

    try:
        if not os.path.isfile(geojson_file):

            cached, uncached = polycache.get_cached(postal_code_ranges)
            print(f"{len(cached)} cached polygons reused, {len(uncached)} uncached")
            for pc in uncached:
                print(polycache.key(pc))

            print(" ## Extracting points")
            point_clouds = extract_points(xml_file, uncached)

            print(" ## Calculating boundaries")
            polygons = calculate_outer_boundaries(point_clouds)

            print(" ## Converting data to geojson format")
            generated = cached + polygons
            generate_geojson(generated, geojson_file)

            print(f" ## GeoJSON file saved as {geojson_file}")

        start_web_server(web_server_port)
    except ValueError as e:
        print(e)


__author__ = 'Avinash'

import pymysql

# Open database connection
db = pymysql.connect("localhost", "root", "", "python_tutorials")

# prepare a cursor object using cursor() method
cursor = db.cursor()

# Prepare SQL query to INSERT a record into the database.
sql = "SELECT * FROM PERSON"
try:
    # Execute the SQL command
    cursor.execute(sql)
    # Fetch all the rows in a list of lists.
    results = cursor.fetchall()
    for row in results:
        fname = row[1]
        lname = row[2]
        age = row[3]
        sex = row[4]
        # Now print fetched result
        print("fname = %s, lname = %s, age = %d, sex = %s" %
              (fname, lname, age, sex, ))
except pymysql.Error:
    print("Error: unable to fetch data")

# disconnect from server
db.close()