From 10263d6de3ef2b6b7848e448169014c2ede32706 Mon Sep 17 00:00:00 2001 From: Gertjan van Zwieten Date: Mon, 23 Mar 2026 10:23:35 +0100 Subject: [PATCH 1/2] Avoid using equals comparison in annotation types --- ags/_mapping.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ags/_mapping.py b/ags/_mapping.py index 7cd9201..c094b47 100644 --- a/ags/_mapping.py +++ b/ags/_mapping.py @@ -150,12 +150,12 @@ def mapping_for(T) -> Mapping: with context(f".{param.name}"): if param.kind not in (param.POSITIONAL_OR_KEYWORD, param.KEYWORD_ONLY): raise TypeError("positional-only arguments are not supported") - if param.annotation != param.empty: + if param.annotation is not param.empty: mapping = mapping_for(param.annotation) - if param.default != param.empty: + if param.default is not param.empty: with context("(default)"): mapping.lower(param.default, inject_none) - elif param.default != param.empty: + elif param.default is not param.empty: mapping = mapping_for(type(param.default)) else: raise TypeError(f"cannot establish type for parameter {param.name}") From 3e2f1e83b4269d93166e3defb9e84a0a9ae6ed0c Mon Sep 17 00:00:00 2001 From: Gertjan van Zwieten Date: Wed, 25 Mar 2026 15:53:13 +0100 Subject: [PATCH 2/2] Replace ErrorContext by notes --- ags/_mapping.py | 32 +++++++++++--------------------- test.py | 34 +++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/ags/_mapping.py b/ags/_mapping.py index c094b47..c4e226d 100644 --- a/ags/_mapping.py +++ b/ags/_mapping.py @@ -28,27 +28,17 @@ def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): - if exc_value and len(exc_value.args) == 1: - (arg,) = exc_value.args - if not isinstance(arg, ErrorContext): - arg = ErrorContext(arg) - exc_value.args = (arg,) - arg.prepend(self.context) - - -class ErrorContext: - def __init__(self, message): - self.message = message - self.context = "" - - def prepend(self, context): - self.context = context + self.context - - def __str__(self): - return f"in {self.context}: {self.message}" - - def __repr__(self): - return f"in {self.context}: {self.message!r}" + if not exc_value: + return + if not hasattr(exc_value, '__notes__'): + notes = [] + exc_value.__notes__ = notes + else: + notes = exc_value.__notes__ + note = "In: " + self.context + if notes and notes[-1].startswith("In: "): + note += notes.pop()[4:] + notes.append(note) def mismatch(expect, got): diff --git a/test.py b/test.py index d14d392..74d2f88 100644 --- a/test.py +++ b/test.py @@ -7,6 +7,7 @@ from datetime import date, time, datetime from doctest import DocFileSuite import sys +import traceback from ags import _mapping @@ -86,10 +87,15 @@ class A: i: int = 10 s: str = 20 - with self.assertRaisesRegex( - ValueError, r"in .s\(default\): expects str, got int" - ): + with self.assertRaises(ValueError) as cm: _mapping.mapping_for(A) + s = traceback.format_exception(cm.exception) + self.assertEqual(s, [ + 'ValueError: expects str, got int\n', + 'In: .s(default)\n', + ] if sys.version_info >= (3, 11) else [ + 'ValueError: expects str, got int\n', + ]) def test_boundargs(self): def f(i: int, s: str): @@ -104,10 +110,15 @@ def f(i: int = 10, s: str = 20): pass sig = signature(f) - with self.assertRaisesRegex( - ValueError, r"in .s\(default\): expects str, got int" - ): + with self.assertRaises(ValueError) as cm: _mapping.mapping_for(sig) + s = traceback.format_exception(cm.exception) + self.assertEqual(s, [ + 'ValueError: expects str, got int\n', + 'In: .s(default)\n', + ] if sys.version_info >= (3, 11) else [ + 'ValueError: expects str, got int\n', + ]) def test_union(self): for modern in False, True: @@ -191,10 +202,15 @@ def __eq__(self, other): def test_exception(self): T = dict[str, list[int]] m = _mapping.mapping_for(T) - with self.assertRaisesRegex( - AssertionError, r"in \[b\]\[1\]: is not " - ): + with self.assertRaises(AssertionError) as cm: m.unlower({"a": [10, 20], "b": [30, "40", 50]}, self.mysurject) + s = traceback.format_exception(cm.exception) + self.assertEqual(s, [ + "AssertionError: is not \n", + 'In: [b][1]\n', + ] if sys.version_info >= (3, 11) else [ + "AssertionError: is not \n", + ]) class Demo: