From e241984058baf775268f93f7b1ef69b4074e0c07 Mon Sep 17 00:00:00 2001
From: jayvdb <>
Date: May 12 2022 21:35:56 +0000
Subject: Update python-django-money to version 2.1.1 / rev 3 via SR 976603
https://build.opensuse.org/request/show/976603
by user jayvdb + dimstar_suse
---
diff --git a/.files b/.files
index e1bde5f..ea16f64 100644
Binary files a/.files and b/.files differ
diff --git a/.rev b/.rev
index 1c07619..a4c0ec4 100644
--- a/.rev
+++ b/.rev
@@ -16,4 +16,12 @@
893761
+
+ e8fe1696d49ceed48b2b47109a640cd9
+ 2.1.1
+
+ dimstar_suse
+
+ 976603
+
diff --git a/django-money-1.3.1.tar.gz b/django-money-1.3.1.tar.gz
deleted file mode 120000
index 7d1beb8..0000000
--- a/django-money-1.3.1.tar.gz
+++ /dev/null
@@ -1 +0,0 @@
-/ipfs/bafkreibmo3qo5rsnp37lgobznomw44sy3mxg556ywfpht77c6ayrkoy26i
\ No newline at end of file
diff --git a/django-money-2.1.1.tar.gz b/django-money-2.1.1.tar.gz
new file mode 120000
index 0000000..655087b
--- /dev/null
+++ b/django-money-2.1.1.tar.gz
@@ -0,0 +1 @@
+/ipfs/bafkreihjwox3wqsk2qzbc63rznksvo4wyvj4cn7obuth2sglsx35v3h4ve
\ No newline at end of file
diff --git a/merged_pr_657.patch b/merged_pr_657.patch
new file mode 100644
index 0000000..726a0a2
--- /dev/null
+++ b/merged_pr_657.patch
@@ -0,0 +1,168 @@
+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
+
+---
+ tests/test_models.py | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/tests/test_models.py b/tests/test_models.py
+index fb5b55cc..0ae6ba4e 100644
+--- a/tests/test_models.py
++++ b/tests/test_models.py
+@@ -5,6 +5,7 @@
+ """
+ import datetime
+ from copy import copy
++from decimal import Decimal
+
+ from django import VERSION
+ from django.core.exceptions import ValidationError
+@@ -373,6 +374,12 @@ def test_fails_with_null_currency(self):
+ 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()
+
+From 2ccaadc4e1d3a7ca06ba96ee683fb9057daa8d94 Mon Sep 17 00:00:00 2001
+From: David Szotten
+Date: Wed, 19 Jan 2022 17:54:30 +0000
+Subject: [PATCH 2/5] suggested better fix for
+ https://github.com/django-money/django-money/pull/427/
+
+TODO: is the currency field guaranteed to appear before the amount (and main)
+field? yes because of the creation_counters?
+---
+ djmoney/models/fields.py | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/djmoney/models/fields.py b/djmoney/models/fields.py
+index 8eb710ba..3bfd7dda 100644
+--- a/djmoney/models/fields.py
++++ b/djmoney/models/fields.py
+@@ -104,7 +104,12 @@ def __get__(self, obj, type=None):
+ 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):
+
+From 952ac5a75b43a632febe733d0aa1a5a716b7735c Mon Sep 17 00:00:00 2001
+From: David Szotten
+Date: Wed, 19 Jan 2022 22:09:06 +0000
+Subject: [PATCH 3/5] fix django error message change
+
+fix for
+https://github.com/django/django/commit/08d8bccbf1b0764a0de68325569ee47da256e206
+---
+ tests/test_models.py | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/tests/test_models.py b/tests/test_models.py
+index 0ae6ba4e..53def7cb 100644
+--- a/tests/test_models.py
++++ b/tests/test_models.py
+@@ -719,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"
+
+From 620af5355a22ca1da0cb43c8e5787c3e8b76f995 Mon Sep 17 00:00:00 2001
+From: David Szotten
+Date: Thu, 20 Jan 2022 08:59:37 +0000
+Subject: [PATCH 4/5] better match the signature of input()
+
+for compat with django 0ab58c120939093fea90822f376e1866fc714d1f
+---
+ tests/migrations/helpers.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/migrations/helpers.py b/tests/migrations/helpers.py
+index f38067fe..cbf2c7fe 100644
+--- 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)
+
+From faf4da5f96193fc1a5e0b2b838f2a13189975abf Mon Sep 17 00:00:00 2001
+From: David Szotten
+Date: Thu, 27 Jan 2022 17:47:01 +0000
+Subject: [PATCH 5/5] changelog
+
+---
+ docs/changes.rst | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/docs/changes.rst b/docs/changes.rst
+index 1968af75..5eab8fd1 100644
+--- 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
diff --git a/pr_638.patch b/pr_638.patch
new file mode 100644
index 0000000..82a3593
--- /dev/null
+++ b/pr_638.patch
@@ -0,0 +1,779 @@
+diff --git a/djmoney/__init__.py b/djmoney/__init__.py
+index d483c54..3358017 100644
+--- a/djmoney/__init__.py
++++ b/djmoney/__init__.py
+@@ -1,2 +1,2 @@
+-__version__ = "2.1.1"
++__version__ = "3.0.0"
+ default_app_config = "djmoney.apps.MoneyConfig"
+diff --git a/djmoney/models/fields.py b/djmoney/models/fields.py
+index 3bfd7dd..582eec2 100644
+--- a/djmoney/models/fields.py
++++ b/djmoney/models/fields.py
+@@ -104,14 +104,6 @@ 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)
+- 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):
+ if isinstance(value, Value):
+ value = self.prepare_value(obj, value.value)
+@@ -120,6 +112,14 @@ class MoneyFieldProxy:
+ prepare_expression(value)
+ else:
+ value = self.prepare_value(obj, value)
++ 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")
+ obj.__dict__[self.field.name] = value
+
+ def prepare_value(self, obj, value):
+@@ -178,7 +178,7 @@ class MoneyField(models.DecimalField):
+ currency_max_length=CURRENCY_CODE_MAX_LENGTH,
+ currency_field_name=None,
+ money_descriptor_class=MoneyFieldProxy,
+- **kwargs
++ **kwargs,
+ ):
+ nullable = kwargs.get("null", False)
+ default = self.setup_default(default, default_currency, nullable)
+@@ -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)
+diff --git a/djmoney/money.py b/djmoney/money.py
+index f11ca38..95a154d 100644
+--- 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_wrapping, conditional_escape
+ 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.
+
+@@ -111,20 +86,7 @@ class Money(DefaultMoney):
+ # https://github.com/py-moneyed/py-moneyed/blob/c518745dd9d7902781409daec1a05699799474dd/moneyed/classes.py#L217-L218
+ raise TypeError("Cannot divide non-Money by a Money instance.")
+
+- @property
+- def is_localized(self):
+- if self.use_l10n is None:
+- return settings.USE_L10N
+- 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 +137,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):
+diff --git a/djmoney/settings.py b/djmoney/settings.py
+index 3509ed2..4aa7e85 100644
+--- 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)
+diff --git a/docs/changes.rst b/docs/changes.rst
+index 5eab8fd..4b4ee01 100644
+--- a/docs/changes.rst
++++ b/docs/changes.rst
+@@ -4,11 +4,19 @@ Changelog
+ `Unreleased`_ - TBA
+ -------------------
+
++**Changed**
++
++- Update py-moneyed to 2.0.
++
+ **Fixed**
+
+ - Improve the internal check for whether a currency is provided `#657`_ (`davidszotten`_)
+ - Fix test suite for django main branch `#657`_ (`davidszotten`_)
+
++**Removed**
++- Remove the deprecated ``Money.decimal_places_display`` property and argument.
++- Remove the deprecated ``CURRENCY_DECIMAL_PLACES_DISPLAY`` setting.
++
+ `2.1.1`_ - 2022-01-02
+ ---------------------
+
+diff --git a/pytest.ini b/pytest.ini
+index 46fd704..dccdd07 100644
+--- 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
+diff --git a/setup.py b/setup.py
+index c6c1fb6..623b713 100644
+--- 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"],
+ python_requires=">=3.6",
+ platforms=["Any"],
+ keywords=["django", "py-money", "money"],
+diff --git a/tests/conftest.py b/tests/conftest.py
+index 666e969..7f8baee 100644
+--- 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
+diff --git a/tests/contrib/test_django_rest_framework.py b/tests/contrib/test_django_rest_framework.py
+index aef52bd..e373910 100644
+--- a/tests/contrib/test_django_rest_framework.py
++++ b/tests/contrib/test_django_rest_framework.py
+@@ -67,7 +67,7 @@ class TestMoneyField:
+ (NullMoneyFieldModel, "field", {"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", None, 10, Money(10, "XYZ")), # TODO
+ (ModelWithVanillaMoneyField, "money", {"default_currency": "EUR"}, 10, Money(10, "EUR")),
+ ),
+ )
+diff --git a/tests/settings.py b/tests/settings.py
+index de5ce53..eb6a7db 100644
+--- 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"
+diff --git a/tests/test_admin.py b/tests/test_admin.py
+index 068700b..5b952cb 100644
+--- a/tests/test_admin.py
++++ b/tests/test_admin.py
+@@ -11,29 +11,11 @@ MONEY_FIELD = ModelWithVanillaMoneyField._meta.get_field("money")
+ INTEGER_FIELD = ModelWithVanillaMoneyField._meta.get_field("integer")
+
+
+-@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(1234, "USD"), "1\xa0234,00\xa0US$"), # 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
+diff --git a/tests/test_models.py b/tests/test_models.py
+index 53def7c..c1ef0db 100644
+--- a/tests/test_models.py
++++ b/tests/test_models.py
+@@ -39,6 +39,8 @@ from .testapp.models import (
+ ModelWithDefaultAsOldMoney,
+ ModelWithDefaultAsString,
+ ModelWithDefaultAsStringWithCurrency,
++ ModelWithDefaultCurrencyOnly,
++ ModelWithDefaultValueAndCurrency,
+ ModelWithNonMoneyField,
+ ModelWithNullableCurrency,
+ ModelWithSharedCurrency,
+@@ -60,8 +62,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 +118,7 @@ class TestVanillaMoneyField:
+ @pytest.mark.parametrize(
+ "model_class, other_value",
+ (
+- (ModelWithVanillaMoneyField, Money("100.0")),
++ (ModelWithDefaultValueAndCurrency, Money("100.0", "USD")),
+ (BaseModel, Money(0, "USD")),
+ (ModelWithDefaultAsMoney, Money("0.01", "RUB")),
+ (ModelWithDefaultAsFloat, OldMoney("12.05", "PLN")),
+@@ -151,7 +153,11 @@ class TestVanillaMoneyField:
+ @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")})
++ kwargs = {
++ "money": money_class("100.0", "USD"),
++ }
++ kwargs[field_name] = money_class("100.0", "USD")
++ ModelWithVanillaMoneyField.objects.create(**kwargs)
+
+ # Try setting the value directly
+ retrieved = ModelWithVanillaMoneyField.objects.get()
+@@ -162,14 +168,14 @@ class TestVanillaMoneyField:
+ assert getattr(retrieved, field_name) == Money(1, "DKK")
+
+ def test_rounding(self):
+- money = Money("100.0623456781123219")
++ money = Money("100.0623456781123219", "EUR")
+
+ 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", "EUR")
+
+ @pytest.fixture(params=[Money, OldMoney])
+ def objects_setup(self, request):
+@@ -238,7 +244,7 @@ class TestVanillaMoneyField:
+ assert ModelWithTwoMoneyFields.objects.filter(**kwargs).count() == expected
+
+ def test_exact_match(self):
+- money = Money("100.0")
++ money = Money("100.0", "EUR")
+
+ instance = ModelWithVanillaMoneyField.objects.create(money=money)
+ retrieved = ModelWithVanillaMoneyField.objects.get(money=money)
+@@ -251,9 +257,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
+@@ -307,9 +313,9 @@ class TestGetOrCreate:
+ @pytest.mark.parametrize(
+ "model, field_name, kwargs, currency",
+ (
+- (ModelWithVanillaMoneyField, "money", {"money_currency": "PLN"}, "PLN"),
+- (ModelWithVanillaMoneyField, "money", {"money": Money(0, "EUR")}, "EUR"),
+- (ModelWithVanillaMoneyField, "money", {"money": OldMoney(0, "EUR")}, "EUR"),
++ (ModelWithDefaultValueAndCurrency, "money", {"money_currency": "PLN"}, "PLN"),
++ (ModelWithDefaultValueAndCurrency, "money", {"money": Money(0, "EUR")}, "EUR"),
++ (ModelWithDefaultValueAndCurrency, "money", {"money": OldMoney(0, "EUR")}, "EUR"),
+ (ModelWithSharedCurrency, "first", {"first": 10, "second": 15, "currency": "CZK"}, "CZK"),
+ ),
+ )
+@@ -382,8 +388,8 @@ class TestNullableCurrency:
+
+ def test_fails_with_nullable_but_no_default(self):
+ with pytest.raises(IntegrityError) as exc:
+- ModelWithTwoMoneyFields.objects.create()
+- assert str(exc.value) == "NOT NULL constraint failed: testapp_modelwithtwomoneyfields.amount1"
++ ModelWithDefaultCurrencyOnly.objects.create()
++ assert str(exc.value) == "NOT NULL constraint failed: testapp_modelwithdefaultcurrencyonly.money"
+
+ def test_query_not_null(self):
+ money = Money(100, "EUR")
+@@ -527,7 +533,7 @@ 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 = ModelWithDefaultValueAndCurrency.objects.create(money=Func(Value(-10), function="ABS"))
+ instance.refresh_from_db()
+ assert instance.money.amount == 10
+
+@@ -560,7 +566,7 @@ def test_find_models_related_to_money_models():
+ 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
+
+@@ -787,17 +793,6 @@ def test_distinct_through_wrapper():
+ assert queryset.count() == 3
+
+
+-def test_mixer_blend():
+- try:
+- from mixer.backend.django import mixer
+- except AttributeError:
+- pass # mixer doesn't work with pypy
+- else:
+- instance = mixer.blend(ModelWithTwoMoneyFields)
+- assert isinstance(instance.amount1, Money)
+- assert isinstance(instance.amount2, Money)
+-
+-
+ @pytest.mark.parametrize(
+ ("attribute", "build_kwargs", "expected"),
+ [
+@@ -827,3 +822,13 @@ def test_deconstruct_includes(attribute, build_kwargs, expected):
+ new = MoneyField(*args, **kwargs)
+ assert getattr(new, attribute) == getattr(instance, attribute)
+ assert getattr(new, attribute) == expected
++
++
++def test_mixer_blend():
++ try:
++ from mixer.backend.django import mixer
++ except AttributeError:
++ pass # mixer doesn't work with pypy
++ else:
++ instance = mixer.blend(ModelWithDefaultCurrencyOnly)
++ assert isinstance(instance.money, Money)
+diff --git a/tests/test_money.py b/tests/test_money.py
+index 9bca69c..789ac6d 100644
+--- a/tests/test_money.py
++++ b/tests/test_money.py
+@@ -9,24 +9,16 @@ def test_repr():
+ assert repr(Money("10.5", "USD")) == "Money('10.5', 'USD')"
+
+
+-def test_legacy_repr():
+- assert repr(Money("10.5", "USD", decimal_places_display=2)) == "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 "