import libtcodpy as libtcod
import random

from Components import TurnTaker

class ActionSystem():
    def __init__( self, world, actions ):
        self.toProcessList = []
        self.world = world
        self.actions = actions
        self.curTurn = 0

        self.world.onRemove.append( lambda ent: self.removeEnt( ent ) )

    def removeEnt( self, ent ):
        while ent in self.toProcessList:
            self.toProcessList.remove( ent )

    def updateProcessList( self ):
        entities = self.world.getEntityByComponent( TurnTaker )
        self.toProcessList = []

        for ent in entities:
            turnTaker = ent.getComponent( TurnTaker )
            ent.__nextTurn = turnTaker.timeTillNextTurn

            self._insertEnt( ent )

    def _insertEnt( self, ent ):
        tp = self.toProcessList
        if ent in self.toProcessList:
            tp.pop( tp.index( ent ) )

        begin = 0
        end = len( tp ) - 1
        listEnd = len( tp )

        key = ent.__nextTurn

        if listEnd == 0:
            tp.append( ent )
            return

        while end >= begin:
            mid = begin + ( ( end - begin ) // 2 )

            comp = tp[ mid ].__nextTurn

            if comp > key:
                begin = mid + 1
            elif comp < key:
                end = mid - 1
            else:
                break

        #Key not found, check if to insert before or after the current index
        if comp > key:
            tp.insert( mid + 1, ent )
        else:
            tp.insert( mid, ent )

    def resetTurnCount( self ):
        if self.curTurn > 100:
            for ent in self.toProcessList:
                ent.__nextTurn -= self.curTurn
            self.curTurn = 0

    def process( self, maxTime ):
        if len( self.toProcessList ) == 0:
            self.updateProcessList()
            if len( self.toProcessList ) == 0:
                print( 'No entities to take actions' )
                return False

        firstEnt = self.toProcessList.pop()
        turnTaker = firstEnt.getComponent( TurnTaker )

        if self.curTurn + maxTime < firstEnt.__nextTurn:
            self.curTurn += maxTime
            self._insertEnt( firstEnt )
            return True

        action = turnTaker.getNextTurn()
        if action is None:
            self._insertEnt( firstEnt )
            return False

        restTime = self.actions[ action.name ]( action.name, self.world, action.entity, action.params )
        if restTime is None:
            self._insertEnt( firstEnt )
            return False

        if restTime == 1:
            turnTaker.wasBlocked += 1
        else:
            turnTaker.wasBlocked = 0

        assert( restTime > 0 )
        randExtra = random.randrange( -turnTaker.randomRange, turnTaker.randomRange+1 )

        firstEnt.__nextTurn = self.curTurn + restTime + randExtra
        self._insertEnt( firstEnt )

        return True


from django.conf.urls import patterns, include, url
from django.contrib import admin
from links.views import Login, Registration, NewLink, Link, logout
from links.views import add_fav, rm_fav

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'livelink.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^link/$', NewLink.as_view(), name='links'),
    url(r'^links/$', Link.as_view(), name='links'),

    url(r'^fav/(?P<id>\d{1,})/$', add_fav, name='fav'),
    url(r'^rfav/(?P<id>\d{1,})/$', rm_fav, name='rfav'),

    url(r'^login/$', Login.as_view(), name='login'),
    url(r'^logout/$', logout),
    url(r'^signup/$', Registration.as_view()),
    url(r'^admin/', include(admin.site.urls)),
)


#import function
#from databasefunction import *
from YourDataPreprocessingModule import *
import pandas as pd
def dataset_extraction():
    #extract data from database
    query1 = '''SELECT [Expedition qty].[# Serie], [Expedition qty].[Qty envoyé], [Expedition qty].wo, [Expedition qty].Docket, [Expedition qty].Loc, [Expedition qty].BL, [Expedition qty].[HRS EXP], Serial.Items, Serial.[No Série], Serial.Lot, [Doc exp].Client, Serial.[Cost Unit], Serial.TRCostUN, Serial.rwcost, [Doc recp].[Taux dev], ([Cost Unit]*[Taux dev])+[TRCostUN]+[rwcost] AS [T COST], [T COST]*[Qty envoyé] AS [G COST], Serial.[Qty-recus], [T COST]*[Qty-recus] AS [COST R], [Doc recp].[br-clef], [Expedition qty].[expedition-clef], [WORK-ORDER].[WO-NO]
    FROM [WORK-ORDER] RIGHT JOIN ([Doc recp] INNER JOIN ([Doc exp] RIGHT JOIN (Serial INNER JOIN [Expedition qty] ON Serial.[Serial-clef] = [Expedition qty].[# Serie]) ON [Doc exp].[bl-clef] = [Expedition qty].[Doc exp]) ON [Doc recp].[br-clef] = Serial.Reception) ON [WORK-ORDER].[WO-NO] = [Doc recp].DEWO;
    '''
    df = extract_data_from_access(query1)
    #convert columns to numerical the columns 'Docket', 'wo', 'WO-NO'
    columns = ['Docket', 'wo', 'WO-NO']
    for column in columns:
        df = convert_to_numerical(df, column)

    #extract Serial table
    query2 = '''SELECT * FROM Serial'''
    Serial = extract_data_from_access(query2)

    #rename the column '# Serie' to 'Serial-clef'
    df.rename(columns={'# Serie': 'Serial-clef'}, inplace=True)

    #merge the two tables
    df_merge = pd.merge(df, Serial, on='Serial-clef')

    #drop useless columns
    columns = [ 'wo', 'Loc',  'HRS EXP','Taux dev', 'No Série_y','Items_y', 'Lot_y', 'Qty-recus_y', 'TAREKG','HRS SERIAL', 'Cost Unit_y','TRCostUN_y', 'QTY-FOUR','rwcost_y', 'print ctrl', 'Client_y','hrsst', 'hrsend', 'hrsst2', 'hrsend2', 'hrs total', 'pers', 'pcused','hrs t numb', 'deviseserial', 'etape', 'SAMPLE', 'COMPTNOTE','printcompt', 'negosurprix', 'cb_pour','INFOETI', 'cost_maj', 'EMP', 'QC_PRISE', 'COSTA', 'COSTB', 'COSTC', 'COSTD', 'COSTE', 'COSTF','Client_x', 'Cost Unit_x', 'TRCostUN_x', 'rwcost_x','T COST', 'G COST', 'COST R']
    df_merge = drop(df_merge, columns)

    #rename some columns after joining
    df_merge.rename(columns={'Items_x': 'Items', 'No Série_x': 'No Série', 'Qty-recus_x': 'Qty-recus', 'Lot_x': 'Lot'}, inplace=True)

    return df_merge

#extract data from database

def preprocess_dataIzod():
  df = dataset_extraction()
  #construct the dataset for izod
  IzodColumns = ['Items','melt', 'flex', 'traction','COULEUR', 'I_F', 'I_CM','I_G', 'I1', 'izode']
  df_izod = df[IzodColumns]
  #rename the columns izode to I48
  df_izod.rename(columns={'izode': 'I48'}, inplace=True)

  #convert to numeric the columns I_F, I_CM, I_G, Items if it is possible
  columns = ['I_F', 'I_CM', 'I_G', 'Items']
  for column in columns:
      df_izod = convert_to_numerical(df_izod, column)

  #replace values in the column ITEMS
  df_izod['Items'] = df_izod['Items'].replace({54: 'NORYL',
    55: 'DIVERS',
    56: 'EVOPRENE-RP',
    63: 'ELASTOLLAN-RP',
    75: 'ADDITIFS',
    102: 'PBT-RG',
    112: 'PPH',
    116: 'PVC-FLEX',
    127: 'PP-RG/RP',
    133: 'ABS/AC-C',
    134: 'LLDPE',
    163: 'PEHD-ROLLS',
    165: 'ASA',
    173: 'SYNPRENE',
    185: 'ABS/AC-BALE',
    199: 'PBT-RP',
    208: 'PP-RP20/2/5',
    214: 'TRI-WIN',
    215: 'PP-RP20/3/2',
    216: 'PP-RP2/10/2',
    225: 'ABS/AC-RG',
    232: 'ABS',
    233: 'ACETAL',
    234: 'AC',
    235: 'CACO3',
    236: 'CONPE',
    237: 'CONPP',
    238: 'CONPS',
    239: 'EMA',
    240: 'EVA',
    241: 'GELOY',
    242: 'PS',
    243: 'GPPS',
    244: 'MIPS',
    245: 'HIPS',
    246: 'HMW',
    247: 'META',
    248: 'NYLON',
    249: 'PC/ABS',
    250: 'PC',
    251: 'PE/PP',
    252: 'HDPE',
    253: 'LDPE',
    254: 'PETE',
    255: 'PLA',
    256: 'PP',
    257: 'PVC',
    258: 'SANTO',
    259: 'SURLYN',
    260: 'TPE',
    261: 'TPO',
    262: 'TPR',
    263: 'REJET',
    264: 'MDPE',
    265: 'PETG',
    266: 'PEROX',
    267: 'PEHD-2057C',
    268: 'CONEVA',
    269: 'PP/PE',
    270: 'KRATON PS',
    271: 'KRATON PP',
    272: 'CARTON',
    273: 'SACS',
    274: 'Exxelclean',
    275: 'TRANSPORT-EXL-528099',
    276: 'PIECES ET EQUIPEMENT',
    277: 'GAYLORDS',
    278: 'PAL CPC',
    279: 'LAVAGE',
    280: 'MANUTENTION',
    281: 'VIDANGE',
    282: 'GRANULATION',
    283: 'EMBALLAGE',
    284: 'EXXELMAX',
    285: 'DELRIN',
    286: 'ABS/PA',
    290: 'SAN',
    291: 'TPU',
    292: 'GAYLORDS-IN',
    293: 'GAYLORDS-OUT EXL-527854',
    294: 'PAL-SCRAP EXL-527853',

    296: 'PAL-CLIENT EXL-528100'})

  #replace values in the column COULEUR
  df_izod['COULEUR'] = df_izod['COULEUR'].replace({1: 'BE',
    2: 'BK',
    3: 'WH',
    4: 'NAT',
    5: 'MIX',
    6: 'BLU',
    7: 'RED',
    8: 'GRE',
    9: 'YEL',
    10: 'BRN',
    11: 'GREY',
    12: 'GREYI',
    13: 'YELI',
    14: 'CL',
    15: 'GD',
    17: 'SMK',
    18: 'BRNI'})

  #replace values in the column I_G
  df_izod['I_G'] = df_izod['I_G'].replace({1: 1,
    2: 2,
    3: 3,
    4: 'L',
    5: 'E',
    6: 'CH',
    7: 'PUF',
    8: 'T',
    9: 'EMB',
    10: 'V',
    11: 'X',
    12: 'F',
    13: 'C',
    14: 'MEL',
    15: 'FO',
    16: 'R',
    17: 'S',
    18: 'HF'})

  #replace values in the column I_F
  df_izod['I_F'] = df_izod['I_F'].replace({1: 'B',
    2: 'C',
    3: 'RG',
    4: 'RL',
    5: 'RP',
    6: 'PW',
    7: 'D',
    8: 'WS',
    9: 'G',
    10: 'PR',
    12: 'P'})

  #replace values in the column I_CM
  df_izod['I_CM'] = df_izod['I_CM'].replace({1: 'EXT', 2: 'INJ', 3: 'OFF', 4: 'X', 5: 'HM'})

  #replace the comma by a dot in the values of all attribute
  df_izod = df_izod.replace(",", ".",regex=True)
  #delete all the spaces in the values of all attribute
  df_izod = df_izod.replace(" ", "",regex=True)
  columns = ['Items','I_F', 'I_CM','I_G', 'I1', 'I48','COULEUR']
  for col in columns:
      df_izod = dropnaand0(df_izod,col)
  return df_izod
  #drop all duplicated rows
  df_izod = df_izod.drop_duplicates()
  #drop rows that contain missing values
  df_izod = df_izod.dropna()


# 12. Write a program to find the sum of the cubes of the first n natural numbers where the value of n is provided by the user.
# prompt user to input value of n
# a natural number start is a = 1
# a formula to calculate cube is a ** 3
# a formula to calculate sum is sum += a
# how many times to calculate the formula is in range of n
# print out the result

# the option using arithmetic progression

# the option using controlled loop
def main2():
    n = int(input("Enter the value of n: "))
    sum = 0
    for i in range(1, n + 1):
        a = i ** 3
        sum += a

    print("The sum of cubes currently is: ", sum)

main2()


import requests

balance_url = "http://weixin.ccnu.edu.cn/App/weixin/CardInfoAjax"
detail_query_url = "http://weixin.ccnu.edu.cn/App/weixin/queryTrans"

def get_balance(sid):
    """
    get balance
    :param sid: student id
    :return: balance in json
    """
    headers = {
        "User-Agent" : "Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E216 MicroMessenger/6.6.6 NetType/WIFI Language/zh_CN",
        "Cookie" : "wxqyuserid=%s" % sid,
    }

    r = requests.get(balance_url,headers=headers)
    return r.json()

def detail_query(sid,startTime,endTime):
    """
    校园卡流水明细
    :param sid: 学号
    :param startTime: 起始时间
    :param endTime: 结束时间
    :return: json  data
    """
    headers = {
        "User-Agent" : "Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E216 MicroMessenger/6.6.6 NetType/WIFI Language/zh_CN",
        "Cookie": "wxqyuserid=%s" % sid,
    }
    params = {
        "page": 1,
        "pageSize": 200,
        "startTime": startTime,
        "endTime": endTime,
    }
    r = requests.get(detail_query_url, params=params, headers=headers)
    return r.json()

if __name__ == '__main__':
    print(get_balance(201621081))
    detail_query(2016210813,"2018-04-28","2018-05-03")


from CSP import Graph
import copy

def create_disc(task,machine,total_time):
    # Asignamos los valores del dominio, vecinos y tiempo de ejecucion de cada tarea. Asignamos cada tarea en un tipo de maquina
    tasks = {} #diccionario con key:tarea, values:(dominio,vecinos,tiempo de ejecucion)
    machines={}
    mac=0
    for m in range(len(machine)):  #guardamos las tareas dentro de cada tipo de maquina
        if machine[m][1] != mac:
            machines.setdefault(machine[m][1],[])
    for i in task:
        listneighbors=[]    #listas vacias para ir guardando los valores de los vecinos y dominio
        listdomain=[]
        for j in machine:
            if i[2]==j[1]:
                if "T"+str(i[0]) not in machines[j[1]] :
                    machines[j[1]].append("T"+str(i[0]))
                for x in range(total_time-i[1]):  #Tenemos el ultimo valor al que puede tomar para no pasarle del tiempo total de produccion. en i[1] esta la duracion de la tarea
                    listdomain.append((j[0],x)) #Guardamos que maquina puede usar y los valores de inicio posibles
        for k in task: #Volvemos a recorrer tdas las tareas y verificamos con cuales otra tarea tiene restricciones para crear los vecinos.
            if i != k:
                if i[2]==k[2]:
                    listneighbors.append("T"+str(k[0]))
        value=(listdomain,listneighbors,i[1])
        tasks.setdefault("T"+str(i[0]),value)   #guardamos los valores en el diccionario
    return tasks,machines

def csp(index,graph,total_time,tasks,assignment,list_not_use,machines):
    flag_allerror=0
    flag=0
    machine_complete=copy.deepcopy(machines)
    while flag==0:      #Iteramos
        if not machines:     #Cuando esta vacio quiere decir que termino de asignar todas las tareas
            flag=1
        else:
            graph.append(Graph(total_time,copy.deepcopy(tasks),copy.deepcopy(assignment))) #Creamos grafos de reestriciones en cada iteracion por si queremos hacer backtracking
            index=index+1
            variable=graph[index].heuristic_MRV(list_not_use[index-1],machines) #Elegimos la variable con menor dominios para elegir (heuristica)
            tasks,assignment,flag_error,machines=graph[index].inference(variable,machines) #Borramos la variable eleiga y sus reestriciones con las demas y podamos el arbol
            if flag_error==1:      #Backtracking: Si esa variable variable da a una solucion no valida hacemos backtracking
                graph.pop()  #borramos el grafo ultimo y volvemos a asignar las variables anteriores para eliminar las erroneas
                index=index-1
                tasks=graph[index].tasks
                assignment=graph[index].assignment
                list_not_use[index].append(variable[0])          #variables para no usar
                if len(list_not_use[index])==len(machines) and len(machines)!=0 : #Backtracking: Si todas las variables de ese arbol no llegan a ningun resultado tenemos que volver al nodo anterior
                    flag_allerror = 1
                while flag_allerror==1: #Por si tenemos que seguir volviendo a nodos anteriores
                    index=index-1
                    list_not_use[index].append(graph[index+1].assignment[index][0]) #agregamos la asignacion usada que no llevaba a ninguna solucion para no usarla
                    machines.append(graph[index+1].assignment[index][0])
                    graph.pop()      #borramos el ultimo grafo
                    list_not_use.pop() #borramos estas variables para volver al nodo anterior del arbol
                    tasks=graph[index].tasks
                    assignment=graph[index].assignment
                    if len(list_not_use[index])!=len(machines):
                        flag_allerror=0
                    if len(list_not_use[index]) == len(machine_complete): #si llegamos a que no podemos tener
                        return "error","error","error"
            else:
                list_not_use.append([])
    return index,tasks,assignment

if __name__ == '__main__':
    task=[[1,10,1], [2,5,1],[3,18,1],[4,13,1],[5,1,2],[6,11,2],[7,10,2]] #Tareas de la forma: [ID, Duracion, Tipo de maquina]
    machine=[[1,1],[2,1],[3,2]] #Maquinas de la forma: [ID,Tipo de maquina]
    total_time=24               #Tomamos una produccion continua de 24 hs
    tasks,machines=create_disc(task,machine,total_time)
    assignment=[]
    graph=[]
    list_not_use=[]     #hacemos una lista para las variables q no dan ningun resultado, y vamos guardando cada variable en cada nodo del arbol
    list_not_use.append([])
    graph.append(Graph(total_time,copy.deepcopy(tasks),copy.deepcopy(assignment))) #Creamos el grafo de restrcciones inicial
    index=0
    for mach in machines:
        index,tasks,assignment=csp(index,graph,total_time,tasks,assignment,list_not_use,machines[mach]) #Satisfaccion de reestricciones
        if assignment=="error":
            print("No se pueden asignar completamente esas tareas en la maquina de tipo: "+ str(mach))
            break
    if assignment == "error":
        print("No se pueden asignar completamente esas tareas")
    else:
        print("La asignacion completa de la forma ['Tarea','numero de maquina','tiempo de inicio'] es: \n")
        print(assignment)


from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
import numpy

def my_feature_univariate(X,Y):

    test = SelectKBest(score_func=chi2, k=10)
    fit = test.fit(X, Y)
    # summarize scores
    numpy.set_printoptions(precision=3)
    #print("* Print out fit scores of features")
    #print(fit.scores_)
    print("* Print out 10 best features")
    fit.scores_.argsort()[-10:][::-1]
    print(X.columns[fit.scores_.argsort()[-10:][::-1]].values.tolist())
    #features = fit.transform(X)


import argparse

__all__ = ['parse_args', ]

BENCHMARK_MODELS = [
    "machine_translation", "resnet", "vgg", "mnist", "stacked_dynamic_lstm"
]

def parse_args():
    parser = argparse.ArgumentParser('Fluid model benchmarks.')
    parser.add_argument(
        '--model',
        type=str,
        choices=BENCHMARK_MODELS,
        default='resnet',
        help='The model to run benchmark with.')
    parser.add_argument(
        '--batch_size', type=int, default=32, help='The minibatch size.')
    #  args related to learning rate
    parser.add_argument(
        '--learning_rate', type=float, default=0.001, help='The learning rate.')
    # TODO(wuyi): add "--use_fake_data" option back.
    parser.add_argument(
        '--skip_batch_num',
        type=int,
        default=5,
        help='The first num of minibatch num to skip, for better performance test'
    )
    parser.add_argument(
        '--iterations', type=int, default=80, help='The number of minibatches.')
    parser.add_argument(
        '--pass_num', type=int, default=100, help='The number of passes.')
    parser.add_argument(
        '--data_format',
        type=str,
        default='NCHW',
        choices=['NCHW', 'NHWC'],
        help='The data data_format, now only support NCHW.')
    parser.add_argument(
        '--device',
        type=str,
        default='GPU',
        choices=['CPU', 'GPU'],
        help='The device type.')
    parser.add_argument(
        '--gpus',
        type=int,
        default=1,
        help='If gpus > 1, will use ParallelExecutor to run, else use Executor.')
    # this option is available only for vgg and resnet.
    parser.add_argument(
        '--cpus',
        type=int,
        default=1,
        help='If cpus > 1, will use ParallelDo to run, else use Executor.')
    parser.add_argument(
        '--data_set',
        type=str,
        default='flowers',
        choices=['cifar10', 'flowers'],
        help='Optional dataset for benchmark.')
    parser.add_argument(
        '--infer_only', action='store_true', help='If set, run forward only.')
    parser.add_argument(
        '--use_cprof', action='store_true', help='If set, use cProfile.')
    parser.add_argument(
        '--use_nvprof',
        action='store_true',
        help='If set, use nvprof for CUDA.')
    parser.add_argument(
        '--no_test',
        action='store_true',
        help='If set, do not test the testset during training.')
    parser.add_argument(
        '--use_fake_data',
        action='store_true',
        help='If set ommit the actual read data operators.')
    parser.add_argument(
        '--profile', action='store_true', help='If set, profile a few steps.')
    parser.add_argument(
        '--update_method',
        type=str,
        default='local',
        choices=['local', 'pserver', 'nccl2'],
        help='Choose parameter update method, can be local, pserver, nccl2.')
    parser.add_argument(
        '--no_split_var',
        action='store_true',
        default=False,
        help='Whether split variables into blocks when update_method is pserver')
    parser.add_argument(
        '--async_mode',
        action='store_true',
        default=False,
        help='Whether start pserver in async mode to support ASGD')
    parser.add_argument(
        '--use_reader_op',
        action='store_true',
        help='Whether to use reader op, and must specify the data path if set this to true.'
    )
    parser.add_argument(
        '--data_path',
        type=str,
        default="",
        help='Directory that contains all the training recordio files.')
    parser.add_argument(
        '--use_inference_transpiler',
        action='store_true',
        help='If set, use inference transpiler to optimize the program.')
    parser.add_argument(
        '--no_random',
        action='store_true',
        help='If set, keep the random seed and do not shuffle the data.')
    args = parser.parse_args()
    return args


from pyspark.sql import SparkSession
from pyspark.sql.avro.functions import from_avro
from pyspark.sql.functions import expr, col, struct, to_json, sum

if __name__ == "__main__":
    spark = SparkSession \
        .builder \
        .appName("Multi Query Demo") \
        .master("yarn") \
        .config("spark.streaming.stopGracefullyOnShutdown", "true") \
        .config("spark.sql.shuffle.partitions", 3) \
        .getOrCreate()

#Read from karka-avro source
    kafka_source_df = spark \
        .readStream \
        .format("kafka") \
        .option("kafka.bootstrap.servers", "localhost:9092") \
        .option("subscribe", "invoice-items") \
        .option("startingOffsets", "earliest") \
        .load()

#Open avro schema
    avroSchema = open('schema/invoice-items', mode='r').read()

#Deserialization using avro schema and from_avro function
    value_df = kafka_source_df.select(from_avro(col("value"), avroSchema).alias("value"))

#Checking schema
    value_df.printSchema()

#Choosing prime customers and calculate total transactions and earned points
    rewards_df = value_df.filter("value.CustomerType == 'PRIME'") \
        .groupBy("value.CustomerCardNo") \
        .agg(sum("value.TotalValue").alias("TotalPurchase"),
             sum(expr("value.TotalValue * 0.2").cast("integer")).alias("AggregatedRewards"))

#Rename column
    rewards_df = rewards_df.withColumn("CustomerCardNo", expr("`value.CustomerCardNo`")) \
                           .drop("value.CustomerCardNo")

#Serilization to json format
    kafka_target_df = rewards_df.select(expr("CustomerCardNo as key"),
                                        to_json(struct("TotalPurchase", "AggregatedRewards")).alias("value"))

#Check schema
    rewards_df.printSchema()
    # Alternative statement for kafka target
    # kafka_target_df = rewards_df.selectExpr("value.CustomerCardNo as key",
    #                                                                 "to_json(struct(*)) as value")

    # kafka_target_df.show(truncate=False)

#Writestream to kafka topic
    rewards_writer_query = kafka_target_df \
        .writeStream \
        .queryName("Rewards Writer") \
        .format("kafka") \
        .option("kafka.bootstrap.servers", "localhost:9092") \
        .option("topic", "customer-rewards") \
        .outputMode("update") \
        .option("checkpointLocation", "KafkaAvro/chk-point-dir") \
        .start()

    rewards_writer_query.awaitTermination()


# encoding: utf-8

# pylint: skip-file

import os
import subprocess
import tempfile
import textwrap
import time
import unittest

from test.constant import SEQUENCES, EX
from test.vim_interface import create_directory, TempFileManager

def plugin_cache_dir():
    """The directory that we check out our bundles to."""
    return os.path.join(tempfile.gettempdir(), "UltiSnips_test_vim_plugins")

class VimTestCase(unittest.TestCase, TempFileManager):
    snippets = ()
    files = {}
    text_before = " --- some text before --- \n\n"
    text_after = "\n\n --- some text after --- "
    expected_error = ""
    wanted = ""
    keys = ""
    sleeptime = 0.00
    output = ""
    plugins = []
    # Skip this test for the given reason or None for not skipping it.
    skip_if = lambda self: None
    version = None  # Will be set to vim --version output
    maxDiff = None  # Show all diff output, always.
    vim_flavor = None  # will be 'vim' or 'neovim'.
    expected_python_version = (
        None  # If set, we need to check that our Vim is running this python version.
    )

    def __init__(self, *args, **kwargs):
        unittest.TestCase.__init__(self, *args, **kwargs)
        TempFileManager.__init__(self, "Case")

    def runTest(self):
        if self.expected_python_version:
            self.assertEqual(self.in_vim_python_version, self.expected_python_version)

        # Only checks the output. All work is done in setUp().
        wanted = self.text_before + self.wanted + self.text_after
        SLEEPTIMES = [0.01, 0.15, 0.3, 0.4, 0.5, 1]
        for i in range(self.retries):
            if self.output and self.expected_error:
                self.assertRegexpMatches(self.output, self.expected_error)
                return
            if self.output != wanted or self.output is None:
                # Redo this, but slower
                self.sleeptime = SLEEPTIMES[min(i, len(SLEEPTIMES) - 1)]
                self.tearDown()
                self.setUp()
        self.assertMultiLineEqual(self.output, wanted)

    def _extra_vim_config(self, vim_config):
        """Adds extra lines to the vim_config list."""

    def _before_test(self):
        """Send these keys before the test runs.

        Used for buffer local variables and other options.

        """

    def _create_file(self, file_path, content):
        """Creates a file in the runtimepath that is created for this test.

        Returns the absolute path to the file.

        """
        return self.write_temp(file_path, textwrap.dedent(content + "\n"))

    def _link_file(self, source, relative_destination):
        """Creates a link from 'source' to the 'relative_destination' in our
        temp dir."""
        absdir = self.name_temp(relative_destination)
        create_directory(absdir)
        os.symlink(source, os.path.join(absdir, os.path.basename(source)))

    def setUp(self):
        if not VimTestCase.version:
            VimTestCase.version, _ = subprocess.Popen(
                [self.vim.vim_executable, "--version"],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
            ).communicate()
            VimTestCase.version = VimTestCase.version.decode("utf-8")

        if self.plugins and not self.test_plugins:
            return self.skipTest("Not testing integration with other plugins.")
        reason_for_skipping = self.skip_if()
        if reason_for_skipping is not None:
            return self.skipTest(reason_for_skipping)

        vim_config = []
        vim_config.append("set nocompatible")
        vim_config.append(
            "set runtimepath=$VIMRUNTIME,%s,%s"
            % (os.path.dirname(os.path.dirname(__file__)), self._temp_dir)
        )

        if self.plugins:
            self._link_file(
                os.path.join(plugin_cache_dir(), "vim-pathogen", "autoload"), "."
            )
            for plugin in self.plugins:
                self._link_file(
                    os.path.join(plugin_cache_dir(), os.path.basename(plugin)), "bundle"
                )
            vim_config.append("execute pathogen#infect()")

        # Some configurations are unnecessary for vanilla Vim, but Neovim
        # defines some defaults differently.
        vim_config.append("syntax on")
        vim_config.append("filetype plugin indent on")
        vim_config.append("set nosmarttab")
        vim_config.append("set noautoindent")
        vim_config.append('set backspace=""')
        vim_config.append('set clipboard=""')
        vim_config.append("set encoding=utf-8")
        vim_config.append("set fileencoding=utf-8")
        vim_config.append("set buftype=nofile")
        vim_config.append("set shortmess=at")
        vim_config.append('let @" = ""')
        assert EX == "\t"  # Otherwise you need to change the next line
        vim_config.append('let g:UltiSnipsExpandTrigger="<tab>"')
        vim_config.append('let g:UltiSnipsJumpForwardTrigger="?"')
        vim_config.append('let g:UltiSnipsJumpBackwardTrigger="+"')
        vim_config.append('let g:UltiSnipsListSnippets="@"')

        vim_config.append(
            "let g:UltiSnipsDebugServerEnable={}".format(1 if self.pdb_enable else 0)
        )
        vim_config.append('let g:UltiSnipsDebugHost="{}"'.format(self.pdb_host))
        vim_config.append("let g:UltiSnipsDebugPort={}".format(self.pdb_port))
        vim_config.append(
            "let g:UltiSnipsPMDebugBlocking={}".format(1 if self.pdb_block else 0)
        )

        # Work around https://github.com/vim/vim/issues/3117 for testing >
        # py3.7 on Vim 8.1. Actually also reported against UltiSnips
        # https://github.com/SirVer/ultisnips/issues/996
        if "Vi IMproved 8.1" in self.version:
            vim_config.append("silent! python3 1")

        vim_config.append('let g:UltiSnipsSnippetDirectories=["us"]')
        if self.python_host_prog:
            vim_config.append('let g:python3_host_prog="%s"' % self.python_host_prog)

        self._extra_vim_config(vim_config)

        # Finally, add the snippets and some configuration for the test.
        vim_config.append("py3 << EOF")
        vim_config.append("from UltiSnips import UltiSnips_Manager\n")

        if len(self.snippets) and not isinstance(self.snippets[0], tuple):
            self.snippets = (self.snippets,)
        for s in self.snippets:
            sv, content = s[:2]
            description = ""
            options = ""
            priority = 0
            if len(s) > 2:
                description = s[2]
            if len(s) > 3:
                options = s[3]
            if len(s) > 4:
                priority = s[4]
            vim_config.append(
                "UltiSnips_Manager.add_snippet(%r, %r, %r, %r, priority=%i)"
                % (sv, content, description, options, priority)
            )

        # fill buffer with default text and place cursor in between.
        prefilled_text = (self.text_before + self.text_after).splitlines()
        vim_config.append("import vim\n")
        vim_config.append("vim.current.buffer[:] = %r\n" % prefilled_text)
        vim_config.append(
            "vim.current.window.cursor = (max(len(vim.current.buffer)//2, 1), 0)"
        )

        # End of python stuff.
        vim_config.append("EOF")

        for name, content in self.files.items():
            self._create_file(name, content)

        self.in_vim_python_version = self.vim.launch(vim_config)

        self._before_test()

        if not self.interrupt:
            # Go into insert mode and type the keys but leave Vim some time to
            # react.
            text = "i" + self.keys
            while text:
                to_send = None
                for seq in SEQUENCES:
                    if text.startswith(seq):
                        to_send = seq
                        break
                to_send = to_send or text[0]
                self.vim.send_to_vim(to_send)
                time.sleep(self.sleeptime)
                text = text[len(to_send) :]
            self.output = self.vim.get_buffer_data()

    def tearDown(self):
        if self.interrupt:
            print("Working directory: %s" % (self._temp_dir))
            return
        self.vim.leave_with_wait()
        self.clear_temp()

# vim:fileencoding=utf-8:


#-*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import absolute_import

__author__ = 'jiho'

"""
Excel 2003-2004 XML Data Structure

Workbook/
    Styles/
        Style/
            @ss:ID
            Font/
                @ss:Underline = "Single"
    Worksheet
        @ss:Name
        Table/
            Row/
                Cell/
                    @ss:StyleID
                    Data
"""

import xml.etree.cElementTree as ET
from .style import Style
from .table import RowMapper

"""
# 최종목적은 row[0]['column'].style.getUnderline()과 같은 형태를 원하는 것임..

Examples:
    >>> obj = ExcelLib(u'제5차국내외문서목록(20130917)테스트.xml')
    >>> obj.setWorksheet(u'2011 국내문서-낱장')
    >>> obj.buildStyles()
    >>> rows = obj.buildRows()

    >>> print rows[0]['기록철'].style.getUnderline()
"""

class ExcelLib:
    def __init__(self, parse_xml_name):
        self.xml = ET.parse(parse_xml_name)
        self.xmlns = 'urn:schemas-microsoft-com:office:spreadsheet'
        self.namespaces = {
            'ss': 'urn:schemas-microsoft-com:office:spreadsheet'
        }
        self.styles = {}
        self.rows = []
        self.column_header = None
        self.sheet = None
        self.header_line = 0
        self.content_line = 1

    def set_header_line(self, num=0):
        self.header_line = num

    def set_content_line(self, num=1):
        self.content_line = num

    # Worksheet 선택 메서드
    def set_worksheet(self, sheet_name):
        for worksheet in self.xml.findall("./{%s}Worksheet" % self.xmlns):
            if worksheet.get('{%s}Name' % self.namespaces['ss']) == sheet_name:
                self.sheet = worksheet

        if not self.sheet:
            raise Exception('%s 이름을 가진 워크시트가 없습니다' % sheet_name)

    def get_sheets(self):
        sheets = [worksheet.get('{%s}Name' % self.namespaces['ss'])
                  for worksheet in self.xml.findall("./{%s}Worksheet" % self.xmlns)]
        return sheets

    # Style 구축 메서드
    def build_styles(self):
        styles = self.xml.find("./{%s}Styles" % self.xmlns)

        for style in styles.findall('./{%s}Style' % self.xmlns):
            obj_style = Style(style)

            self.styles[obj_style.styleID] = obj_style

    # 로우 정보 구축하기
    def build_rows(self):
        if self.header_line < -1:
            raise ExcelLibException('헤더 라인 번호가 입력되어 있지 않습니다')

        if not self.content_line:
            raise ExcelLibException('콘텐츠 라인 시작 번호가 입력되어 있지 않습니다')

        table = self.sheet.find("./{%s}Table" % self.xmlns)
        rows = table.findall("./{%s}Row" % self.xmlns)

        build_rows = []

        # 헤더라인을 미리 가져온다(컬럼명 라인 - 사용자가 입력한)
        row_header = rows[self.header_line]

        for i, row in enumerate(rows[self.content_line:]):
            data_row_meta = RowMapper(row_header, row, self.styles)
            build_rows.append(data_row_meta)

        self.column_header = tuple(build_rows[self.header_line].keys())

        return build_rows

    def get_column_header(self):
        return self.column_header.keys()

class ExcelLibException(Exception):
    pass

if __name__ == "__main__":
    obj = ExcelLib(u'제5차국내외문서목록(20130917)테스트.xml')
    obj.set_worksheet(u'2011 국내문서-낱장')
    obj.build_styles()
    obj.build_rows()
    print(obj.get_column_header())


# pylint: disable=missing-docstring

import os
import re
import subprocess
import socket

import structlog

from celery.schedules import crontab

from readthedocs.core.logs import shared_processors
from corsheaders.defaults import default_headers
from readthedocs.core.settings import Settings
from readthedocs.builds import constants_docker

try:
    import readthedocsext  # noqa
    ext = True
except ImportError:
    ext = False

try:
    import readthedocsext.theme  # noqa
    ext_theme = True
except ImportError:
    ext_theme = False

_ = gettext = lambda s: s
log = structlog.get_logger(__name__)

class CommunityBaseSettings(Settings):

    """Community base settings, don't use this directly."""

    # Django settings
    SITE_ID = 1
    ROOT_URLCONF = 'readthedocs.urls'
    LOGIN_REDIRECT_URL = '/dashboard/'
    FORCE_WWW = False
    SECRET_KEY = 'replace-this-please'  # noqa
    ATOMIC_REQUESTS = True

    DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

    # Debug settings
    DEBUG = True
    RTD_FORCE_SHOW_DEBUG_TOOLBAR = False

    @property
    def DEBUG_TOOLBAR_CONFIG(self):
        def _show_debug_toolbar(request):
            return request.environ.get('SERVER_NAME', None) != 'testserver' and self.SHOW_DEBUG_TOOLBAR

        return {
            'SHOW_TOOLBAR_CALLBACK': _show_debug_toolbar,
        }

    @property
    def SHOW_DEBUG_TOOLBAR(self):
        """
        Show django-debug-toolbar on DEBUG or if it's forced by RTD_FORCE_SHOW_DEBUG_TOOLBAR.

        This will show the debug toolbar on:

          - Docker local instance
          - web-extra production instance
        """
        return self.DEBUG or self.RTD_FORCE_SHOW_DEBUG_TOOLBAR

    # Domains and URLs
    RTD_IS_PRODUCTION = False
    PRODUCTION_DOMAIN = 'readthedocs.org'
    PUBLIC_DOMAIN = None
    PUBLIC_DOMAIN_USES_HTTPS = False
    PUBLIC_API_URL = 'https://{}'.format(PRODUCTION_DOMAIN)
    RTD_INTERSPHINX_URL = 'https://{}'.format(PRODUCTION_DOMAIN)
    RTD_EXTERNAL_VERSION_DOMAIN = 'external-builds.readthedocs.io'

    # Doc Builder Backends
    MKDOCS_BACKEND = 'readthedocs.doc_builder.backends.mkdocs'
    SPHINX_BACKEND = 'readthedocs.doc_builder.backends.sphinx'

    # slumber settings
    SLUMBER_API_HOST = 'https://readthedocs.org'

    # Email
    DEFAULT_FROM_EMAIL = 'no-reply@readthedocs.org'
    SERVER_EMAIL = DEFAULT_FROM_EMAIL
    SUPPORT_EMAIL = None
    SUPPORT_FORM_ENDPOINT = None

    # Sessions
    SESSION_COOKIE_DOMAIN = 'readthedocs.org'
    SESSION_COOKIE_HTTPONLY = True
    SESSION_COOKIE_AGE = 30 * 24 * 60 * 60  # 30 days
    SESSION_SAVE_EVERY_REQUEST = False

    @property
    def SESSION_COOKIE_SAMESITE(self):
        """
        Cookie used in cross-origin API requests from *.rtd.io to rtd.org/api/v2/sustainability/.
        """
        if self.USE_PROMOS:
            return None
        # This is django's default.
        return 'Lax'

    # CSRF
    CSRF_COOKIE_HTTPONLY = True
    CSRF_COOKIE_AGE = 30 * 24 * 60 * 60  # 30 days

    # Security & X-Frame-Options Middleware
    # https://docs.djangoproject.com/en/1.11/ref/middleware/#django.middleware.security.SecurityMiddleware
    SECURE_CONTENT_TYPE_NOSNIFF = True
    SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"
    X_FRAME_OPTIONS = 'DENY'

    # Content Security Policy
    # https://django-csp.readthedocs.io/
    CSP_BLOCK_ALL_MIXED_CONTENT = True
    CSP_DEFAULT_SRC = None  # This could be improved
    CSP_FRAME_ANCESTORS = ("'none'",)
    CSP_OBJECT_SRC = ("'none'",)
    CSP_REPORT_URI = None
    CSP_REPORT_ONLY = False
    CSP_EXCLUDE_URL_PREFIXES = (
        "/admin/",
    )

    # Read the Docs
    READ_THE_DOCS_EXTENSIONS = ext
    RTD_LATEST = 'latest'
    RTD_LATEST_VERBOSE_NAME = 'latest'
    RTD_STABLE = 'stable'
    RTD_STABLE_VERBOSE_NAME = 'stable'
    RTD_CLEAN_AFTER_BUILD = False
    RTD_MAX_CONCURRENT_BUILDS = 4
    RTD_BUILDS_MAX_RETRIES = 25
    RTD_BUILDS_RETRY_DELAY = 5 * 60  # seconds
    RTD_BUILD_STATUS_API_NAME = 'docs/readthedocs'
    RTD_ANALYTICS_DEFAULT_RETENTION_DAYS = 30 * 3
    RTD_AUDITLOGS_DEFAULT_RETENTION_DAYS = 30 * 3

    # Number of days the validation process for a domain will be retried.
    RTD_CUSTOM_DOMAINS_VALIDATION_PERIOD = 30

    # Keep BuildData models on database during this time
    RTD_TELEMETRY_DATA_RETENTION_DAYS = 30 * 6  # 180 days / 6 months

    # Number of days an invitation is valid.
    RTD_INVITATIONS_EXPIRATION_DAYS = 15

    RTD_ENFORCE_BROWNOUTS_FOR_DEPRECATIONS = False

    @property
    def RTD_DEFAULT_FEATURES(self):
        # Features listed here will be available to users that don't have a
        # subscription or if their subscription doesn't include the feature.
        # Depending on the feature type, the numeric value represents a
        # number of days or limit of the feature.
        from readthedocs.subscriptions import constants
        from readthedocs.subscriptions.products import RTDProductFeature
        return dict((
            RTDProductFeature(type=constants.TYPE_CNAME).to_item(),
            RTDProductFeature(type=constants.TYPE_EMBED_API).to_item(),
            # Retention days for search analytics.
            RTDProductFeature(type=constants.TYPE_SEARCH_ANALYTICS, value=self.RTD_ANALYTICS_DEFAULT_RETENTION_DAYS).to_item(),
            # Retention days for page view analytics.
            RTDProductFeature(type=constants.TYPE_PAGEVIEW_ANALYTICS, value=self.RTD_ANALYTICS_DEFAULT_RETENTION_DAYS).to_item(),
            # Retention days for audit logs.
            RTDProductFeature(type=constants.TYPE_AUDIT_LOGS, value=self.RTD_AUDITLOGS_DEFAULT_RETENTION_DAYS).to_item(),
            # Max number of concurrent builds.
            RTDProductFeature(type=constants.TYPE_CONCURRENT_BUILDS, value=self.RTD_MAX_CONCURRENT_BUILDS).to_item(),
        ))

    # A dictionary of Stripe products mapped to a RTDProduct object.
    # In .org we don't have subscriptions/products, default features are
    # defined in RTD_DEFAULT_FEATURES.
    RTD_PRODUCTS = {}

    # Database and API hitting settings
    DONT_HIT_DB = True
    RTD_SAVE_BUILD_COMMANDS_TO_STORAGE = False
    DATABASE_ROUTERS = ['readthedocs.core.db.MapAppsRouter']

    USER_MATURITY_DAYS = 7

    # override classes
    CLASS_OVERRIDES = {}

    DOC_PATH_PREFIX = '_/'

    @property
    def RTD_EXT_THEME_ENABLED(self):
        return ext_theme and 'RTD_EXT_THEME_ENABLED' in os.environ

    RTD_EXT_THEME_DEV_SERVER = None

    # Application classes
    @property
    def INSTALLED_APPS(self):  # noqa
        apps = [
            'django.contrib.auth',
            'django.contrib.admin',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.sites',
            'django.contrib.messages',
            'django.contrib.humanize',

            # readthedocs.core app needs to be before
            # django.contrib.staticfiles to use our custom collectstatic
            # command
            'readthedocs.core',
            'django.contrib.staticfiles',

            # third party apps
            'dj_pagination',
            'taggit',
            'django_gravatar',
            'rest_framework',
            'rest_framework.authtoken',
            "rest_framework_api_key",
            'corsheaders',
            'annoying',
            'django_extensions',
            'crispy_forms',
            'messages_extends',
            'django_elasticsearch_dsl',
            'django_filters',
            'polymorphic',
            'simple_history',
            'djstripe',
            'django_celery_beat',

            # our apps
            'readthedocs.projects',
            'readthedocs.organizations',
            'readthedocs.builds',
            'readthedocs.doc_builder',
            'readthedocs.oauth',
            'readthedocs.redirects',
            'readthedocs.sso',
            'readthedocs.audit',
            'readthedocs.rtd_tests',
            'readthedocs.api.v2',
            'readthedocs.api.v3',

            'readthedocs.gold',
            'readthedocs.payments',
            'readthedocs.subscriptions',
            'readthedocs.notifications',
            'readthedocs.integrations',
            'readthedocs.analytics',
            'readthedocs.search',
            'readthedocs.embed',
            'readthedocs.telemetry',
            'readthedocs.domains',
            'readthedocs.invitations',

            # allauth
            'allauth',
            'allauth.account',
            'allauth.socialaccount',
            'allauth.socialaccount.providers.github',
            'allauth.socialaccount.providers.gitlab',
            'allauth.socialaccount.providers.bitbucket',
            'allauth.socialaccount.providers.bitbucket_oauth2',
            'cacheops',
        ]
        if ext:
            apps.append('readthedocsext.cdn')
            apps.append('readthedocsext.donate')
            apps.append('readthedocsext.spamfighting')
        if self.RTD_EXT_THEME_ENABLED:
            apps.append('readthedocsext.theme')
        if self.SHOW_DEBUG_TOOLBAR:
            apps.append('debug_toolbar')

        return apps

    @property
    def CRISPY_TEMPLATE_PACK(self):
        if self.RTD_EXT_THEME_ENABLED:
            return 'semantic-ui'
        return 'bootstrap'

    @property
    def CRISPY_ALLOWED_TEMPLATE_PACKS(self):
        if self.RTD_EXT_THEME_ENABLED:
            return ('semantic-ui',)
        return ("bootstrap", "uni_form", "bootstrap3", "bootstrap4")

    @property
    def USE_PROMOS(self):  # noqa
        return 'readthedocsext.donate' in self.INSTALLED_APPS

    @property
    def MIDDLEWARE(self):
        middlewares = [
            'readthedocs.core.middleware.NullCharactersMiddleware',
            'readthedocs.core.middleware.ReadTheDocsSessionMiddleware',
            'django.middleware.locale.LocaleMiddleware',
            'corsheaders.middleware.CorsMiddleware',
            'django.middleware.common.CommonMiddleware',
            'django.middleware.security.SecurityMiddleware',
            'django.middleware.csrf.CsrfViewMiddleware',
            'django.middleware.clickjacking.XFrameOptionsMiddleware',
            'django.contrib.auth.middleware.AuthenticationMiddleware',
            'django.contrib.messages.middleware.MessageMiddleware',
            'dj_pagination.middleware.PaginationMiddleware',
            'csp.middleware.CSPMiddleware',
            'readthedocs.core.middleware.ReferrerPolicyMiddleware',
            'simple_history.middleware.HistoryRequestMiddleware',
            'readthedocs.core.logs.ReadTheDocsRequestMiddleware',
            'django_structlog.middlewares.CeleryMiddleware',
        ]
        if self.SHOW_DEBUG_TOOLBAR:
            middlewares.insert(0, 'debug_toolbar.middleware.DebugToolbarMiddleware')
        return middlewares

    AUTHENTICATION_BACKENDS = (
        # Needed to login by username in Django admin, regardless of `allauth`
        'django.contrib.auth.backends.ModelBackend',
        # `allauth` specific authentication methods, such as login by e-mail
        'allauth.account.auth_backends.AuthenticationBackend',
    )

    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
            'OPTIONS': {
                'min_length': 9,
            }
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]

    MESSAGE_STORAGE = 'readthedocs.notifications.storages.FallbackUniqueStorage'

    NOTIFICATION_BACKENDS = [
        'readthedocs.notifications.backends.EmailBackend',
        'readthedocs.notifications.backends.SiteBackend',
    ]

    # Paths
    SITE_ROOT = os.path.dirname(
        os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    TEMPLATE_ROOT = os.path.join(SITE_ROOT, 'readthedocs', 'templates')
    DOCROOT = os.path.join(SITE_ROOT, 'user_builds')
    LOGS_ROOT = os.path.join(SITE_ROOT, 'logs')
    PRODUCTION_ROOT = os.path.join(SITE_ROOT, 'prod_artifacts')
    PRODUCTION_MEDIA_ARTIFACTS = os.path.join(PRODUCTION_ROOT, 'media')

    # Assets and media
    STATIC_ROOT = os.path.join(SITE_ROOT, 'static')
    STATIC_URL = '/static/'
    MEDIA_ROOT = os.path.join(SITE_ROOT, 'media/')
    MEDIA_URL = '/media/'
    ADMIN_MEDIA_PREFIX = '/media/admin/'
    STATICFILES_DIRS = [
        os.path.join(SITE_ROOT, 'readthedocs', 'static'),
        os.path.join(SITE_ROOT, 'media'),
    ]
    STATICFILES_FINDERS = [
        'readthedocs.core.static.SelectiveFileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
        'readthedocs.core.finders.DebugToolbarFinder',
    ]
    PYTHON_MEDIA = False

    # Django Storage subclass used to write build artifacts to cloud or local storage
    # https://docs.readthedocs.io/page/development/settings.html#rtd-build-media-storage
    RTD_BUILD_MEDIA_STORAGE = 'readthedocs.builds.storage.BuildMediaFileSystemStorage'
    RTD_BUILD_ENVIRONMENT_STORAGE = 'readthedocs.builds.storage.BuildMediaFileSystemStorage'
    RTD_BUILD_TOOLS_STORAGE = 'readthedocs.builds.storage.BuildMediaFileSystemStorage'
    RTD_BUILD_COMMANDS_STORAGE = 'readthedocs.builds.storage.BuildMediaFileSystemStorage'
    RTD_STATICFILES_STORAGE = 'readthedocs.builds.storage.StaticFilesStorage'

    @property
    def TEMPLATES(self):
        dirs = [self.TEMPLATE_ROOT]
        if self.RTD_EXT_THEME_ENABLED:
            dirs.insert(0, os.path.join(
                os.path.dirname(readthedocsext.theme.__file__),
                'templates',
            ))

        # Disable ``cached.Loader`` on development
        # https://docs.djangoproject.com/en/4.2/ref/templates/api/#django.template.loaders.cached.Loader
        default_loaders = [
            "django.template.loaders.filesystem.Loader",
            "django.template.loaders.app_directories.Loader",
        ]
        cached_loaders = [("django.template.loaders.cached.Loader", default_loaders)]

        return [
            {
                'BACKEND': 'django.template.backends.django.DjangoTemplates',
                'DIRS': dirs,
                'OPTIONS': {
                    'debug': self.DEBUG,
                    'loaders': default_loaders if self.DEBUG else cached_loaders,
                    'context_processors': [
                        'django.contrib.auth.context_processors.auth',
                        'django.contrib.messages.context_processors.messages',
                        'django.template.context_processors.debug',
                        'django.template.context_processors.i18n',
                        'django.template.context_processors.media',
                        'django.template.context_processors.request',
                        # Read the Docs processor
                        'readthedocs.core.context_processors.readthedocs_processor',
                    ],
                },
            },
        ]

    # Cache
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'PREFIX': 'docs',
        }
    }
    CACHE_MIDDLEWARE_SECONDS = 60

    # I18n
    TIME_ZONE = 'UTC'
    USE_TZ = True
    LANGUAGE_CODE = 'en-us'
    LANGUAGES = (
        ('ca', gettext('Catalan')),
        ('en', gettext('English')),
        ('es', gettext('Spanish')),
        ('pt-br', gettext('Brazilian Portuguese')),
        ('nb', gettext('Norwegian Bokmål')),
        ('fr', gettext('French')),
        ('ru', gettext('Russian')),
        ('de', gettext('German')),
        ('gl', gettext('Galician')),
        ('vi', gettext('Vietnamese')),
        ('zh-cn', gettext('Simplified Chinese')),
        ('zh-tw', gettext('Traditional Chinese')),
        ('ja', gettext('Japanese')),
        ('uk', gettext('Ukrainian')),
        ('it', gettext('Italian')),
        ('ko', gettext('Korean')),
    )
    LOCALE_PATHS = [
        os.path.join(SITE_ROOT, 'readthedocs', 'locale'),
    ]
    USE_I18N = True
    USE_L10N = True

    # Celery
    CELERY_APP_NAME = 'readthedocs'
    CELERY_ALWAYS_EAGER = True
    CELERYD_TASK_TIME_LIMIT = 60 * 60  # 60 minutes
    CELERY_SEND_TASK_ERROR_EMAILS = False
    CELERY_IGNORE_RESULT = True
    CELERYD_HIJACK_ROOT_LOGGER = False
    # This stops us from pre-fetching a task that then sits around on the builder
    CELERY_ACKS_LATE = True
    # Don't queue a bunch of tasks in the workers
    CELERYD_PREFETCH_MULTIPLIER = 1
    CELERY_CREATE_MISSING_QUEUES = True

    CELERY_DEFAULT_QUEUE = 'celery'
    CELERYBEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
    CELERYBEAT_SCHEDULE = {
        'quarter-finish-inactive-builds': {
            'task': 'readthedocs.projects.tasks.utils.finish_inactive_builds',
            'schedule': crontab(minute='*/15'),
            'options': {'queue': 'web'},
        },
        'every-three-hour-clear-persistent-messages': {
            'task': 'readthedocs.core.tasks.clear_persistent_messages',
            'schedule': crontab(minute=0, hour='*/3'),
            'options': {'queue': 'web'},
        },
        'every-day-delete-old-search-queries': {
            'task': 'readthedocs.search.tasks.delete_old_search_queries_from_db',
            'schedule': crontab(minute=0, hour=0),
            'options': {'queue': 'web'},
        },
        'every-day-delete-old-page-views': {
            'task': 'readthedocs.analytics.tasks.delete_old_page_counts',
            'schedule': crontab(minute=27, hour='*/6'),
            'options': {'queue': 'web'},
        },
        'every-day-delete-old-buildata-models': {
            'task': 'readthedocs.telemetry.tasks.delete_old_build_data',
            'schedule': crontab(minute=0, hour=2),
            'options': {'queue': 'web'},
        },
        'weekly-delete-old-personal-audit-logs': {
            'task': 'readthedocs.audit.tasks.delete_old_personal_audit_logs',
            'schedule': crontab(day_of_week="wed", minute=0, hour=7),
            'options': {'queue': 'web'},
        },
        'every-day-resync-sso-organization-users': {
            'task': 'readthedocs.oauth.tasks.sync_remote_repositories_organizations',
            'schedule': crontab(minute=0, hour=4),
            'options': {'queue': 'web'},
        },
        'quarter-archive-builds': {
            'task': 'readthedocs.builds.tasks.archive_builds_task',
            'schedule': crontab(minute='*/15'),
            'options': {'queue': 'web'},
            'kwargs': {
                'days': 1,
                'limit': 500,
                'delete': True,
            },
        },
        'every-three-hours-delete-inactive-external-versions': {
            'task': 'readthedocs.builds.tasks.delete_closed_external_versions',
            # Increase the frequency because we have 255k closed versions and they keep growing.
            # It's better to increase this frequency than the `limit=` of the task.
            'schedule': crontab(minute=0, hour='*/3'),
            'options': {'queue': 'web'},
        },
        'every-day-resync-remote-repositories': {
            'task': 'readthedocs.oauth.tasks.sync_active_users_remote_repositories',
            'schedule': crontab(minute=30, hour=2),
            'options': {'queue': 'web'},
        },
        'every-day-email-pending-custom-domains': {
            'task': 'readthedocs.domains.tasks.email_pending_custom_domains',
            'schedule': crontab(minute=0, hour=3),
            'options': {'queue': 'web'},
        },
        'every-15m-delete-pidbox-objects': {
            'task': 'readthedocs.core.tasks.cleanup_pidbox_keys',
            'schedule': crontab(minute='*/15'),
            'options': {'queue': 'web'},
        },
        'every-day-delete-old-revoked-build-api-keys': {
            'task': 'readthedocs.api.v2.tasks.delete_old_revoked_build_api_keys',
            'schedule': crontab(minute=0, hour=4),
            'options': {'queue': 'web'},
        },
    }

    # Sentry
    SENTRY_CELERY_IGNORE_EXPECTED = True

    # Docker
    DOCKER_ENABLE = False
    DOCKER_SOCKET = 'unix:///var/run/docker.sock'

    # User used to create the container.
    # In production we use the same user than the one defined by the
    # ``USER docs`` instruction inside the Dockerfile.
    # In development, we can use the "UID:GID" of the current user running the
    # instance to avoid file permissions issues.
    # https://docs.docker.com/engine/reference/run/#user
    RTD_DOCKER_USER = 'docs:docs'
    RTD_DOCKER_SUPER_USER = 'root:root'
    RTD_DOCKER_WORKDIR = '/home/docs/'

    RTD_DOCKER_COMPOSE = False

    DOCKER_VERSION = 'auto'
    DOCKER_DEFAULT_VERSION = 'ubuntu-22.04'
    DOCKER_IMAGE = '{}:{}'.format(constants_docker.DOCKER_DEFAULT_IMAGE, DOCKER_DEFAULT_VERSION)

    # Additional binds for the build container
    RTD_DOCKER_ADDITIONAL_BINDS = {}
    RTD_DOCKER_BUILD_SETTINGS = constants_docker.RTD_DOCKER_BUILD_SETTINGS
    # This is used for the image used to clone the users repo,
    # since we can't read their config file image choice before cloning
    RTD_DOCKER_CLONE_IMAGE = RTD_DOCKER_BUILD_SETTINGS["os"]["ubuntu-22.04"]

    def _get_docker_memory_limit(self):
        try:
            total_memory = int(subprocess.check_output(
                "free -m | awk '/^Mem:/{print $2}'",
                shell=True,
            ))
            return total_memory, round(total_memory - 1000, -2)
        except ValueError:
            # On systems without a `free` command it will return a string to
            # int and raise a ValueError
            log.exception('Failed to get memory size, using defaults Docker limits.')

    # Coefficient used to determine build time limit, as a percentage of total
    # memory. Historical values here were 0.225 to 0.3.
    DOCKER_TIME_LIMIT_COEFF = 0.25

    @property
    def DOCKER_LIMITS(self):
        """
        Set docker limits dynamically, if in production, based on system memory.

        We do this to avoid having separate build images. This assumes 1 build
        process per server, which will be allowed to consume all available
        memory.

        We subtract 750MiB for overhead of processes and base system, and set
        the build time as proportional to the memory limit.
        """
        # Our normal default
        limits = {
            'memory': '1g',
            'time': 600,
        }

        # Only run on our servers
        if self.RTD_IS_PRODUCTION:
            total_memory, memory_limit = self._get_docker_memory_limit()
            if memory_limit:
                limits = {
                    'memory': f'{memory_limit}m',
                    'time': max(
                        limits['time'],
                        round(total_memory * self.DOCKER_TIME_LIMIT_COEFF, -2),
                    )
                }
        log.info(
            'Using dynamic docker limits.',
            hostname=socket.gethostname(),
            memory=limits['memory'],
            time=limits['time'],
        )
        return limits

    # All auth
    ACCOUNT_ADAPTER = 'readthedocs.core.adapters.AccountAdapter'
    ACCOUNT_EMAIL_REQUIRED = True

    # Make email verification mandatory.
    # Users won't be able to login until they verify the email address.
    ACCOUNT_EMAIL_VERIFICATION = 'mandatory'

    ACCOUNT_AUTHENTICATION_METHOD = 'username_email'
    ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 7
    SOCIALACCOUNT_AUTO_SIGNUP = False
    SOCIALACCOUNT_STORE_TOKENS = True

    SOCIALACCOUNT_PROVIDERS = {
        'github': {
            "VERIFIED_EMAIL": True,
            'SCOPE': [
                'user:email',
                'read:org',
                'admin:repo_hook',
                'repo:status',
            ],
        },
        'gitlab': {
            "VERIFIED_EMAIL": True,
            'SCOPE': [
                'api',
                'read_user',
            ],
        },
        # Bitbucket scope/permissions are determined by the Oauth consumer setup on bitbucket.org
    }
    ACCOUNT_FORMS = {
        'signup': 'readthedocs.forms.SignupFormWithNewsletter',
    }

    # CORS
    # Don't allow sending cookies in cross-domain requests, this is so we can
    # relax our CORS headers for more views, but at the same time not opening
    # users to CSRF attacks. The sustainability API is the only view that requires
    # cookies to be send cross-site, we override that for that view only.
    CORS_ALLOW_CREDENTIALS = False

    # Allow cross-site requests from any origin,
    # all information from our allowed endpoits is public.
    #
    # NOTE: We don't use `CORS_ALLOW_ALL_ORIGINS=True`,
    # since that will set the `Access-Control-Allow-Origin` header to `*`,
    # we won't be able to pass credentials fo the sustainability API with that value.
    CORS_ALLOWED_ORIGIN_REGEXES = [re.compile(".+")]
    CORS_ALLOW_HEADERS = list(default_headers) + [
        'x-hoverxref-version',
    ]
    # Additional protection to allow only idempotent methods.
    CORS_ALLOW_METHODS = [
        'GET',
        'OPTIONS',
        'HEAD',
    ]

    # URLs to allow CORS to read from unauthed.
    CORS_URLS_REGEX = re.compile(
        r"""
        ^(
            /api/v2/footer_html
            |/api/v2/search
            |/api/v2/docsearch
            |/api/v2/embed
            |/api/v3/embed
            |/api/v2/sustainability
        )
        """,
        re.VERBOSE,
    )

    # RTD Settings
    ALLOW_PRIVATE_REPOS = False
    DEFAULT_PRIVACY_LEVEL = 'public'
    DEFAULT_VERSION_PRIVACY_LEVEL = 'public'
    ALLOW_ADMIN = True

    # Organization settings
    RTD_ALLOW_ORGANIZATIONS = False
    RTD_ORG_DEFAULT_STRIPE_SUBSCRIPTION_PRICE = 'trial-v2-monthly'
    RTD_ORG_TRIAL_PERIOD_DAYS = 30

    # Elasticsearch settings.
    ELASTICSEARCH_DSL = {
        'default': {
            'hosts': 'http://elastic:password@search:9200',
        },
    }
    # Chunk size for elasticsearch reindex celery tasks
    ES_TASK_CHUNK_SIZE = 500

    # Info from Honza about this:
    # The key to determine shard number is actually usually not the node count,
    # but the size of your data.
    # There are advantages to just having a single shard in an index since
    # you don't have to do the distribute/collect steps when executing a search.
    # If your data will allow it (not significantly larger than 40GB)
    # I would recommend going to a single shard and one replica meaning
    # any of the two nodes will be able to serve any search without talking to the other one.
    # Scaling to more searches will then just mean adding a third node
    # and a second replica resulting in immediate 50% bump in max search throughput.

    ES_INDEXES = {
        'project': {
            'name': 'project_index',
            'settings': {
                'number_of_shards': 1,
                'number_of_replicas': 1
            },
        },
        'page': {
            'name': 'page_index',
            'settings': {
                'number_of_shards': 1,
                'number_of_replicas': 1,
            },
        },
    }

    # ANALYZER = 'analysis': {
    #     'analyzer': {
    #         'default_icu': {
    #             'type': 'custom',
    #             'tokenizer': 'icu_tokenizer',
    #             'filter': ['word_delimiter', 'icu_folding', 'icu_normalizer'],
    #         }
    #     }
    # }

    # Disable auto refresh for increasing index performance
    ELASTICSEARCH_DSL_AUTO_REFRESH = False

    ALLOWED_HOSTS = ['*']

    ABSOLUTE_URL_OVERRIDES = {
        'auth.user': lambda o: '/profiles/{}/'.format(o.username)
    }

    INTERNAL_IPS = ('127.0.0.1',)

    # Taggit
    # https://django-taggit.readthedocs.io
    TAGGIT_TAGS_FROM_STRING = 'readthedocs.projects.tag_utils.rtd_parse_tags'

    # Stripe
    # Existing values we use
    STRIPE_SECRET = None
    STRIPE_PUBLISHABLE = None

    # DJStripe values -- **CHANGE THESE IN PRODUCTION**
    STRIPE_LIVE_SECRET_KEY = None
    STRIPE_TEST_SECRET_KEY = "sk_test_x" # A default so the `checks` don't fail
    DJSTRIPE_WEBHOOK_SECRET = None
    STRIPE_LIVE_MODE = False  # Change to True in production
    # This is less optimal than setting the webhook secret
    # However, the app won't start without the secret
    # with this setting set to the default
    DJSTRIPE_WEBHOOK_VALIDATION = "retrieve_event"

    # These values shouldn't need to change..
    DJSTRIPE_FOREIGN_KEY_TO_FIELD = "id"
    DJSTRIPE_USE_NATIVE_JSONFIELD = True  # We recommend setting to True for new installations

    # Disable adding djstripe metadata to the Customer objects.
    # We are managing the subscriber relationship by ourselves,
    # since we have subscriptions attached to an organization or gold user
    # we can't make use of the DJSTRIPE_SUBSCRIBER_MODEL setting.
    DJSTRIPE_SUBSCRIBER_CUSTOMER_KEY = None

    # Do Not Track support
    DO_NOT_TRACK_ENABLED = False

    # Advertising configuration defaults
    ADSERVER_API_BASE = None
    ADSERVER_API_KEY = None
    ADSERVER_API_TIMEOUT = 0.35  # seconds

    # Misc application settings
    GLOBAL_ANALYTICS_CODE = None
    DASHBOARD_ANALYTICS_CODE = None  # For the dashboard, not docs
    GRAVATAR_DEFAULT_IMAGE = 'https://assets.readthedocs.org/static/images/silhouette.png'  # NOQA
    OAUTH_AVATAR_USER_DEFAULT_URL = GRAVATAR_DEFAULT_IMAGE
    OAUTH_AVATAR_ORG_DEFAULT_URL = GRAVATAR_DEFAULT_IMAGE
    REST_FRAMEWORK = {
        'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',  # NOQA
        'DEFAULT_THROTTLE_RATES': {
            'anon': '5/minute',
            'user': '60/minute',
        },
        'PAGE_SIZE': 10,
        'TEST_REQUEST_DEFAULT_FORMAT': 'json',
    }

    SILENCED_SYSTEM_CHECKS = ['fields.W342']

    # Logging
    LOG_FORMAT = '%(name)s:%(lineno)s[%(process)d]: %(levelname)s %(message)s'
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': True,
        'formatters': {
            'default': {
                'format': LOG_FORMAT,
                'datefmt': '%d/%b/%Y %H:%M:%S',
            },
            # structlog
            "plain_console": {
                "()": structlog.stdlib.ProcessorFormatter,
                "processors": [
                    structlog.stdlib.ProcessorFormatter.remove_processors_meta,
                    structlog.dev.ConsoleRenderer(colors=False),
                ],
                # Allows to add extra data to log entries generated via ``logging`` module
                # See https://www.structlog.org/en/stable/standard-library.html#rendering-using-structlog-based-formatters-within-logging
                "foreign_pre_chain": shared_processors,
            },
            "colored_console": {
                "()": structlog.stdlib.ProcessorFormatter,
                "processors": [
                    structlog.stdlib.ProcessorFormatter.remove_processors_meta,
                    structlog.dev.ConsoleRenderer(colors=True),
                ],
                # Allows to add extra data to log entries generated via ``logging`` module
                # See https://www.structlog.org/en/stable/standard-library.html#rendering-using-structlog-based-formatters-within-logging
                "foreign_pre_chain": shared_processors,
            },
            "key_value": {
                "()": structlog.stdlib.ProcessorFormatter,
                "processors": [
                    structlog.processors.TimeStamper(fmt='iso'),
                    structlog.stdlib.ProcessorFormatter.remove_processors_meta,
                    structlog.processors.KeyValueRenderer(key_order=['timestamp', 'level', 'event', 'logger']),
                ],
                # Allows to add extra data to log entries generated via ``logging`` module
                # See https://www.structlog.org/en/stable/standard-library.html#rendering-using-structlog-based-formatters-within-logging
                "foreign_pre_chain": shared_processors,
            },
        },
        'handlers': {
            'console': {
                'level': 'INFO',
                'class': 'logging.StreamHandler',
                'formatter': 'plain_console',
            },
            'debug': {
                'level': 'DEBUG',
                'class': 'logging.handlers.RotatingFileHandler',
                'filename': os.path.join(LOGS_ROOT, 'debug.log'),
                'formatter': 'key_value',
            },
            'null': {
                'class': 'logging.NullHandler',
            },
        },
        'loggers': {
            '': {  # root logger
                'handlers': ['debug', 'console'],
                # Always send from the root, handlers can filter levels
                'level': 'INFO',
            },
            'docker.utils.config': {
                'handlers': ['null'],
                # Don't double log at the root logger for these.
                'propagate': False,
            },
            'django_structlog.middlewares.request': {
                'handlers': ['null'],
                # Don't double log at the root logger for these.
                'propagate': False,
            },
            'readthedocs': {
                'handlers': ['debug', 'console'],
                'level': 'DEBUG',
                # Don't double log at the root logger for these.
                'propagate': False,
            },
            'django.security.DisallowedHost': {
                'handlers': ['null'],
                'propagate': False,
            },
        },
    }

    # MailerLite API for newsletter signups
    MAILERLITE_API_SUBSCRIBERS_URL = 'https://api.mailerlite.com/api/v2/subscribers'
    MAILERLITE_API_ONBOARDING_GROUP_ID = None
    MAILERLITE_API_ONBOARDING_GROUP_URL = None
    MAILERLITE_API_KEY = None

    RTD_EMBED_API_EXTERNAL_DOMAINS = [
        r'docs\.python\.org',
        r'docs\.scipy\.org',
        r'docs\.sympy\.org',
        r'numpy\.org',
    ]
    RTD_EMBED_API_PAGE_CACHE_TIMEOUT = 5 * 10
    RTD_EMBED_API_DEFAULT_REQUEST_TIMEOUT = 1
    RTD_EMBED_API_DOMAIN_RATE_LIMIT = 50
    RTD_EMBED_API_DOMAIN_RATE_LIMIT_TIMEOUT = 60

    RTD_SPAM_THRESHOLD_DONT_SHOW_ADS = 100
    RTD_SPAM_THRESHOLD_DENY_ON_ROBOTS = 200
    RTD_SPAM_THRESHOLD_DONT_SHOW_DASHBOARD = 300
    RTD_SPAM_THRESHOLD_DONT_SERVE_DOCS = 500
    RTD_SPAM_THRESHOLD_DELETE_PROJECT = 1000
    RTD_SPAM_MAX_SCORE = 9999

    CACHEOPS_ENABLED = False
    CACHEOPS_TIMEOUT = 60 * 60  # seconds
    CACHEOPS_OPS = {'get', 'fetch'}
    CACHEOPS_DEGRADE_ON_FAILURE = True
    CACHEOPS = {
        # readthedocs.projects.*
        'projects.project': {
            'ops': CACHEOPS_OPS,
            'timeout': CACHEOPS_TIMEOUT,
        },
        'projects.feature': {
            'ops': CACHEOPS_OPS,
            'timeout': CACHEOPS_TIMEOUT,
        },
        'projects.projectrelationship': {
            'ops': CACHEOPS_OPS,
            'timeout': CACHEOPS_TIMEOUT,
        },
        'projects.domain': {
            'ops': CACHEOPS_OPS,
            'timeout': CACHEOPS_TIMEOUT,
        },

        # readthedocs.builds.*
        'builds.version': {
            'ops': CACHEOPS_OPS,
            'timeout': CACHEOPS_TIMEOUT,
        },

        # readthedocs.organizations.*
        'organizations.organization': {
            'ops': CACHEOPS_OPS,
            'timeout': CACHEOPS_TIMEOUT,
        },

        # readthedocs.subscriptions.*
        'subscriptions.planfeature': {
            'ops': CACHEOPS_OPS,
            'timeout': CACHEOPS_TIMEOUT,
        },
    }


# coding=UTF-8
#!flask/bin/python
from flask import Flask, jsonify, request, abort, url_for, send_from_directory
from produtos import RepositorioProdutos, ElementoInexistente, ElementoInvalido
from operacoes import RepositorioOperacoes
import os

HTTP_200_OK = 200
HTTP_201_CREATED = 201
HTTP_400_BAD_REQUEST = 400
HTTP_404_NOT_FOUND  = 404

app = Flask(__name__, static_folder='static', static_url_path='/ui')
repProdutos = RepositorioProdutos()

@app.route("/")
def hello():
    return send_from_directory(app.static_folder, 'index.html')

@app.route('/app/produtos', methods=['GET'])
def list_Produtos():
    produtos = repProdutos.listar()
    return jsonify({'produtos': produtos})

@app.route('/app/produtos', methods=['POST'])
def create_prod():
    try:
        if not request.json['id']:
            produto = repProdutos.adicionar(request.json)
        else:
            produto = repProdutos.atualizar(request.json)

        return jsonify({'resultado': produto}), HTTP_201_CREATED
    except ElementoInvalido:
       abort(HTTP_400_BAD_REQUEST)

if __name__ == "__main__":
    app.run(host=os.getenv('IP', '0.0.0.0'),port=int(os.getenv('PORT', 8080)))


#!/usr/bin/env python3

from math import *

def welcomeMessage():
	print("Welcome to my program!")
	print("It computes the area of a circle")
	print("Then it computes the area of a rectangle")

def areaOfCircle(radius):
	area = radius * radius * pi
	return area

def areaOfRect(length, width):
	area = length * width
	return area

r = float(input("Enter a radius: "))
a = areaOfCircle(r)
print("The area of the circle is", a)
l = float(input("Enter a length: "))
w = float(input("Enter a width: "))
a = areaOfRect(l, w)
print("The area of the rectangle is", a)


# -*- coding:utf-8 -*-
# Author：hankcs
# Date: 2018-05-23 17:35
import zipfile
import os

from pyhanlp.static import download, remove_file, HANLP_DATA_PATH

def test_data_path():
    """
    获取测试数据路径，位于$root/data/test，根目录由配置文件指定。
    :return:
    """
    data_path = os.path.join(HANLP_DATA_PATH, 'test')
    if not os.path.isdir(data_path):
        os.mkdir(data_path)
    return data_path

def ensure_data(data_name, data_url):
    root_path = test_data_path()
    dest_path = os.path.join(root_path, data_name)
    if os.path.exists(dest_path):
        return dest_path
    if data_url.endswith('.zip'):
        dest_path += '.zip'
    download(data_url, dest_path)
    if data_url.endswith('.zip'):
        with zipfile.ZipFile(dest_path, "r") as archive:
            archive.extractall(root_path)
        remove_file(dest_path)
        dest_path = dest_path[:-len('.zip')]
    return dest_path


'''
Day 28: RegEx, Patterns, and Intro to Databases
Task:
Consider a database table, Emails, which has the attributes First Name
and Email ID. Given N rows of data simulating the Emails table, print
an alphabetically-ordered list of people whose email address ends in
@gmail.com.

Print an alphabetically-ordered list of first names for every user with
a gmail account. Each name must be printed on a new line.

Sample Input:
6
riya riya@gmail.com
julia julia@julia.me
julia sjulia@gmail.com
julia julia@gmail.com
samantha samantha@gmail.com
tanya tanya@gmail.com

Sample Output:
julia
julia
riya
samantha
tanya
'''

#!/bin/python3

import sys
import re

N = int(input().strip())
gmail_accounts = []
for a0 in range(N):
    firstName, emailID = str(input()).strip().split(' ')

    if re.search("^[a-z\.]+@gmail.com$", emailID):
        gmail_accounts.append(firstName)

gmail_accounts.sort()
for n in gmail_accounts:
    print(n)


import os
from setuptools import setup, find_packages

_THIS_DIR = os.path.dirname(__file__)

with open(os.path.join(_THIS_DIR, 'README.rst')) as f:
    _LONG_DESCRIPTION = f.read().strip()

__version__ = None  # updated in the next line
exec(open(os.path.join(_THIS_DIR, 'pycantonese', '_version.py')).read())
assert __version__ is not None

def main():
    setup(name='pycantonese',
          version=__version__,
          description='PyCantonese',
          long_description=_LONG_DESCRIPTION,
          url='http://pycantonese.org/',
          author='Jackson Lee',
          author_email='jacksonlunlee@gmail.com',
          license='MIT License',
          packages=find_packages(),
          keywords=['computational linguistics', 'natural language processing',
                    'NLP', 'Cantonese', 'linguistics', 'corpora', 'speech',
                    'language', 'Chinese', 'Jyutping', 'tagging'],

          install_requires=[
              'pylangacq>=0.10.0'
          ],

          package_data={
              'pycantonese': ['data/hkcancor/*'],
          },

          zip_safe=False,

          classifiers=[
              'Development Status :: 4 - Beta',
              'Environment :: Console',
              'Intended Audience :: Developers',
              'Intended Audience :: Education',
              'Intended Audience :: Information Technology',
              'Intended Audience :: Science/Research',
              'License :: OSI Approved :: MIT License',
              'Natural Language :: Chinese (Traditional)',
              'Natural Language :: Cantonese',
              'Operating System :: OS Independent',
              'Programming Language :: Python :: 3',
              'Programming Language :: Python :: 3.4',
              'Programming Language :: Python :: 3.5',
              'Programming Language :: Python :: 3.6',
              'Topic :: Scientific/Engineering',
              'Topic :: Scientific/Engineering :: Artificial Intelligence',
              'Topic :: Scientific/Engineering :: Human Machine Interfaces',
              'Topic :: Scientific/Engineering :: Information Analysis',
              'Topic :: Text Processing',
              'Topic :: Text Processing :: Filters',
              'Topic :: Text Processing :: General',
              'Topic :: Text Processing :: Indexing',
              'Topic :: Text Processing :: Linguistic',
              ],
          )

if __name__ == '__main__':
    main()


"""
" author : kaneshige
" created : 20.02.2022 20:55:44
"""

import sys
import itertools
from collections import deque

def main():
    n,x = map(int,readline().split())
    dp = [[0]*(x+1) for i in range(n+1)]
    dp[0][0] = 1

    for i in range(1,n+1):
        a,b = map(int,readline().split())
        for j in range(x+1):
            if dp[i-1][j] == 1:
                if j+a <= x:
                    dp[i][j+a] = 1
                if j+b <= x:
                    dp[i][j+b] = 1

    if dp[n][x]:
        print("Yes")
    else:
        print("No")

if __name__ == "__main__":
    "----------Constants------------"
    INF = (1 << 62) - 1
    MOD = 10 ** 9 + 7
    # MOD = 998244353
    # sys.setrecursionlimit(10**6)
    true_ceil = lambda x, y: (x + y - 1) // y
    "----------Input------------"
    readline = sys.stdin.readline
    "----------Run------------"
    main()


# coding='utf-8'
from pathlib import Path
import re

def remove_durchen_marker(text):
    """
    this cleans up all note markers
    :param text: plain text
    :return: cleaned text
    """

    patterns = [
        # normalize single zeros '༥༥་' --> '༥༥༠

        ["༌", "་"],  # normalize NB tsek
        ["([0-9]+?)[ཝ—-]་?([0-9]+)", " <p\g<1>-\g<2>> "],
        ["”", ""],
        ["“", ""],
        ["’", ""],
        ["®", ""],
        ["=", ""],
        ["º", ""],
        ["°", ""],
        ["\*", ""],
        ["\+", ""],
        [":", ""],
        ["-", ""],
        [";", ""],
        ["�", ""],
        ['"', ''],
        ["·",""],
        ["[#€»@\{\$«\!¢\&%\?]", ""],
        ["([①-㊿༠-༩1-9]+)", ""]
    ]

    for p in patterns:
        text = re.sub(p[0], p[1], text)

    text = re.sub("<p.+?>", "", text)
    text = re.sub("([aA-zZ]+)", "", text)
    text = re.sub("<r.*?>", "", text)
    text = text.replace("<", "")
    text = text.replace(">", "")

    return text

if __name__ == "__main__":
    pecha_id = "IEA653111"
    base_path = Path(f'./test/opfs/{pecha_id}/{pecha_id}.opf/base/I1PD95878.txt')
    base_text = base_path.read_text(encoding='utf-8')
    clean_base = remove_durchen_marker(base_text)
    base_path.write_text(clean_base, encoding='utf-8')


import csv
import Deck
import pandas as pd
import os.path
from os.path import exists
from datetime import datetime
reference = {'royal flush': 0.00000154,
             'straight flush': .0000139,
             'four of a kind': .0002401,
             'full house': .001441,
             'flush': .003925,
             'straight': .003925,
             'three of a kind': .021128,
             'two pairs': .047539,
             'pair': .422569,
             'high card': .501177
             }

# Averages each trials and calculates the percent difference from the theroretical values
# returns dictionary with hands as keys and percentage as values
def run(draws):
    results = {'royal flush': 0,
             'straight flush': 0,
             'four of a kind': 0,
             'full house': 0,
             'flush': 0,
             'straight': 0,
             'three of a kind': 0,
             'two pairs': 0,
             'pair': 0,
             'high card': 0
             }
    print("Running...")
    for x in range(draws):
        d = Deck.Deck()
        d.shuffle()
        hand = d.deal()
        if hand in results:
            results[hand] += 1
        else:
            results[hand] = 1
    print("Done!")
    return results

def print_percentage(ratio):
    l = ['royal flush', 'straight flush', 'four of a kind', 'full house', 'flush', 'straight', 'three of a kind', 'two pairs', 'pair', 'high card']
    s = ""
    for x in l:
        print(x.upper() + ": " + f"{ratio[x]:.6%}")
        s += (x.upper() + ": " + f"{ratio[x]:.6%}\n")
    print()
    return s

def main():
    name = input("Enter your name: ")
    while name == "":
        name = input("Name cannot be empty. Enter your name: ")
    print("press 'q' to exit and save data\n*Warning! pressing Ctrl+C will not save data*\n")

    data = []
    while True:
        draws = input("Enter the number of draws in range of 1 - 10 (millions): ")

        if draws == "q":
            break

        try:
            int(draws)
            isInt = True
        except ValueError:
            isInt = False

        while (not isInt) or int(draws) < 1 or int(draws) > 10:
            draws = input("Invalid number of draws, enter in range of 1 - 10 (millions): ")
            try:
                int(draws)
                isInt = True
            except ValueError:
                isInt = False

        draws =  int(draws) * 1000000

        start = datetime.now()
        temp = run(draws)
        print("Total Runtime: " + str(datetime.now()-start))

        temp['draws'] = draws
        data.append(temp)

    df = pd.DataFrame.from_dict(data)
    print(df)
    df.to_csv('./data/'+name+'.csv', mode='a', index=False, header=False)

if __name__ == "__main__":
    main()


import pygame
from checkers.constants import WIDTH, HEIGHT, BOXSIZE, BROWN, WHITE, MAINMENU
from checkers.gamepiece import GamePiece
from checkers.gameLogic import GameLogic
from minimax import minimaxAlgo, getMoveList
import random

FRAMES_PER_SEC = 60

# Receive imported constants and set the width and height
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Welcome to our checkers gameLogic!')

def useMouse(location):
    x, y = location
    row = int(y // BOXSIZE)
    column = int(x // BOXSIZE)
    return row, column

#displays options when game has ended
def showGameOverScreen(winner):
    font = pygame.font.SysFont('comicsansms', 36)
    if winner == BROWN:
        text = font.render("GAME OVER !!", True, WHITE)
        text2 = font.render("Brown player wins!", True, WHITE)
    elif winner == WHITE:
        text = font.render("GAME OVER !!", True, WHITE)
        text2 = font.render("White player wins!", True, WHITE)
    else:
        text = font.render("GAME OVER !!", True, WHITE)
        text2 = font.render("It's a draw!", True, WHITE)

    play_again_text = font.render("Play Again", True, WHITE)
    quit_text = font.render("Quit", True, WHITE)

    text_rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 50))
    text2_rect = text2.get_rect(center=(WIDTH // 2, HEIGHT // 2))
    play_again_rect = play_again_text.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 50))
    quit_rect = quit_text.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 100))

    WINDOW.fill((0, 0, 0))
    WINDOW.blit(text, text_rect)
    WINDOW.blit(text2, text2_rect)
    pygame.draw.rect(WINDOW, (0, 0, 255), play_again_rect, border_radius=5)
    pygame.draw.rect(WINDOW, (0, 0, 255), quit_rect, border_radius=5)
    WINDOW.blit(play_again_text, play_again_rect)
    WINDOW.blit(quit_text, quit_rect)
    pygame.display.update()

#gameLoop for advanced mode
def twoPlayer():
    run = True
    clock = pygame.time.Clock()
    gameLogic = GameLogic(WINDOW)

    while run:
        clock.tick(FRAMES_PER_SEC)

        if gameLogic.getWinner() != None:
            print(gameLogic.getWinner())
            run = False

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            if event.type == pygame.MOUSEBUTTONDOWN:
                location = pygame.mouse.get_pos()
                row, column = useMouse(location)
                gameLogic.choose(row, column)

        gameLogic.update()

    pygame.quit()

#game loop for hard mode
def hardMode():
    run = True
    clock = pygame.time.Clock()
    gameLogic = GameLogic(WINDOW)
    pygame.display.set_caption('Welcome to our checkers gameLogic -> hard mode')

    while run:
        clock.tick(FRAMES_PER_SEC)

        if gameLogic.turn == WHITE:
            v, newBoard = minimaxAlgo(gameLogic.getBoard(), 4, WHITE, gameLogic)
            gameLogic.aiMove(newBoard)

        if gameLogic.getWinner() != None:
            showGameOverScreen(gameLogic.getWinner())
            if playAgain() == True:
                run = playAgain()
                gameLogic.reset()
                mainMenu()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            if event.type == pygame.MOUSEBUTTONDOWN:
                location = pygame.mouse.get_pos()
                row, column = useMouse(location)
                gameLogic.choose(row, column)

        gameLogic.update()

    pygame.quit()

#game loop for easy mode
def easyMode():
    run = True
    clock = pygame.time.Clock()
    gameLogic = GameLogic(WINDOW)
    pygame.display.set_caption('Welcome to our checkers gameLogic -> easy mode')

    while run:
        clock.tick(FRAMES_PER_SEC)

        if gameLogic.turn == WHITE:
            moves = getMoveList(gameLogic.getBoard(), WHITE, gameLogic)
            if moves:
                move = random.choice(moves)
                gameLogic.aiMove(move)

        gameLogic.update()

        if gameLogic.getWinner() != None:
            showGameOverScreen(gameLogic.getWinner())
            if playAgain() == True:
                run = playAgain()
                gameLogic.reset()
                mainMenu()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            if event.type == pygame.MOUSEBUTTONDOWN:
                location = pygame.mouse.get_pos()
                row, column = useMouse(location)
                gameLogic.choose(row, column)

        gameLogic.update()

    pygame.quit()

#resart game funtion
def playAgain():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONDOWN:
                location = pygame.mouse.get_pos()
                if WIDTH // 2 - 100 <= location[0] <= WIDTH // 2 + 100:
                    if HEIGHT // 2 + 50 <= location[1] <= HEIGHT // 2 + 100:
                        return True
                    elif HEIGHT // 2 + 100 <= location[1] <= HEIGHT // 2 + 150:
                        return False

#main selection menu
def mainMenu():
    pygame.init()

    run = True
    clock = pygame.time.Clock()

    while run:
        clock.tick(FRAMES_PER_SEC)
        WINDOW.fill((0, 0, 0))  # Fill the window with black color

        # Draw menu options
        font = pygame.font.SysFont('comicsansms', 36)

        intro = font.render("WELCOME TO OUR CHECKERS GAME", True, WHITE)
        easy_mode = font.render("1. Easy Mode", True, WHITE)
        start_text = font.render("2. Hard mode", True, WHITE)
        quit_text = font.render("Quit", True, WHITE)
        two_player = font.render("3. Multiplayer", True, WHITE)

        WINDOW.blit(MAINMENU, (0,0))
        WINDOW.blit(intro, (WIDTH // 2 - intro.get_width() // 2, HEIGHT // 2 - 200))
        WINDOW.blit(start_text, (WIDTH // 2 - start_text.get_width() // 2, HEIGHT // 2 + 50))
        WINDOW.blit(quit_text, (WIDTH // 2 - quit_text.get_width() // 2, HEIGHT // 2 + 250))
        WINDOW.blit(easy_mode, (WIDTH // 2 - easy_mode.get_width() // 2, HEIGHT // 2 - 50))
        WINDOW.blit(two_player, (WIDTH // 2 - easy_mode.get_width() // 2, HEIGHT // 2 + 150))

        pygame.display.update()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            if event.type == pygame.MOUSEBUTTONDOWN:
                location = pygame.mouse.get_pos()
                if WIDTH // 2 - start_text.get_width() // 2 <= location[0] <= WIDTH // 2 + start_text.get_width() // 2:
                    if HEIGHT // 2 - 50 <= location[1] <= HEIGHT // 2 - 50 + start_text.get_height():
                        hardMode()

                if WIDTH // 2 - easy_mode.get_width() // 2 <= location[0] <= WIDTH // 2 + easy_mode.get_width() // 2:
                    if HEIGHT // 2 + 50 <= location[1] <= HEIGHT // 2 + 50 + easy_mode.get_height():
                        easyMode()

                if WIDTH // 2 - two_player.get_width() // 2 <= location[0] <= WIDTH // 2 + two_player.get_width() // 2:
                    if HEIGHT // 2 + 150 <= location[1] <= HEIGHT // 2 + 150 + two_player.get_height():
                        twoPlayer()

                if WIDTH // 2 - quit_text.get_width() // 2 <= location[0] <= WIDTH // 2 + quit_text.get_width() // 2:
                    if HEIGHT // 2 + 250 <= location[1] <= HEIGHT // 2 + 250 + quit_text.get_height():
                        print("Thank you for playing!")
                        run = False

    pygame.quit()

mainMenu()


#	Write a program which accept number from user and return different between summation of all its factors
#	and non-factors.

def diffOfFactorsNonFactors(iNum):

	iSumFact = 0
	iSumNonFact = 0

	for iCnt in range(1,iNum,1):

		if((iNum % iCnt) != 0):
			iSumNonFact = iSumNonFact + iCnt

		if((iNum % iCnt) == 0):
			iSumFact = iSumFact + iCnt

	return int(iSumFact - iSumNonFact)

def main():

	print("Enter number : ")
	iNo = int(input())

	iRet = diffOfFactorsNonFactors(iNo)
	print("Difference between of all factors and non-factors of {} is : {}".format(iNo,iRet))

if __name__ == "__main__":
	main()


"""Where to sit in the waiting area : floor ., seat empty L, seat taken #
"""
import copy
import numpy as np

seats_data_raw = open("inputs/day11_input.txt", "r").readlines()
seats_data = [row.replace("\n", "") for row in seats_data_raw]

# seats_data = [
#     "L.LL.LL.LL",
#     "LLLLLLL.LL",
#     "L.L.L..L..",
#     "LLLL.LL.LL",
#     "L.LL.LL.LL",
#     "L.LLLLL.LL",
#     "..L.L.....",
#     "LLLLLLLLLL",
#     "L.LLLLLL.L",
#     "L.LLLLL.LL"
# ]

def get_occupied_places(data, row_id, place_id):
    nearby_places = []

    # rule 1
    if place_id != 0:
        nearby_places.append(data[row_id][place_id - 1])
    if place_id != len(data[0]) - 1:
        nearby_places.append(data[row_id][place_id + 1])

    if row_id != len(data) - 1:
        nearby_places.append(data[row_id + 1][place_id])
    if row_id != len(data) - 1 and place_id != 0:
        nearby_places.append(data[row_id + 1][place_id - 1])
    if row_id != len(data) - 1 and place_id != len(data[0]) - 1:
        nearby_places.append(data[row_id + 1][place_id + 1])

    if row_id != 0:
        nearby_places.append(data[row_id - 1][place_id])
    if row_id != 0 and place_id != 0:
        nearby_places.append(data[row_id - 1][place_id - 1])
    if row_id != 0 and place_id != len(data[0]) - 1:
        nearby_places.append(data[row_id - 1][place_id + 1])

    n_occupied = 0
    for place in nearby_places:
        if place == "#":
            n_occupied += 1
    return n_occupied

def look_at(data, row_id, place_id, direction):
    position_x = row_id
    position_y = place_id
    while True:
        position_x += direction[0]
        position_y += direction[1]

        if position_x < 0 or position_x >= len(data):
            break
        if position_y < 0 or position_y >= len(data[0]):
            break

        if data[position_x][position_y] in ["L", "#"]:
            return data[position_x][position_y]

    return "."

def get_occupied_places2(data, row_id, place_id):
    nearby_places = []

    # rule 2
    if place_id != 0:
        nearby_places.append(look_at(data, row_id, place_id, [0, -1]))
    if place_id != len(data[0]) - 1:
        nearby_places.append(look_at(data, row_id, place_id, [0, 1]))

    if row_id != len(data) - 1:
        nearby_places.append(look_at(data, row_id, place_id, [1, 0]))
    if row_id != len(data) - 1 and place_id != 0:
        nearby_places.append(look_at(data, row_id, place_id, [1, -1]))
    if row_id != len(data) - 1 and place_id != len(data[0]) - 1:
        nearby_places.append(look_at(data, row_id, place_id, [1, 1]))

    if row_id != 0:
        nearby_places.append(look_at(data, row_id, place_id, [-1, 0]))
    if row_id != 0 and place_id != 0:
        nearby_places.append(look_at(data, row_id, place_id, [-1, -1]))
    if row_id != 0 and place_id != len(data[0]) - 1:
        nearby_places.append(look_at(data, row_id, place_id, [-1, 1]))

    n_occupied = 0
    for place in nearby_places:
        if place == "#":
            n_occupied += 1

    return n_occupied

seat_tolerance = 5
n_steps = 0
while True:
    temp_data = []
    for row_id, seat_row in enumerate(seats_data):
        temp_row = []
        for place_id, place in enumerate(seat_row):
            if place == "L" and get_occupied_places2(seats_data, row_id, place_id) == 0:
                temp_row.append("#")
            elif place == "#" and get_occupied_places2(seats_data, row_id, place_id) >= seat_tolerance:
                temp_row.append("L")
            else:
                temp_row.append(place)
        temp_data.append(temp_row)
    n_steps += 1

    array_diff = False
    for row, temp_row in zip(seats_data, temp_data):
        for place, temp_place in zip(row, temp_row):
            if place != temp_place:
                array_diff = True

    if not array_diff:
        print(f"Chaos stabilized after {n_steps} steps")
        break
    seats_data = temp_data

n_occupied = 0
for row in seats_data:
    for place in row:
        if place == "#":
            n_occupied += 1

print(f"Number of occupied places : {n_occupied}")


import metachao
from metachao import aspect
from metachao.aspect import Aspect

class child_aspect(Aspect):
    child_aspect = aspect.aspectkw(child_aspect=None)

    @aspect.plumb
    def __getitem__(_next, self, key):
        child = _next(key)
        if self.child_aspect:
            # XXX: hack
            dn = child.dn
            directory = child.directory
            child = self.child_aspect(child)
            child.dn = dn
            child.directory = directory
        return child

    @aspect.plumb
    def search(_next, self, *args, **kw):
        for node in _next(*args, **kw):
            if self.child_aspect:
                # XXX: hack
                dn = node.dn
                directory = node.directory
                node = self.child_aspect(node)
                node.dn = dn
                node.directory = directory
            yield node

class getattr_children(Aspect):
    def __getattr__(self, name):
        """Blend in children as attributes

        Children can be accessed via getattr, except if aliased by a
        real attribute.
        """
        try:
            return self.__getitem__(name)
        except KeyError:
            raise AttributeError(name)

class set_children_on_init(Aspect):
    """Set children during init
    """
    @aspect.plumb
    def __init__(_next, self, children=None, **kw):
        _next(self, **kw)
        if children is not None:
            self.update(children)

class configure(Aspect):
    """Provide configuration

    Instantiates a model's classes on demand, supplying them config.

    This creates the read only part of a model.

    """
    config = aspect.aspectkw(config=None)

    # XXX: needed for now as prototyping does not work as expected yet
    # XXX: might work also via inheritance
    def __getattr__(self, name):
        """Blend in children as attributes

        Children can be accessed via getattr, except if aliased by a
        real attribute.
        """
        try:
            return self.__getitem__(name)
        except KeyError:
            raise AttributeError(name)

    @aspect.plumb
    def __getitem__(_next, self, key):
        node = _next(key)
        config = (self.config or dict()).get(key, dict())
        if metachao.utils.isclass(node):
            # XXX: this destroys order
            node = node(**config)
        else:
            node = configure(node, config=config)
        return node

    def values(self):
        for k in self.keys():
            yield self[k]

class keys(Aspect):
    def keys(self):
        return list(self)

class values(Aspect):
    def values(self, **kw):
        return list(self.itervalues(**kw))

class items(Aspect):
    def items(self, **kw):
        return list(self.iteritems(**kw))


#!/usr/bin/env python
import rospy
from baxter_core_msgs.msg import JointCommand

def main():
	rospy.init_node('baxter_arm')
	rospy.loginfo('main method called')
	rate = rospy.Rate(10)
	pub = rospy.Publisher('/robot/limb/left/joint_command', JointCommand, queue_size=1)

	while not rospy.is_shutdown():
		msg = JointCommand()
		msg.mode = msg.POSITION_MODE
		msg.names = {'right_s0', 'right_s1', 'right_w0', 'right_w1', 'right_w2', 'right_e0', 'right_e1'}
		msg.command = {0.0,0.0,0.1,0.1,0.0,0.0,0.0}
		pub.publish(msg)
		rate.sleep()

if __name__ == '__main__':
		rospy.loginfo('Initialising node....')
		try:
			main()
		except rospy.ROSInterruptException:
			pass