From 148e9f0fc8655b9985c1c2d903d4cf6690572607 Mon Sep 17 00:00:00 2001 From: mcepl <> Date: Mar 14 2023 17:29:42 +0000 Subject: Update python-django-money to version 3.0 / rev 7 via SR 1071154 https://build.opensuse.org/request/show/1071154 by user mcepl + dimstar_suse - Update to 3.0: - Changed - Update py-moneyed to 2.0. - Remove the deprecated Money.decimal_places_display property and argument. - Remove the deprecated CURRENCY_DECIMAL_PLACES_DISPLAY setting. - Null constraint on an implicit CurrencyField is now declared from null=... argument to MoneyField. - Fixed - Improve the internal check for whether a currency is provided - Fix test suite for django main branch - MoneyField raises TypeError when default contains a valid amount but no currence, i.e. Money(123, None). - MoneyField supports default of type bytes - Added - Add support for Django 4.0 and 4.1. - Add support for Python 3.10. - Removed - Drop support for Django 3.1. - Drop support for Python 3.6. - Remo --- diff --git a/.files b/.files index 7d049c6..0f9e035 100644 Binary files a/.files and b/.files differ diff --git a/.rev b/.rev index f005a68..df8592c 100644 --- a/.rev +++ b/.rev @@ -50,4 +50,37 @@ 981048 + + 1a40ac16f69fddd7b772ae2084ba815d + 3.0 + + dimstar_suse + - Update to 3.0: + - Changed + - Update py-moneyed to 2.0. + - Remove the deprecated Money.decimal_places_display property + and argument. + - Remove the deprecated CURRENCY_DECIMAL_PLACES_DISPLAY + setting. + - Null constraint on an implicit CurrencyField is now + declared from null=... argument to MoneyField. + - Fixed + - Improve the internal check for whether a currency is + provided + - Fix test suite for django main branch + - MoneyField raises TypeError when default contains a valid + amount but no currence, i.e. Money(123, None). + - MoneyField supports default of type bytes + - Added + - Add support for Django 4.0 and 4.1. + - Add support for Python 3.10. + - Removed + - Drop support for Django 3.1. + - Drop support for Python 3.6. +- Remove upstreamed patches: + - merged_pr_657.patch + - pr_638.patch + + 1071154 + diff --git a/django-money-2.1.1.tar.gz b/django-money-2.1.1.tar.gz deleted file mode 120000 index 655087b..0000000 --- a/django-money-2.1.1.tar.gz +++ /dev/null @@ -1 +0,0 @@ -/ipfs/bafkreihjwox3wqsk2qzbc63rznksvo4wyvj4cn7obuth2sglsx35v3h4ve \ No newline at end of file diff --git a/django-money-3.0.tar.gz b/django-money-3.0.tar.gz new file mode 120000 index 0000000..388499d --- /dev/null +++ b/django-money-3.0.tar.gz @@ -0,0 +1 @@ +/ipfs/bafkreicc4c5pbnc35wzezl24ppvc6getxdg3mopethiepxdzx7lshuurwe \ No newline at end of file diff --git a/merged_pr_657.patch b/merged_pr_657.patch deleted file mode 100644 index 80f61a0..0000000 --- a/merged_pr_657.patch +++ /dev/null @@ -1,113 +0,0 @@ -From b140c16ca8f9ed0227f5295878c3f6b346a8472c Mon Sep 17 00:00:00 2001 -From: David Szotten -Date: Wed, 19 Jan 2022 17:53:07 +0000 -Subject: [PATCH 1/5] failing test to expose issue - ---- - djmoney/models/fields.py | 7 ++++++- - docs/changes.rst | 13 +++++++++++-- - tests/migrations/helpers.py | 2 +- - tests/test_models.py | 11 ++++++++++- - 4 files changed, 28 insertions(+), 5 deletions(-) - ---- a/djmoney/models/fields.py -+++ b/djmoney/models/fields.py -@@ -104,7 +104,12 @@ class MoneyFieldProxy: - return data[self.field.name] - - def __set__(self, obj, value): # noqa -- if value is not None and self.field._currency_field.null and not isinstance(value, MONEY_CLASSES + (Decimal,)): -+ if ( -+ value is not None -+ and self.field._currency_field.null -+ and not isinstance(value, MONEY_CLASSES) -+ and not obj.__dict__[self.currency_field_name] -+ ): - # For nullable fields we need either both NULL amount and currency or both NOT NULL - raise ValueError("Missing currency value") - if isinstance(value, BaseExpression): ---- a/docs/changes.rst -+++ b/docs/changes.rst -@@ -1,6 +1,14 @@ - Changelog - ========= - -+`Unreleased`_ - TBA -+------------------- -+ -+**Fixed** -+ -+- Improve the internal check for whether a currency is provided `#657`_ (`davidszotten`_) -+- Fix test suite for django main branch `#657`_ (`davidszotten`_) -+ - `2.1.1`_ - 2022-01-02 - --------------------- - -@@ -709,8 +717,7 @@ wrapping with ``money_manager``. - - - Initial public release - --# .. _Unreleased: https:///github.com/django-money/django-money/compare/2.1.1...HEAD -- -+.. _Unreleased: https:///github.com/django-money/django-money/compare/2.1.1...HEAD - .. _2.1.1: https:///github.com/django-money/django-money/compare/2.1...2.1.1 - .. _2.1: https:///github.com/django-money/django-money/compare/2.0.3...2.1 - .. _2.0.3: https://github.com/django-money/django-money/compare/2.0.2...2.0.3 -@@ -773,6 +780,7 @@ wrapping with ``money_manager``. - .. _0.3: https://github.com/django-money/django-money/compare/0.2...0.3 - .. _0.2: https://github.com/django-money/django-money/compare/0.2...a6d90348085332a393abb40b86b5dd9505489b04 - -+.. _#657: https://github.com/django-money/django-money/issues/657 - .. _#648: https://github.com/django-money/django-money/issues/648 - .. _#646: https://github.com/django-money/django-money/issues/646 - .. _#637: https://github.com/django-money/django-money/issues/637 -@@ -966,3 +974,4 @@ wrapping with ``money_manager``. - .. _washeck: https://github.com/washeck - .. _fara: https://github.com/fara - .. _wearebasti: https://github.com/wearebasti -+.. _davidszotten: https://github.com/davidszotten ---- a/tests/migrations/helpers.py -+++ b/tests/migrations/helpers.py -@@ -12,7 +12,7 @@ def makemigrations(): - from django.db.migrations import questioner - - # We should answer yes for all migrations questioner questions -- questioner.input = lambda x: "y" -+ questioner.input = lambda prompt=None: "y" - - os.system("find . -name \\*.pyc -delete") - call_command("makemigrations", "money_app", name=MIGRATION_NAME) ---- a/tests/test_models.py -+++ b/tests/test_models.py -@@ -5,6 +5,7 @@ Created on May 7, 2011 - """ - import datetime - from copy import copy -+from decimal import Decimal - - from django import VERSION - from django.core.exceptions import ValidationError -@@ -373,6 +374,12 @@ class TestNullableCurrency: - assert str(exc.value) == "Missing currency value" - assert not ModelWithNullableCurrency.objects.exists() - -+ def test_fails_with_null_currency_decimal(self): -+ with pytest.raises(ValueError) as exc: -+ ModelWithNullableCurrency.objects.create(money=Decimal(10)) -+ assert str(exc.value) == "Missing currency value" -+ assert not ModelWithNullableCurrency.objects.exists() -+ - def test_fails_with_nullable_but_no_default(self): - with pytest.raises(IntegrityError) as exc: - ModelWithTwoMoneyFields.objects.create() -@@ -712,7 +719,9 @@ def test_override_decorator(): - def test_properties_access(): - with pytest.raises(TypeError) as exc: - ModelWithVanillaMoneyField(money=Money(1, "USD"), bla=1) -- if VERSION[:2] > (2, 1): -+ if VERSION[:2] > (4, 0): -+ assert str(exc.value) == "ModelWithVanillaMoneyField() got unexpected keyword arguments: 'bla'" -+ elif VERSION[:2] > (2, 1): - assert str(exc.value) == "ModelWithVanillaMoneyField() got an unexpected keyword argument 'bla'" - else: - assert str(exc.value) == "'bla' is an invalid keyword argument for this function" diff --git a/pr_638.patch b/pr_638.patch deleted file mode 100644 index b90c2d8..0000000 --- a/pr_638.patch +++ /dev/null @@ -1,711 +0,0 @@ -From d29ff6f488c9d0478d29dd32a77e2fe0e76e4fb6 Mon Sep 17 00:00:00 2001 -From: Anton Agestam -Date: Mon, 19 Apr 2021 17:21:12 +0200 -Subject: [PATCH 01/16] Drop support for legacy versions - -- Drop support for Django 1.11, 2.1 and 3.0. -- Drop support for Python 3.5. ---- - .github/workflows/main.yml | 2 - djmoney/models/fields.py | 4 - - djmoney/money.py | 52 +--------------------- - djmoney/settings.py | 15 +----- - docs/changes.rst | 15 ++++++ - pytest.ini | 3 - - setup.py | 2 - tests/conftest.py | 8 --- - tests/contrib/test_django_rest_framework.py | 3 - - tests/settings.py | 16 ------- - tests/test_admin.py | 19 -------- - tests/test_models.py | 62 +++++++++++++++++---------- - tests/test_money.py | 64 ++++------------------------ - tests/test_tags.py | 35 --------------- - tests/testapp/models.py | 2 - 15 files changed, 80 insertions(+), 222 deletions(-) - ---- a/.github/workflows/main.yml -+++ b/.github/workflows/main.yml -@@ -13,7 +13,7 @@ jobs: - - - uses: actions/setup-python@v2 - with: -- python-version: 3.7 -+ python-version: 3.9 - - - run: pip install pre-commit - - run: pre-commit run --all-files ---- a/djmoney/models/fields.py -+++ b/djmoney/models/fields.py -@@ -213,7 +213,7 @@ class MoneyField(models.DecimalField): - elif isinstance(default, OldMoney): - default = Money(default.amount, default.currency) - if default is not None and default is not NOT_PROVIDED and not isinstance(default, Money): -- raise ValueError("default value must be an instance of Money, is: %s" % default) -+ raise ValueError(f"default value must be an instance of Money, is: {default}") - return default - - def to_python(self, value): -@@ -261,7 +261,7 @@ class MoneyField(models.DecimalField): - default=self.default_currency, - editable=False, - choices=self.currency_choices, -- null=self.default_currency is None, -+ null=self.null, - ) - currency_field.creation_counter = self.creation_counter - 1 - currency_field_name = get_currency_field_name(name, self) ---- a/djmoney/money.py -+++ b/djmoney/money.py -@@ -1,5 +1,3 @@ --import warnings --from functools import partial - from types import MappingProxyType - - from django.conf import settings -@@ -10,20 +8,13 @@ from django.utils.html import avoid_wrap - from django.utils.safestring import mark_safe - - import moneyed.l10n --import moneyed.localization - from moneyed import Currency, Money as DefaultMoney - --from .settings import DECIMAL_PLACES, DECIMAL_PLACES_DISPLAY, IS_DECIMAL_PLACES_DISPLAY_SET, MONEY_FORMAT -+from .settings import DECIMAL_PLACES, MONEY_FORMAT - - - __all__ = ["Money", "Currency"] - --_warn_decimal_places_display_deprecated = partial( -- warnings.warn, -- "`Money.decimal_places_display` is deprecated and will be removed in django-money 3.0.", -- DeprecationWarning, --) -- - - @deconstructible - class Money(DefaultMoney): -@@ -33,27 +24,11 @@ class Money(DefaultMoney): - - use_l10n = None - -- def __init__(self, *args, decimal_places_display=None, format_options=None, **kwargs): -+ def __init__(self, *args, format_options=None, **kwargs): - self.decimal_places = kwargs.pop("decimal_places", DECIMAL_PLACES) -- self._decimal_places_display = decimal_places_display -- if decimal_places_display is not None: -- _warn_decimal_places_display_deprecated() - self.format_options = MappingProxyType(format_options) if format_options is not None else None - super().__init__(*args, **kwargs) - -- @property -- def decimal_places_display(self): -- _warn_decimal_places_display_deprecated() -- if self._decimal_places_display is None: -- return DECIMAL_PLACES_DISPLAY.get(self.currency.code, self.decimal_places) -- return self._decimal_places_display -- -- @decimal_places_display.setter -- def decimal_places_display(self, value): -- """ Set number of digits being displayed - `None` resets to `DECIMAL_PLACES_DISPLAY` setting """ -- _warn_decimal_places_display_deprecated() -- self._decimal_places_display = value -- - def _copy_attributes(self, source, target): - """Copy attributes to the new `Money` instance. - -@@ -118,13 +93,6 @@ class Money(DefaultMoney): - return self.use_l10n - - def __str__(self): -- if self._decimal_places_display is not None or IS_DECIMAL_PLACES_DISPLAY_SET: -- kwargs = {"money": self, "decimal_places": self.decimal_places_display} -- if self.is_localized: -- locale = get_current_locale(for_babel=False) -- if locale: -- kwargs["locale"] = locale -- return moneyed.localization.format_money(**kwargs) - format_options = { - **MONEY_FORMAT, - **(self.format_options or {}), -@@ -175,22 +143,10 @@ class Money(DefaultMoney): - __rmul__ = __mul__ - - --def get_current_locale(for_babel=True): -+def get_current_locale(): - # get_language can return None starting from Django 1.8 - language = translation.get_language() or settings.LANGUAGE_CODE -- locale = translation.to_locale(language) -- -- if for_babel: -- return locale -- -- if locale.upper() in moneyed.localization._FORMATTER.formatting_definitions: -- return locale -- -- locale = f"{locale}_{locale}".upper() -- if locale in moneyed.localization._FORMATTER.formatting_definitions: -- return locale -- -- return "" -+ return translation.to_locale(language) - - - def maybe_convert(value, currency): ---- a/djmoney/settings.py -+++ b/djmoney/settings.py -@@ -1,15 +1,14 @@ - import operator --import warnings - from types import MappingProxyType - - from django.conf import settings - --from moneyed import CURRENCIES, DEFAULT_CURRENCY, DEFAULT_CURRENCY_CODE -+from moneyed import CURRENCIES, Currency - - - # The default currency, you can define this in your project's settings module - # This has to be a currency object imported from moneyed --DEFAULT_CURRENCY = getattr(settings, "DEFAULT_CURRENCY", DEFAULT_CURRENCY) -+DEFAULT_CURRENCY: Currency = getattr(settings, "DEFAULT_CURRENCY", None) - - - # The default currency choices, you can define this in your project's -@@ -21,18 +20,10 @@ if CURRENCY_CHOICES is None: - if PROJECT_CURRENCIES: - CURRENCY_CHOICES = [(code, CURRENCIES[code].name) for code in PROJECT_CURRENCIES] - else: -- CURRENCY_CHOICES = [(c.code, c.name) for i, c in CURRENCIES.items() if c.code != DEFAULT_CURRENCY_CODE] -+ CURRENCY_CHOICES = [(c.code, c.name) for i, c in CURRENCIES.items() if c != DEFAULT_CURRENCY] - - CURRENCY_CHOICES.sort(key=operator.itemgetter(1, 0)) - DECIMAL_PLACES = getattr(settings, "CURRENCY_DECIMAL_PLACES", 2) --_decimal_display_value = getattr(settings, "CURRENCY_DECIMAL_PLACES_DISPLAY", None) --if _decimal_display_value is not None: -- warnings.warn( -- "`CURRENCY_DECIMAL_PLACES_DISPLAY` is deprecated and will be removed in django-money 3.0.", -- DeprecationWarning, -- ) --DECIMAL_PLACES_DISPLAY = _decimal_display_value or {currency[0]: DECIMAL_PLACES for currency in CURRENCY_CHOICES} --IS_DECIMAL_PLACES_DISPLAY_SET = _decimal_display_value is not None - - OPEN_EXCHANGE_RATES_URL = getattr(settings, "OPEN_EXCHANGE_RATES_URL", "https://openexchangerates.org/api/latest.json") - OPEN_EXCHANGE_RATES_APP_ID = getattr(settings, "OPEN_EXCHANGE_RATES_APP_ID", None) ---- a/docs/changes.rst -+++ b/docs/changes.rst -@@ -4,6 +4,12 @@ Changelog - `Unreleased`_ - TBA - ------------------- - -+**Changed** -+- Update py-moneyed to 2.0. `#638`_ (`antonagestam`_, `flaeppe`_, `paoloxnet`_) -+- Remove the deprecated ``Money.decimal_places_display`` property and argument. `#638`_ (`antonagestam`_, `flaeppe`_, `paoloxnet`_) -+- Remove the deprecated ``CURRENCY_DECIMAL_PLACES_DISPLAY`` setting. `#638`_ (`antonagestam`_, `flaeppe`_, `paoloxnet`_) -+- Null constraint on an implicit ``CurrencyField`` is now declared from ``null=...`` argument to ``MoneyField``. `#638`_ (`antonagestam`_, `flaeppe`_, `paoloxnet`_) -+ - **Fixed** - - - Improve the internal check for whether a currency is provided `#657`_ (`davidszotten`_) -@@ -70,6 +76,13 @@ Changelog - - ``Money.decimal_places_display`` will be removed in django-money 3.0. - - ``CURRENCY_DECIMAL_PLACES_DISPLAY`` will be removed in django-money 3.0. - -+- Drop support for Django 1.11, 2.1 and 3.0. -+- Drop support for Python 3.5. -+- Add support for Django 3.2. -+- Update py-moneyed to 2.0. -+- Remove the deprecated ``Money.decimal_places_display`` property and argument. -+- Remove the deprecated ``CURRENCY_DECIMAL_PLACES_DISPLAY`` setting. -+ - `1.3.1`_ - 2021-02-04 - --------------------- - -@@ -783,6 +796,7 @@ wrapping with ``money_manager``. - .. _#657: https://github.com/django-money/django-money/issues/657 - .. _#648: https://github.com/django-money/django-money/issues/648 - .. _#646: https://github.com/django-money/django-money/issues/646 -+.. _#638: https://github.com/django-money/django-money/issues/638 - .. _#637: https://github.com/django-money/django-money/issues/637 - .. _#630: https://github.com/django-money/django-money/pull/630 - .. _#629: https://github.com/django-money/django-money/pull/629 -@@ -951,6 +965,7 @@ wrapping with ``money_manager``. - .. _mstarostik: https://github.com/mstarostik - .. _niklasb: https://github.com/niklasb - .. _nerdoc: https://github.com/nerdoc -+.. _paoloxnet: https://github.com/paoloxnet - .. _pjdelport: https://github.com/pjdelport - .. _plumdog: https://github.com/plumdog - .. _rach: https://github.com/rach ---- a/pytest.ini -+++ b/pytest.ini -@@ -2,6 +2,3 @@ - DJANGO_SETTINGS_MODULE=tests.settings - filterwarnings = - error::DeprecationWarning -- ignore:This module and all its contents is deprecated in favour of new moneyed.l10n.format_money\.:DeprecationWarning -- ignore:`Money\.decimal_places_display` is deprecated and will be removed in django-money 3\.0\.:DeprecationWarning -- ignore:`CURRENCY_DECIMAL_PLACES_DISPLAY` is deprecated and will be removed in django-money 3\.0\.:DeprecationWarning ---- a/setup.py -+++ b/setup.py -@@ -66,7 +66,7 @@ setup( - maintainer_email="greg@reinbach.com", - license="BSD", - packages=find_packages(include=["djmoney", "djmoney.*"]), -- install_requires=["setuptools", "Django>=2.2", "py-moneyed>=1.2,<2.0"], -+ install_requires=["setuptools", "Django>=2.2", "py-moneyed>=2.0,<3.0"], - python_requires=">=3.6", - platforms=["Any"], - keywords=["django", "py-money", "money"], ---- a/tests/conftest.py -+++ b/tests/conftest.py -@@ -1,5 +1,3 @@ --from unittest import mock -- - import pytest - - from djmoney.contrib.exchange.models import ExchangeBackend, Rate, get_default_backend_name -@@ -31,9 +29,3 @@ def concrete_instance(m2m_object): - - - pytest_plugins = "pytester" -- -- --@pytest.yield_fixture --def legacy_formatting(): -- with mock.patch("djmoney.money.IS_DECIMAL_PLACES_DISPLAY_SET", True): -- yield ---- a/tests/contrib/test_django_rest_framework.py -+++ b/tests/contrib/test_django_rest_framework.py -@@ -64,10 +64,9 @@ class TestMoneyField: - (NullMoneyFieldModel, "field", {"default_currency": "EUR", "allow_null": True}, None, None), - (NullMoneyFieldModel, "field", None, Money(10, "USD"), Money(10, "USD")), - (NullMoneyFieldModel, "field", {"default_currency": "EUR"}, Money(10, "USD"), Money(10, "USD")), -- (NullMoneyFieldModel, "field", {"default_currency": "EUR"}, 10, Money(10, "EUR")), -+ (ModelWithVanillaMoneyField, "money", {"default_currency": "EUR"}, 10, Money(10, "EUR")), - (ModelWithVanillaMoneyField, "money", None, Money(10, "USD"), Money(10, "USD")), - (ModelWithVanillaMoneyField, "money", {"default_currency": "EUR"}, Money(10, "USD"), Money(10, "USD")), -- (ModelWithVanillaMoneyField, "money", None, 10, Money(10, "XYZ")), - (ModelWithVanillaMoneyField, "money", {"default_currency": "EUR"}, 10, Money(10, "EUR")), - ), - ) ---- a/tests/settings.py -+++ b/tests/settings.py -@@ -1,8 +1,6 @@ - import warnings --from decimal import ROUND_HALF_EVEN - - import moneyed --from moneyed.localization import _FORMATTER, DEFAULT - - - DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}} -@@ -36,20 +34,6 @@ SECRET_KEY = "foobar" - USE_L10N = True - - --_FORMATTER.add_sign_definition("pl_PL", moneyed.PLN, suffix=" zł") --_FORMATTER.add_sign_definition(DEFAULT, moneyed.PLN, suffix=" zł") --_FORMATTER.add_formatting_definition( -- "pl_PL", -- group_size=3, -- group_separator=" ", -- decimal_point=",", -- positive_sign="", -- trailing_positive_sign="", -- negative_sign="-", -- trailing_negative_sign="", -- rounding_method=ROUND_HALF_EVEN, --) -- - moneyed.add_currency("USDT", "000", "Tether", None) - - OPEN_EXCHANGE_RATES_APP_ID = "test" ---- a/tests/test_admin.py -+++ b/tests/test_admin.py -@@ -14,26 +14,7 @@ INTEGER_FIELD = ModelWithVanillaMoneyFie - @pytest.mark.parametrize( - "value, expected", - ( -- (Money(10, "RUB"), "10.00 руб."), # Issue 232 -- (Money(1234), "1,234.00 XYZ"), # Issue 220 -- (Money(1000, "SAR"), "ر.س1,000.00"), # Issue 196 -- (Money(1000, "PLN"), "1,000.00 zł"), # Issue 102 -- (Money("3.33", "EUR"), "3.33 €"), # Issue 90 -- ), --) --def test_display_for_field_with_legacy_formatting(legacy_formatting, settings, value, expected): -- settings.USE_L10N = True -- # This locale has no definitions in py-moneyed, so it will work for localized money representation. -- settings.LANGUAGE_CODE = "cs" -- settings.DECIMAL_PLACES_DISPLAY = {} -- assert admin_utils.display_for_field(value, MONEY_FIELD, "") == expected -- -- --@pytest.mark.parametrize( -- "value, expected", -- ( - (Money(10, "RUB"), "10,00\xa0RUB"), # Issue 232 -- (Money(1234), "1\xa0234,00\xa0XYZ"), # Issue 220 - (Money(1000, "SAR"), "1\xa0000,00\xa0SAR"), # Issue 196 - (Money(1000, "PLN"), "1\xa0000,00\xa0PLN"), # Issue 102 - (Money("3.33", "EUR"), "3,33\xa0€"), # Issue 90 ---- a/tests/test_models.py -+++ b/tests/test_models.py -@@ -60,8 +60,8 @@ class TestVanillaMoneyField: - @pytest.mark.parametrize( - "model_class, kwargs, expected", - ( -- (ModelWithVanillaMoneyField, {"money": Money("100.0")}, Money("100.0")), -- (ModelWithVanillaMoneyField, {"money": OldMoney("100.0")}, Money("100.0")), -+ (ModelWithVanillaMoneyField, {"money": Money("100.0", "USD")}, Money("100.0", "USD")), -+ (ModelWithVanillaMoneyField, {"money": OldMoney("100.0", "USD")}, Money("100.0", "USD")), - (BaseModel, {}, Money(0, "USD")), - (BaseModel, {"money": "111.2"}, Money("111.2", "USD")), - (BaseModel, {"money": Money("123", "PLN")}, Money("123", "PLN")), -@@ -116,7 +116,6 @@ class TestVanillaMoneyField: - @pytest.mark.parametrize( - "model_class, other_value", - ( -- (ModelWithVanillaMoneyField, Money("100.0")), - (BaseModel, Money(0, "USD")), - (ModelWithDefaultAsMoney, Money("0.01", "RUB")), - (ModelWithDefaultAsFloat, OldMoney("12.05", "PLN")), -@@ -149,27 +148,35 @@ class TestVanillaMoneyField: - BaseModel.objects.create(money=value) - - @pytest.mark.parametrize("money_class", (Money, OldMoney)) -- @pytest.mark.parametrize("field_name", ("money", "second_money")) -- def test_save_new_value(self, field_name, money_class): -- ModelWithVanillaMoneyField.objects.create(**{field_name: money_class("100.0")}) -+ def test_save_new_value_on_field_without_default(self, money_class): -+ ModelWithVanillaMoneyField.objects.create(money=money_class("100.0", "DKK")) - - # Try setting the value directly - retrieved = ModelWithVanillaMoneyField.objects.get() -- setattr(retrieved, field_name, Money(1, "DKK")) -+ retrieved.money = Money(1, "DKK") - retrieved.save() - retrieved = ModelWithVanillaMoneyField.objects.get() -+ assert retrieved.money == Money(1, "DKK") - -- assert getattr(retrieved, field_name) == Money(1, "DKK") -+ def test_save_new_value_on_field_with_default(self): -+ ModelWithDefaultAsMoney.objects.create() -+ -+ # Try setting the value directly -+ retrieved = ModelWithDefaultAsMoney.objects.get() -+ retrieved.money = Money(1, "DKK") -+ retrieved.save() -+ retrieved = ModelWithDefaultAsMoney.objects.get() -+ assert retrieved.money == Money(1, "DKK") - - def test_rounding(self): -- money = Money("100.0623456781123219") -+ money = Money("100.0623456781123219", "USD") - - instance = ModelWithVanillaMoneyField.objects.create(money=money) - # TODO. Should instance.money be rounded too? - - retrieved = ModelWithVanillaMoneyField.objects.get(pk=instance.pk) - -- assert retrieved.money == Money("100.06") -+ assert retrieved.money == Money("100.06", "USD") - - @pytest.fixture(params=[Money, OldMoney]) - def objects_setup(self, request): -@@ -238,7 +245,7 @@ class TestVanillaMoneyField: - assert ModelWithTwoMoneyFields.objects.filter(**kwargs).count() == expected - - def test_exact_match(self): -- money = Money("100.0") -+ money = Money("100.0", "USD") - - instance = ModelWithVanillaMoneyField.objects.create(money=money) - retrieved = ModelWithVanillaMoneyField.objects.get(money=money) -@@ -251,9 +258,9 @@ class TestVanillaMoneyField: - ModelIssue300.objects.filter(money__created__gt=date) - - def test_range_search(self): -- money = Money("3") -+ money = Money("3", "EUR") - -- instance = ModelWithVanillaMoneyField.objects.create(money=Money("100.0")) -+ instance = ModelWithVanillaMoneyField.objects.create(money=Money("100.0", "EUR")) - retrieved = ModelWithVanillaMoneyField.objects.get(money__gt=money) - - assert instance.pk == retrieved.pk -@@ -302,12 +309,23 @@ class TestVanillaMoneyField: - instance = NullMoneyFieldModel.objects.create() - assert instance.field is None - -+ def test_raises_type_error_setting_currency_to_none_on_nullable_currency_field_while_having_amount(self): -+ with pytest.raises(ValueError, match=r"Missing currency value"): -+ NullMoneyFieldModel(field=10, field_currency=None) -+ -+ def test_currency_field_null_switch_not_triggered_from_default_currency(self): -+ # We want a sane default behaviour and simply declaring a `MoneyField(...)` -+ # without any default value args should create non nullable amount and currency -+ # fields -+ assert not ModelWithVanillaMoneyField._meta.get_field("money").null -+ assert not ModelWithVanillaMoneyField._meta.get_field("money_currency").null -+ - - class TestGetOrCreate: - @pytest.mark.parametrize( - "model, field_name, kwargs, currency", - ( -- (ModelWithVanillaMoneyField, "money", {"money_currency": "PLN"}, "PLN"), -+ (ModelWithDefaultAsInt, "money", {"money_currency": "PLN"}, "PLN"), - (ModelWithVanillaMoneyField, "money", {"money": Money(0, "EUR")}, "EUR"), - (ModelWithVanillaMoneyField, "money", {"money": OldMoney(0, "EUR")}, "EUR"), - (ModelWithSharedCurrency, "first", {"first": 10, "second": 15, "currency": "CZK"}, "CZK"), -@@ -381,9 +399,9 @@ class TestNullableCurrency: - assert not ModelWithNullableCurrency.objects.exists() - - def test_fails_with_nullable_but_no_default(self): -- with pytest.raises(IntegrityError) as exc: -+ match = r"NOT NULL constraint failed: testapp_modelwithtwomoneyfields.amount1" -+ with pytest.raises(IntegrityError, match=match): - ModelWithTwoMoneyFields.objects.create() -- assert str(exc.value) == "NOT NULL constraint failed: testapp_modelwithtwomoneyfields.amount1" - - def test_query_not_null(self): - money = Money(100, "EUR") -@@ -527,9 +545,11 @@ class TestExpressions: - assert ModelWithVanillaMoneyField.objects.get(integer=1).money == Money(0, "USD") - - def test_create_func(self): -- instance = ModelWithVanillaMoneyField.objects.create(money=Func(Value(-10), function="ABS")) -+ instance = ModelWithVanillaMoneyField.objects.create( -+ money=Func(Value(-10), function="ABS"), money_currency="USD" -+ ) - instance.refresh_from_db() -- assert instance.money.amount == 10 -+ assert instance.money == Money(10, "USD") - - @pytest.mark.parametrize( - "value, expected", ((None, None), (10, Money(10, "USD")), (Money(10, "EUR"), Money(10, "EUR"))) -@@ -541,7 +561,7 @@ class TestExpressions: - - def test_value_create_invalid(self): - with pytest.raises(ValidationError): -- ModelWithVanillaMoneyField.objects.create(money=Value("string")) -+ ModelWithVanillaMoneyField.objects.create(money=Value("string"), money_currency="DKK") - - def test_expressions_for_non_money_fields(self): - instance = ModelWithVanillaMoneyField.objects.create(money=Money(1, "USD"), integer=0) -@@ -560,7 +580,7 @@ def test_find_models_related_to_money_mo - def test_allow_expression_nodes_without_money(): - """Allow querying on expression nodes that are not Money""" - desc = "hundred" -- ModelWithNonMoneyField.objects.create(money=Money(100.0), desc=desc) -+ ModelWithNonMoneyField.objects.create(money=Money(100.0, "USD"), desc=desc) - instance = ModelWithNonMoneyField.objects.filter(desc=F("desc")).get() - assert instance.desc == desc - -@@ -793,7 +813,7 @@ def test_mixer_blend(): - except AttributeError: - pass # mixer doesn't work with pypy - else: -- instance = mixer.blend(ModelWithTwoMoneyFields) -+ instance = mixer.blend(ModelWithTwoMoneyFields, amount1_currency="EUR", amount2_currency="USD") - assert isinstance(instance.amount1, Money) - assert isinstance(instance.amount2, Money) - ---- a/tests/test_money.py -+++ b/tests/test_money.py -@@ -10,23 +10,19 @@ def test_repr(): - - - def test_legacy_repr(): -- assert repr(Money("10.5", "USD", decimal_places_display=2)) == "Money('10.5', 'USD')" -+ assert repr(Money("10.5", "USD")) == "Money('10.5', 'USD')" - - - def test_html_safe(): - assert Money("10.5", "EUR").__html__() == "€10.50" - - --def test_legacy_html_safe(): -- assert Money("10.5", "EUR", decimal_places_display=2).__html__() == "10.50\xa0€" -- -- - def test_html_unsafe(): - class UnsafeMoney(Money): - def __str__(self): - return "