Fetches the latest exchange rate info from the European Central Bank. These
    rates need to be used for displaying invoices since some countries require
    local currency be quoted. Also useful to store the GBP rate of the VAT
    collected at time of purchase to prevent fluctuations in exchange rates from
    significantly altering the amount of tax due the HMRC (if you are using them
    for VAT MOSS).

    :return:
        A dict with string keys that are currency codes and values that are
        Decimals of the exchange rate with the base (1.0000) being the Euro
        (EUR). The following currencies are included, based on this library
        being build for EU and Norway VAT, plus USD for the author:
         - BGN
         - CZK
         - DKK
         - EUR
         - GBP
         - HUF
         - HRK
         - NOK
         - PLN
         - RON
         - SEK
         - USD

def fetch():
    """
    Fetches the latest exchange rate info from the European Central Bank. These
    rates need to be used for displaying invoices since some countries require
    local currency be quoted. Also useful to store the GBP rate of the VAT
    collected at time of purchase to prevent fluctuations in exchange rates from
    significantly altering the amount of tax due the HMRC (if you are using them
    for VAT MOSS).

    :return:
        A dict with string keys that are currency codes and values that are
        Decimals of the exchange rate with the base (1.0000) being the Euro
        (EUR). The following currencies are included, based on this library
        being build for EU and Norway VAT, plus USD for the author:
         - BGN
         - CZK
         - DKK
         - EUR
         - GBP
         - HUF
         - HRK
         - NOK
         - PLN
         - RON
         - SEK
         - USD
    """

    response = urlopen('https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml')
    _, params = cgi.parse_header(response.headers['Content-Type'])
    if 'charset' in params:
        encoding = params['charset']
    else:
        encoding = 'utf-8'

    return_xml = response.read().decode(encoding)

    # Example return data
    #
    # <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    #     <gesmes:subject>Reference rates</gesmes:subject>
    #     <gesmes:Sender>
    #         <gesmes:name>European Central Bank</gesmes:name>
    #     </gesmes:Sender>
    #     <Cube>
    #         <Cube time="2015-01-09">
    #             <Cube currency="USD" rate="1.1813"/>
    #             <Cube currency="JPY" rate="140.81"/>
    #             <Cube currency="BGN" rate="1.9558"/>
    #             <Cube currency="CZK" rate="28.062"/>
    #             <Cube currency="DKK" rate="7.4393"/>
    #             <Cube currency="GBP" rate="0.77990"/>
    #             <Cube currency="HUF" rate="317.39"/>
    #             <Cube currency="PLN" rate="4.2699"/>
    #             <Cube currency="RON" rate="4.4892"/>
    #             <Cube currency="SEK" rate="9.4883"/>
    #             <Cube currency="CHF" rate="1.2010"/>
    #             <Cube currency="NOK" rate="9.0605"/>
    #             <Cube currency="HRK" rate="7.6780"/>
    #             <Cube currency="RUB" rate="72.8910"/>
    #             <Cube currency="TRY" rate="2.7154"/>
    #             <Cube currency="AUD" rate="1.4506"/>
    #             <Cube currency="BRL" rate="3.1389"/>
    #             <Cube currency="CAD" rate="1.3963"/>
    #             <Cube currency="CNY" rate="7.3321"/>
    #             <Cube currency="HKD" rate="9.1593"/>
    #             <Cube currency="IDR" rate="14925.34"/>
    #             <Cube currency="ILS" rate="4.6614"/>
    #             <Cube currency="INR" rate="73.6233"/>
    #             <Cube currency="KRW" rate="1290.29"/>
    #             <Cube currency="MXN" rate="17.3190"/>
    #             <Cube currency="MYR" rate="4.2054"/>
    #             <Cube currency="NZD" rate="1.5115"/>
    #             <Cube currency="PHP" rate="53.090"/>
    #             <Cube currency="SGD" rate="1.5789"/>
    #             <Cube currency="THB" rate="38.846"/>
    #             <Cube currency="ZAR" rate="13.6655"/>
    #         </Cube>
    #     </Cube>
    # </gesmes:Envelope>

    # If we don't explicitly recode to UTF-8, ElementTree stupidly uses
    # ascii on Python 2.7
    envelope = ElementTree.fromstring(return_xml.encode('utf-8'))

    namespaces = {
        'gesmes': 'http://www.gesmes.org/xml/2002-08-01',
        'eurofxref': 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref'
    }

    date_elements = envelope.findall('./eurofxref:Cube/eurofxref:Cube[@time]', namespaces)
    if not date_elements:
        # Fail loudly if the XML seems to have changed
        raise WebServiceError('Unable to find <Cube time=""> tag in ECB XML')

    date = date_elements[0].get('time')
    if not isinstance(date, str_cls):
        date = date.decode('utf-8')

    currency_elements = envelope.findall('./eurofxref:Cube/eurofxref:Cube/eurofxref:Cube[@currency][@rate]', namespaces)
    if not currency_elements:
        # Fail loudly if the XML seems to have changed
        raise WebServiceError('Unable to find <Cube currency="" rate=""> tags in ECB XML')

    rates = {
        'EUR': Decimal('1.0000')
    }

    applicable_currenties = {
        'BGN': True,
        'CZK': True,
        'DKK': True,
        'EUR': True,
        'GBP': True,
        'HRK': True,
        'HUF': True,
        'NOK': True,
        'PLN': True,
        'RON': True,
        'SEK': True,
        'USD': True
    }

    for currency_element in currency_elements:
        code = currency_element.attrib.get('currency')

        if code not in applicable_currenties:
            continue

        rate = currency_element.attrib.get('rate')
        rates[code] = Decimal(rate)

    return (date, rates)