diff options
author | Eugene Toder <eltoder@users.noreply.github.com> | 2024-02-20 15:14:34 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-20 15:14:34 (GMT) |
commit | c0b0c2f2015fb27db4306109b2b3781eb2057c2b (patch) | |
tree | 49b34e2f7d762b0abeb3c09e508c8e2fd9255c08 /Lib | |
parent | 9af80ec83d1647a472331bd1333a7fa9108fe98e (diff) | |
download | cpython-c0b0c2f2015fb27db4306109b2b3781eb2057c2b.zip cpython-c0b0c2f2015fb27db4306109b2b3781eb2057c2b.tar.gz cpython-c0b0c2f2015fb27db4306109b2b3781eb2057c2b.tar.bz2 |
gh-101860: Expose __name__ on property (GH-101876)
Useful for introspection and consistent with functions and other
descriptors.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/inspect.py | 5 | ||||
-rwxr-xr-x | Lib/pydoc.py | 5 | ||||
-rw-r--r-- | Lib/test/test_inspect/inspect_fodder.py | 4 | ||||
-rw-r--r-- | Lib/test/test_property.py | 53 | ||||
-rw-r--r-- | Lib/test/test_pydoc/test_pydoc.py | 23 |
5 files changed, 76 insertions, 14 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index 450093a..da50403 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -834,9 +834,8 @@ def _finddoc(obj): cls = self.__class__ # Should be tested before isdatadescriptor(). elif isinstance(obj, property): - func = obj.fget - name = func.__name__ - cls = _findclass(func) + name = obj.__name__ + cls = _findclass(obj.fget) if cls is None or getattr(cls, name) is not obj: return None elif ismethoddescriptor(obj) or isdatadescriptor(obj): diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 9bb64fe..d32fa8d 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -127,9 +127,8 @@ def _finddoc(obj): cls = self.__class__ # Should be tested before isdatadescriptor(). elif isinstance(obj, property): - func = obj.fget - name = func.__name__ - cls = _findclass(func) + name = obj.__name__ + cls = _findclass(obj.fget) if cls is None or getattr(cls, name) is not obj: return None elif inspect.ismethoddescriptor(obj) or inspect.isdatadescriptor(obj): diff --git a/Lib/test/test_inspect/inspect_fodder.py b/Lib/test/test_inspect/inspect_fodder.py index 60ba7aa..febd54c 100644 --- a/Lib/test/test_inspect/inspect_fodder.py +++ b/Lib/test/test_inspect/inspect_fodder.py @@ -68,9 +68,9 @@ class FesteringGob(MalodorousPervert, ParrotDroppings): def abuse(self, a, b, c): pass - @property - def contradiction(self): + def _getter(self): pass + contradiction = property(_getter) async def lobbest(grenade): pass diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py index ad5ab5a..408e64f 100644 --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -201,6 +201,59 @@ class PropertyTests(unittest.TestCase): self.assertIsNone(prop.fdel) self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + def test_property_name(self): + def getter(self): + return 42 + + def setter(self, value): + pass + + class A: + @property + def foo(self): + return 1 + + @foo.setter + def oof(self, value): + pass + + bar = property(getter) + baz = property(None, setter) + + self.assertEqual(A.foo.__name__, 'foo') + self.assertEqual(A.oof.__name__, 'oof') + self.assertEqual(A.bar.__name__, 'bar') + self.assertEqual(A.baz.__name__, 'baz') + + A.quux = property(getter) + self.assertEqual(A.quux.__name__, 'getter') + A.quux.__name__ = 'myquux' + self.assertEqual(A.quux.__name__, 'myquux') + self.assertEqual(A.bar.__name__, 'bar') # not affected + A.quux.__name__ = None + self.assertIsNone(A.quux.__name__) + + with self.assertRaisesRegex( + AttributeError, "'property' object has no attribute '__name__'" + ): + property(None, setter).__name__ + + with self.assertRaisesRegex( + AttributeError, "'property' object has no attribute '__name__'" + ): + property(1).__name__ + + class Err: + def __getattr__(self, attr): + raise RuntimeError('fail') + + p = property(Err()) + with self.assertRaisesRegex(RuntimeError, 'fail'): + p.__name__ + + p.__name__ = 'not_fail' + self.assertEqual(p.__name__, 'not_fail') + def test_property_set_name_incorrect_args(self): p = property() diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index d7a333a..b07d911 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -1162,6 +1162,17 @@ class PydocImportTest(PydocBaseTest): self.assertEqual(loaded_pydoc.__spec__, pydoc.__spec__) +class Rect: + @property + def area(self): + '''Area of the rect''' + return self.w * self.h + + +class Square(Rect): + area = property(lambda self: self.side**2) + + class TestDescriptions(unittest.TestCase): def test_module(self): @@ -1550,13 +1561,13 @@ cm(x) class method of test.test_pydoc.test_pydoc.X @requires_docstrings def test_property(self): - class Rect: - @property - def area(self): - '''Area of the rect''' - return self.w * self.h - self.assertEqual(self._get_summary_lines(Rect.area), """\ +area + Area of the rect +""") + # inherits the docstring from Rect.area + self.assertEqual(self._get_summary_lines(Square.area), """\ +area Area of the rect """) self.assertIn(""" |