Beispiel #1
0
def fetch_exchange_rates():
    """Retrieve all currency exchange rates.

    Batch currencies into requests of `SYMBOLS_PER_REQUEST` currencies each.

    Returns:
        list: List of `{abbr : n.nn}` dicts of exchange rates
            (relative to EUR).

    """
    rates = {}
    futures = []
    active = load_active_currencies()

    syms = [s for s in CURRENCIES.keys() if s in active]
    if not OPENX_APP_KEY:
        log.warning('fetching limited set of fiat currency exchange rates: '
                    'APP_KEY for openexchangerates.org not set. '
                    'Please sign up for a free account here: '
                    'https://openexchangerates.org/signup/free')
        jobs = [(load_xra_rates, (syms, ))]
    else:
        jobs = [(load_openx_rates, (syms, ))]

    syms = []
    for s in CRYPTO_CURRENCIES.keys():
        if s in CURRENCIES:
            log.warning(
                'ignoring crytopcurrency "%s", as it conflicts with '
                'a fiat currency', s)
            continue
        if s in active:
            syms.append(s)

    for symbols in grouper(SYMBOLS_PER_REQUEST, syms):
        jobs.append((load_cryptocurrency_rates, (symbols, )))

    # fetch data in a thread pool
    pool = Pool(2)
    for job in jobs:
        futures.append(pool.apply_async(*job))

    pool.close()
    pool.join()

    for f in futures:
        for currency, rate in f.get().iteritems():
            if is_valid_currency(currency) and is_valid_exchange_rate(rate):
                rates[currency] = rate
                log.debug("Currency %s has new rate %s", currency, rate)
            else:
                log.warn("Got invalid rate update for currency '%s' to '%s'",
                         currency, rate)

    return rates
Beispiel #2
0
def handle_delimited_query(query):
    """Process sub-commands.

    Args:
        query (str): User query

    """
    # Currencies or decimal places
    if query.endswith(DELIMITER):  # User deleted trailing space
        run_trigger('config')
        # subprocess.call(['osascript', '-e', ALFRED_AS])
        # return

    mode, query = [s.strip() for s in query.split(DELIMITER)]

    if mode == 'currencies':

        currencies = sorted([(name, symbol)
                             for (symbol, name) in CURRENCIES.items()] +
                            [(name, symbol)
                             for (symbol, name) in CRYPTO_CURRENCIES.items()])

        if query:
            currencies = wf.filter(query,
                                   currencies,
                                   key=lambda t: ' '.join(t),
                                   match_on=MATCH_ALL ^ MATCH_ALLCHARS,
                                   min_score=30)

        else:  # Show last update time
            age = wf.cached_data_age(CURRENCY_CACHE_NAME)
            if age > 0:  # Exchange rates in cache
                td = timedelta(seconds=age)
                wf.add_item('Exchange rates updated {}'.format(
                    human_timedelta(td)),
                            icon=ICON_INFO)

        if not currencies:
            wf.add_item('No matching currencies',
                        'Try a different query',
                        icon=ICON_WARNING)

        for name, symbol in currencies:
            wf.add_item(u'{} // {}'.format(name, symbol),
                        u'Use `{}` in conversions'.format(symbol),
                        copytext=symbol,
                        valid=False,
                        icon=ICON_CURRENCY)

        wf.send_feedback()
Beispiel #3
0
def handle_delimited_query(query):
    """Process sub-commands.

    Args:
        query (str): User query

    """
    # Currencies or decimal places
    if query.endswith(DELIMITER):  # User deleted trailing space
        run_trigger('config')
        # subprocess.call(['osascript', '-e', ALFRED_AS])
        # return

    mode, query = [s.strip() for s in query.split(DELIMITER)]

    if mode == 'currencies':

        currencies = sorted([(name, symbol) for (symbol, name)
                            in CURRENCIES.items()] +
                            [(name, symbol) for (symbol, name)
                            in CRYPTO_CURRENCIES.items()])

        if query:
            currencies = wf.filter(query, currencies,
                                   key=lambda t: ' '.join(t),
                                   match_on=MATCH_ALL ^ MATCH_ALLCHARS,
                                   min_score=30)

        else:  # Show last update time
            age = wf.cached_data_age(CURRENCY_CACHE_NAME)
            if age > 0:  # Exchange rates in cache
                td = timedelta(seconds=age)
                wf.add_item('Exchange rates updated {}'.format(
                            human_timedelta(td)),
                            icon=ICON_INFO)

        if not currencies:
            wf.add_item('No matching currencies',
                        'Try a different query',
                        icon=ICON_WARNING)

        for name, symbol in currencies:
            wf.add_item(u'{} // {}'.format(name, symbol),
                        u'Use `{}` in conversions'.format(symbol),
                        copytext=symbol,
                        valid=False,
                        icon=ICON_CURRENCY)

        wf.send_feedback()
def fetch_currency_rates():
    """Retrieve all currency exchange rates.

    Batch currencies into requests of `SYMBOLS_PER_REQUEST` currencies each.

    Returns:
        list: List of `{abbr : n.nn}` dicts of exchange rates
            (relative to EUR).
    """

    rates = {}

    for symbols in grouper(SYMBOLS_PER_REQUEST, CURRENCIES.keys()):
        symbols = [s for s in symbols if s]
        d = load_yahoo_rates(symbols)
        rates.update(d)

    return rates
Beispiel #5
0
def fetch_exchange_rates():
    """Retrieve all currency exchange rates.

    Batch currencies into requests of `SYMBOLS_PER_REQUEST` currencies each.

    Returns:
        list: List of `{abbr : n.nn}` dicts of exchange rates
            (relative to EUR).

    """
    rates = {}
    futures = []
    active = load_active_currencies()

    syms = [s for s in CURRENCIES.keys() if s in active]
    # rates.update(load_openx_rates(syms))
    jobs = [(load_openx_rates, (syms, ))]

    syms = []
    for s in CRYPTO_CURRENCIES.keys():
        if s in CURRENCIES:
            log.warning(
                'ignoring crytopcurrency "%s", as it conflicts with '
                'a fiat currency', s)
            continue
        if s in active:
            syms.append(s)
    # syms = [s for s in CRYPTO_CURRENCIES.keys() if s in active]
    for symbols in grouper(SYMBOLS_PER_REQUEST, syms):
        jobs.append((load_cryptocurrency_rates, (symbols, )))

    # fetch data in a thread pool
    pool = Pool(2)
    for job in jobs:
        futures.append(pool.apply_async(*job))

    pool.close()
    pool.join()

    for f in futures:
        rates.update(f.get())

    return rates
Beispiel #6
0
def fetch_exchange_rates():
    """Retrieve all currency exchange rates.

    Batch currencies into requests of `SYMBOLS_PER_REQUEST` currencies each.

    Returns:
        list: List of `{abbr : n.nn}` dicts of exchange rates
            (relative to EUR).

    """
    rates = {}
    futures = []
    active = load_active_currencies()

    syms = [s for s in CURRENCIES.keys() if s in active]
    # rates.update(load_openx_rates(syms))
    jobs = [(load_openx_rates, (syms,))]

    syms = []
    for s in CRYPTO_CURRENCIES.keys():
        if s in CURRENCIES:
            log.warning('ignoring crytopcurrency "%s", as it conflicts with '
                        'a fiat currency', s)
            continue
        if s in active:
            syms.append(s)
    # syms = [s for s in CRYPTO_CURRENCIES.keys() if s in active]
    for symbols in grouper(SYMBOLS_PER_REQUEST, syms):
        jobs.append((load_cryptocurrency_rates, (symbols,)))

    # fetch data in a thread pool
    pool = Pool(2)
    for job in jobs:
        futures.append(pool.apply_async(*job))

    pool.close()
    pool.join()

    for f in futures:
        rates.update(f.get())

    return rates
Beispiel #7
0
def fetch_exchange_rates():
    """Retrieve all currency exchange rates.

    Batch currencies into requests of `SYMBOLS_PER_REQUEST` currencies each.

    Returns:
        list: List of `{abbr : n.nn}` dicts of exchange rates
            (relative to EUR).

    """
    rates = {}
    futures = []
    active = load_active_currencies()

    # batch symbols into groups and interleave requests to the
    # different services
    yjobs = []
    syms = [s for s in CURRENCIES.keys() if s in active]
    for symbols in grouper(SYMBOLS_PER_REQUEST, syms):
        yjobs.append((load_yahoo_rates, (symbols,)))

    cjobs = []
    syms = [sym for sym in CRYPTO_CURRENCIES.keys() if sym in active]
    for symbols in grouper(SYMBOLS_PER_REQUEST, syms):
        cjobs.append((load_cryptocurrency_rates, (symbols,)))

    # fetch data in a thread pool
    pool = Pool(4)
    for job in interleave(yjobs, cjobs):
        futures.append(pool.apply_async(*job))

    pool.close()
    pool.join()

    for f in futures:
        rates.update(f.get())

    return rates
Beispiel #8
0
def main(wf):
    """Run Script Filter.

    Args:
        wf (workflow.Workflow): Workflow object.

    Returns:
        int: Exit status.
    """
    args = docopt(__doc__, wf.args)

    log.debug('args : {!r}'.format(args))

    query = args.get('<query>')

    if args.get('--openhelp'):
        subprocess.call(['open', README_URL])
        return 0

    if args.get('--openunits'):
        path = wf.datafile(CUSTOM_DEFINITIONS_FILENAME)
        if not os.path.exists(path):
            shutil.copy(
                wf.workflowfile('{0}.sample'.format(
                                CUSTOM_DEFINITIONS_FILENAME)),
                path)

        subprocess.call(['open', path])
        return 0

    if args.get('--places'):
        value = int(query)
        log.debug('Setting `decimal_places` to {!r}'.format(value))
        wf.settings['decimal_places'] = value
        print('Set decimal places to {}'.format(value))
        # subprocess.call(['osascript', '-e', ALFRED_AS])
        return 0

    if not query or not query.strip():
        wf.add_item('View Help File',
                    'Open help file in your browser',
                    valid=True,
                    arg='--openhelp',
                    icon=ICON_HELP)

        wf.add_item('View Supported Currencies',
                    'View and search list of supported currencies',
                    autocomplete=' currencies {0} '.format(DELIMITER),
                    icon=ICON_CURRENCY)

        wf.add_item(('Decimal Places in Results '
                    '(current : {0})'.format(wf.settings.get(
                                            'decimal_places',
                                            DECIMAL_PLACES_DEFAULT))),
                    'View and search list of supported currencies',
                    autocomplete=' places {0} '.format(DELIMITER),
                    icon=ICON_SETTINGS)

        wf.add_item('Edit Custom Units',
                    'Add and edit your own custom units',
                    valid=True,
                    arg='--openunits',
                    icon='icon.png')

        wf.send_feedback()
        return 0

    else:  # Currencies or decimal places
        if query.endswith(DELIMITER):  # User deleted trailing space
            subprocess.call(['osascript', '-e', ALFRED_AS])
            return 0

        mode, query = [s.strip() for s in query.split(DELIMITER)]

        if mode == 'currencies':

            currencies = sorted([(name, symbol) for (symbol, name)
                                in CURRENCIES.items()])

            if query:
                currencies = wf.filter(query, currencies,
                                       key=lambda t: ' '.join(t),
                                       match_on=MATCH_ALL ^ MATCH_ALLCHARS,
                                       min_score=30)

            else:  # Show last update time
                age = wf.cached_data_age(CURRENCY_CACHE_NAME)
                if age > 0:  # Exchange rates in cache
                    td = timedelta(seconds=age)
                    wf.add_item('Exchange rates updated {}'.format(
                                human_timedelta(td)),
                                icon=ICON_INFO)

            if not currencies:
                wf.add_item('No matching currencies',
                            'Try a different query',
                            icon=ICON_WARNING)

            for name, symbol in currencies:
                wf.add_item('{0} // {1}'.format(name, symbol),
                            'Use `{0}` in conversions'.format(symbol),
                            icon=ICON_CURRENCY)

            wf.send_feedback()

        elif mode == 'places':

            if query:
                if not query.isdigit():
                    wf.add_item('Invalid number : {0}'.format(query),
                                'Please enter a number',
                                icon=ICON_WARNING)
                else:
                    wf.add_item('Set decimal places to : {0}'.format(query),
                                'Hit `ENTER` to save',
                                valid=True,
                                arg='--places {0}'.format(query),
                                icon=ICON_SETTINGS)
            else:
                wf.add_item('Enter a number of decimal places',
                            'Current number is {0}'.format(
                                wf.settings.get('decimal_places',
                                                DECIMAL_PLACES_DEFAULT)),
                            icon=ICON_INFO)

            wf.send_feedback()
Beispiel #9
0
def respond_external(action, **kw):
    exchange_error = 0
    exchange_message = ''
    error_code = ''
    error_description = ''
    errors = ''
    response = {}
    dom = None
    data = ''
    total = ''
    price = ''
    currency = ''
    document = ''
    order_number = ''
    order_date = ''

    print_action(action, 'Respond.External')

    locale = request.form.get('currentUsedLocalization') or ''
    wizard = request.form.get('wizardID') or ''

    try:
        # -------------------------------------
        # Get DOM and XML response from Service
        # -------------------------------------
        exchange_error, exchange_message, dom, data = send(action, request, session, **kw)

        if demo():
            exchange_error, exchange_message, total, currency = _demo_price(action)
            order_number, order_date = _demo_order(action)
        elif exchange_error:
            total = 0.0
        elif dom is not None:
            total = float(getDOMItemValue(dom, 'total') or '0')
            currency = CURRENCIES.get(getDOMItemValue(dom, 'currency'), gettext('undefined'))
            error_code = getDOMItemValue(dom, 'errorCode').strip()
            error_description = getDOMItemValue(dom, 'errorDescription')

            if action == '207':
                order = _order(dom)
                order_number = order.get('number', '')
                order_date = order.get('date', '')
        elif data:
            x = request.form.get('price')
            total = x and float(x.split()[0])*1.288726 or 0
    except:
        msg = '--> Send error!'
        print_to(errorlog, [msg, data], request=request)
        # ----------------------
        # Service Exchange Error
        # ----------------------
        if IsDeepDebug:
            print msg
        raise

    #print_to(errorlog, ['>>> Data:', data])

    IsValid = data and True or False

    if exchange_message and exchange_message == exchange_error:
        exchange_message = ''
    if error_description and error_description == error_code:
        error_description = ''

    # -----------------
    # Response is valid
    # -----------------

    if IsValid:
        errors = getDOMErrors(dom) or ''

        if IsDeepDebug:
            print errors

        if currency in ('undefined', n_a, '') or not total:
            if not exchange_message:
                if action == '203' and error_code in ('', '0',):
                    pass
                else:
                    exchange_message = gettext('Calculation is not performed.')
            IsValid = False

        total = IsValid and '%.2f' % total or ''
        price = IsValid and '%s %s' % (total, currency) or ''

        if IsDebug:
            print '--> Total: %s' % price

        document = order_number and ('# %s %s %s' % (order_number, gettext('at'), order_date)) or ''

    # -------------------------------------------
    # Make parameters and Register response in DB
    # -------------------------------------------

    attrs = { \
        'locale'            : locale,
        'selected_item'     : kw.get('id') or request.form.get('selected_item'),
        'title'             : request.form.get('title') or '',
        'document'          : document or action,
        'total'             : total,
        'currency'          : currency,
        'countryID'         : getCountryID(getDOMItemValue(dom, 'countryID'), locale),
        'regionID'          : getRegionID(getDOMItemValue(dom, 'regionID'), locale),
        'userID'            : getUserID(getDOMItemValue(dom, 'userID'), locale),
        'userName'          : getClient(getDOMItemValue(dom, 'userName'), locale),
        'wizardID'          : wizard,
        'wizardName'        : request.form.get('wizardName') or '',
        'custom_code'       : request.form.get('custom_code') or '',
        'option_update'     : request.form.get('option_update') or '',
        'option_cost'       : request.form.get('option_cost') or '',
        'data'              : data, #getDOMTagStrippedValue(dom, 'parameters'),
    }

    #print_to(errorlog, ['>>> Total:', total])

    if IsValid and action in ('203','204','205','207',): # and dom
        response = register(action, dom, attrs)

        if IsDeepDebug:
            print '>>> DB Response:%s' % response

    order = action == '205' and response.get('custom_code') or document

    return { \
        'action'            : action,
        'op'                : '',
        # --------------
        # Service Errors
        # --------------
        'exchange_error'    : exchange_error, 
        'exchange_message'  : exchange_message,
        'error_code'        : error_code,
        'error_description' : error_description,
        'errors'            : errors,
        # ---
        # IDs
        # ---
        'countryID'         : getDOMItemValue(dom, 'countryID') or '',
        'regionID'          : getDOMItemValue(dom, 'regionID') or '',
        'userID'            : attrs['userID'],
        # --------------
        # Client Details
        # --------------
        'country_name'      : getDOMItemValue(dom, 'countryName') or getCountry(getDOMItemValue(dom, 'countryID'), locale),
        'region_name'       : getDOMItemValue(dom, 'regionName') or getRegion(getDOMItemValue(dom, 'regionID'), locale),
        'client_name'       : attrs['userName'],
        # ----------
        # Order Info
        # ----------
        'document_number'   : order_number,
        'document_date'     : order_date,
        'order'             : order,
        # -------
        # DB Data
        # -------
        'total_log_rows'    : getLogTotal({'userID' : attrs['userID'], 'wizardID' : wizard}),
        'custom_code'       : response.get('custom_code', ''),
        'next_custom_code'  : response.get('next_custom_code', ''),
        'option_update'     : response.get('option_update', ''),
        'option_cost'       : response.get('option_cost', ''),
        'title'             : response.get('title', ''),
        # ------------------------------
        # Results (Price & XML-Response)
        # ------------------------------
        'price'             : price,
        'data'              : data,
    }
Beispiel #10
0
def respond_internal(action, **kw):
    exchange_error = 0
    exchange_message = ''
    error_code = ''
    error_description = ''
    response = {}
    dom = None
    data = ''
    currency = ''
    order_number = ''
    order_date = ''

    print_action(action, 'Respond.Internal')

    op = request.form.get('op') or kw.get('op')

    if IsDebug:
        print '--> op: [%s]' % op

    if not op:
        pass

    elif op == 'get':
        # --------------------------------------------------------------
        # Generate and Send XML to Service (from WEB-form to JavaScript)
        # --------------------------------------------------------------
        data = getXml(action, request, session)
        errors = []

    elif op == 'set':
        # -----------------------------------------------
        # Receive XML from Service (loaded by JavaScript)
        # -----------------------------------------------
        dom, data = receive(action, request, session, **kw)

        if demo():
            exchange_error, exchange_message, total, currency = _demo_price(action)
            order_number, order_date = _demo_order(action)
        else:
            total = float(getDOMItemValue(dom, 'total'))
            currency = CURRENCIES.get(getDOMItemValue(dom, 'currency'), gettext('undefined'))
            error_code = getDOMItemValue(dom, 'errorCode').strip()
            error_description = getDOMItemValue(dom, 'errorDescription')

        errors = getDOMErrors(dom) or ''

        if IsDebug:
            print '--> Total: %s %s' % (total, currency)

        total = '%.2f' % total or ''
        price = '%s %s' % (total, currency) or ''

    return { \
        'action'            : action,
        'op'                : op,
        # --------------
        # Service Errors
        # --------------
        'exchange_error'    : exchange_error, 
        'exchange_message'  : exchange_message,
        'error_code'        : error_code,
        'error_description' : error_description,
        'errors'            : errors,
        # ---
        # IDs
        # ---
        'countryID'         : getDOMItemValue(dom, 'countryID') or '',
        'regionID'          : getDOMItemValue(dom, 'regionID') or '',
        'userID'            : getUserID(getDOMItemValue(dom, 'userID')),
        # --------------
        # Client Details
        # --------------
        'country_name'      : getDOMItemValue(dom, 'countryName') or getCountry(getDOMItemValue(dom, 'countryID')),
        'region_name'       : getDOMItemValue(dom, 'regionName') or getRegion(getDOMItemValue(dom, 'regionID')),
        'client_name'       : getClient(getDOMItemValue(dom, 'userName')),
        # ------------------------------
        # Results (Price & XML-Response)
        # ------------------------------
        'price'             : price,
        'data'              : data,
    }