-
Money
objects can be used in Pydantic (Pydantic>=2.2
supported) models and used with Pydantic's JSON serialization and validation – the same goes forNumber
andCurrency
objects as well. See examples below.Previously validation of these types required the Pydantic config option
arbitrary_types_allowed
and JSON serialization withmodel_dump_json()
resulted in an exception. With these updates there's no need forarbitrary_types_allowed
and pydantic model's usingMoney
fields can use JSON serialization+deserialization natively. -
It's also possible to use the coercible types as Pydantic field type – mainly suited for experimentation and early development. These types will automatically coerce input into
Money
,Number
orCurrency
objects.stockholm.types.ConvertibleToMoney
stockholm.types.ConvertibleToMoneyWithRequiredCurrency
stockholm.types.ConvertibleToNumber
stockholm.types.ConvertibleToCurrency
-
Dropped support for Python 3.7.
from pydantic import BaseModel
from stockholm import Money
class Transaction(BaseModel):
reference: str
amount: Money
transaction = Transaction(reference="abc123", amount=Money("100.00", "SEK"))
# Transaction(reference='abc123', amount=<stockholm.Money: "100.00 SEK">)
json_data = transaction.model_dump_json()
# '{"reference":"abc123","amount":{"value":"100.00 SEK","units":100,"nanos":0,"currency_code":"SEK"}}'
Transaction.model_validate_json(json_data)
# Transaction(reference='abc123', amount=<stockholm.Money: "100.00 SEK">)
from pydantic import BaseModel
from stockholm import Money
from stockholm.types import ConvertibleToMoney
class ExampleModel(BaseModel):
amount: ConvertibleToMoney
example = ExampleModel(amount="4711.50 USD")
# ExampleModel(amount=<stockholm.Money: "4711.50 USD">)
example.model_dump_json()
# '{"amount":{"value":"4711.50 USD","units":4711,"nanos":500000000,"currency_code":"USD"}}'
Note that it's generally recommended to opt for the more strict types (stockholm.Money
, stockholm.Number
and stockholm.Currency
) when possible.
- Added so that
Money
,Number
andRate
objects can now be copied using thecopy.copy()
andcopy.deepcopy()
functions. - Python 3.12 added to test matrix and trove classifiers.
- Fixes some type hints that previously would show as
Unknown
in some LSPs.
- Additional support to parse input values from third parties, data models, etc.
- Primarily load protobuf message class from
google.type.money_pb2
before falling back to the included class instockholm.protobuf.money_pb2
. - Added
SLE
andVED
tostockholm.currency
.
- The
money.asdict()
function can now be called with an optionalkeys
argument, which can be used to specify a tuple of keys which shuld be used in the returned dict. - A
Number
class has been added, which can be used to differentiate between monetary values and values that doesn't hold a currency –stockholm.Number
. LikeRate
objects, theNumber
objects cannot be instantiated with a currency or currency code. - Added additional documentation and examples to the README.
The default behaviour for calling money.asdict()
without arguments has not changed. money.asdict()
is equivalent to money.asdict(keys=("value", "units", "nanos", "currency_code"))
.
Values to use in the keys
tuple for stockholm.Money
objects are any combination of the following:
key | description | return type | example |
---|---|---|---|
value |
amount + currency code | str |
"9001.50 USD" |
units |
units of the amount | int |
9001 |
nanos |
number of nano units of the amount | int |
500000000 |
currency_code |
currency code if available | str | None |
"USD" |
currency |
currency code if available | str | None |
"USD" |
amount |
the monetary amount (excl. currency code) | str |
"9001.50" |
Code examples:
from stockholm import Money
Money("4711 USD").asdict(keys=("value", "units", "nanos", "currency_code"))
# {'value': '4711.00 USD', 'units': 4711, 'nanos': 0, 'currency_code': 'USD'}
Money("4711 USD").asdict(keys=("amount", "currency"))
# {'amount': '4711.00', 'currency': 'USD'}
Money(nanos=10).asdict(keys=("value", "currency", "units", "nanos"))
# {'value': '0.00000001', 'currency': None, 'units': 0, 'nanos': 10}
- Python 3.11 added to test matrix and trove classifiers to officially claim support.
- Adds support for the
protobuf
Python bindings versioned 4.x.x. - Fixes an issue with the
__hash__
method onCurrency
objects which affected currencies with aninterchangeable_with
value, such asCNY
(+CNH
/RMB
),ILS
(+NIS
),TWD
(+NTD
). [Thanks @th-ad]
- Python 3.10 added to test matrix and trove classifiers to officially claim support.
- Major updates to improve type hints and intellisense within editors.
- Reworked the currency classes to utilize the metaclass in a better way.
- Additional updates to ease development working with Protocol Buffers and monetary amounts (mostly related to better type hint annotations which gives a better developer experience).
- Updates to the readme with additional examples.
- Dropped support for Python 3.6.
- Python 3.9 supported.
- Minor type annotation fixes.
- Fixes an issue that caused a monetary amount without currency to get a
"None"
string instead of an empty string as value tocurrency_code
when creating a protobuf message using the.as_protobuf()
method.
- Added support for conversion to and from Protocol Buffers using the new
Money.from_protobuf
ormoney.as_protobuf
functions. By default using thegoogle.type.Money
protobuf definition. - Instantiation of monetary object by passing JSON data and the possibility to get a JSON string based on a monetary amount object.
- Added documentation. Mostly regarding the use and examples about Protocol Buffers, but also a whole new section about the properties that are available on the
stockholm.Money
object.
- Updated versions for test suite (
flake8
,pytest
,mypy
, among others) and then corrected a newly found type hinting issue tracked down by the updated versions. - Added target-versions of the supported Python versions for
black
to not accidentally break any backwards compatibility. - Fixes default decimal digit formatting of the Ugandan shilling (currency code UGX). [Thanks @tritas]
- Added a sub type of
Money
which is namedRate
, which mostly works the same way but doesn't support currencies. In many applications monetary values can be multiplied with rates (the rate can for example be the units of an item on an invoice, where the sum of the item row would be the item price multiplied with the rate). TheRate
sub type is merely for differentiating monetary values (which fully supports currencies) from the simpler rate type. - Updated type hinting and object creation methods to work with inheritance.
- Monetary amounts can also be exported to
dict
as well as created withdict
value inputs, which can be great to for example transport a monetary value in JSON. - To return a dict from a
stockholm.Money
object it can either be casted todict
(dict(money)
) or by usingmoney.asdict()
. - Monetary amounts can also be created using dict input either by using
Money.from_dict(input_dict)
or by calling the constructor directly withdict
input such asMoney(dict_input)
.
- Project documentation improvements.
- Removed debug output on currency imports.
- Added money() method to currency objects. For example
stockholm.Currency.EUR.money(100)
would equalstockholm.Money(100, stockholm.Currency.EUR)
. - Prevents currency objects to create new currency objects by using them as object constructors.
- Added shortcut to
round(self, 0)
as the methodto_integral
which also returns aMoney
object. - Added
currency_code
as a property which outputs the currency in string format.
- Added
sub_units
property of money objects for easy conversion to and from sub_units.
- Updated README with examples about
units
andnanos
properties. - Added
get_currency(ticker)
method available directly from root package, to make it importable withfrom stockholm import get_currency
.
- Adds method
to_sub_units()
on monetary amounts which for most currencies multiplies the value with 100, but for example forstockholm.currency.JPY
wouldn't change the value at all. - Adds method
to_currency(currency)
(and shortedto(currency)
) on monetary amounts which just changes the currency of the monetary amount without any kind of changes to the amount itself.
Money.from_sub_units(amount, currency)
method is a classmethod which does the same thing asMoney(amount, currency, from_sub_units=True)
. For example a100
subunits ofstockholm.Currency.SEK
would result in a monetary amount of1.00 SEK
, while 100 subunits ofstockholm.Currency.JPY
would result in100 JPY
.
- Replaces
is_cents
withfrom_sub_units
which is aware of number of digits in aBaseCurrency
.
- Added support for custom currency types with non-uppercase ticker symbols.
- Restructured currency to also be able to fetch currencies directly on
stockholm.Currency
- Added
get_currency(currency)
method tostockholm.currency
which returns a currency type that includes metadata about formatting and the default minimum decimals digits, etc.
- First release with support for monetary amounts using currency types.
- All ISO 4217 currency types available in
stockholm.currency
. All currencies uses official values for the default minimum decimal digit count.