gh-102947: Improve traceback when calling fields() on a non-dataclass (GH-102948)

(cherry picked from commit baf4eb083c)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Miss Islington (bot) 2023-03-23 07:45:59 -07:00 committed by GitHub
parent f79cfb6625
commit 6ffeeb2199
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 15 additions and 1 deletions

View file

@ -1234,7 +1234,7 @@ def fields(class_or_instance):
try: try:
fields = getattr(class_or_instance, _FIELDS) fields = getattr(class_or_instance, _FIELDS)
except AttributeError: except AttributeError:
raise TypeError('must be called with a dataclass type or instance') raise TypeError('must be called with a dataclass type or instance') from None
# Exclude pseudo-fields. Note that fields is sorted by insertion # Exclude pseudo-fields. Note that fields is sorted by insertion
# order, so the order of the tuple is as the fields were defined. # order, so the order of the tuple is as the fields were defined.

View file

@ -5,11 +5,13 @@
from dataclasses import * from dataclasses import *
import abc import abc
import io
import pickle import pickle
import inspect import inspect
import builtins import builtins
import types import types
import weakref import weakref
import traceback
import unittest import unittest
from unittest.mock import Mock from unittest.mock import Mock
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol
@ -1500,6 +1502,16 @@ class TestCase(unittest.TestCase):
with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): with self.assertRaisesRegex(TypeError, 'dataclass type or instance'):
fields(C()) fields(C())
def test_clean_traceback_from_fields_exception(self):
stdout = io.StringIO()
try:
fields(object)
except TypeError as exc:
traceback.print_exception(exc, file=stdout)
printed_traceback = stdout.getvalue()
self.assertNotIn("AttributeError", printed_traceback)
self.assertNotIn("__dataclass_fields__", printed_traceback)
def test_helper_asdict(self): def test_helper_asdict(self):
# Basic tests for asdict(), it should return a new dictionary. # Basic tests for asdict(), it should return a new dictionary.
@dataclass @dataclass

View file

@ -0,0 +1,2 @@
Improve traceback when :func:`dataclasses.fields` is called on a
non-dataclass. Patch by Alex Waygood