Last active
July 12, 2019 22:09
-
-
Save seblin/54e6e061b440e9be81de1c26ed1bb6c9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from decimal import Decimal | |
import re | |
from urllib.request import urlopen | |
from xml.etree import ElementTree as etree | |
EUROFXREF_URL = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml' | |
XPATH_PATTERN = './/*[@currency]' | |
RATES = {} | |
_CONVERT_RE = r'\W*'.join([ | |
r'(?P<amount>\d+(\.\d+)?)', | |
r'(?P<from_currency>[A-Z]{3})', | |
r'->', | |
r'(?P<to_currency>[A-Z]{3})', | |
]) | |
def update_rates(url=EUROFXREF_URL, pattern=XPATH_PATTERN): | |
with urlopen(url) as stream: | |
tree = etree.parse(stream) | |
for elem in tree.iterfind(pattern): | |
RATES[elem.get('currency')] = Decimal(elem.get('rate')) | |
RATES['EUR'] = Decimal(1) | |
def get_rate(currency): | |
if not RATES: | |
update_rates() | |
if currency not in RATES: | |
raise ValueError(f'Unknown currency: {currency}') | |
return RATES[currency] | |
def get_currencies(): | |
if not RATES: | |
update_rates() | |
return sorted(RATES.keys()) | |
def convert(amount, from_currency, to_currency): | |
if from_currency != 'EUR': | |
# All rates refer to Euro | |
amount /= get_rate(from_currency) | |
return amount * get_rate(to_currency) | |
def convert_string(string, format_spec='.2f', show_currency=False): | |
match = re.match(_CONVERT_RE, string.strip().upper()) | |
if not match: | |
raise ValueError('Invalid string format') | |
params = match.groupdict() | |
params['amount'] = Decimal(params['amount']) | |
result = format(convert(**params), format_spec) | |
if not show_currency: | |
return result | |
return f'{result} {params["to_currency"]}' | |
def main(): | |
all_currencies = ', '.join(get_currencies()) | |
print(f'Available currencies:\n{all_currencies}\n') | |
print(f'1 EUR equals {get_rate("USD")} US Dollar or {get_rate("JPY")} Yen') | |
print(f'42 US Dollar = {convert(42, "USD", "JPY"):.2f} Yen') | |
print(f'50 Euro = {convert_string("50 EUR -> CNY")} Chinese Yuan') | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment