From 24675f8da0747ad3bfd4da406373054931f1f8ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= <thrnciar@redhat.com>
Date: Mon, 27 Apr 2026 14:15:54 +0200
Subject: [PATCH] Fix re.Scanner capturing group for Python 3.15 compatibility

Python 3.15 forbids capturing groups in re.Scanner lexicon patterns.
Convert the capturing group to a non-capturing group in num_re.

Assisted-by: Cursor
---
 patsy/constraint.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/patsy/constraint.py b/patsy/constraint.py
index 6c044144..17ee1dee 100644
--- a/patsy/constraint.py
+++ b/patsy/constraint.py
@@ -187,7 +187,7 @@ def _tokenize_constraint(string, variable_names):
     lparen_re = r"\("
     rparen_re = r"\)"
     op_re = "|".join([re.escape(op.token_type) for op in _ops])
-    num_re = r"[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?"
+    num_re = r"[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?"
     whitespace_re = r"\s+"
 
     # Prefer long matches:
