From e137c888a116b517d9696d2ce979e1bc52af4431 Mon Sep 17 00:00:00 2001 From: Sander van Grieken Date: Wed, 26 Nov 2025 16:33:44 +0100 Subject: [PATCH] qeconfig: fix btc amount regex, add msat regex property, add regex tests --- electrum/gui/qml/qeconfig.py | 14 +++++-- tests/test_qml_qeconfig.py | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/electrum/gui/qml/qeconfig.py b/electrum/gui/qml/qeconfig.py index 979565e5e..349f87365 100644 --- a/electrum/gui/qml/qeconfig.py +++ b/electrum/gui/qml/qeconfig.py @@ -94,14 +94,22 @@ class QEConfig(AuthMixin, QObject): @pyqtProperty('QRegularExpression', notify=baseUnitChanged) def btcAmountRegex(self): + return self._btcAmountRegex() + + @pyqtProperty('QRegularExpression', notify=baseUnitChanged) + def btcAmountRegexMsat(self): + return self._btcAmountRegex(3) + + def _btcAmountRegex(self, extra_precision: int = 0): decimal_point = base_unit_name_to_decimal_point(self.config.get_base_unit()) max_digits_before_dp = ( len(str(TOTAL_COIN_SUPPLY_LIMIT_IN_BTC)) + (base_unit_name_to_decimal_point("BTC") - decimal_point)) - exp = '[0-9]{0,%d}' % max_digits_before_dp + exp = '^[0-9]{0,%d}' % max_digits_before_dp + decimal_point += extra_precision if decimal_point > 0: - exp += '\\.' - exp += '[0-9]{0,%d}' % decimal_point + exp += '(\\.[0-9]{0,%d})?' % decimal_point + exp += '$' return QRegularExpression(exp) thousandsSeparatorChanged = pyqtSignal() diff --git a/tests/test_qml_qeconfig.py b/tests/test_qml_qeconfig.py index d76c54338..f58956b73 100644 --- a/tests/test_qml_qeconfig.py +++ b/tests/test_qml_qeconfig.py @@ -1,7 +1,11 @@ +from typing import TYPE_CHECKING from electrum import SimpleConfig from electrum.gui.qml.qeconfig import QEConfig from tests.qt_util import QETestCase, qt_test +if TYPE_CHECKING: + from PyQt6.QtCore import QRegularExpression + class TestConfig(QETestCase): @classmethod @@ -64,3 +68,71 @@ class TestConfig(QETestCase): self.assertFalse(qa.isEmpty) self.assertEqual(qa.satsInt, 1) self.assertEqual(qa.msatsInt, 1001) + + @qt_test + def test_btc_amount_regexes(self): + self.q.config.BTC_AMOUNTS_DECIMAL_POINT = 8 + + a: 'QRegularExpression' = self.q.btcAmountRegex + b: 'QRegularExpression' = self.q.btcAmountRegexMsat + + self.assertTrue(a.isValid()) + self.assertTrue(b.isValid()) + + self.assertTrue(a.match('1').hasMatch()) + self.assertTrue(a.match('1.').hasMatch()) + self.assertTrue(a.match('1.00000000').hasMatch()) + self.assertFalse(a.match('1.000000000').hasMatch()) + self.assertTrue(a.match('21000000').hasMatch()) + self.assertFalse(a.match('121000000').hasMatch()) + + self.assertTrue(b.match('1').hasMatch()) + self.assertTrue(b.match('1.').hasMatch()) + self.assertTrue(b.match('1.00000000').hasMatch()) + self.assertTrue(b.match('1.00000000000').hasMatch()) + self.assertFalse(b.match('1.000000000000').hasMatch()) + self.assertTrue(b.match('21000000').hasMatch()) + self.assertFalse(b.match('121000000').hasMatch()) + + self.q.config.BTC_AMOUNTS_DECIMAL_POINT = 5 + + a: 'QRegularExpression' = self.q.btcAmountRegex + b: 'QRegularExpression' = self.q.btcAmountRegexMsat + + self.assertTrue(a.isValid()) + self.assertTrue(b.isValid()) + + self.assertTrue(a.match('1').hasMatch()) + self.assertTrue(a.match('1.').hasMatch()) + self.assertTrue(a.match('1.00000').hasMatch()) + self.assertFalse(a.match('1.000000').hasMatch()) + self.assertTrue(a.match('21000000000').hasMatch()) + self.assertFalse(a.match('121000000000').hasMatch()) + + self.assertTrue(b.match('1').hasMatch()) + self.assertTrue(b.match('1.').hasMatch()) + self.assertTrue(b.match('1.0000000').hasMatch()) + self.assertTrue(b.match('1.00000000').hasMatch()) + self.assertFalse(b.match('1.000000000000').hasMatch()) + self.assertTrue(b.match('21000000000').hasMatch()) + self.assertFalse(b.match('121000000000').hasMatch()) + + self.q.config.BTC_AMOUNTS_DECIMAL_POINT = 0 + + a: 'QRegularExpression' = self.q.btcAmountRegex + b: 'QRegularExpression' = self.q.btcAmountRegexMsat + + self.assertTrue(a.isValid()) + self.assertTrue(b.isValid()) + + self.assertTrue(a.match('1').hasMatch()) + self.assertFalse(a.match('1.').hasMatch()) + self.assertTrue(a.match('2100000000000000').hasMatch()) + self.assertFalse(a.match('12100000000000000').hasMatch()) + + self.assertTrue(b.match('1').hasMatch()) + self.assertTrue(b.match('1.').hasMatch()) + self.assertTrue(b.match('1.000').hasMatch()) + self.assertFalse(b.match('1.0000').hasMatch()) + self.assertTrue(b.match('2100000000000000').hasMatch()) + self.assertFalse(b.match('12100000000000000').hasMatch())