Python money class with optional CLDR-backed locale-aware formatting and an extensible currency exchange solution.

Related tags

E-commercemoney
Overview

Python Money

Money class with optional CLDR-backed locale-aware formatting and an extensible currency exchange solution.

This is version 1.4.0-dev.

Development: https://github.com/carlospalol/money
Latest release: https://pypi.python.org/pypi/money/

This package is compatible with Python 2.7, 3.4, 3.5, but there are important Differences between Python versions. All code examples use Python 3.5.

Contents

Installation

Install the latest release with:

pip install money

For locale-aware formatting, also install the latest version of Babel (2.2 or 2.3 required):

pip install babel

Usage

>>> from money import Money
>>> m = Money(amount='2.22', currency='EUR')
>>> m
EUR 2.22

amount can be any valid value in decimal.Decimal(value) and currency should be a three-letter currency code. Money objects are immutable by convention and hashable. Once created, you can use read-only properties amount (decimal.Decimal) and currency (str) to access its internal components:

>>> m = Money(2, 'USD')
>>> m.amount
Decimal('2')
>>> m.currency
'USD'

Money emulates a numeric type and you can apply most arithmetic and comparison operators between money objects, as well as addition, subtraction, and division with integers (int) and decimal numbers (decimal.Decimal):

>>> m = Money('2.22', 'EUR')
>>> m / 2
EUR 1.11
>>> m + Money('7.77', 'EUR')
EUR 9.99

More formally, with AAA and BBB being different currencies:

  Operator Money AAA Money BBB int, Decimal
Money AAA +, - Money N/A Money
* N/A N/A Money
/, // Decimal N/A Money
>, >= <, <= Compares amount. N/A N/A
== False False

Arithmetic operations with floats are not directly supported. If you need to operate with floats, you must first convert the float to a Decimal, or the Money object to a float (i.e. float(m)). Please be aware of the issues and limitations of floating point arithmetics.

Currency presets

If you use fixed currencies in your code, you may find convenient to create currency-preset Money subclasses:

class EUR(Money):
    def __init__(self, amount='0'):
        super().__init__(amount=amount, currency='EUR')

price = EUR('9.99')

Formatting

Money objects are printed by default with en_US formatting and the currency code.

>>> m = Money('1234.567', 'EUR')
>>> str(m)
'EUR 1,234.57'

Use format(locale=LC_NUMERIC, pattern=None, currency_digits=True, format_type='standard') for locale-aware formatting with currency expansion. format() relies on babel.numbers.format_currency(), and requires Babel to be installed.

>>> m = Money('1234.567', 'USD')
>>> m.format('en_US')
'$1,234.57'
>>> m.format('es_ES')
'1.234,57\xa0$'

The character \xa0 is an unicode non-breaking space. If no locale is passed, Babel will use your system's locale. You can also provide a specific pattern to format():

>>> m = Money('-1234.567', 'USD')
>>> # Regular US format:
>>> m.format('en_US', '¤#,##0.00')
'-$1,234.57'
>>> # Custom negative format:
>>> m.format('en_US', '¤#,##0.00;<¤#,##0.00>')
'<$1,234.57>'
>>> # Spanish format, full currency name:
>>> m.format('es_ES', '#,##0.00 ¤¤¤')
'-1.234,57 dólares estadounidenses'
>>> # Same as above, but rounding (overriding currency natural format):
>>> m.format('es_ES', '#0 ¤¤¤', currency_digits=False)
'-1235 dólares estadounidenses'

For more details on formatting see Babel docs on currency formatting. To learn more about the formatting pattern syntax check out Unicode TR35.

Currency exchange

Currency exchange works by "installing" a backend class that implements the abstract base class (abc) money.exchange.BackendBase. Its API is exposed through money.xrates, along with setup functions xrates.install(pythonpath), xrates.uninstall(), and xrates.backend_name.

A simple proof-of-concept backend money.exchange.SimpleBackend is included:

from decimal import Decimal
from money import Money, xrates

xrates.install('money.exchange.SimpleBackend')
xrates.base = 'USD'
xrates.setrate('AAA', Decimal('2'))
xrates.setrate('BBB', Decimal('8'))

a = Money(1, 'AAA')
b = Money(1, 'BBB')

assert a.to('BBB') == Money('4', 'BBB')
assert b.to('AAA') == Money('0.25', 'AAA')
assert a + b.to('AAA') == Money('1.25', 'AAA')

XMoney

You can use money.XMoney (a subclass of Money), for automatic currency conversion while adding, subtracting, and dividing money objects (+, +=, -, -=, /, //). This is useful when aggregating lots of money objects with heterogeneous currencies. The currency of the leftmost object has priority.

from money import XMoney

# Register backend and rates as above...

a = XMoney(1, 'AAA')
b = XMoney(1, 'BBB')

assert sum([a, b]) == XMoney('1.25', 'AAA')

Exceptions

Found in money.exceptions.

MoneyException(Exception)
Base class for all exceptions.
CurrencyMismatch(MoneyException, ValueError)
Thrown when mixing different currencies, e.g. Money(2, 'EUR') + Money(2, 'USD'). Money objects must be converted first to the same currency, or XMoney could be used for automatic conversion.
InvalidOperandType(MoneyException, TypeError)
Thrown when attempting invalid operations, e.g. multiplication between money objects.
ExchangeError(MoneyException)
Base class for exchange exceptions.
ExchangeBackendNotInstalled(ExchangeError)
Thrown if a conversion is attempted, but there is no backend available.
ExchangeRateNotFound(ExchangeError)
The installed backend failed to provide a suitable exchange rate between the origin and target currencies.

Hierarchy

  • MoneyException
    • CurrencyMismatch
    • InvalidOperandType
    • ExchangeError
      • ExchangeBackendNotInstalled
      • ExchangeRateNotFound

Differences between Python versions

Expression Python 2.x Python 3.x
round(Money('2.5', 'EUR')) Returns 3.0, a float rounded amount away from zero. Returns EUR 2, a Money object with rounded amount to the nearest even.
Money('0', 'EUR').amount < '0' Returns True. This is the weird but expected behaviour in Python 2.x when comparing Decimal objects with non-numerical objects (Note the '0' is a string). See note in docs. TypeError: unorderable types: decimal.Decimal() > str()

Design decisions

There are several design decisions in money that differ from currently available money class implementations:

Localization

Do not keep any kind of locale conventions database inside this package. Locale conventions are extensive and change over time; keeping track of them is a project of its own. There is already such a project and database (the Unicode Common Locale Data Repository), and an excellent python API for it: Babel.

Currency

There is no need for a currency class. A currency is fully identified by its ISO 4217 code, and localization or exchange rates data are expected to be centralized as databases/services because of their changing nature.

Also:

  • Modulo operator (%): do not override to mean "percentage".
  • Numeric type: you can mix numbers and money in binary operations, and objects evaluate to False if their amount is zero.
  • Global default currency: subclassing is a safer solution.

Contributions

Contributions are welcome. You can use the regular github mechanisms.

To test your changes you will need tox and python 2.7, 3.4, and 3.5. Simply cd to the package root (by setup.py) and run tox.

License

money is released under the MIT license, which can be found in the file LICENSE.

Owner
Carlos Palol
Carlos Palol
EasyShop User Interface - a shopping program we created for people who want to buy specific cloth wear

EasyShop-User-Interface Welcome to the EasyShop User Interface! This program fetches images from urls as per choices of clothes made by you and displa

Adit Sinha 1 Apr 23, 2022
Re-write of floppshop e-commerce site

Floppshop V2 Python: 3.9.5 FastAPI: 0.68 Tortoise-orm: 0.17.8 pytest: 5.2 PostgreSQL: 13.4 Setup Srak jak nie wiesz jak Clone repository $ git clone

jakub-figat 3 Nov 30, 2022
A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React.

Saleor Commerce Customer-centric e-commerce on a modern stack A headless, GraphQL commerce platform delivering ultra-fast, dynamic, personalized shopp

Saleor Commerce 17.7k Jan 01, 2023
Fully functional ecommerce website with user and guest checkout capabilities and Paypal payment integration.

ecommerce_website Fully functional ecommerce website with user and guest checkout capabilities and Paypal payment integration. pip install django pyth

2 Jan 05, 2022
Domain-driven e-commerce for Django

Domain-driven e-commerce for Django Oscar is an e-commerce framework for Django designed for building domain-driven sites. It is structured such that

Oscar 5.6k Dec 30, 2022
Storefront - An E-commerce StoreFront Application Built With Python

An E-commerce StoreFront Application A very robust storefront project. This is a

Fachii Felix Zasha 1 Apr 04, 2022
imager is a modern ecommerce & social network platform that helps users to find the most matching products

imager is a modern ecommerce & social network platform that helps users to find the most matching products. Users can follow their favourite brands and to be aware of friends' actions. If you have se

Sardor 1 Jan 11, 2022
Currency Conversion in Python

CurrencyConversion connect to an API to do currency conversions, save as json text or screen output exchangeratesAPI.py -h Exchange Rates via 'api.cur

soup-works 1 Jan 29, 2022
A Django e-commerce website

BRIKKHO.com E-commerce website created with Django Run It: Clone the project or download as zip: $ git clone https://github.com/FahadulShadhin/brikkho

Shadhin 1 Dec 17, 2021
Ecommerce for Mezzanine

Created by Stephen McDonald Overview Cartridge is a shopping cart application built using the Django framework. It is BSD licensed, and designed to pr

Stephen McDonald 680 Jan 03, 2023
Ecommerce app using Django, Rest API and ElasticSearch

e-commerce-app Ecommerce app using Django, Rest API, Docker and ElasticSearch Sort pipfile pipfile-sort Runserver with Werkzeug (django-extensions) .

Nhat Tai NGUYEN 1 Jan 31, 2022
Display money format and its filthy currencies, for all money lovers out there.

Python Currencies Display money format and its filthy currencies, for all money lovers out there. Installation currencies is available on PyPi http://

Alireza Savand 64 Dec 28, 2022
Django_E-commerce - an open-source ecommerce platform built on the Django Web Framework.

Django E-commerce Django-ecommerce is an open-source ecommerce platform built on the Django Web Framework. Demo Homepage Cartpage Orderpage Features I

Biswajit Paloi 6 Nov 06, 2022
PVE with tcaledger app for payments and simulation of payment requests

tcaledger PVE with tcaledger app for payments and simulation of payment requests. The purpose of this API is to empower users to accept cryptocurrenci

3 Jan 29, 2022
A Django app to accept payments from various payment processors via Pluggable backends.

Django-Merchant Django-Merchant is a django application that enables you to use multiple payment processors from a single API. Gateways Following gate

Agiliq 997 Dec 24, 2022
E-Commerce Platform

Shuup Shuup is an Open Source E-Commerce Platform based on Django and Python. https://shuup.com/ Copyright Copyright (c) 2012-2021 by Shuup Commerce I

Shuup 2k Dec 30, 2022
Foreign exchange rates, Bitcoin price index and currency conversion using ratesapi.io

forex-python Forex Python is a Free Foreign exchange rates and currency conversion. Note: Install latest forex-python==1.1 to avoid RatesNotAvailableE

MicroPyramid 540 Jan 05, 2023
Portfolio and E-commerce site built on Python-Django and Stripe checkout

StripeMe Introduction Stripe Me is an e-commerce and portfolio website offering communication services, including web-development, graphic design and

3 Jul 05, 2022
A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React.

Saleor Commerce Customer-centric e-commerce on a modern stack A headless, GraphQL-first e-commerce platform delivering ultra-fast, dynamic, personaliz

Mirumee Labs 17.7k Dec 31, 2022
An Unofficial Alipay API for Python

An Unofficial Alipay API for Python Overview An Unofficial Alipay API for Python, It Contain these API: Generate direct payment url Generate partner t

Eric Lo 321 Dec 24, 2022