'''
Unit test
'''

import unittest
from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
    ''' Tests for name_function.py '''

    def test_first_last_name(self):
        ''' Do names like Janis Joplin work '''
        formatted_name = get_formatted_name("Janis", "Joplin")
        self.assertEqual(formatted_name, "Janis Joplin")

    def test_first_last_middle_name(self):
        formatted_name = get_formatted_name("wolfgang", "wimmer", "bob")
        self.assertEqual(formatted_name, "Wolfgang Bob Wimmer")

if __name__ == "__main__":

    unittest.main()

'''

Example of a failing unittest:

Testing started at 06:42 ...

Ran 1 test in 0.000s

Janis Joplin1 != Janis Joplin

Expected :Janis Joplin
Actual   :Janis Joplin1
 <Click to see difference>

AssertionError: 'Janis Joplin' != 'Janis Joplin1'
- Janis Joplin
+ Janis Joplin1
?             +

'''

Python Crash Course/Chapter 11 Testing your code/test_name_function.py


from flask import Flask
import random

app = Flask(__name__)
rand_num = random.randint(0, 9)

@app.route("/")
def hello_world(text="Guess a number between 0 & 9",
                image="https://media.giphy.com/media/3o7aCSPqXE5C6T8tBC/giphy.gif"):
    return f'
{text}
' \
           f''

@app.route("/<int:number>")
def guess(number):
    if number > rand_num:
        return hello_world(text="Too high, try again!", image="https://media.giphy.com/media/3o6ZtaO9BZHcOjmErm/giphy.gif")
    elif number < rand_num:
        return hello_world(text="Too low, try again!", image="https://media.giphy.com/media/jD4DwBtqPXRXa/giphy.gif")
    else:
        return hello_world(text="You found me!", image="https://media.giphy.com/media/4T7e4DmcrP9du/giphy.gif")

if __name__ == "__main__":
    app.run(debug=True)


import ubelt as ub
import pytest

def test_auto_dict():
    auto = ub.AutoDict()
    assert 0 not in auto
    auto[0][10][100] = None
    assert 0 in auto
    assert isinstance(auto[0], ub.AutoDict)

def test_auto_dict_to_dict():
    from ubelt.util_dict import AutoDict
    auto = AutoDict()
    auto[1] = 1
    auto['n1'] = AutoDict()
    auto['n1']['n2'] = AutoDict()
    auto['n1']['n2'][2] = 2
    auto['n1']['n2'][3] = 3
    auto['dict'] = {}
    auto['dict']['n3'] = AutoDict()
    auto['dict']['n3']['n4'] = AutoDict()
    print('auto = {!r}'.format(auto))
    static = auto.to_dict()
    print('static = {!r}'.format(static))
    assert not isinstance(static, AutoDict), '{}'.format(type(static))
    assert not isinstance(static['n1'], AutoDict), '{}'.format(type(static['n1']))
    assert not isinstance(static['n1']['n2'], AutoDict)
    assert isinstance(static['dict']['n3'], AutoDict)
    assert isinstance(static['dict']['n3']['n4'], AutoDict)

def test_auto_dict_ordered():
    # To Dict should repsect ordering
    from ubelt.util_dict import AutoOrderedDict, AutoDict
    auto = AutoOrderedDict()
    auto[0][3] = 3
    auto[0][2] = 2
    auto[0][1] = 1
    auto[0][4] = AutoDict()
    assert isinstance(auto, AutoDict)
    print('auto = {!r}'.format(auto))
    static = auto.to_dict()
    print('static = {!r}'.format(static))
    assert not isinstance(static, AutoDict), 'bad cast {}'.format(type(static))
    assert not isinstance(static[0][4], AutoDict), 'bad cast {}'.format(type(static[0][4]))
    assert list(auto[0].values())[0:3] == [3, 2, 1], 'maintain order'

def test_group_items_sorted():
    pairs = [
        ('ham', 'protein'),
        ('jam', 'fruit'),
        ('spam', 'protein'),
        ('eggs', 'protein'),
        ('cheese', 'dairy'),
        ('banana', 'fruit'),
    ]
    item_list, groupid_list = zip(*pairs)
    result1 = ub.group_items(item_list, groupid_list, sorted_=False)
    result2 = ub.group_items(item_list, groupid_list, sorted_=True)
    result1 = ub.map_vals(set, result1)
    result2 = ub.map_vals(set, result2)
    assert result1 == result2

def test_group_items_sorted_mixed_types():
    import random
    groupid_list = [
        1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,
        '1', '2', '3', '1', '2', '3', '1', '2', '3', '1', '2', '3',
    ]
    item_list = list(range(len(groupid_list)))

    # Randomize the order
    random.Random(947043).shuffle(groupid_list)
    random.Random(947043).shuffle(item_list)

    result1 = ub.group_items(item_list, groupid_list, sorted_=True)
    result2 = ub.group_items(item_list, groupid_list, sorted_=False)

    result1 = ub.map_vals(set, result1)
    result2 = ub.map_vals(set, result2)
    assert result1 == result2

    assert '1' in result1
    assert 1 in result1

def test_dzip_errors():
    with pytest.raises(TypeError):
        ub.dzip([1], 2)
    with pytest.raises(TypeError):
        ub.dzip(1, [2])
    with pytest.raises(ValueError):
        ub.dzip([1, 2, 3], [])
    with pytest.raises(ValueError):
        ub.dzip([], [4, 5, 6])
    with pytest.raises(ValueError):
        ub.dzip([1, 2, 3], [4, 5])


from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from keras.utils import to_categorical
import numpy as np

PerfilI = np.zeros((1, 1000))

idade = np.random.randint(25,89, size=(1, 1000))
Iendiv = np.random.randint(70, 100, size=(1, 1000))
Poup = np.random.randint(9, size=(1, 1000))
Liqui = np.random.randint(81,100, size=(1, 1000))
Cobert = np.random.randint(30, size=(1, 1000))/100
Riqueza = np.random.randint(30, size=(1, 1000))
Score = np.random.randint(499, size=(1, 1000))
Faixa_Salarial  = np.random.randint(1045,2090, size=(1, 1000))
TempoEmpresa= np.random.randint(12, size=(1, 1000))
list = (idade, Iendiv, Poup, Liqui, Cobert, Riqueza, Score, Faixa_Salarial, TempoEmpresa)
for i in list:
    PerfilI= np.vstack((PerfilI,i))
PerfilI = PerfilI.T

PerfilR = np.ones((1, 1000))
idade = np.random.randint(25,89, size=(1, 1000))
Iendiv = np.random.randint(20, 70, size=(1, 1000))
Poup = np.random.randint(10,20, size=(1, 1000))
Liqui = np.random.randint(60, 80, size=(1, 1000))
Cobert = np.random.randint(30, 180, size=(1, 1000))
Riqueza = np.random.randint(30, 50, size=(1, 1000))/100
Score = np.random.randint(500, 700, size=(1, 1000))
Faixa_Salarial  = np.random.randint(2090,5225, size=(1, 1000))
TempoEmpresa= np.random.randint(12, 36, size=(1, 1000))
list = (idade, Iendiv, Poup, Liqui, Cobert, Riqueza, Score, Faixa_Salarial, TempoEmpresa)
for i in list:
    PerfilR= np.vstack((PerfilR,i))
PerfilR = PerfilR.T

PerfilBP = np.ones((1, 1000))+1
idade = np.random.randint(25,89, size=(1, 1000))
Iendiv = np.random.randint(20, size=(1, 1000))
Poup = np.random.randint(20, 100, size=(1, 1000))
Liqui = np.random.randint(60, size=(1, 1000))
Cobert = np.random.randint(72, 288, size=(1, 1000))
Riqueza = np.random.randint(50, 100, size=(1, 1000))/100
Score = np.random.randint(700,1000, size=(1, 1000))
Faixa_Salarial  = np.random.randint(6270, 31350, size=(1, 1000))
TempoEmpresa= np.random.randint(36, 240, size=(1, 1000))
list = (idade, Iendiv, Poup, Liqui, Cobert, Riqueza, Score, Faixa_Salarial, TempoEmpresa)
for i in list:
    PerfilBP= np.vstack((PerfilBP,i))
PerfilBP = PerfilBP.T

PerfilGeral = np.zeros((1,10))
PerfilGeral= np.vstack((PerfilGeral,PerfilI))
PerfilGeral= np.vstack((PerfilGeral,PerfilR))
PerfilGeral= np.vstack((PerfilGeral,PerfilBP))
PerfilGeral = PerfilGeral[1:]
print(PerfilGeral)

X = PerfilGeral [:,1:]
y = PerfilGeral[:,:1]
y = y.astype(int)
y = to_categorical(y)

# Dividindo o dataset em dados de treino e de teste.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 100)

# Normalização dos dados.
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

#  EXECUÇÃO DA REDE PARA OBTENÇÃO DE UM MODELO(APREDIZAGEM) PARA PREDIÇÕES
classifier = Sequential()
classifier.add(Dense(units = 22, kernel_initializer = 'uniform', activation = 'relu', input_dim = 9))
classifier.add(Dropout(p = 0.1))
classifier.add(Dense(units = 22, kernel_initializer = 'uniform', activation = 'relu'))
# classifier.add(Dropout(p = 0.1))
classifier.add(Dense(units = 3, kernel_initializer = 'uniform', activation = 'softmax'))
classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
classifier.fit(X_train, y_train, batch_size = 32, epochs = 100)

#MELHORIAS PARA AUMENTAR A ACURÁCIA DA REDE

#implementação da rede com Keras e novas "configurações"
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import cross_val_score
def build_classifieres():
    classifier = Sequential()
    classifier.add(Dense(units = 12, kernel_initializer = 'uniform', activation = 'relu', input_dim = 9))
    classifier.add(Dense(units = 12, kernel_initializer = 'uniform', activation = 'relu'))
    classifier.add(Dense(units = 3, kernel_initializer = 'uniform', activation = 'softmax'))
    classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
    return classifier
classifieres = KerasClassifier(build_fn = build_classifieres, batch_size = 32, epochs = 100)
accuracies = cross_val_score(estimator = classifieres, X = X_train, y = y_train, cv = 10, n_jobs = -1)
a= accuracies.mean()
print(a)

# FAZENDO UMA PREDIÇÃO SIMPLES, DE UM CLIENTE FICTÍCIO, APÓS O TREINAMENTO DO REDE.
print(' ')
print(' ')
print('PREDIÇÃO DO PERFIL DO CLIENTE')
print(' ')
Client_01 = classifier.predict(sc.transform(np.array([[66,51,10,66,104,0.33,645,3997,25]])))
for i in Client_01:
    if i[0] > 0.5:
            print('Cliente JOÃO possui: PERFIL O1')
            print('............')
            print('LIBERAR CRÉDTIO DE ATÉ 1.000 REAIS')
    if i[1] > 0.5:
            print('Cliente JOÃO possui: PERFIL O2')
            print('............')
            print('LIBERAR CRÉDTIO DE ATÉ 5.000 REAIS')
    if i[2] > 0.5:
            print('Cliente JOÃO possui: PERFIL O1')
            print('............')
            print('LIBERAR CRÉDTIO DE ATÉ 20.000 REAIS')


from typing import Union
from magma.bit import Bit
from magma.logging import root_logger
from magma.primitives.mux import mux
from magma.t import Type, In, Out, Direction
from magma.protocol_type import MagmaProtocol
from magma.tuple import Product, ProductKind

_logger = root_logger()

class ReadyValidException(Exception):
    pass

def _check_T(cls, T):
    if not issubclass(T, (Type, MagmaProtocol)):
        raise TypeError(
            f"{cls}[T] expected T to be a subclass of m.Type or"
            f" m.MagmaProtocol not {T}"
        )
    undirected_T = T.undirected_t
    if undirected_T is not T:
        _logger.warning(
            f"Type {T} used with ReadyValid is not undirected, converting"
            " to undirected type"
        )
    return undirected_T

def _maybe_add_data(cls, fields, T, qualifier):
    if T is None:
        return
    T = _check_T(cls, T)
    fields["data"] = qualifier(T)

class HandShakeError(Exception):
    pass

class EnqError(HandShakeError):
    def __init__(self, cls):
        super().__init__(f"{cls} does not support enq")

class NoEnqError(HandShakeError):
    def __init__(self, cls):
        super().__init__(f"{cls} does not support no_enq")

class DeqError(HandShakeError):
    def __init__(self, cls):
        super().__init__(f"{cls} does not support deq")

class NoDeqError(HandShakeError):
    def __init__(self, cls):
        super().__init__(f"{cls} does not support no_deq")

def _enq_error(self, value, when=True):
    raise EnqError(type(self))

def _no_enq_error(self, value, when=True):
    raise NoEnqError(type(self))

def _deq_error(self, value, when=True):
    raise DeqError(type(self))

def _no_deq_error(self, value, when=True):
    raise NoDeqError(type(self))

class HandShakeKind(ProductKind):
    """Undirected handshake type."""
    _qualifers_ = {
        "output": lambda x: x,
        "input": lambda x: x,
        "data": lambda x: x
    }

    def _make_fields(cls, T):
        """
        Each HandShake implementation should define a dict of _field_names_ for
        the signals (e.g. "ready" and "valid").  For consistency, we define the
        output/input names in terms of a Producer (i.e. ReadyValid outputs a
        valid and inputs a ready).

        Each implementation should define a dict of _qualifiers_ used to
        qualify the ports for producer, consumer, etc...
        """
        fields = {
            cls._field_names_["handshake_output"]:
                cls._qualifers_["output"](Bit),
            cls._field_names_["handshake_input"]:
                cls._qualifers_["input"](Bit)
        }
        _maybe_add_data(cls, fields, T, cls._qualifers_["data"])
        return fields

    def __getitem__(cls, T: Union[Type, MagmaProtocol]):
        assert cls._field_names_ is not None, "Undefined field name impl"
        fields = cls._make_fields(T)

        bases = (cls, )
        if hasattr(cls, "Base_T"):
            # Qualified variants include the unqualified type as a base class.
            # e.g. Producer(ReadyValid[Bits[8]]) will be a subtype of
            # ReadyValid[Bits[8]].
            bases += (cls.Base_T[T], )
        name = f"{cls}[{T}]"

        # Populates namespace for proper cache behavior (based on
        # hwtypes.adt_meta logic).
        ns = {}
        ns['__module__'] = cls.__module__
        name = f'{cls}[{T}]'
        ns['__qualname__'] = name

        # _cache_handler is implemented in hwtypes.adt_meta.
        return cls._cache_handler(True, fields, name, bases, ns)

    def __new__(mcs, name, bases, namespace, fields=None, **kwargs):
        cls = super().__new__(mcs, name, bases, namespace, fields, **kwargs)

        if not cls._field_names_:
            # Skip for base class (variants already exist and pointer is not
            # needed).
            return cls

        variants = (HandShakeMonitor, HandShakeDriver, HandShakeConsumer,
                    HandShakeProducer)
        if issubclass(cls, variants):
            return cls  # these don't need variants

        # Metaprogram variants for base type (e.g. for ReadyValid[Bits[8]],
        # create Producer(ReadyValid[Bits[8]])).
        for variant in variants:
            # Strip "HandShake" prefix for string name.
            suffix = f"{variant.__name__}"[len("HandShake"):]

            # Make variant type with appropriate base classes.
            variant_T = type(f"{suffix}({cls.__name__})",
                             (variant, cls), {})

            # Store pointer to variant (used by qualifiers).
            setattr(cls, f"{suffix}_T", variant_T)
            variant_T.Base_T = cls  # store pointer to base type

        return cls

    def flip(cls):
        raise TypeError(f"Cannot flip {cls.__name__} (undirected)")

    def qualify(cls, direction):
        if direction is Direction.In:
            return Monitor(cls)
        if direction is Direction.Out:
            return Driver(cls)
        if direction is Direction.Undirected:
            return Undirected(cls)
        raise TypeError(f"Cannot qualify {cls.__name__} with {direction}")

    @property
    def undirected_data_t(cls):
        try:
            data = cls.field_dict["data"]
        except KeyError:
            return None
        return data.undirected_t

    def __str__(cls):
        return cls.__name__

class HandShake(Product, metaclass=HandShakeKind):
    _field_names_ = None  # must be defined by implementation

    def fired(self):
        """
        Returns a bit that is high when ready and valid are both high.
        """
        raise NotImplementedError

class HandShakeProducerKind(HandShakeKind):
    _qualifers_ = {"output": Out, "input": In, "data": Out}

    def __getitem__(cls, T: Union[Type, MagmaProtocol]):
        t = super().__getitem__(T)
        if T is None:
            # Remove deq/no_deq methods if no data.
            t.deq = _deq_error
            t.no_deq = _no_deq_error
        return t

    def flip(cls):
        return Consumer(cls)

class HandShakeConsumerKind(HandShakeKind):
    _qualifers_ = {"output": In, "input": Out, "data": In}

    def __getitem__(cls, T: Union[Type, MagmaProtocol]):
        t = super().__getitem__(T)
        if T is None:
            t.enq = _enq_error
            t.no_enq = _no_enq_error
        return t

    def flip(cls):
        return Producer(cls)

class HandShakeConsumer(HandShake, metaclass=HandShakeConsumerKind):
    def fired(self):
        if not self.valid.driven():
            raise ReadyValidException(
                "Cannot invoke fired on consumer when valid isn't driven"
            )

        return self.ready & self.valid.value()

    def enq(self, value, when=True):
        """
        Produces the data `value` when `when` is high.

        Uses "last connect semantics", which allows multiple `enq` methods to
        be invoked with different conditions with precedence given to the later
        invocations.
        """
        if when is not True:
            if not (self.valid.driven() and self.data.driven()):
                raise ReadyValidException(
                    "Cannot use enq when without default driver"
                )
            curr_valid = self.valid.value()
            when |= curr_valid
            self.valid.unwire(curr_valid)

            curr_data = self.data.value()
            value = mux([curr_data, value], when)
            self.data.unwire(curr_data)
        self.valid @= when
        self.data @= value
        return value

    def no_enq(self, when=True):
        """
        Indicates no enqueue occurs.  Valid is set to false, and bits are
        connected to 0. (TODO: Should be an unitialized wire (Don't Care))
        """
        if when is not True:
            if not (self.valid.driven() and self.data.driven()):
                raise ReadyValidException(
                    "Cannot use no_deq with condition without an existing"
                    "valid and data driver"
                )
            valid = self.valid.value()
            data = self.data.value()
            self.valid.unwire(valid)
            self.data.unwire(data)
            self.valid @= mux([valid, False], when)
            self.data @= mux([data, 0], when)
        else:
            self.valid @= False
            self.data @= 0

class HandShakeProducer(HandShake, metaclass=HandShakeProducerKind):
    def fired(self):
        if not self.ready.driven():
            raise ReadyValidException(
                "Cannot invoke fired on producer when ready isn't driven"
            )
        return self.ready.value() & self.valid

    def deq(self, when=True):
        """
        Assert ready on this port and return associated data when `when` is
        high.

        This is typically used when valid has been asserted on the producer
        side.
        """
        if when is not True:
            if not self.ready.driven():
                raise ReadyValidException(
                    "Cannot use deq with when without a default ready driver"
                )
            ready = self.ready.value()
            self.ready.unwire(ready)
            self.ready @= ready | when
        else:
            self.ready @= when
        return self.data

    def no_deq(self, when=True):
        """
        Indicates no dequeue occurs, ready is set to False.
        """
        if when is not True:
            if not self.ready.driven():
                raise ReadyValidException(
                    "Cannot use no_deq with condition without an existing"
                    " ready driver"
                )
            ready = self.ready.value()
            self.ready.unwire(ready)
            self.ready @= mux([ready, False], when)
        else:
            self.ready @= False

class HandShakeMonitorKind(HandShakeKind):
    _qualifers_ = {"output": In, "input": In, "data": In}

    def flip(cls):
        return Driver(cls)

class HandShakeMonitor(HandShake, metaclass=HandShakeMonitorKind):
    pass

class HandShakeDriverKind(HandShakeKind):
    _qualifers_ = {"output": Out, "input": Out, "data": Out}

    def flip(cls):
        return Monitor(cls)

class HandShakeDriver(HandShake, metaclass=HandShakeDriverKind):
    pass

class ReadyValid(HandShake):
    """
    An I/O Bundle containing 'valid' and 'ready' signals that handshake
    the transfer of data stored in the 'data' subfield.

    The base protocol is undirected and is meant to be used with the modifiers:
    * m.Consumer(m.ReadyValid[T])  # data/valid are inputs, ready is output
    * m.Producer(m.ReadyValid[T])  # data/valid are outputs, ready is input

    T is the type of data to be wrapped in Ready/Valid.

    To create a ReadyValid type with no data, use T=None.  In this case, there
    will be no data port.

    The actual semantics of ready/valid are enforced via the use of concrete
    subclasses.
    """
    _field_names_ = {"handshake_output": "valid", "handshake_input": "ready"}

class Decoupled(ReadyValid):
    """
    `valid` indicates the prdoucer has put valid data in `data`, and `ready`
    indicates that the consumer is ready to accept the data this cycle.  No
    requirements are made on the signaling of ready or valid.
    """
    # TODO: Add down convert logic from Irrevocable consumer to Decoupled,
    # dropping guarantees of irrevocability.  Cannot be used on producer
    pass

class EnqIO(Decoupled.Producer_T):
    """
    Alias for Producer(Decoupled[T]).

    drives (outputs) `valid` and `data`, inputs `ready`.
    """
    pass

class DeqIO(Decoupled.Consumer_T):
    """
    Alias for Consumer(Decoupled[T]).

    drives (outputs) `ready`, inputs `valid` and `data`.
    """
    pass

class Irrevocable(ReadyValid):
    """
    Promises not to change the value of `data` after a cycle where `valid` is
    high and `ready` is low.  Additionally, once `valid` is raised, it will
    never be lowered until after `ready` has also been raised.
    """
    # TODO: Add upconvert logic from Decoupled producer to Irrevocable (can use
    # Irrevocable where a Decoupled is expected). Cannot be used on consumer.
    pass

class CreditValid(HandShake):
    _field_names_ = {"handshake_output": "valid", "handshake_input": "credit"}

def Consumer(T: HandShakeKind):
    if not issubclass(T, HandShake):
        raise TypeError(f"Consumer({T}) is unsupported")
    undirected_T = T.undirected_data_t
    return T.Consumer_T[undirected_T]

def Producer(T: HandShakeKind):
    if not issubclass(T, HandShake):
        raise TypeError(f"Producer({T}) is unsupported")
    undirected_T = T.undirected_data_t
    return T.Producer_T[undirected_T]

def Monitor(T: HandShakeKind):
    if not issubclass(T, HandShake):
        raise TypeError(f"Monitor({T}) is unsupported")
    undirected_T = T.undirected_data_t
    return T.Monitor_T[undirected_T]

def Driver(T: HandShakeKind):
    if not issubclass(T, HandShake):
        raise TypeError(f"Driver({T}) is unsupported")
    undirected_T = T.undirected_data_t
    return T.Driver_T[undirected_T]

def Undirected(T: HandShakeKind):
    if not issubclass(T, HandShake):
        raise TypeError(f"Undirected({T}) is unsupported")
    if not hasattr(T, 'Base_T'):
        return T  # already undirected
    undirected_T = T.undirected_data_t
    return T.Base_T[undirected_T]

def is_producer(T):
    return isinstance(T, (HandShakeProducerKind, HandShakeProducer))

def is_consumer(T):
    return isinstance(T, (HandShakeConsumerKind, HandShakeConsumer))

# TODO: QueueIO and Queue


#!/usr/bin/python3

import sys

time = input().strip().split(":")

if time[2][2] == 'A':
   offset = 0
elif time[2][2] == 'P':
   offset = 12
else:
   print("Invalid meridiem format")
   offset = -1

if offset >= 0:
   hour = int(time[0]) % 12 + offset
   minute = time[1]
   second = time[2][:2]
   print("%.2d:%s:%s" % (hour, minute, second))


# Question:- You have an array of length N which have some two digit numbers in it.
# Each number is only occurring once. You have to find out count of those number
# which have their reverse number present.
# Do not use Two Nested Loops
# Example :
# Input:- [21, 43, 54, 23, 67, 90, 84, 34, 45, 55, 76, 26, 48, 52, 25]
# Output:- 4
arr = [21, 43, 54, 23, 67, 90, 84, 34, 45, 55, 76, 26, 48]
count = 0
checked = []
for i in arr:
    checked.append(i)
    a = int(str(i)[::-1])
    if a in checked:
        continue
    if a in arr:
        count += 1
print(count)


def main():

    print("This program will give the sum of numbers as entered by the user")
    howmany=int(input("How many numbers would you like to add?"))
    sum=0
    for i in range(howmany):
        whichones=eval(input("Select one of the numbers that you would like to add?"))
        sum=sum+whichones
    print("The addition of the",howmany,"numbers you selected is",sum)

main()


#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
The top level of the package.
"""
import pkg_resources
EXAMPLE = pkg_resources.resource_filename("smg",
                                          "assets/dummy.txt")

from .utils import Sequencer, MidiRouter
from .evolutionary import Optimizer

__all__ = [
    "Sequencer",
    "MidiRouter",
    "Optimizer",
]


import numpy as np
from scipy.ndimage import map_coordinates

def rectify_orders(image_data, trace, half_window=10, debug=False, nullify_mapped_values=True):
    """
    :param image_data: xwavecal.images.Image.data
    :param trace: Trace object
    :param half_window: half of the size of the extraction window about the center of the traces. E.g. 10 means 21 pixel
                        window will be extracted.
    :param debug: boolean for returning an internal copy of the image which is used in extract.
    :param nullify_mapped_values: bool.
                                  True if the flux from a pixel can only be used in one order's spectrum.
                                  False if a pixel's flux can be double (or triple etc..) counted.
    :return rectified_orders: Dictionary
    Dictionary where the keys are the trace id's from trace.get_id(),
    where rectified_2d_spectrum[trace_id]['val'] is a 2d float array (flux for the trace_id order).
    If half extraction window was 10, then rectified_2d_spectrum[trace_id]['val']
    is 21 rows by 4096 columns (for a 4096 pixel wide image). One would sum this 2d
    spectrum along-columns to get a box extracted spectrum.
    """
    rectified_orders = {}
    num_orders = trace.num_traces_found()
    image_copy = np.copy(image_data)
    x_coordinates, y_coordinates = np.meshgrid(np.arange(image_data.shape[1]), np.arange(image_data.shape[0]))
    image_coordinates = {'x': x_coordinates, 'y': y_coordinates}
    for index in np.arange(num_orders):
        rectified_orders[trace.get_id(index)], image_copy = rectify_order(image_copy, image_coordinates,
                                                                          trace.get_centers(index),
                                                                          half_window=half_window,
                                                                          nullify_mapped_values=nullify_mapped_values)
    if debug:
        return rectified_orders, image_copy
    else:
        return rectified_orders

def rectify_order(image_data, image_coordinates, single_order_centers, half_window=10, nullify_mapped_values=True):
    """
    :param image_data: xwavecal.images.Image.data
    :param image_coordinates: dictionary with x and y coordinates for each pixel.
    :param single_order_centers: the y centers of the center of the rectification window
    :param half_window: the half width of the window about which one is rectifying the trace/order
    :param nullify_mapped_values: True if the flux from a pixel can only be used in one order's spectrum.
                                  False if a pixel's flux can be double (or triple etc..) counted.
    :return: An array of 2*half_window + 1 rows by width(image_data) about the order. The center of the order
             is right at the index of half_window, e.g. rectified_order[half_window] gives the flux down the
             center of the order.
    """
    spectrum_shape = (2*half_window + 1, image_data.shape[1])
    rectified_order = {'val': np.zeros(spectrum_shape),
                       'y': np.zeros(spectrum_shape),
                       'x': np.zeros(spectrum_shape)}
    x_coords = np.arange(image_data.shape[1])
    for offset, row in zip(np.arange(-half_window, half_window + 1), np.arange(spectrum_shape[0])):
        mapped_y_values = map_coordinates(image_coordinates['y'], [single_order_centers + offset, x_coords],
                                          order=0, mode='constant', cval=0, prefilter=False)
        rectified_order['val'][row] = image_data[(mapped_y_values, x_coords)]
        rectified_order['y'][row] = mapped_y_values
        rectified_order['x'][row] = x_coords
        if nullify_mapped_values:
            image_data[(mapped_y_values, x_coords)] = 0
    return rectified_order, image_data


#trabalhar com páginas da web
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
#import para tempo de pausa
import pyautogui as tempo
#import para usar teclas
import pyautogui as tecla
#By serve para trabalhar com as atualizações mais recentes
from selenium.webdriver.common.by import By
import xlsxwriter
import os

#autprização para acessar configurações do chrome
navegador = webdriver.Chrome()
navegador.get("https://www.google.com.br/")
tempo.sleep(2)

#---------------------------------------------- DOLAR -------------------------------------------------------#

#Digita na caixa de pesquisa
navegador.find_element(By.NAME, 'q').send_keys('Dolar hoje')
tempo.sleep(2)

#Tecla enter
navegador.find_element(By.NAME, 'q').send_keys(Keys.RETURN)
tempo.sleep(2)

#recebe o XPATH do item na tela e pegamos o primeiro valor da lista
dolar = navegador.find_elements(By.XPATH, '//*[@id="knowledge-currency__updatable-data-column"]/div[1]/div[2]/span[1]')[0].text
print(dolar)

#---------------------------------------------- EURO -------------------------------------------------------#
tempo.sleep(2)

#retorna para a caixa de pesquisa
navegador.find_element(By.NAME, 'q').send_keys("")
tempo.sleep(2)

#apertar tab
tecla.press('tab')
tempo.sleep(2)
#apertar enter para limpar campo de pesquisa
tecla.press('enter')

#Digita na caixa de pesquisa
navegador.find_element(By.NAME, 'q').send_keys('Euro hoje')
tempo.sleep(2)

#Tecla enter
navegador.find_element(By.NAME, 'q').send_keys(Keys.RETURN)
tempo.sleep(2)

#recebe o XPATH do item na tela e pegamos o primeiro valor da lista
euro = navegador.find_elements(By.XPATH, '//*[@id="knowledge-currency__updatable-data-column"]/div[1]/div[2]/span[1]')[0].text
print(euro)

#---------------------------------------------- EXCEL -------------------------------------------------------#

url = "C:\workspace\Python-RPA\secao02\Dolar e Euro.xlsx"
planilha = xlsxwriter.Workbook(url)
cotacao = planilha.add_worksheet()

dolar = dolar.replace(',','.')
euro = euro.replace(',','.')

dolar = float(dolar)
euro = float(euro)

#escreve nas células
cotacao.write("A1","Dolar")
cotacao.write("B1","Euro")
cotacao.write("A2",dolar)
cotacao.write("B2",euro)

planilha.close()

os.startfile(url)


from typing import Optional
from absl import logging
from intrinsic.icon.equipment import icon_equipment_pb2
from intrinsic.icon.python import icon_api
from intrinsic.skills.proto import equipment_pb2
from intrinsic.util.grpc import connection

ICON2_POSITION_PART_KEY = "Icon2PositionPart"
ICON2_TORQUE_PART_KEY = "Icon2TorquePart"
ICON2_GRIPPER_PART_KEY = "Icon2GripperPart"
ICON2_ADIO_PART_KEY = "Icon2AdioPart"
ICON2_FORCE_TORQUE_SENSOR_PART_KEY = "Icon2ForceTorqueSensorPart"
ICON2_RANGEFINDER_PART_KEY = "Icon2RangefinderPart"

def make_icon_equipment_selector(
    with_position_controlled_part: bool = False,
    with_torque_controlled_part: bool = False,
    with_gripper_part: bool = False,
    with_adio_part: bool = False,
    with_force_torque_sensor_part: bool = False,
    with_rangefinder_part: bool = False,
    with_observation_stream: bool = False,
) -> equipment_pb2.EquipmentSelector:
  """Creates an equipment selector for an ICON equipment handle with specific parts.

  Args:
    with_position_controlled_part: If true, requires a position-controlled part.
    with_torque_controlled_part: If true, requires a torque-controlled part.
    with_gripper_part: If true, requires a gripper part.
    with_adio_part: If true, requires an adio part.
    with_force_torque_sensor_part: If true, requires a force_torque_sensor part.
    with_rangefinder_part: If true, requires a rangefinder part.
    with_observation_stream: If true, requires an observation stream config.

  Returns:
    A populated equipment selector.
  """

  equipment_type_names = ["Icon2Connection"]
  if with_position_controlled_part:
    equipment_type_names.append(ICON2_POSITION_PART_KEY)
  if with_torque_controlled_part:
    equipment_type_names.append(ICON2_TORQUE_PART_KEY)
  if with_gripper_part:
    equipment_type_names.append(ICON2_GRIPPER_PART_KEY)
  if with_adio_part:
    equipment_type_names.append(ICON2_ADIO_PART_KEY)
  if with_force_torque_sensor_part:
    equipment_type_names.append(ICON2_FORCE_TORQUE_SENSOR_PART_KEY)
  if with_rangefinder_part:
    equipment_type_names.append(ICON2_RANGEFINDER_PART_KEY)
  if with_observation_stream:
    equipment_type_names.append("IconRobotObservationStreamParams")

  return equipment_pb2.EquipmentSelector(
      equipment_type_names=equipment_type_names
  )

def _get_params_from_connection_info(
    equipment_handle: equipment_pb2.EquipmentHandle,
) -> Optional[connection.ConnectionParams]:
  """Creates params to start an ICON client from a handle's connection_info.

  Args:
    equipment_handle: The equipment handle for the robot we want to control.

  Returns:
    The connected ConnectionParams if the handle provides enough information.
  """
  if not equipment_handle.HasField("connection_info"):
    return None
  if not equipment_handle.connection_info.HasField("grpc"):
    return None
  return connection.ConnectionParams(
      equipment_handle.connection_info.grpc.address,
      equipment_handle.connection_info.grpc.server_instance,
      equipment_handle.connection_info.grpc.header,
  )

def init_icon_client(
    equipment_handle: equipment_pb2.EquipmentHandle,
) -> icon_api.Client:
  """Creates a client for talking to the icon server.

  Args:
    equipment_handle: The equipment handle for the robot we want to control.

  Returns:
    The connected Client.

  Raises:
    KeyError: If equipment_handle does not include any connection config.
  """
  connection_params = _get_params_from_connection_info(equipment_handle)

  if not connection_params:
    raise KeyError("No ICON connection config was provided.")

  logging.info("ICON connection_params: %s", connection_params)
  return icon_api.Client.connect_with_params(connection_params, insecure=True)

def get_position_part_name(
    equipment_handle: equipment_pb2.EquipmentHandle,
) -> str:
  """Gets the name of the Icon2PositionPart from the equipment data.

  Args:
    equipment_handle: The equipment handle for the robot we want to control.

  Returns:
    The part name.

  Raises:
    KeyError: If equipment_handle does not include an Icon2PositionPart data.
  """
  icon_position_part = icon_equipment_pb2.Icon2PositionPart()
  pos_key = ICON2_POSITION_PART_KEY
  if pos_key not in equipment_handle.equipment_data:
    raise KeyError(
        "%s is not in equipment_handle.equipment_data. Available: %r"
        % (pos_key, equipment_handle.equipment_data.keys())
    )
  equipment_handle.equipment_data[pos_key].contents.Unpack(icon_position_part)
  logging.info("ICON position_part: %s", icon_position_part)
  return icon_position_part.part_name

def get_torque_part_name(
    equipment_handle: equipment_pb2.EquipmentHandle,
) -> str:
  """Gets the name of the Icon2TorquePart from the equipment data.

  Args:
    equipment_handle: The equipment handle for the robot we want to control.

  Returns:
    The part name.

  Raises:
    KeyError: If equipment_handle does not include an Icon2TorquePart data.
  """
  icon_torque_part = icon_equipment_pb2.Icon2TorquePart()
  torque_key = ICON2_TORQUE_PART_KEY
  if torque_key not in equipment_handle.equipment_data:
    raise KeyError(
        "%s is not in equipment_handle.equipment_data. Available: %r"
        % (torque_key, equipment_handle.equipment_data.keys())
    )
  equipment_handle.equipment_data[torque_key].contents.Unpack(icon_torque_part)
  logging.info("ICON torque_part: %s", icon_torque_part)
  return icon_torque_part.part_name

def get_gripper_part_name(
    equipment_handle: equipment_pb2.EquipmentHandle,
) -> str:
  """Gets the name of the Icon2GripperPart from the equipment data.

  Args:
    equipment_handle: The equipment handle for the robot we want to control.

  Returns:
    The part name.

  Raises:
    KeyError: If equipment_handle does not include an Icon2GripperPart data.
  """
  icon_gripper_part = icon_equipment_pb2.Icon2GripperPart()
  gripper_key = ICON2_GRIPPER_PART_KEY
  if gripper_key not in equipment_handle.equipment_data:
    raise KeyError(
        "%s is not in equipment_handle.equipment_data. Available: %r"
        % (gripper_key, equipment_handle.equipment_data.keys())
    )
  equipment_handle.equipment_data[gripper_key].contents.Unpack(
      icon_gripper_part
  )
  logging.info("ICON gripper_part: %s", icon_gripper_part)
  return icon_gripper_part.part_name

def get_force_torque_sensor_part_name(
    equipment_handle: equipment_pb2.EquipmentHandle,
) -> str:
  """Gets the name of the Icon2ForceTorqueSensorPart from the equipment data.

  Args:
    equipment_handle: The equipment handle for the robot we want to control.

  Returns:
    The part name.

  Raises:
    KeyError: If equipment_handle does not include an Icon2ForceTorqueSensorPart
    data.
  """
  icon_force_torque_sensor_part = (
      icon_equipment_pb2.Icon2ForceTorqueSensorPart()
  )
  ft_key = ICON2_FORCE_TORQUE_SENSOR_PART_KEY
  if ft_key not in equipment_handle.equipment_data:
    raise KeyError(
        "%s is not in equipment_handle.equipment_data. Available: %r"
        % (ft_key, equipment_handle.equipment_data.keys())
    )
  equipment_handle.equipment_data[ft_key].contents.Unpack(
      icon_force_torque_sensor_part
  )
  logging.info(
      "ICON force_torque_sensor_part: %s", icon_force_torque_sensor_part
  )
  return icon_force_torque_sensor_part.part_name

def get_adio_part_name(equipment_handle: equipment_pb2.EquipmentHandle) -> str:
  """Gets the name of the Icon2AdioPart from the equipment data.

  Args:
    equipment_handle: The equipment handle for the adio we want to read/control.

  Returns:
    The part name.

  Raises:
    KeyError: If equipment_handle does not include an Icon2AdioPart data.
    ValueError: If adio_part does not include an icon_target data, i.e. a adio
      configuration that uses a different backend than icon.
  """
  adio_key = ICON2_ADIO_PART_KEY
  icon_adio_part = icon_equipment_pb2.Icon2AdioPart()
  if adio_key not in equipment_handle.equipment_data:
    raise KeyError(
        "%s is not in equipment_handle.equipment_data. Available: %r"
        % (adio_key, equipment_handle.equipment_data.keys())
    )
  equipment_handle.equipment_data[adio_key].contents.Unpack(icon_adio_part)
  if not icon_adio_part.HasField("icon_target"):
    raise ValueError(
        "adio part is not an icon_target and thus does not have a part name."
    )
  return icon_adio_part.icon_target.part_name

def get_rangefinder_part_name(
    equipment_handle: equipment_pb2.EquipmentHandle,
) -> str:
  """Gets the name of the Icon2RangefinderPart from the equipment data.

  Args:
    equipment_handle: The equipment handle for the robot we want to control.

  Returns:
    The part name.

  Raises:
    KeyError: If equipment_handle does not include Icon2RangefinderPart data.
  """
  icon_rangefinder_part = icon_equipment_pb2.Icon2RangefinderPart()
  part_key = ICON2_RANGEFINDER_PART_KEY
  if part_key not in equipment_handle.equipment_data:
    raise KeyError(
        "%s is not in equipment_handle.equipment_data. Available: %r"
        % (part_key, equipment_handle.equipment_data.keys())
    )
  if not equipment_handle.equipment_data[part_key].contents.Unpack(
      icon_rangefinder_part
  ):
    raise ValueError(
        "Failed to unpack %s as 'Icon2RangefinderPart'. Actual type is '%r'"
        % (part_key, icon_rangefinder_part.DESCRIPTOR)
    )

  logging.info("ICON %s: %s", ICON2_RANGEFINDER_PART_KEY, icon_rangefinder_part)
  return icon_rangefinder_part.part_name


from mmcv.runner import IterBasedRunner, RUNNERS
import torch
import numpy as np
from torch import nn
import torch.nn.functional as F
from torch.nn import Parameter
import math
from typing import (Any, Callable, Dict, List, Optional, Tuple, Union,
                    no_type_check)
import logging

def gkern2d(l=21, sig=3):
    """Returns a 2D Gaussian kernel array."""
    ax = np.arange(-l // 2 + 1., l // 2 + 1.)
    xx, yy = np.meshgrid(ax, ax)
    kernel = np.exp(-(xx ** 2 + yy ** 2) / (2. * sig ** 2))
    return kernel / (1.0 / (2 * math.pi * (sig ** 2)))

# This class is partially adapted from https://github.com/anlcnydn/bilateral/blob/master/bilateral_filter.py
# And modified to work with multiple channels
class Shift(nn.Module):
    def __init__(self, kernel_size=3):
        super(Shift, self).__init__()
        self.kernel_size = kernel_size
        self.pad = self.kernel_size//2

    def forward(self, x):
        n, c, h, w = x.size()
        x_pad = F.pad(x, (self.pad, self.pad, self.pad, self.pad))
        x_pad = x_pad.reshape(n,1,c,h+self.pad*2,w+self.pad*2)

        cat_layers = []
        for y in range(0,self.kernel_size):
            y2 = y+h
            for x in range(0, self.kernel_size):
                x2 = x+w
                xx = x_pad[:,:,:,y:y2,x:x2]
                cat_layers += [xx]
        return torch.cat(cat_layers, 1)

# This class is partially adapted from https://github.com/anlcnydn/bilateral/blob/master/bilateral_filter.py
# And modified to work with multiple channels
class BilateralFilterModule(nn.Module):
    r"""BilateralFilter computes:
        If = 1/W * Sum_{xi C Omega}(I * f(||I(xi)-I(x)||) * g(||xi-x||))
    """

    def __init__(self, channels=3, height=480, width=640, k=7, sigma_space=5, sigma_color=0.1):
        super(BilateralFilterModule, self).__init__()

        self.g = Parameter(torch.Tensor(channels,k*k))
        self.gw = gkern2d(k,sigma_space)
        self.k = k
        gw = np.tile(self.gw.reshape(1,k*k,1,1),(1,1,height,width))
        self.g.data = torch.from_numpy(gw).float()
        #shift
        self.shift = Shift(k)
        self.norm_term_color = (1.0 / (2 * math.pi * (sigma_color ** 2)))
        self.sigma_color = 2*sigma_color**2

    def forward(self, I):
        n, c, h, w = I.size()
        #Is contains the original image mutiple shifted
        Is = self.shift(I).data
        Iex = I.expand(*Is.size())
        D = ((Is-Iex)**2).sum(2)
        g_i = torch.exp(-D / self.sigma_color) * self.norm_term_color
        g_i_s = g_i * self.g.data
        W_denom = torch.sum(g_i_s,dim=1)
        g_i_s = g_i_s.reshape(n, self.k*self.k, 1, h, w).expand((n, self.k*self.k, c, h, w))
        If = torch.sum(g_i_s*Is,dim=1) / W_denom
        return If

class BilateralFilterTorch(object):
    def __init__(self, prob=0.5, max_blur=15, img_size=None, channels=3):
        self.prob = prob
        self.max_blur = max_blur
        self.filter = []
        h,w = img_size
        for k in range(max_blur//2):
            f = BilateralFilterModule(channels,h,w, k=k*2+1, sigma_space=75.0, sigma_color=75.0/255.0)
            f.cuda()
            self.filter.append(f)

    def bilateral_filter(self, img):
        with torch.no_grad():
            c,h,w = img.shape
            img = img.reshape(1, c, h, w)
            img = img.to('cuda')
            blur = np.random.choice(self.max_blur//2)
            color = self.filter[blur](img)
            img_out = color[0]
            return img_out

    def __call__(self, results):
        results["bilateral_filter"] = False
        if np.random.random() < self.prob:
            results["img"] = self.bilateral_filter(results["img"])
            results["bilateral_filter"] = True
            return results
        return results

@RUNNERS.register_module()
class BilateralFilterRunner(IterBasedRunner):
    def __init__(self,
                 model: torch.nn.Module,
                 batch_processor: Optional[Callable] = None,
                 optimizer: Union[Dict, torch.optim.Optimizer, None] = None,
                 work_dir: Optional[str] = None,
                 logger: Optional[logging.Logger] = None,
                 meta: Optional[Dict] = None,
                 max_iters: Optional[int] = None,
                 max_epochs: Optional[int] = None,
                 prob=0.5, max_blur=15,
                 img_size=None, channels=3) -> None:
        super(BilateralFilterRunner, self).__init__(model, batch_processor,
                                                    optimizer, work_dir, logger,
                                                    meta, max_iters, max_epochs)
        self.filter = BilateralFilterTorch(prob, max_blur, img_size, channels)

    def filter_batch(self, batch):
        for i, img_metas in enumerate(batch["img_metas"].data[0]):
            res_dict = dict()
            res_dict["img"] = batch["img"].data[0][i]
            res_dict = self.filter(res_dict)
            batch["img_metas"].data[0][i]["bilateral_filter"] = res_dict["bilateral_filter"]
            batch["img"].data[0][i] = res_dict["img"]
        return batch

    def train(self, data_loader, **kwargs):
        self.model.train()
        self.mode = 'train'
        self.data_loader = data_loader
        self._epoch = data_loader.epoch
        data_batch = next(data_loader)
        data_batch = self.filter_batch(data_batch)
        self.data_batch = data_batch
        self.call_hook('before_train_iter')
        outputs = self.model.train_step(data_batch, self.optimizer, **kwargs)
        if not isinstance(outputs, dict):
            raise TypeError('model.train_step() must return a dict')
        if 'log_vars' in outputs:
            self.log_buffer.update(outputs['log_vars'], outputs['num_samples'])
        self.outputs = outputs
        self.call_hook('after_train_iter')
        del self.data_batch
        self._inner_iter += 1
        self._iter += 1


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

from odoo import api, fields, models, _

class AssignMechanicWizard(models.TransientModel):
    _name = 'assign.mechanic.wizard'
    _description = 'Assign Mechanic Wizard'

    # relations
    mechanic_ids = fields.Many2many('hr.employee', string="Assign Mechanic")
    repair_id = fields.Many2one("repair.order")

    def assign_mechanic(self):
        """
        Assign mechanic to the repair.order.
        """
        self.repair_id.mechanic_ids = [(6, 0, self.mechanic_ids.ids)]
        return True

class AssignBayWizard(models.TransientModel):
    _name='assign.bay.wizard'
    _description = 'Assign Bay Wizard'

    # relations
    bay_id = fields.Many2one("bay", "Bay")
    repair_id = fields.Many2one("repair.order")

    def assign_bay(self):
        """
        Assign bay to the repair.order.
        """
        self.repair_id.assign_bay_id = self.bay_id
        return True


# Whitney Music Box in Pyo - Jim Bumgardner

from pyo import *

nbrDots = 60              # Number of dots
period = 60.0             # Duration of cycle in seconds
chromatic = True          # use Chromatic Scale vs harmonics
basePitch = 60-nbrDots/2  # base midi pitch for Chromatic version
baseFreq = 50             # fundamental frequency for Harmonics
reverse = True            # reverse order of pitches/harmonics

s = Server().boot()
s.start()

durs = [period/(i+1) for i in range(nbrDots)]
freqs = [(midiToHz(basePitch+i) if chromatic else baseFreq*(i+1)) for i in range(nbrDots)]
if reverse:
  freqs = list(reversed(freqs))
trig = Metro(durs,True).play()
env = TrigExpseg(trig, [(0,0),(0.01,1),(5,0)])
v = Sine(freq=freqs,mul=env*2.0/nbrDots).out()

s.gui(locals())


import mimetypes
import posixpath

from compiled_file_system import SingleFile
from directory_zipper import DirectoryZipper
from docs_server_utils import ToUnicode
from file_system import FileNotFoundError
from future import Gettable, Future
from path_canonicalizer import PathCanonicalizer
from path_util import AssertIsValid, Join, ToDirectory
from special_paths import SITE_VERIFICATION_FILE
from third_party.handlebar import Handlebar
from third_party.markdown import markdown

_MIMETYPE_OVERRIDES = {
  # SVG is not supported by mimetypes.guess_type on AppEngine.
  '.svg': 'image/svg+xml',
}

class ContentAndType(object):
  '''Return value from ContentProvider.GetContentAndType.
  '''

  def __init__(self, content, content_type):
    self.content = content
    self.content_type = content_type

class ContentProvider(object):
  '''Returns file contents correctly typed for their content-types (in the HTTP
  sense). Content-type is determined from Python's mimetype library which
  guesses based on the file extension.

  Typically the file contents will be either str (for binary content) or
  unicode (for text content). However, HTML files *may* be returned as
  Handlebar templates (if |supports_templates| is True on construction), in
  which case the caller will presumably want to Render them.

  Zip file are automatically created and returned for .zip file extensions if
  |supports_zip| is True.

  |default_extensions| is a list of file extensions which are queried when no
  file extension is given to GetCanonicalPath/GetContentAndType.  Typically
  this will include .html.
  '''

  def __init__(self,
               name,
               compiled_fs_factory,
               file_system,
               object_store_creator,
               default_extensions=(),
               supports_templates=False,
               supports_zip=False):
    # Public.
    self.name = name
    self.file_system = file_system
    # Private.
    self._content_cache = compiled_fs_factory.Create(file_system,
                                                     self._CompileContent,
                                                     ContentProvider)
    self._path_canonicalizer = PathCanonicalizer(file_system,
                                                 object_store_creator,
                                                 default_extensions)
    self._default_extensions = default_extensions
    self._supports_templates = supports_templates
    if supports_zip:
      self._directory_zipper = DirectoryZipper(compiled_fs_factory, file_system)
    else:
      self._directory_zipper = None

  @SingleFile
  def _CompileContent(self, path, text):
    assert text is not None, path
    _, ext = posixpath.splitext(path)
    mimetype = _MIMETYPE_OVERRIDES.get(ext, mimetypes.guess_type(path)[0])
    if ext == '.md':
      # See http://pythonhosted.org/Markdown/extensions
      # for details on "extensions=".
      content = markdown(ToUnicode(text),
                         extensions=('extra', 'headerid', 'sane_lists'))
      if self._supports_templates:
        content = Handlebar(content, name=path)
      mimetype = 'text/html'
    elif mimetype is None:
      content = text
      mimetype = 'text/plain'
    elif mimetype == 'text/html':
      content = ToUnicode(text)
      if self._supports_templates:
        content = Handlebar(content, name=path)
    elif (mimetype.startswith('text/') or
          mimetype in ('application/javascript', 'application/json')):
      content = ToUnicode(text)
    else:
      content = text
    return ContentAndType(content, mimetype)

  def GetCanonicalPath(self, path):
    '''Gets the canonical location of |path|. This class is tolerant of
    spelling errors and missing files that are in other directories, and this
    returns the correct/canonical path for those.

    For example, the canonical path of "browseraction" is probably
    "extensions/browserAction.html".

    Note that the canonical path is relative to this content provider i.e.
    given relative to |path|. It does not add the "serveFrom" prefix which
    would have been pulled out in ContentProviders, callers must do that
    themselves.
    '''
    AssertIsValid(path)
    base, ext = posixpath.splitext(path)
    if self._directory_zipper and ext == '.zip':
      # The canonical location of zip files is the canonical location of the
      # directory to zip + '.zip'.
      return self._path_canonicalizer.Canonicalize(base + '/').rstrip('/') + ext
    return self._path_canonicalizer.Canonicalize(path)

  def GetContentAndType(self, path):
    '''Returns the ContentAndType of the file at |path|.
    '''
    AssertIsValid(path)
    base, ext = posixpath.splitext(path)

    # Check for a zip file first, if zip is enabled.
    if self._directory_zipper and ext == '.zip':
      zip_future = self._directory_zipper.Zip(ToDirectory(base))
      return Future(delegate=Gettable(
          lambda: ContentAndType(zip_future.Get(), 'application/zip')))

    # If there is no file extension, look for a file with one of the default
    # extensions.
    #
    # Note that it would make sense to guard this on Exists(path), since a file
    # without an extension may actually exist, but it's such an uncommon case
    # it hardly seems worth the potential performance hit.
    if not ext:
      for default_ext in self._default_extensions:
        if self.file_system.Exists(path + default_ext).Get():
          path += default_ext
          break

    return self._content_cache.GetFromFile(path)

  def Cron(self):
    futures = [self._path_canonicalizer.Cron()]
    for root, _, files in self.file_system.Walk(''):
      for f in files:
        futures.append(self.GetContentAndType(Join(root, f)))
        # Also cache the extension-less version of the file if needed.
        base, ext = posixpath.splitext(f)
        if f != SITE_VERIFICATION_FILE and ext in self._default_extensions:
          futures.append(self.GetContentAndType(Join(root, base)))
      # TODO(kalman): Cache .zip files for each directory (if supported).
    return Future(delegate=Gettable(lambda: [f.Get() for f in futures]))

  def __repr__(self):
    return 'ContentProvider of <%s>' % repr(self.file_system)