<commit_before>### This script calculates the cumulative above and belowground carbon dioxide gain in mangrove forest pixels from 2001-2015.
### It multiplies the annual biomass gain rate by the number of years of gain by the biomass-to-carbon conversion and
### by to the C to CO2 conversion.

import multiprocessing
import cumulative_gain_mangrove
import argparse
from functools import partial
import sys
sys.path.append('../')
import constants_and_names as cn
import universal_util as uu

def main ():

    # List of output directories and output file name patterns
    output_dir_list = [cn.cumul_gain_AGCO2_mangrove_dir, cn.cumul_gain_BGCO2_mangrove_dir]
    output_pattern_list = [cn.pattern_cumul_gain_AGCO2_mangrove, cn.pattern_cumul_gain_BGCO2_mangrove]

    tile_id_list = uu.tile_list(cn.annual_gain_AGB_mangrove_dir)
    # tile_id_list = ['20S_110E', '30S_110E'] # test tiles
    tile_id_list = ['00N_110E'] # test tiles
    print tile_id_list
    print "There are {} tiles to process".format(str(len(tile_id_list))) + "\n"

    # The argument for what kind of model run is being done: standard conditions or a sensitivity analysis run
    parser = argparse.ArgumentParser(description='Create tiles of the number of years of carbon gain for mangrove forests')
    parser.add_argument('--model-type', '-t', required=True,
                        help='{}'.format(cn.model_type_arg_help))
    args = parser.parse_args()
    sensit_type = args.model_type

    # Checks whether the sensitivity analysis argument is valid
    uu.check_sensit_type(sensit_type)

    # For downloading all tiles in the input folders
    download_list = [cn.annual_gain_AGB_mangrove_dir, cn.annual_gain_BGB_mangrove_dir, cn.gain_year_count_mangrove_dir]

    # If the model run isn't the standard one, the output directory and file names are changed
    if sensit_type != 'std':

        print "Changing output directory and file name pattern based on sensitivity analysis"

        download_list = uu.alter_dirs(sensit_type, download_list)
        output_dir_list = uu.alter_dirs(sensit_type, output_dir_list)
        output_pattern_list = uu.alter_patterns(sensit_type, output_pattern_list)

    # for input in download_list:
    #     uu.s3_folder_download(input, '.')

    download_dict = {
        cn.annual_gain_AGB_mangrove_dir: [cn.pattern_annual_gain_AGB_mangrove, 'false'],
        cn.annual_gain_BGB_mangrove_dir: [cn.pattern_annual_gain_BGB_mangrove, 'false'],
        cn.gain_year_count_mangrove_dir: [cn.pattern_gain_year_count_mangrove, 'true']
    }

    for key, values in download_dict.iteritems():
        dir = key
        pattern = values[0]
        sensit_use = values[1]
        uu.s3_flexible_download(dir, pattern, '.', sensit_type, sensit_use, tile_id_list)

    sys.quit()

    # For copying individual tiles to spot machine for testing
    for tile in tile_id_list:

        uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.annual_gain_AGB_mangrove_dir, tile, cn.pattern_annual_gain_AGB_mangrove), '.', sensit_type, 'false')      # annual AGB gain rate tiles
        uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.annual_gain_BGB_mangrove_dir, tile, cn.pattern_annual_gain_BGB_mangrove), '.', sensit_type, 'false')      # annual AGB gain rate tiles
        uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.gain_year_count_mangrove_dir, tile, cn.pattern_gain_year_count_mangrove), '.', sensit_type, 'true')      # number of years with gain tiles

    # Creates a single filename pattern to pass to the multiprocessor call
    pattern = output_pattern_list[0]

    count = multiprocessing.cpu_count()
    pool = multiprocessing.Pool(count / 3)
    # Calculates cumulative aboveground carbon gain in mangroves
    # count/3 peaks at about 380 GB, so this is okay on r4.16xlarge
    pool.map(partial(cumulative_gain_mangrove.cumulative_gain_AGCO2, pattern=pattern, sensit_type=sensit_type), tile_id_list)

    # Creates a single filename pattern to pass to the multiprocessor call
    pattern = output_pattern_list[1]

    # Calculates cumulative belowground carbon gain in mangroves
    pool.map(partial(cumulative_gain_mangrove.cumulative_gain_BGCO2, pattern=pattern, sensit_type=sensit_type), tile_id_list)
    pool.close()
    pool.join()

    # For single processor use
    for tile in tile_id_list:
        cumulative_gain_mangrove.cumulative_gain_AGCO2(tile, output_pattern_list[0], sensit_type)

    for tile in tile_id_list:
        cumulative_gain_mangrove.cumulative_gain_BGCO2(tile, output_pattern_list[1], sensit_type)

    for i in range(0, len(output_dir_list)):
        uu.upload_final_set(output_dir_list[i], output_pattern_list[i])

if __name__ == '__main__':
    main()<commit_msg>Experimenting with different functions for downloading files and directories.<commit_after>### This script calculates the cumulative above and belowground carbon dioxide gain in mangrove forest pixels from 2001-2015.
### It multiplies the annual biomass gain rate by the number of years of gain by the biomass-to-carbon conversion and
### by to the C to CO2 conversion.

import multiprocessing
import cumulative_gain_mangrove
import argparse
from functools import partial
import sys
sys.path.append('../')
import constants_and_names as cn
import universal_util as uu

def main ():

    # List of output directories and output file name patterns
    output_dir_list = [cn.cumul_gain_AGCO2_mangrove_dir, cn.cumul_gain_BGCO2_mangrove_dir]
    output_pattern_list = [cn.pattern_cumul_gain_AGCO2_mangrove, cn.pattern_cumul_gain_BGCO2_mangrove]

    tile_id_list = uu.tile_list(cn.annual_gain_AGB_mangrove_dir)
    # tile_id_list = ['20S_110E', '30S_110E'] # test tiles
    tile_id_list = ['00N_110E'] # test tiles
    print tile_id_list
    print "There are {} tiles to process".format(str(len(tile_id_list))) + "\n"

    # The argument for what kind of model run is being done: standard conditions or a sensitivity analysis run
    parser = argparse.ArgumentParser(description='Create tiles of the number of years of carbon gain for mangrove forests')
    parser.add_argument('--model-type', '-t', required=True,
                        help='{}'.format(cn.model_type_arg_help))
    args = parser.parse_args()
    sensit_type = args.model_type

    # Checks whether the sensitivity analysis argument is valid
    uu.check_sensit_type(sensit_type)

    # For downloading all tiles in the input folders
    download_list = [cn.annual_gain_AGB_mangrove_dir, cn.annual_gain_BGB_mangrove_dir, cn.gain_year_count_mangrove_dir]

    # If the model run isn't the standard one, the output directory and file names are changed
    if sensit_type != 'std':

        print "Changing output directory and file name pattern based on sensitivity analysis"

        download_list = uu.alter_dirs(sensit_type, download_list)
        output_dir_list = uu.alter_dirs(sensit_type, output_dir_list)
        output_pattern_list = uu.alter_patterns(sensit_type, output_pattern_list)

    # for input in download_list:
    #     uu.s3_folder_download(input, '.')

    download_dict = {
        cn.annual_gain_AGB_mangrove_dir: [cn.pattern_annual_gain_AGB_mangrove, 'false'],
        cn.annual_gain_BGB_mangrove_dir: [cn.pattern_annual_gain_BGB_mangrove, 'false'],
        cn.gain_year_count_mangrove_dir: [cn.pattern_gain_year_count_mangrove, 'true'],
        cn.loss_dir: ['', 'false']      # Don't need for this script-- just included for testing
    }

    for key, values in download_dict.iteritems():
        dir = key
        pattern = values[0]
        sensit_use = values[1]
        uu.s3_flexible_download(dir, pattern, '.', sensit_type, sensit_use, tile_id_list)

    sys.quit()

    # For copying individual tiles to spot machine for testing
    for tile in tile_id_list:

        uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.annual_gain_AGB_mangrove_dir, tile, cn.pattern_annual_gain_AGB_mangrove), '.', sensit_type, 'false')      # annual AGB gain rate tiles
        uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.annual_gain_BGB_mangrove_dir, tile, cn.pattern_annual_gain_BGB_mangrove), '.', sensit_type, 'false')      # annual AGB gain rate tiles
        uu.s3_file_download('{0}{1}_{2}.tif'.format(cn.gain_year_count_mangrove_dir, tile, cn.pattern_gain_year_count_mangrove), '.', sensit_type, 'true')      # number of years with gain tiles

    # Creates a single filename pattern to pass to the multiprocessor call
    pattern = output_pattern_list[0]

    count = multiprocessing.cpu_count()
    pool = multiprocessing.Pool(count / 3)
    # Calculates cumulative aboveground carbon gain in mangroves
    # count/3 peaks at about 380 GB, so this is okay on r4.16xlarge
    pool.map(partial(cumulative_gain_mangrove.cumulative_gain_AGCO2, pattern=pattern, sensit_type=sensit_type), tile_id_list)

    # Creates a single filename pattern to pass to the multiprocessor call
    pattern = output_pattern_list[1]

    # Calculates cumulative belowground carbon gain in mangroves
    pool.map(partial(cumulative_gain_mangrove.cumulative_gain_BGCO2, pattern=pattern, sensit_type=sensit_type), tile_id_list)
    pool.close()
    pool.join()

    # For single processor use
    for tile in tile_id_list:
        cumulative_gain_mangrove.cumulative_gain_AGCO2(tile, output_pattern_list[0], sensit_type)

    for tile in tile_id_list:
        cumulative_gain_mangrove.cumulative_gain_BGCO2(tile, output_pattern_list[1], sensit_type)

    for i in range(0, len(output_dir_list)):
        uu.upload_final_set(output_dir_list[i], output_pattern_list[i])

if __name__ == '__main__':
    main()<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import csv
import json
import requests
import traceback
import time
import urllib
from datetime import datetime
from HTMLParser import HTMLParser
from termcolor import colored

# files in this project
from setting import USER_STOCK_LIST
from setting import TWSE_SERVER
from setting import TW_FUTURE_URL

class TaiwanStock:
    def __init__(self, argv):
        self.user_stock_list = USER_STOCK_LIST
        self.stock_list = []
        self.query_list = []
        self.stock_query_str = ''
        self.data = []
        self.twse_url = TWSE_SERVER + '/stock/api/getStockInfo.jsp?ex_ch='
        self.json_data = ''
        self.argv = argv

    # append stock in monitor mode
    def append_stock(self, stock_no):
        if self.check_stock_no(stock_no) == False:
            return
        if stock_no.upper() not in self.user_stock_list and stock_no.lower() not in self.user_stock_list:
            self.user_stock_list.append(stock_no.upper())

    # remove stock in monitor mode
    def remove_stock(self, stock_no):
        if self.check_stock_no(stock_no) == False:
            return
        if stock_no.upper() in self.user_stock_list:
            self.user_stock_list.remove(stock_no.upper())
        if stock_no.lower() in self.user_stock_list:
            self.user_stock_list.remove(stock_no.lower())

    # check format of stock number
    def check_stock_no(self, stock_no):
        if len(stock_no) > 6 or len(stock_no) < 4 or stock_no[0:1].isdigit() == False:
            return False
        return True

    def create_stock_list(self):
        self.stock_list = []

        # add stock in user_stock_list
        for x in self.user_stock_list:
            if x.upper() not in self.stock_list:
                self.stock_list.append(x.upper())

        # add stock in argv
        for x in self.argv:
            if self.check_stock_no(x) == False:
                continue
            if x.find('-') == -1 and x.upper() not in self.stock_list:
                self.stock_list.append(x.upper())

    def create_query_list(self, show_twse_index):
        self.query_list = []

        if show_twse_index:
           self.query_list.append('tse_t00.tw')
           self.query_list.append('otc_o00.tw')

        for stock_no in self.stock_list:
            found = False
            f = open('tse.csv', 'r')
            for row in csv.reader(f):
                if row[0] == str(stock_no):
                    self.query_list.append('tse_' + stock_no + '.tw')
                    found = True
                    break
            f.close()
            if not found:
                f = open('otc.csv', 'r')
                for row in csv.reader(f):
                    if row[0] == str(stock_no):
                        self.query_list.append('otc_' + stock_no + '.tw')
                        found = True
                        break
                f.close()

        #print self.query_list

    def query_stock_info(self, stock_str):
        query_url = self.twse_url + stock_str + '&json=1&delay=0&_=' + '{0}'.format(int(time.time() * 1000))
        r = requests.session()

        # we need access the website before query data
        r.get(TWSE_SERVER)

        # query data
        self.json_data = r.get(query_url).content

        #print self.json_data

    def parse_json_data(self):
        now = datetime.now()
        json_data = json.loads(self.json_data)

        for i in range(len(json_data['msgArray'])):
            j = json_data['msgArray'][i]
            price = j["z"]
            stock_no = j["c"]
            name     = j["n"]
            volume   = j["v"]
            highest = float(j['h'])
            lowest = float(j['l'])

            diff = float(j["z"]) - float(j["y"])
            if diff > 0:
                sign = '+'
            elif diff < 0:
                sign = ''
            else:
                sign = ' '

            change_str = sign + '{0:.2f}'.format(diff)
            change_str_p = sign + '{0:.2f}'.format(diff / float(j["y"]) *100)

            # status
            status = ''
            if (float(price) == highest):
                status = 'H'
            elif (float(price) == lowest):
                status = 'L'

            if stock_no != 't00' and stock_no != 'o00':
                h_limit = float(j['u'])
                l_limit = float(j['w'])
                if (float(price) == h_limit):
                    status = 'H-limit !!!'
                elif (float(price) == l_limit):
                    status = 'L-limit !!!'

            if stock_no == 't00':
                stock_no = 'TWSE'
                name = u'上市'
                price = '{0:.0f} '.format(float(price))
                change_str = sign + '{0:.0f} '.format(diff)
                volume = '{0:d}'.format(int(volume)/100)
            elif stock_no == 'o00':
                stock_no = 'OTC'
                name = u'上櫃'
                volume = '{0:d}'.format(int(volume)/100)

            # check data time
            date = datetime.strptime(j["d"], '%Y%m%d')
            result_time_str = j["d"] + ' ' + j["t"]
            result_time = datetime.strptime(result_time_str, '%Y%m%d %H:%M:%S')

            if now.month == date.month and now.day == date.day:
                if (now.hour > 13) or (now.hour == 13 and now.minute > 30):
                    time_str = j["t"] + ' (today)'
                else:
                    time_str = j["t"]
            else:
                time_str = j["t"] + date.strftime(' (%m/%d)')

            # FIXME: To avoid too long stock name
            if len(name) > 4:
                name = stock_no

            # save to self.data
            result = {'id':'', 'name':'', 'price':'', 'change':'', 'ratio':'', 'volume':'', 'time': '', 'H': '', 'L': '', 'status': ''}
            result['id']     = stock_no
            result['name']   = name
            result['price']  = price
            result['change'] = change_str
            result['ratio']  = change_str_p
            result['volume'] = volume
            result['time']   = time_str
            result['L'] = str(lowest)
            result['H'] = str(highest)
            result['status'] = status
            self.data.append(result)

    def print_stock_info(self, profile):
        show_twse_index = profile['show_twse_index']
        show_simple = profile['show_simple']
        color_print = profile['color_print']
        color_attrs = ['bold']

        if color_print:
            color = 'yellow'
        else:
            color = 'white'

        if not show_simple and len(self.data) > 0:
            print colored(' 股號     股名     成交價     漲跌    百分比   成交量        股價區間         資料時間 & 狀態', color, attrs = color_attrs)
            print '-----------------------------------------------------------------------------------------------'

        for stock in self.data:
            if not show_twse_index:
                if stock['id'] == 'TWSE' or stock['id'] == 'OTC' or stock['id'] == 'WTX':
                    continue

            if color_print:
                change = float(stock['change'])
                color_attrs = ['bold']
                if stock['status'].find(u'停') > -1:
                    color_attrs = ['reverse', 'blink']
                if change > 0:
                    color = 'red'
                elif change < 0:
                    color = 'green'
                else:
                    color = 'white'

            if show_simple:
                print colored(' {0:8s}'.format(stock['id'])
                      + '{0:>8s}'.format(stock['price'])
                      + '{0:>10s}'.format(stock['change'])
                      + '{0:>10s}%'.format(stock['ratio'])
                      + '{0:>9s}'.format(stock['volume'])
                      + '{0:>12s}'.format(stock['L'])
                      + ' ~ '
                      + '{0:<8s}'.format(stock['H'])
                      + '   ' + stock['status'], color, attrs = color_attrs)
            else:
                print colored(' {0:8s}'.format(stock['id'])
                      + stock['name'] + '\t'
                      + '{0:>9s}' .format(stock['price'])
                      + '{0:>9s}' .format(stock['change'])
                      + '{0:>9s}%'.format(stock['ratio'])
                      + '{0:>9s}' .format(stock['volume'])
                      + '{0:>11s}'.format(stock['L'])
                      + ' ~ '
                      + '{0:<8s}'.format(stock['H'])
                      + '     ' + stock['time'] + ' ' + stock['status'], color, attrs = color_attrs)
        print ''

    def add_tw_future(self):
        tw_future = TaiwanFuture()
        future_data = tw_future.get_data()
        if future_data != None:
            self.data.append(future_data)

    def get_data(self, profile):
        self.data = []
        if profile['show_twse_index']:
            self.add_tw_future()

        self.create_stock_list()
        self.create_query_list(profile['show_twse_index'])
        # self.create_query_url(profile['show_twse_index'])

        try:
            for i in self.query_list:
                self.query_stock_info(i)
                self.parse_json_data()
        except:
            traceback.print_exc()
            return False

        return True

class TaiwanFuture(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.data = []
        self.item_limit = 15
        self.item_index = 0

    def handle_starttag(self, tag, attrs):
        if tag == 'td':
            for attr in attrs:
                if attr[1] == 'bu13':
                    self.item_index = self.item_index + 1
                    break

    def handle_data(self, data):
        if self.item_index == 3 or self.item_index == 4:
            if self.item_limit and len(data) < 14:
                self.item_limit = self.item_limit - 1
                self.data.append(data)

    def read_data(self):
        if (self.data[1] == '收盤'):
            i = 6
            time_str = self.data[i+8] + ' (close)'
        else:
            i = 5
            time_str = self.data[i+8]

        price   = float(self.data[i].replace(',',''))
        change  = float(self.data[i+1])
        volume  = self.data[i+3].replace(',','')
        last_day_price = float(self.data[i+7].replace(',',''))
        ratio   = '{0:.02f}'.format(change / last_day_price * 100)
        highest = float(self.data[i+5].replace(',',''))
        lowest = float(self.data[i+6].replace(',',''))

        status = ''
        if price == highest:
            status = 'H'
        elif price == lowest:
            status = 'L'

        if change > 0:
            sign = '+'
        else:
            sign = ''

        change_str = sign + '{0:.0f} '.format(change)
        ratio_str = sign + ratio
        result = {'id':'', 'name':'', 'price':'', 'change':'', 'ratio':'', 'volume':'', 'time': '', 'H': '', 'L': '', 'status': ''}
        result['id']     = 'WTX'
        result['name']   = '台指期'
        result['price']  = '{0:.0f} '.format(price)
        result['change'] = change_str
        result['ratio']  = ratio_str
        result['volume'] = volume
        result['L']      = str(lowest)
        result['H']      = str(highest)
        result['time']   = time_str
        result['status'] = status
        return result

    def get_data(self):
        try:
            self.feed(urllib.urlopen(TW_FUTURE_URL).read())
            self.close()
            return self.read_data()
        except:
            print 'add_tw_future() failed'
            return None
<commit_msg>Add timeout, fix ETF limit price, and change output format<commit_after># -*- coding: utf-8 -*-
import csv
import json
import requests
import traceback
import time
import urllib2
from datetime import datetime
from HTMLParser import HTMLParser
from termcolor import colored

# files in this project
from setting import USER_STOCK_LIST
from setting import TWSE_SERVER
from setting import TW_FUTURE_URL

class TaiwanStock:
    def __init__(self, argv):
        self.user_stock_list = USER_STOCK_LIST
        self.stock_list = []
        self.query_list = []
        self.stock_query_str = ''
        self.data = []
        self.twse_url = TWSE_SERVER + '/stock/api/getStockInfo.jsp?ex_ch='
        self.json_data = ''
        self.argv = argv

    # append stock in monitor mode
    def append_stock(self, stock_no):
        if self.check_stock_no(stock_no) == False:
            return
        if stock_no.upper() not in self.user_stock_list and stock_no.lower() not in self.user_stock_list:
            self.user_stock_list.append(stock_no.upper())

    # remove stock in monitor mode
    def remove_stock(self, stock_no):
        if self.check_stock_no(stock_no) == False:
            return
        if stock_no.upper() in self.user_stock_list:
            self.user_stock_list.remove(stock_no.upper())
        if stock_no.lower() in self.user_stock_list:
            self.user_stock_list.remove(stock_no.lower())

    # check format of stock number
    def check_stock_no(self, stock_no):
        if len(stock_no) > 6 or len(stock_no) < 4 or stock_no[0:1].isdigit() == False:
            return False
        return True

    def create_stock_list(self):
        self.stock_list = []

        # add stock in user_stock_list
        for x in self.user_stock_list:
            if x.upper() not in self.stock_list:
                self.stock_list.append(x.upper())

        # add stock in argv
        for x in self.argv:
            if self.check_stock_no(x) == False:
                continue
            if x.find('-') == -1 and x.upper() not in self.stock_list:
                self.stock_list.append(x.upper())

    def create_query_list(self, show_twse_index):
        self.query_list = []

        if show_twse_index:
           self.query_list.append('tse_t00.tw')
           self.query_list.append('otc_o00.tw')

        for stock_no in self.stock_list:
            found = False
            f = open('tse.csv', 'r')
            for row in csv.reader(f):
                if row[0] == str(stock_no):
                    self.query_list.append('tse_' + stock_no + '.tw')
                    found = True
                    break
            f.close()
            if not found:
                f = open('otc.csv', 'r')
                for row in csv.reader(f):
                    if row[0] == str(stock_no):
                        self.query_list.append('otc_' + stock_no + '.tw')
                        found = True
                        break
                f.close()

        #print self.query_list

    def query_stock_info(self, stock_str):
        query_url = self.twse_url + stock_str + '&json=1&delay=0&_=' + '{0}'.format(int(time.time() * 1000))
        r = requests.session()

        try:
            # we need access the website before query data
            r.get(TWSE_SERVER, timeout=10)
            # query data
            self.json_data = r.get(query_url, timeout=10).content
        except:
            self.json_data = ''

        #print self.json_data

    def parse_json_data(self):
        now = datetime.now()
        json_data = json.loads(self.json_data)

        for i in range(len(json_data['msgArray'])):
            j = json_data['msgArray'][i]
            price = j["z"]
            stock_no = j["c"]
            name     = j["n"]
            volume   = j["v"]
            highest = float(j['h'])
            lowest = float(j['l'])

            diff = float(j["z"]) - float(j["y"])
            if diff > 0:
                sign = '+'
            elif diff < 0:
                sign = ''
            else:
                sign = ' '

            change_str = sign + '{0:.2f}'.format(diff)
            change_str_p = sign + '{0:.2f}'.format(diff / float(j["y"]) *100)

            # status
            status = ''
            if (float(price) == highest):
                status = 'H'
            elif (float(price) == lowest):
                status = 'L'

            # I cannot found 'w' in 00633L
            if stock_no != 't00' and stock_no != 'o00' and len(stock_no) == 4:
                h_limit = float(j['u'])
                l_limit = float(j['w'])
                if (float(price) == h_limit):
                    status = 'H-limit !!!'
                elif (float(price) == l_limit):
                    status = 'L-limit !!!'

            if stock_no == 't00':
                stock_no = 'TWSE'
                name = u'上市'
                price = '{0:.0f}'.format(float(price))
                change_str = sign + '{0:.0f} '.format(diff)
                volume = '{0:d}E'.format(int(volume)/100)
            elif stock_no == 'o00':
                stock_no = 'OTC'
                name = u'上櫃'
                volume = '{0:d}E'.format(int(volume)/100)
            else:
                if float(price) > 999.5:
                    price = '{0:.0f}'.format(float(price))

            # check data time
            date = datetime.strptime(j["d"], '%Y%m%d')
            result_time_str = j["d"] + ' ' + j["t"]
            result_time = datetime.strptime(result_time_str, '%Y%m%d %H:%M:%S')

            if now.month == date.month and now.day == date.day:
                if (now.hour > 13) or (now.hour == 13 and now.minute > 30):
                    time_str = j["t"] + ' (today)'
                else:
                    time_str = j["t"]
            else:
                time_str = j["t"] + date.strftime(' (%m/%d)')

            # FIXME: To avoid too long stock name
            if len(name) > 4:
                name = stock_no

            # save to self.data
            result = {'id':'', 'name':'', 'price':'', 'change':'', 'ratio':'', 'volume':'', 'time': '', 'H': '', 'L': '', 'status': ''}
            result['id']     = stock_no
            result['name']   = name
            result['price']  = price
            result['change'] = change_str
            result['ratio']  = change_str_p
            result['volume'] = volume
            result['time']   = time_str
            result['L'] = str(lowest)
            result['H'] = str(highest)
            result['status'] = status
            self.data.append(result)

    def print_stock_info(self, profile):
        show_twse_index = profile['show_twse_index']
        show_simple = profile['show_simple']
        color_print = profile['color_print']
        color_attrs = ['bold']

        if color_print:
            color = 'yellow'
        else:
            color = 'white'

        if not show_simple and len(self.data) > 0:
            print colored(' 股號     股名     成交價     漲跌    百分比   成交量        股價區間         資料時間 & 狀態', color, attrs = color_attrs)
            print '-----------------------------------------------------------------------------------------------'

        for stock in self.data:
            if not show_twse_index:
                if stock['id'] == 'TWSE' or stock['id'] == 'OTC' or stock['id'] == 'WTX':
                    continue

            if color_print:
                change = float(stock['change'])
                color_attrs = ['bold']
                if stock['status'].find(u'停') > -1:
                    color_attrs = ['reverse', 'blink']
                if change > 0:
                    color = 'red'
                elif change < 0:
                    color = 'green'
                else:
                    color = 'white'

            if show_simple:
                print colored(' {0:7s}'.format(stock['id'])
                      + '{0:>6s}'.format(stock['price'])
                      + '{0:>8s}'.format(stock['change'])
                      + ' ({0:>5s}%)'.format(stock['ratio'])
                      + '{0:>7s}'.format(stock['volume'])
                      + ' ' + stock['status'], color, attrs = color_attrs)
            else:
                print colored(' {0:8s}'.format(stock['id'])
                      + stock['name'] + '\t'
                      + '{0:>9s}' .format(stock['price'])
                      + '{0:>9s}' .format(stock['change'])
                      + '{0:>9s}%'.format(stock['ratio'])
                      + '{0:>9s}' .format(stock['volume'])
                      + '{0:>11s}'.format(stock['L'])
                      + ' ~ '
                      + '{0:<8s}'.format(stock['H'])
                      + '   ' + stock['time'] + ' ' + stock['status'], color, attrs = color_attrs)
        print ''

    def add_tw_future(self):
        tw_future = TaiwanFuture()
        future_data = tw_future.get_data()
        if future_data != None:
            self.data.append(future_data)

    def get_data(self, profile):
        self.data = []
        if profile['show_twse_index']:
            self.add_tw_future()

        self.create_stock_list()
        self.create_query_list(profile['show_twse_index'])
        # self.create_query_url(profile['show_twse_index'])

        try:
            for i in self.query_list:
                self.query_stock_info(i)
                self.parse_json_data()
        except:
            traceback.print_exc()
            return False

        return True

class TaiwanFuture(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.data = []
        self.item_limit = 15
        self.item_index = 0

    def handle_starttag(self, tag, attrs):
        if tag == 'td':
            for attr in attrs:
                if attr[1] == 'bu13':
                    self.item_index = self.item_index + 1
                    break

    def handle_data(self, data):
        if self.item_index == 3 or self.item_index == 4:
            if self.item_limit and len(data) < 14:
                self.item_limit = self.item_limit - 1
                self.data.append(data)

    def read_data(self):
        if (self.data[1] == '收盤'):
            i = 6
            time_str = self.data[i+8] + ' (close)'
        else:
            i = 5
            time_str = self.data[i+8]

        price   = float(self.data[i].replace(',',''))
        change  = float(self.data[i+1])
        volume  = self.data[i+3].replace(',','')
        last_day_price = float(self.data[i+7].replace(',',''))
        ratio   = '{0:.02f}'.format(change / last_day_price * 100)
        highest = float(self.data[i+5].replace(',',''))
        lowest = float(self.data[i+6].replace(',',''))

        status = ''
        if price == highest:
            status = 'H'
        elif price == lowest:
            status = 'L'

        if change > 0:
            sign = '+'
        else:
            sign = ''

        change_str = sign + '{0:.0f} '.format(change)
        ratio_str = sign + ratio
        result = {'id':'', 'name':'', 'price':'', 'change':'', 'ratio':'', 'volume':'', 'time': '', 'H': '', 'L': '', 'status': ''}
        result['id']     = 'WTX'
        result['name']   = '台指期'
        result['price']  = '{0:.0f}'.format(price)
        result['change'] = change_str
        result['ratio']  = ratio_str
        result['volume'] = str(int(float(volume)/1000)) + 'K'
        result['L']      = str(lowest)
        result['H']      = str(highest)
        result['time']   = time_str
        result['status'] = status
        return result

    def get_data(self):
        try:
            self.feed(urllib2.urlopen(TW_FUTURE_URL, timeout=10).read())
            self.close()
            return self.read_data()
        except:
            print 'add_tw_future() failed'
            traceback.print_exc()
            return None
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''

    Payment Gateway Transaction

    :copyright: (c) 2013 by Openlabs Technologies & Consulting (P) Ltd.
    :license: BSD, see LICENSE for more details

'''
import authorize
from authorize.exceptions import AuthorizeInvalidError, \
    AuthorizeResponseError
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval
from trytond.model import fields

__all__ = [
    'PaymentGatewayAuthorize', 'AddPaymentProfileView', 'AddPaymentProfile',
    'AuthorizeNetTransaction', 'Party', 'Address'
]
__metaclass__ = PoolMeta

class PaymentGatewayAuthorize:
    "Authorize.net Gateway Implementation"
    __name__ = 'payment_gateway.gateway'

    authorize_net_login = fields.Char(
        'API Login', states={
            'required': Eval('provider') == 'authorize_net',
            'invisible': Eval('provider') != 'authorize_net',
        }, depends=['provider']
    )
    authorize_net_transaction_key = fields.Char(
        'Transaction Key', states={
            'required': Eval('provider') == 'authorize_net',
            'invisible': Eval('provider') != 'authorize_net',
        }, depends=['provider']
    )

    @classmethod
    def get_providers(cls, values=None):
        """
        Downstream modules can add to the list
        """
        rv = super(PaymentGatewayAuthorize, cls).get_providers()
        authorize_record = ('authorize_net', 'Authorize.net')
        if authorize_record not in rv:
            rv.append(authorize_record)
        return rv

    def get_methods(self):
        if self.provider == 'authorize_net':
            return [
                ('credit_card', 'Credit Card - Authorize.net'),
            ]
        return super(PaymentGatewayAuthorize, self).get_methods()

    def get_authorize_client(self):
        """
        Return an authenticated authorize.net client.
        """
        assert self.provider == 'authorize_net', 'Invalid provider'
        authorize.Configuration.configure(
            authorize.Environment.TEST if self.test else authorize.Environment.PRODUCTION,  # noqa
            self.authorize_net_login,
            self.authorize_net_transaction_key,
        )

class AuthorizeNetTransaction:
    """
    Implement the authorize and capture methods
    """
    __name__ = 'payment_gateway.transaction'

    @classmethod
    def __setup__(cls):
        super(AuthorizeNetTransaction, cls).__setup__()

        cls._error_messages.update({
            'cancel_only_authorized': 'Only authorized transactions can be' + (
                ' cancelled.'),
        })

    def authorize_authorize_net(self, card_info=None):
        """
        Authorize using authorize.net for the specific transaction.
        """
        TransactionLog = Pool().get('payment_gateway.transaction.log')

        # Initialize authorize client
        self.gateway.get_authorize_client()

        auth_data = {
            'amount': self.amount,
        }
        if hasattr(self, 'sale'):
            auth_data.update({
                'order': {
                    'invoice_number': self.sale.reference or '',
                    'description': self.sale.description or '',
                },
            })
        if card_info:
            billing_address = self.address.get_authorize_address(
                card_info.owner)
            shipping_address = {}
            if self.shipping_address:
                shipping_address = self.shipping_address.get_authorize_address(
                    card_info.owner)

            auth_data.update({
                'email': self.party.email,
                'credit_card': {
                    'card_number': card_info.number,
                    'card_code': str(card_info.csc),
                    'expiration_date': "%s/%s" % (
                        card_info.expiry_month, card_info.expiry_year
                    ),
                },
                'billing': billing_address,
                'shipping': shipping_address,
            })

        elif self.payment_profile:
            if self.shipping_address:
                if self.shipping_address.authorize_id:
                    address_id = self.shipping_address.authorize_id
                else:
                    address_id = self.shipping_address.send_to_authorize(
                        self.party.authorize_profile_id)
            else:
                if self.address.authorize_id:
                    address_id = self.address.authorize_id
                else:
                    address_id = self.address.send_to_authorize(
                        self.party.authorize_profile_id)
            auth_data.update({
                'customer_id': self.party.authorize_profile_id,
                'payment_id': self.payment_profile.provider_reference,
                'address_id': address_id,
            })
        else:
            self.raise_user_error('no_card_or_profile')

        try:
            result = authorize.Transaction.auth(auth_data)
        except AuthorizeResponseError, exc:
            self.state = 'failed'
            self.save()
            TransactionLog.serialize_and_create(self, exc.full_response)
        else:
            self.state = 'authorized'
            self.provider_reference = str(result.transaction_response.trans_id)
            self.save()
            TransactionLog.serialize_and_create(self, result)

    def settle_authorize_net(self):
        """
        Settles this transaction if it is a previous authorization.
        """
        TransactionLog = Pool().get('payment_gateway.transaction.log')

        # Initialize authorize.net client
        self.gateway.get_authorize_client()

        try:
            result = authorize.Transaction.settle(
                self.provider_reference, self.amount
            )
        except AuthorizeResponseError, exc:
            self.state = 'failed'
            self.save()
            TransactionLog.serialize_and_create(self, exc.full_response)
        else:
            self.state = 'completed'
            self.provider_reference = str(result.transaction_response.trans_id)
            self.save()
            TransactionLog.serialize_and_create(self, result)
            self.safe_post()

    def capture_authorize_net(self, card_info=None):
        """
        Capture using authorize.net for the specific transaction.
        """
        TransactionLog = Pool().get('payment_gateway.transaction.log')

        # Initialize authorize client
        self.gateway.get_authorize_client()

        capture_data = {
            'amount': self.amount,
        }
        if hasattr(self, 'sale'):
            capture_data.update({
                'order': {
                    'invoice_number': self.sale.reference or '',
                    'description': self.sale.description or '',
                },
            })
        if card_info:
            billing_address = self.address.get_authorize_address(
                card_info.owner)
            shipping_address = {}
            if self.shipping_address:
                shipping_address = self.shipping_address.get_authorize_address(
                    card_info.owner)

            capture_data.update({
                'email': self.party.email,
                'credit_card': {
                    'card_number': card_info.number,
                    'card_code': str(card_info.csc),
                    'expiration_date': "%s/%s" % (
                        card_info.expiry_month, card_info.expiry_year
                    ),
                },
                'billing': billing_address,
                'shipping': shipping_address,
            })

        elif self.payment_profile:
            if self.shipping_address:
                if self.shipping_address.authorize_id:
                    address_id = self.shipping_address.authorize_id
                else:
                    address_id = self.shipping_address.send_to_authorize(
                        self.party.authorize_profile_id)
            else:
                if self.address.authorize_id:
                    address_id = self.address.authorize_id
                else:
                    address_id = self.address.send_to_authorize(
                        self.party.authorize_profile_id)
            capture_data.update({
                'customer_id': self.party.authorize_profile_id,
                'payment_id': self.payment_profile.provider_reference,
                'address_id': address_id,
            })
        else:
            self.raise_user_error('no_card_or_profile')

        try:
            result = authorize.Transaction.sale(capture_data)
        except AuthorizeResponseError, exc:
            self.state = 'failed'
            self.save()
            TransactionLog.serialize_and_create(self, exc.full_response)
        else:
            self.state = 'completed'
            self.provider_reference = str(result.transaction_response.trans_id)
            self.save()
            TransactionLog.serialize_and_create(self, result)
            self.safe_post()

    def retry_authorize_net(self, credit_card=None):  # pragma: no cover
        """
        Authorize using Authorize.net for the specific transaction.

        :param credit_card: An instance of CreditCardView
        """
        raise self.raise_user_error('feature_not_available')

    def update_authorize_net(self):  # pragma: no cover
        """
        Update the status of the transaction from Authorize.net
        """
        raise self.raise_user_error('feature_not_available')

    def cancel_authorize_net(self):
        """
        Cancel this authorization or request
        """
        TransactionLog = Pool().get('payment_gateway.transaction.log')

        if self.state != 'authorized':
            self.raise_user_error('cancel_only_authorized')

        # Initialize authurize.net client
        self.gateway.get_authorize_client()

        # Try to void the transaction
        try:
            result = authorize.Transaction.void(self.provider_reference)
        except AuthorizeResponseError, exc:
            TransactionLog.serialize_and_create(self, exc.full_response)
        else:
            self.state = 'cancel'
            self.save()
            TransactionLog.serialize_and_create(self, result)

class AddPaymentProfileView:
    __name__ = 'party.payment_profile.add_view'

    @classmethod
    def get_providers(cls):
        """
        Return the list of providers who support credit card profiles.
        """
        res = super(AddPaymentProfileView, cls).get_providers()
        res.append(('authorize_net', 'Authorize.net'))
        return res

class AddPaymentProfile:
    """
    Add a payment profile
    """
    __name__ = 'party.party.payment_profile.add'

    def transition_add_authorize_net(self):
        """
        Handle the case if the profile should be added for authorize.net
        """
        Party = Pool().get('party.party')

        card_info = self.card_info

        # Initialize authorize.net client
        card_info.gateway.get_authorize_client()

        customer_data = {}

        # Create new customer profile if no old profile is there
        if not card_info.party.authorize_profile_id:
            customer_data = {
                'description': card_info.party.name,
                'email': card_info.party.email,
            }
            try:
                customer = authorize.Customer.create(customer_data)
            except AuthorizeInvalidError, exc:
                self.raise_user_error(unicode(exc))

            # Write customer profile ID in party
            Party.write([card_info.party], {
                'authorize_profile_id': customer.customer_id
            })

        # Now create new credit card and associate it with the above
        # created customer
        credit_card_data = {
            'card_number': card_info.number,
            'card_code': str(card_info.csc),
            'expiration_month': card_info.expiry_month,
            'expiration_year': card_info.expiry_year,
            'billing': card_info.address.get_authorize_address(card_info.owner)
        }
        try:
            credit_card = authorize.CreditCard.create(
                card_info.party.authorize_profile_id, credit_card_data
            )
        except AuthorizeInvalidError, exc:
            self.raise_user_error(unicode(exc))
        return self.create_profile(credit_card.payment_id)

class Party:
    __name__ = 'party.party'

    authorize_profile_id = fields.Char(
        'Authorize.net Profile ID', readonly=True
    )

class Address:
    __name__ = 'party.address'

    authorize_id = fields.Char(
        'Authorize.net ID', readonly=True
    )

    def send_to_authorize(self, profile_id):
        """
        Helpler method which creates a new address record on
        authorize.net servers and returns it's ID.

        :param profile_id: The profile_id of customer profile for
            which you want to create address. Required if create=True
        """
        Address = Pool().get('party.address')

        address = authorize.Address.create(
            profile_id, self.get_authorize_address())
        address_id = address.address_id
        Address.write([self], {
            'authorize_id': address_id,
        })
        return address_id

    def get_authorize_address(self, name=None):
        """
        Returns address as a dictionary to send to authorize.net

        :param name: Name to send as first name in address.
            Default is party's name.
        """
        return {
            'first_name': name if name else self.party.name,
            'last_name': '',
            'company': '',
            'address': '\n'.join(filter(None, [self.street, self.streetbis])),
            'city': self.city,
            'state': self.subdivision and self.subdivision.code,
            'zip': self.zip,
            'country': self.country and self.country.code,
            'phone_number': self.party.phone,
            'fax_number': self.party.fax,
        }
<commit_msg>Fix while checking if sale is there in transaction<commit_after># -*- coding: utf-8 -*-
'''

    Payment Gateway Transaction

    :copyright: (c) 2013 by Openlabs Technologies & Consulting (P) Ltd.
    :license: BSD, see LICENSE for more details

'''
import authorize
from authorize.exceptions import AuthorizeInvalidError, \
    AuthorizeResponseError
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval
from trytond.model import fields

__all__ = [
    'PaymentGatewayAuthorize', 'AddPaymentProfileView', 'AddPaymentProfile',
    'AuthorizeNetTransaction', 'Party', 'Address'
]
__metaclass__ = PoolMeta

class PaymentGatewayAuthorize:
    "Authorize.net Gateway Implementation"
    __name__ = 'payment_gateway.gateway'

    authorize_net_login = fields.Char(
        'API Login', states={
            'required': Eval('provider') == 'authorize_net',
            'invisible': Eval('provider') != 'authorize_net',
        }, depends=['provider']
    )
    authorize_net_transaction_key = fields.Char(
        'Transaction Key', states={
            'required': Eval('provider') == 'authorize_net',
            'invisible': Eval('provider') != 'authorize_net',
        }, depends=['provider']
    )

    @classmethod
    def get_providers(cls, values=None):
        """
        Downstream modules can add to the list
        """
        rv = super(PaymentGatewayAuthorize, cls).get_providers()
        authorize_record = ('authorize_net', 'Authorize.net')
        if authorize_record not in rv:
            rv.append(authorize_record)
        return rv

    def get_methods(self):
        if self.provider == 'authorize_net':
            return [
                ('credit_card', 'Credit Card - Authorize.net'),
            ]
        return super(PaymentGatewayAuthorize, self).get_methods()

    def get_authorize_client(self):
        """
        Return an authenticated authorize.net client.
        """
        assert self.provider == 'authorize_net', 'Invalid provider'
        authorize.Configuration.configure(
            authorize.Environment.TEST if self.test else authorize.Environment.PRODUCTION,  # noqa
            self.authorize_net_login,
            self.authorize_net_transaction_key,
        )

class AuthorizeNetTransaction:
    """
    Implement the authorize and capture methods
    """
    __name__ = 'payment_gateway.transaction'

    @classmethod
    def __setup__(cls):
        super(AuthorizeNetTransaction, cls).__setup__()

        cls._error_messages.update({
            'cancel_only_authorized': 'Only authorized transactions can be' + (
                ' cancelled.'),
        })

    def authorize_authorize_net(self, card_info=None):
        """
        Authorize using authorize.net for the specific transaction.
        """
        TransactionLog = Pool().get('payment_gateway.transaction.log')

        # Initialize authorize client
        self.gateway.get_authorize_client()

        auth_data = {
            'amount': self.amount,
        }
        if hasattr(self, 'sale') and self.sale:
            auth_data.update({
                'order': {
                    'invoice_number': self.sale.reference or '',
                    'description': self.sale.description or '',
                },
            })
        if card_info:
            billing_address = self.address.get_authorize_address(
                card_info.owner)
            shipping_address = {}
            if self.shipping_address:
                shipping_address = self.shipping_address.get_authorize_address(
                    card_info.owner)

            auth_data.update({
                'email': self.party.email,
                'credit_card': {
                    'card_number': card_info.number,
                    'card_code': str(card_info.csc),
                    'expiration_date': "%s/%s" % (
                        card_info.expiry_month, card_info.expiry_year
                    ),
                },
                'billing': billing_address,
                'shipping': shipping_address,
            })

        elif self.payment_profile:
            if self.shipping_address:
                if self.shipping_address.authorize_id:
                    address_id = self.shipping_address.authorize_id
                else:
                    address_id = self.shipping_address.send_to_authorize(
                        self.party.authorize_profile_id)
            else:
                if self.address.authorize_id:
                    address_id = self.address.authorize_id
                else:
                    address_id = self.address.send_to_authorize(
                        self.party.authorize_profile_id)
            auth_data.update({
                'customer_id': self.party.authorize_profile_id,
                'payment_id': self.payment_profile.provider_reference,
                'address_id': address_id,
            })
        else:
            self.raise_user_error('no_card_or_profile')

        try:
            result = authorize.Transaction.auth(auth_data)
        except AuthorizeResponseError, exc:
            self.state = 'failed'
            self.save()
            TransactionLog.serialize_and_create(self, exc.full_response)
        else:
            self.state = 'authorized'
            self.provider_reference = str(result.transaction_response.trans_id)
            self.save()
            TransactionLog.serialize_and_create(self, result)

    def settle_authorize_net(self):
        """
        Settles this transaction if it is a previous authorization.
        """
        TransactionLog = Pool().get('payment_gateway.transaction.log')

        # Initialize authorize.net client
        self.gateway.get_authorize_client()

        try:
            result = authorize.Transaction.settle(
                self.provider_reference, self.amount
            )
        except AuthorizeResponseError, exc:
            self.state = 'failed'
            self.save()
            TransactionLog.serialize_and_create(self, exc.full_response)
        else:
            self.state = 'completed'
            self.provider_reference = str(result.transaction_response.trans_id)
            self.save()
            TransactionLog.serialize_and_create(self, result)
            self.safe_post()

    def capture_authorize_net(self, card_info=None):
        """
        Capture using authorize.net for the specific transaction.
        """
        TransactionLog = Pool().get('payment_gateway.transaction.log')

        # Initialize authorize client
        self.gateway.get_authorize_client()

        capture_data = {
            'amount': self.amount,
        }
        if hasattr(self, 'sale') and self.sale:
            capture_data.update({
                'order': {
                    'invoice_number': self.sale.reference or '',
                    'description': self.sale.description or '',
                },
            })
        if card_info:
            billing_address = self.address.get_authorize_address(
                card_info.owner)
            shipping_address = {}
            if self.shipping_address:
                shipping_address = self.shipping_address.get_authorize_address(
                    card_info.owner)

            capture_data.update({
                'email': self.party.email,
                'credit_card': {
                    'card_number': card_info.number,
                    'card_code': str(card_info.csc),
                    'expiration_date': "%s/%s" % (
                        card_info.expiry_month, card_info.expiry_year
                    ),
                },
                'billing': billing_address,
                'shipping': shipping_address,
            })

        elif self.payment_profile:
            if self.shipping_address:
                if self.shipping_address.authorize_id:
                    address_id = self.shipping_address.authorize_id
                else:
                    address_id = self.shipping_address.send_to_authorize(
                        self.party.authorize_profile_id)
            else:
                if self.address.authorize_id:
                    address_id = self.address.authorize_id
                else:
                    address_id = self.address.send_to_authorize(
                        self.party.authorize_profile_id)
            capture_data.update({
                'customer_id': self.party.authorize_profile_id,
                'payment_id': self.payment_profile.provider_reference,
                'address_id': address_id,
            })
        else:
            self.raise_user_error('no_card_or_profile')

        try:
            result = authorize.Transaction.sale(capture_data)
        except AuthorizeResponseError, exc:
            self.state = 'failed'
            self.save()
            TransactionLog.serialize_and_create(self, exc.full_response)
        else:
            self.state = 'completed'
            self.provider_reference = str(result.transaction_response.trans_id)
            self.save()
            TransactionLog.serialize_and_create(self, result)
            self.safe_post()

    def retry_authorize_net(self, credit_card=None):  # pragma: no cover
        """
        Authorize using Authorize.net for the specific transaction.

        :param credit_card: An instance of CreditCardView
        """
        raise self.raise_user_error('feature_not_available')

    def update_authorize_net(self):  # pragma: no cover
        """
        Update the status of the transaction from Authorize.net
        """
        raise self.raise_user_error('feature_not_available')

    def cancel_authorize_net(self):
        """
        Cancel this authorization or request
        """
        TransactionLog = Pool().get('payment_gateway.transaction.log')

        if self.state != 'authorized':
            self.raise_user_error('cancel_only_authorized')

        # Initialize authurize.net client
        self.gateway.get_authorize_client()

        # Try to void the transaction
        try:
            result = authorize.Transaction.void(self.provider_reference)
        except AuthorizeResponseError, exc:
            TransactionLog.serialize_and_create(self, exc.full_response)
        else:
            self.state = 'cancel'
            self.save()
            TransactionLog.serialize_and_create(self, result)

class AddPaymentProfileView:
    __name__ = 'party.payment_profile.add_view'

    @classmethod
    def get_providers(cls):
        """
        Return the list of providers who support credit card profiles.
        """
        res = super(AddPaymentProfileView, cls).get_providers()
        res.append(('authorize_net', 'Authorize.net'))
        return res

class AddPaymentProfile:
    """
    Add a payment profile
    """
    __name__ = 'party.party.payment_profile.add'

    def transition_add_authorize_net(self):
        """
        Handle the case if the profile should be added for authorize.net
        """
        Party = Pool().get('party.party')

        card_info = self.card_info

        # Initialize authorize.net client
        card_info.gateway.get_authorize_client()

        customer_data = {}

        # Create new customer profile if no old profile is there
        if not card_info.party.authorize_profile_id:
            customer_data = {
                'description': card_info.party.name,
                'email': card_info.party.email,
            }
            try:
                customer = authorize.Customer.create(customer_data)
            except AuthorizeInvalidError, exc:
                self.raise_user_error(unicode(exc))

            # Write customer profile ID in party
            Party.write([card_info.party], {
                'authorize_profile_id': customer.customer_id
            })

        # Now create new credit card and associate it with the above
        # created customer
        credit_card_data = {
            'card_number': card_info.number,
            'card_code': str(card_info.csc),
            'expiration_month': card_info.expiry_month,
            'expiration_year': card_info.expiry_year,
            'billing': card_info.address.get_authorize_address(card_info.owner)
        }
        try:
            credit_card = authorize.CreditCard.create(
                card_info.party.authorize_profile_id, credit_card_data
            )
        except AuthorizeInvalidError, exc:
            self.raise_user_error(unicode(exc))
        return self.create_profile(credit_card.payment_id)

class Party:
    __name__ = 'party.party'

    authorize_profile_id = fields.Char(
        'Authorize.net Profile ID', readonly=True
    )

class Address:
    __name__ = 'party.address'

    authorize_id = fields.Char(
        'Authorize.net ID', readonly=True
    )

    def send_to_authorize(self, profile_id):
        """
        Helpler method which creates a new address record on
        authorize.net servers and returns it's ID.

        :param profile_id: The profile_id of customer profile for
            which you want to create address. Required if create=True
        """
        Address = Pool().get('party.address')

        address = authorize.Address.create(
            profile_id, self.get_authorize_address())
        address_id = address.address_id
        Address.write([self], {
            'authorize_id': address_id,
        })
        return address_id

    def get_authorize_address(self, name=None):
        """
        Returns address as a dictionary to send to authorize.net

        :param name: Name to send as first name in address.
            Default is party's name.
        """
        return {
            'first_name': name if name else self.party.name,
            'last_name': '',
            'company': '',
            'address': '\n'.join(filter(None, [self.street, self.streetbis])),
            'city': self.city,
            'state': self.subdivision and self.subdivision.code,
            'zip': self.zip,
            'country': self.country and self.country.code,
            'phone_number': self.party.phone,
            'fax_number': self.party.fax,
        }
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

# vim: tabstop=4 shiftwidth=4 softtabstop=4

#    Copyright (C) 2012 Yahoo! Inc. All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import abc
import uuid

from taskflow import exceptions as exc
from taskflow import states
from taskflow import utils

def task_and_state(task, state):
    return "%s:%s" % (task.name, state)

class Claimer(object):
    """A base class for objects that can attempt to claim a given
    job, so that said job can be worked on."""

    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def claim(self, job, owner):
        """This method will attempt to claim said job and must
        either succeed at this or throw an exception signaling the job can not
        be claimed."""
        raise NotImplementedError()

    @abc.abstractmethod
    def unclaim(self, job, owner):
        """This method will attempt to unclaim said job and must
        either succeed at this or throw an exception signaling the job can not
        be unclaimed."""
        raise NotImplementedError()

class Job(object):
    """A job is connection to some set of work to be done by some agent. Basic
    information is provided about said work to be able to attempt to
    fullfill said work."""

    __metaclass__ = abc.ABCMeta

    def __init__(self, name, context, catalog, claimer, jid=None):
        self.name = name
        self.context = context
        self.owner = None
        self.posted_on = []
        self._catalog = catalog
        self._claimer = claimer
        self._logbook = None
        if not jid:
            self._id = str(uuid.uuid4().hex)
        else:
            self._id = str(jid)
        self._state = states.UNCLAIMED

    def __str__(self):
        return "Job (%s, %s): %s" % (self.name, self.tracking_id, self.state)

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, new_state):
        self._change_state(new_state)

    def _change_state(self, new_state):
        if self.state != new_state:
            self._state = new_state
            # TODO(harlowja): add logbook info?

    def _workflow_listener(self, context, flow, old_state):
        """Ensure that when we receive an event from said workflow that we
        make sure a logbook entry exists for that flow."""
        if flow.name in self.logbook:
            return
        self.logbook.add_flow(flow.name)

    def _task_listener(self, context, state, flow, task, result=None):
        """Store the result of the task under the given flow in the log
        book so that it can be retrieved later."""
        metadata = None
        flow_details = self.logbook[flow.name]
        if state == states.SUCCESS:
            metadata = {
                'result': result,
            }
        task_state = task_and_state(task, state)
        if task_state not in flow_details:
            task_details = flow_details.add_task(task_state)
            task_details.metadata = metadata

    def _task_result_fetcher(self, context, flow, task):
        flow_details = self.logbook[flow.name]
        # See if it completed before so that we can use its results instead
        # of having to recompute them.
        task_state = task_and_state(task, states.SUCCESS)
        if task_state in flow_details:
            # TODO(harlowja): should we be a little more cautious about
            # duplicate task results? Maybe we shouldn't allow them to
            # have the same name in the first place?
            task_details = flow_details[task_state][0]
            if task_details.metadata and 'result' in task_details.metadata:
                return (True, task_details.metadata['result'])
        return (False, None)

    def associate(self, flow):
        """Attachs the needed resumption and state change tracking listeners
        to the given workflow so that the workflow can be resumed/tracked
        using the jobs components."""
        if self._task_listener not in flow.task_listeners:
            flow.task_listeners.append(self._task_listener)
        if self._workflow_listener not in flow.listeners:
            flow.listeners.append(self._workflow_listener)
        flow.result_fetcher = self._task_result_fetcher

    @property
    def logbook(self):
        """Fetches (or creates) a logbook entry for this job."""
        if self._logbook is None:
            self._logbook = self._catalog.create_or_fetch(self)
        return self._logbook

    def claim(self, owner):
        """This can be used to attempt transition this job from unclaimed
        to claimed.

        This must be done in a way that likely uses some type of locking or
        ownership transfer so that only a single entity gets this job to work
        on. This will avoid multi-job ownership, which can lead to
        inconsistent state."""
        if self.state != states.UNCLAIMED:
            raise exc.UnclaimableJobException("Unable to claim job when job is"
                                              " in state %s" % (self.state))
        self._claimer.claim(self, owner)
        self._change_state(states.CLAIMED)

    def run(self, flow, *args, **kwargs):
        self.associate(flow)
        return flow.run(self.context, *args, **kwargs)

    def unclaim(self):
        """Atomically transitions this job from claimed to unclaimed."""
        if self.state == states.UNCLAIMED:
            return
        self._claimer.unclaim(self, self.owner)
        self._change_state(states.UNCLAIMED)

    def erase(self):
        """Erases any traces of this job from its associated resources."""
        for b in self.posted_on:
            b.erase(self)
        self._catalog.erase(self)
        if self._logbook is not None:
            self._logbook.close()
            self._logbook = None
        if self.state != states.UNCLAIMED:
            self._claimer.unclaim(self, self.owner)

    def await(self, timeout=None):
        """Awaits until either the job fails or succeeds or the provided
        timeout is reached."""

        def check_functor():
            if self.state not in (states.FAILURE, states.SUCCESS):
                return False
            return True

        return utils.await(check_functor, timeout)

    @property
    def tracking_id(self):
        """Returns a tracking *unique* identifier that can be used to identify
        this job among other jobs."""
        return "j-%s-%s" % (self.name, self._id)
<commit_msg>Ensure we associate with parent flows as well.<commit_after># -*- coding: utf-8 -*-

# vim: tabstop=4 shiftwidth=4 softtabstop=4

#    Copyright (C) 2012 Yahoo! Inc. All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import abc
import uuid

from taskflow import exceptions as exc
from taskflow import states
from taskflow import utils

def task_and_state(task, state):
    return "%s:%s" % (task.name, state)

class Claimer(object):
    """A base class for objects that can attempt to claim a given
    job, so that said job can be worked on."""

    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def claim(self, job, owner):
        """This method will attempt to claim said job and must
        either succeed at this or throw an exception signaling the job can not
        be claimed."""
        raise NotImplementedError()

    @abc.abstractmethod
    def unclaim(self, job, owner):
        """This method will attempt to unclaim said job and must
        either succeed at this or throw an exception signaling the job can not
        be unclaimed."""
        raise NotImplementedError()

class Job(object):
    """A job is connection to some set of work to be done by some agent. Basic
    information is provided about said work to be able to attempt to
    fullfill said work."""

    __metaclass__ = abc.ABCMeta

    def __init__(self, name, context, catalog, claimer, jid=None):
        self.name = name
        self.context = context
        self.owner = None
        self.posted_on = []
        self._catalog = catalog
        self._claimer = claimer
        self._logbook = None
        if not jid:
            self._id = str(uuid.uuid4().hex)
        else:
            self._id = str(jid)
        self._state = states.UNCLAIMED

    def __str__(self):
        return "Job (%s, %s): %s" % (self.name, self.tracking_id, self.state)

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, new_state):
        self._change_state(new_state)

    def _change_state(self, new_state):
        if self.state != new_state:
            self._state = new_state
            # TODO(harlowja): add logbook info?

    def _workflow_listener(self, context, flow, old_state):
        """Ensure that when we receive an event from said workflow that we
        make sure a logbook entry exists for that flow."""
        if flow.name in self.logbook:
            return
        self.logbook.add_flow(flow.name)

    def _task_listener(self, context, state, flow, task, result=None):
        """Store the result of the task under the given flow in the log
        book so that it can be retrieved later."""
        metadata = None
        flow_details = self.logbook[flow.name]
        if state == states.SUCCESS:
            metadata = {
                'result': result,
            }
        task_state = task_and_state(task, state)
        if task_state not in flow_details:
            task_details = flow_details.add_task(task_state)
            task_details.metadata = metadata

    def _task_result_fetcher(self, context, flow, task):
        flow_details = self.logbook[flow.name]
        # See if it completed before so that we can use its results instead
        # of having to recompute them.
        task_state = task_and_state(task, states.SUCCESS)
        if task_state in flow_details:
            # TODO(harlowja): should we be a little more cautious about
            # duplicate task results? Maybe we shouldn't allow them to
            # have the same name in the first place?
            task_details = flow_details[task_state][0]
            if task_details.metadata and 'result' in task_details.metadata:
                return (True, task_details.metadata['result'])
        return (False, None)

    def associate(self, flow):
        """Attachs the needed resumption and state change tracking listeners
        to the given workflow so that the workflow can be resumed/tracked
        using the jobs components."""
        if self._task_listener not in flow.task_listeners:
            flow.task_listeners.append(self._task_listener)
        if self._workflow_listener not in flow.listeners:
            flow.listeners.append(self._workflow_listener)
        flow.result_fetcher = self._task_result_fetcher

    @property
    def logbook(self):
        """Fetches (or creates) a logbook entry for this job."""
        if self._logbook is None:
            self._logbook = self._catalog.create_or_fetch(self)
        return self._logbook

    def claim(self, owner):
        """This can be used to attempt transition this job from unclaimed
        to claimed.

        This must be done in a way that likely uses some type of locking or
        ownership transfer so that only a single entity gets this job to work
        on. This will avoid multi-job ownership, which can lead to
        inconsistent state."""
        if self.state != states.UNCLAIMED:
            raise exc.UnclaimableJobException("Unable to claim job when job is"
                                              " in state %s" % (self.state))
        self._claimer.claim(self, owner)
        self._change_state(states.CLAIMED)

    def run(self, flow, *args, **kwargs):
        already_associated = []

        def associate_all(f):
            # Associate with the flow and the flows parents and so on.
            if f in already_associated:
                return
            self.associate(f)
            already_associated.append(f)
            if f.parents:
                for p in f.parents:
                    associate_all(p)

        associate_all(flow)
        return flow.run(self.context, *args, **kwargs)

    def unclaim(self):
        """Atomically transitions this job from claimed to unclaimed."""
        if self.state == states.UNCLAIMED:
            return
        self._claimer.unclaim(self, self.owner)
        self._change_state(states.UNCLAIMED)

    def erase(self):
        """Erases any traces of this job from its associated resources."""
        for b in self.posted_on:
            b.erase(self)
        self._catalog.erase(self)
        if self._logbook is not None:
            self._logbook.close()
            self._logbook = None
        if self.state != states.UNCLAIMED:
            self._claimer.unclaim(self, self.owner)

    def await(self, timeout=None):
        """Awaits until either the job fails or succeeds or the provided
        timeout is reached."""

        def check_functor():
            if self.state not in (states.FAILURE, states.SUCCESS):
                return False
            return True

        return utils.await(check_functor, timeout)

    @property
    def tracking_id(self):
        """Returns a tracking *unique* identifier that can be used to identify
        this job among other jobs."""
        return "j-%s-%s" % (self.name, self._id)
<|endoftext|>


<commit_before>CEGUI_BASEDIR = "C:\\Users\\Martin Preisler\\Devel\\CEGUI"
BOOST_BASEDIR = "C:\\Program Files (x86)\\boost\\boost_1_46_1"

from distutils.core import setup, Extension
from distutils.sysconfig import get_python_inc

import os
from glob import *

global_defines = []# [("CEGUI_STATIC", "1")]
# turn on exceptions for MSVC
global_extra_compile_args = ["/EHsc"]
global_include_dirs = [get_python_inc(plat_specific = True), "../", "../../../../../include", "../../../../../../build/cegui/include", BOOST_BASEDIR]
global_library_dirs = [CEGUI_BASEDIR + "/build/lib", BOOST_BASEDIR + "/lib"]
# Windows is special and picks the libraries magically!
global_libraries = []

PyCEGUI_sources = glob(os.path.join("..", "output", "CEGUI", "*.cpp"))
PyCEGUIOpenGLRenderer_sources = glob(os.path.join("..", "output", "CEGUIOpenGLRenderer", "*.cpp"))
PyCEGUIOgreRenderer_sources = glob(os.path.join("..", "output", "CEGUIOgreRenderer", "*.cpp"))
PyCEGUINullRenderer_sources = glob(os.path.join("..", "output", "CEGUINullRenderer", "*.cpp"))

setup(
    name = "PyCEGUI",
    version = "0.8",
    description = "Python bindings for CEGUI library",
    long_description =
"""Crazy Eddie's GUI System is a free library providing windowing
and widgets for graphics APIs / engines where such functionality
is not natively available, or severely lacking. The library is
object orientated, written in C++, and targeted at games developers
who should be spending their time creating great games, not building GUI sub-systems.

note: For Linux and MacOSX packages, see http://www.cegui.org.uk, we provide them
      in SDKs. Distutils package is only provided for Windows since it's hard to
      install the binding there as it involves lots of wrappers and nasty tricks.
      Shame on you Windows!""",
    author = "CEGUI team",
    author_email = "team@cegui.org.uk",
    #maintainer = "Martin Preisler", # authors get shadowed by this
    #maintainer_email = "preisler.m@gmail.com",
    url = "http://www.cegui.org.uk",
    license = "MIT",
    platforms = ["Windows", "Linux", "MacOSX"],

    classifiers = [
        "Development Status :: 4 - Beta",
        "Environment :: MacOS X",
        "Environment :: Win32 (MS Windows)",
        "Environment :: X11 Applications",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: MIT License",
        "Natural Language :: English",
        "Operating System :: MacOS :: MacOS X",
        "Operating System :: Microsoft :: Windows",
        "Operating System :: POSIX",
        "Programming Language :: Python",
        "Programming Language :: C++"
        "Topic :: Games/Entertainment",
        "Topic :: Multimedia :: Graphics",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Topic :: Software Development :: User Interfaces",
        "Topic :: Software Development :: Widget Sets",
    ],

    packages = [
        "PyCEGUI" # nasty nasty wrapper for a nasty nasty OS
    ],

    # this doesn't work as I expected so I am doing data files further down
    #package_data = { "PyCEGUI/datafiles": [CEGUI_BASEDIR + "/datafiles/*"] },

    ext_modules = [
        Extension(
            "PyCEGUI.PyCEGUI",
            PyCEGUI_sources,
            define_macros = global_defines,
            extra_compile_args = global_extra_compile_args,
            include_dirs = global_include_dirs + ["../output/CEGUI"],
            library_dirs = global_library_dirs,
            libraries = ["CEGUIBase"] + global_libraries,
        ),
        Extension(
            "PyCEGUIOpenGLRenderer",
            PyCEGUIOpenGLRenderer_sources,
            define_macros = global_defines,
            extra_compile_args = global_extra_compile_args,
            include_dirs = global_include_dirs + ["../output/CEGUIOpenGLRenderer"],
            library_dirs = global_library_dirs,
            libraries = ["CEGUIBase", "CEGUIOpenGLRenderer"] + global_libraries,
        ),
        # no ogre for now, I will use SDK binaries later for this
        #Extension(
        #    "PyCEGUIOgreRenderer",
        #    PyCEGUIOgreRenderer_sources,
        #    define_macros = global_defines,
        #    extra_compile_args = global_extra_compile_args,
        #    include_dirs = global_include_dirs + ["../output/CEGUIOgreRenderer"],
        #    library_dirs = global_library_dirs,
        #    libraries = ["CEGUIBase", "CEGUIOgreRenderer"] + global_libraries,
        #),
        Extension(
            "PyCEGUINullRenderer",
            PyCEGUINullRenderer_sources,
            define_macros = global_defines,
            extra_compile_args = global_extra_compile_args,
            include_dirs = global_include_dirs + ["../output/CEGUINullRenderer"],
            library_dirs = global_library_dirs,
            libraries = ["CEGUIBase", "CEGUINullRenderer"] + global_libraries,
        ),
    ],

    # the first string is directory where the files should go
    # - leave empty for C:/Python26 for example
    data_files = [
        # we have to bundle CEGUIBase.dll, CEGUIOpenGLRenderer.dll, etc...
        ("Lib/site-packages/PyCEGUI",
        # this is obviously a workaround, I would be happy to hear what the clean
        # solution should look like
            [
                BOOST_BASEDIR + "/lib/boost_python-vc90-mt-1_46_1.dll",

                CEGUI_BASEDIR + "/build/bin/CEGUIBase.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUIOpenGLRenderer.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUINullRenderer.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUIFalagardWRBase.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUISILLYImageCodec.dll",
                CEGUI_BASEDIR + "/dependencies/bin/SILLY.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUIExpatParser.dll",
            ]
        ),

        # distutils doesn't allow to bundle folders (or to be precise: I have no idea how to do that)
        # therefore I do this the ugly way!
        ("Lib/site-packages/PyCEGUI/datafiles/animations",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/animations", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/configs",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/configs", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/fonts",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/fonts", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/imagesets",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/imagesets", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/layouts",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/layouts", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/looknfeel",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/looknfeel", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/lua_scripts",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/lua_scripts", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/schemes",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/schemes", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/xml_schemas",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/xml_schemas", "*")),
        )
    ]
)
<commit_msg>MOD: support boostpro default directory on both 64bit and 32bit Windows when building PyCEGUI using distutils<commit_after>import sys

CEGUI_BASEDIR = "C:\\Users\\Admin\\Devel\\CEGUI\\cegui_mk2"
is_64bits = sys.maxsize > 2**32
BOOST_BASEDIR = "C:\\Program Files (x86)\\boost\\boost_1_46_1" if is_64bits else "C:\\Program Files\\boost\\boost_1_46_1"

from distutils.core import setup, Extension
from distutils.sysconfig import get_python_inc

import os
from glob import *

global_defines = []# [("CEGUI_STATIC", "1")]
# turn on exceptions for MSVC
global_extra_compile_args = ["/EHsc"]
global_include_dirs = [get_python_inc(plat_specific = True), "../", "../../../../../include", "../../../../../../build/cegui/include", BOOST_BASEDIR]
global_library_dirs = [CEGUI_BASEDIR + "/build/lib", BOOST_BASEDIR + "/lib"]
# Windows is special and picks the libraries magically!
global_libraries = []

PyCEGUI_sources = glob(os.path.join("..", "output", "CEGUI", "*.cpp"))
PyCEGUIOpenGLRenderer_sources = glob(os.path.join("..", "output", "CEGUIOpenGLRenderer", "*.cpp"))
PyCEGUIOgreRenderer_sources = glob(os.path.join("..", "output", "CEGUIOgreRenderer", "*.cpp"))
PyCEGUINullRenderer_sources = glob(os.path.join("..", "output", "CEGUINullRenderer", "*.cpp"))

setup(
    name = "PyCEGUI",
    version = "0.8",
    description = "Python bindings for CEGUI library",
    long_description =
"""Crazy Eddie's GUI System is a free library providing windowing
and widgets for graphics APIs / engines where such functionality
is not natively available, or severely lacking. The library is
object orientated, written in C++, and targeted at games developers
who should be spending their time creating great games, not building GUI sub-systems.

note: For Linux and MacOSX packages, see http://www.cegui.org.uk, we provide them
      in SDKs. Distutils package is only provided for Windows since it's hard to
      install the binding there as it involves lots of wrappers and nasty tricks.
      Shame on you Windows!""",
    author = "CEGUI team",
    author_email = "team@cegui.org.uk",
    #maintainer = "Martin Preisler", # authors get shadowed by this
    #maintainer_email = "preisler.m@gmail.com",
    url = "http://www.cegui.org.uk",
    license = "MIT",
    platforms = ["Windows", "Linux", "MacOSX"],

    classifiers = [
        "Development Status :: 4 - Beta",
        "Environment :: MacOS X",
        "Environment :: Win32 (MS Windows)",
        "Environment :: X11 Applications",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: MIT License",
        "Natural Language :: English",
        "Operating System :: MacOS :: MacOS X",
        "Operating System :: Microsoft :: Windows",
        "Operating System :: POSIX",
        "Programming Language :: Python",
        "Programming Language :: C++"
        "Topic :: Games/Entertainment",
        "Topic :: Multimedia :: Graphics",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Topic :: Software Development :: User Interfaces",
        "Topic :: Software Development :: Widget Sets",
    ],

    packages = [
        "PyCEGUI" # nasty nasty wrapper for a nasty nasty OS
    ],

    # this doesn't work as I expected so I am doing data files further down
    #package_data = { "PyCEGUI/datafiles": [CEGUI_BASEDIR + "/datafiles/*"] },

    ext_modules = [
        Extension(
            "PyCEGUI.PyCEGUI",
            PyCEGUI_sources,
            define_macros = global_defines,
            extra_compile_args = global_extra_compile_args,
            include_dirs = global_include_dirs + ["../output/CEGUI"],
            library_dirs = global_library_dirs,
            libraries = ["CEGUIBase"] + global_libraries,
        ),
        Extension(
            "PyCEGUIOpenGLRenderer",
            PyCEGUIOpenGLRenderer_sources,
            define_macros = global_defines,
            extra_compile_args = global_extra_compile_args,
            include_dirs = global_include_dirs + ["../output/CEGUIOpenGLRenderer"],
            library_dirs = global_library_dirs,
            libraries = ["CEGUIBase", "CEGUIOpenGLRenderer"] + global_libraries,
        ),
        # no ogre for now, I will use SDK binaries later for this
        #Extension(
        #    "PyCEGUIOgreRenderer",
        #    PyCEGUIOgreRenderer_sources,
        #    define_macros = global_defines,
        #    extra_compile_args = global_extra_compile_args,
        #    include_dirs = global_include_dirs + ["../output/CEGUIOgreRenderer"],
        #    library_dirs = global_library_dirs,
        #    libraries = ["CEGUIBase", "CEGUIOgreRenderer"] + global_libraries,
        #),
        Extension(
            "PyCEGUINullRenderer",
            PyCEGUINullRenderer_sources,
            define_macros = global_defines,
            extra_compile_args = global_extra_compile_args,
            include_dirs = global_include_dirs + ["../output/CEGUINullRenderer"],
            library_dirs = global_library_dirs,
            libraries = ["CEGUIBase", "CEGUINullRenderer"] + global_libraries,
        ),
    ],

    # the first string is directory where the files should go
    # - leave empty for C:/Python26 for example
    data_files = [
        # we have to bundle CEGUIBase.dll, CEGUIOpenGLRenderer.dll, etc...
        ("Lib/site-packages/PyCEGUI",
        # this is obviously a workaround, I would be happy to hear what the clean
        # solution should look like
            [
                BOOST_BASEDIR + "/lib/boost_python-vc90-mt-1_46_1.dll",

                CEGUI_BASEDIR + "/build/bin/CEGUIBase.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUIOpenGLRenderer.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUINullRenderer.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUIFalagardWRBase.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUISILLYImageCodec.dll",
                CEGUI_BASEDIR + "/dependencies/bin/SILLY.dll",
                CEGUI_BASEDIR + "/build/bin/CEGUIExpatParser.dll",
            ]
        ),

        # distutils doesn't allow to bundle folders (or to be precise: I have no idea how to do that)
        # therefore I do this the ugly way!
        ("Lib/site-packages/PyCEGUI/datafiles/animations",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/animations", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/configs",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/configs", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/fonts",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/fonts", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/imagesets",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/imagesets", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/layouts",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/layouts", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/looknfeel",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/looknfeel", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/lua_scripts",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/lua_scripts", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/schemes",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/schemes", "*")),
        ),
        ("Lib/site-packages/PyCEGUI/datafiles/xml_schemas",
            glob(os.path.join(CEGUI_BASEDIR + "/datafiles/xml_schemas", "*")),
        )
    ]
)
<|endoftext|>