# Test case for property
# more tests are in test_descr

import sys
import unittest
from test import support

class PropertyBase(Exception):
    pass

class PropertyGet(PropertyBase):
    pass

class PropertySet(PropertyBase):
    pass

class PropertyDel(PropertyBase):
    pass

class BaseClass(object):
    def __init__(self):
        self._spam = 5

    @property
    def spam(self):
        """BaseClass.getter"""
        return self._spam

    @spam.setter
    def spam(self, value):
        self._spam = value

    @spam.deleter
    def spam(self):
        del self._spam

class SubClass(BaseClass):

    @BaseClass.spam.getter
    def spam(self):
        """SubClass.getter"""
        raise PropertyGet(self._spam)

    @spam.setter
    def spam(self, value):
        raise PropertySet(self._spam)

    @spam.deleter
    def spam(self):
        raise PropertyDel(self._spam)

class PropertyDocBase(object):
    _spam = 1
    def _get_spam(self):
        return self._spam
    spam = property(_get_spam, doc="spam spam spam")

class PropertyDocSub(PropertyDocBase):
    @PropertyDocBase.spam.getter
    def spam(self):
        """The decorator does not use this doc string"""
        return self._spam

class PropertySubNewGetter(BaseClass):
    @BaseClass.spam.getter
    def spam(self):
        """new docstring"""
        return 5

class PropertyNewGetter(object):
    @property
    def spam(self):
        """original docstring"""
        return 1
    @spam.getter
    def spam(self):
        """new docstring"""
        return 8

class PropertyTests(unittest.TestCase):
    def test_property_decorator_baseclass(self):
        # see #1620
        base = BaseClass()
        self.assertEqual(base.spam, 5)
        self.assertEqual(base._spam, 5)
        base.spam = 10
        self.assertEqual(base.spam, 10)
        self.assertEqual(base._spam, 10)
        delattr(base, "spam")
        self.assertNotHasAttr(base, "spam")
        self.assertNotHasAttr(base, "_spam")
        base.spam = 20
        self.assertEqual(base.spam, 20)
        self.assertEqual(base._spam, 20)

    def test_property_decorator_subclass(self):
        # see #1620
        sub = SubClass()
        self.assertRaises(PropertyGet, getattr, sub, "spam")
        self.assertRaises(PropertySet, setattr, sub, "spam", None)
        self.assertRaises(PropertyDel, delattr, sub, "spam")

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_decorator_subclass_doc(self):
        sub = SubClass()
        self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter")

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_decorator_baseclass_doc(self):
        base = BaseClass()
        self.assertEqual(base.__class__.spam.__doc__, "BaseClass.getter")

    def test_property_decorator_doc(self):
        base = PropertyDocBase()
        sub = PropertyDocSub()
        self.assertEqual(base.__class__.spam.__doc__, "spam spam spam")
        self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam")

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_getter_doc_override(self):
        newgettersub = PropertySubNewGetter()
        self.assertEqual(newgettersub.spam, 5)
        self.assertEqual(newgettersub.__class__.spam.__doc__, "new docstring")
        newgetter = PropertyNewGetter()
        self.assertEqual(newgetter.spam, 8)
        self.assertEqual(newgetter.__class__.spam.__doc__, "new docstring")

    def test_property___isabstractmethod__descriptor(self):
        for val in (True, False, [], [1], '', '1'):
            class C(object):
                def foo(self):
                    pass
                foo.__isabstractmethod__ = val
                foo = property(foo)
            self.assertIs(C.foo.__isabstractmethod__, bool(val))

        # check that the property's __isabstractmethod__ descriptor does the
        # right thing when presented with a value that fails truth testing:
        class NotBool(object):
            def __bool__(self):
                raise ValueError()
            __len__ = __bool__
        with self.assertRaises(ValueError):
            class C(object):
                def foo(self):
                    pass
                foo.__isabstractmethod__ = NotBool()
                foo = property(foo)
            C.foo.__isabstractmethod__

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_builtin_doc_writable(self):
        p = property(doc='basic')
        self.assertEqual(p.__doc__, 'basic')
        p.__doc__ = 'extended'
        self.assertEqual(p.__doc__, 'extended')

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_decorator_doc_writable(self):
        class PropertyWritableDoc(object):

            @property
            def spam(self):
                """Eggs"""
                return "eggs"

        sub = PropertyWritableDoc()
        self.assertEqual(sub.__class__.spam.__doc__, 'Eggs')
        sub.__class__.spam.__doc__ = 'Spam'
        self.assertEqual(sub.__class__.spam.__doc__, 'Spam')

    @support.refcount_test
    def test_refleaks_in___init__(self):
        gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount')
        fake_prop = property('fget', 'fset', 'fdel', 'doc')
        refs_before = gettotalrefcount()
        for i in range(100):
            fake_prop.__init__('fget', 'fset', 'fdel', 'doc')
        self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)

    @support.refcount_test
    def test_gh_115618(self):
        # Py_XDECREF() was improperly called for None argument
        # in property methods.
        gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount')
        prop = property()
        refs_before = gettotalrefcount()
        for i in range(100):
            prop = prop.getter(None)
        self.assertIsNone(prop.fget)
        for i in range(100):
            prop = prop.setter(None)
        self.assertIsNone(prop.fset)
        for i in range(100):
            prop = prop.deleter(None)
        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()

        for i in (0, 1, 3):
            with self.assertRaisesRegex(
                TypeError,
                fr'^__set_name__\(\) takes 2 positional arguments but {i} were given$'
            ):
                p.__set_name__(*([0] * i))

    def test_property_setname_on_property_subclass(self):
        # https://github.com/python/cpython/issues/100942
        # Copy was setting the name field without first
        # verifying that the copy was an actual property
        # instance.  As a result, the code below was
        # causing a segfault.

        class pro(property):
            def __new__(typ, *args, **kwargs):
                return "abcdef"

        class A:
            pass

        p = property.__new__(pro)
        p.__set_name__(A, 1)
        np = p.getter(lambda self: 1)

# Issue 5890: subclasses of property do not preserve method __doc__ strings
class PropertySub(property):
    """This is a subclass of property"""

class PropertySubWoDoc(property):
    pass

class PropertySubSlots(property):
    """This is a subclass of property that defines __slots__"""
    __slots__ = ()

class PropertySubclassTests(unittest.TestCase):

    @support.requires_docstrings
    def test_slots_docstring_copy_exception(self):
        # A special case error that we preserve despite the GH-98963 behavior
        # that would otherwise silently ignore this error.
        # This came from commit b18500d39d791c879e9904ebac293402b4a7cd34
        # as part of https://bugs.python.org/issue5890 which allowed docs to
        # be set via property subclasses in the first place.
        with self.assertRaises(AttributeError):
            class Foo(object):
                @PropertySubSlots
                def spam(self):
                    """Trying to copy this docstring will raise an exception"""
                    return 1

    def test_property_with_slots_no_docstring(self):
        # https://github.com/python/cpython/issues/98963#issuecomment-1574413319
        class slotted_prop(property):
            __slots__ = ("foo",)

        p = slotted_prop()  # no AttributeError
        self.assertIsNone(getattr(p, "__doc__", None))

        def undocumented_getter():
            return 4

        p = slotted_prop(undocumented_getter)  # New in 3.12: no AttributeError
        self.assertIsNone(getattr(p, "__doc__", None))

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_with_slots_docstring_silently_dropped(self):
        # https://github.com/python/cpython/issues/98963#issuecomment-1574413319
        class slotted_prop(property):
            __slots__ = ("foo",)

        p = slotted_prop(doc="what's up")  # no AttributeError
        self.assertIsNone(p.__doc__)

        def documented_getter():
            """getter doc."""
            return 4

        # Historical behavior: A docstring from a getter always raises.
        # (matches test_slots_docstring_copy_exception above).
        with self.assertRaises(AttributeError):
            p = slotted_prop(documented_getter)

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_with_slots_and_doc_slot_docstring_present(self):
        # https://github.com/python/cpython/issues/98963#issuecomment-1574413319
        class slotted_prop(property):
            __slots__ = ("foo", "__doc__")

        p = slotted_prop(doc="what's up")
        self.assertEqual("what's up", p.__doc__)  # new in 3.12: This gets set.

        def documented_getter():
            """what's up getter doc?"""
            return 4

        p = slotted_prop(documented_getter)
        self.assertEqual("what's up getter doc?", p.__doc__)

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_issue41287(self):

        self.assertEqual(PropertySub.__doc__, "This is a subclass of property",
                         "Docstring of `property` subclass is ignored")

        doc = PropertySub(None, None, None, "issue 41287 is fixed").__doc__
        self.assertEqual(doc, "issue 41287 is fixed",
                         "Subclasses of `property` ignores `doc` constructor argument")

        def getter(x):
            """Getter docstring"""

        def getter_wo_doc(x):
            pass

        for ps in property, PropertySub, PropertySubWoDoc:
            doc = ps(getter, None, None, "issue 41287 is fixed").__doc__
            self.assertEqual(doc, "issue 41287 is fixed",
                             "Getter overrides explicit property docstring (%s)" % ps.__name__)

            doc = ps(getter, None, None, None).__doc__
            self.assertEqual(doc, "Getter docstring", "Getter docstring is not picked-up (%s)" % ps.__name__)

            doc = ps(getter_wo_doc, None, None, "issue 41287 is fixed").__doc__
            self.assertEqual(doc, "issue 41287 is fixed",
                             "Getter overrides explicit property docstring (%s)" % ps.__name__)

            doc = ps(getter_wo_doc, None, None, None).__doc__
            self.assertIsNone(doc, "Property class doc appears in instance __doc__ (%s)" % ps.__name__)

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_docstring_copy(self):
        class Foo(object):
            @PropertySub
            def spam(self):
                """spam wrapped in property subclass"""
                return 1
        self.assertEqual(
            Foo.spam.__doc__,
            "spam wrapped in property subclass")

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_docstring_copy2(self):
        """
        Property tries to provide the best docstring it finds for its instances.
        If a user-provided docstring is available, it is preserved on copies.
        If no docstring is available during property creation, the property
        will utilize the docstring from the getter if available.
        """
        def getter1(self):
            return 1
        def getter2(self):
            """doc 2"""
            return 2
        def getter3(self):
            """doc 3"""
            return 3

        # Case-1: user-provided doc is preserved in copies
        #         of property with undocumented getter
        p = property(getter1, None, None, "doc-A")

        p2 = p.getter(getter2)
        self.assertEqual(p.__doc__, "doc-A")
        self.assertEqual(p2.__doc__, "doc-A")

        # Case-2: user-provided doc is preserved in copies
        #         of property with documented getter
        p = property(getter2, None, None, "doc-A")

        p2 = p.getter(getter3)
        self.assertEqual(p.__doc__, "doc-A")
        self.assertEqual(p2.__doc__, "doc-A")

        # Case-3: with no user-provided doc new getter doc
        #         takes precedence
        p = property(getter2, None, None, None)

        p2 = p.getter(getter3)
        self.assertEqual(p.__doc__, "doc 2")
        self.assertEqual(p2.__doc__, "doc 3")

        # Case-4: A user-provided doc is assigned after property construction
        #         with documented getter. The doc IS NOT preserved.
        #         It's an odd behaviour, but it's a strange enough
        #         use case with no easy solution.
        p = property(getter2, None, None, None)
        p.__doc__ = "user"
        p2 = p.getter(getter3)
        self.assertEqual(p.__doc__, "user")
        self.assertEqual(p2.__doc__, "doc 3")

        # Case-5: A user-provided doc is assigned after property construction
        #         with UNdocumented getter. The doc IS preserved.
        p = property(getter1, None, None, None)
        p.__doc__ = "user"
        p2 = p.getter(getter2)
        self.assertEqual(p.__doc__, "user")
        self.assertEqual(p2.__doc__, "user")

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_prefer_explicit_doc(self):
        # Issue 25757: subclasses of property lose docstring
        self.assertEqual(property(doc="explicit doc").__doc__, "explicit doc")
        self.assertEqual(PropertySub(doc="explicit doc").__doc__, "explicit doc")

        class Foo:
            spam = PropertySub(doc="spam explicit doc")

            @spam.getter
            def spam(self):
                """ignored as doc already set"""
                return 1

            def _stuff_getter(self):
                """ignored as doc set directly"""
            stuff = PropertySub(doc="stuff doc argument", fget=_stuff_getter)

        #self.assertEqual(Foo.spam.__doc__, "spam explicit doc")
        self.assertEqual(Foo.stuff.__doc__, "stuff doc argument")

    def test_property_no_doc_on_getter(self):
        # If a property's getter has no __doc__ then the property's doc should
        # be None; test that this is consistent with subclasses as well; see
        # GH-2487
        class NoDoc:
            @property
            def __doc__(self):
                raise AttributeError

        self.assertEqual(property(NoDoc()).__doc__, None)
        self.assertEqual(PropertySub(NoDoc()).__doc__, None)

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_setter_copies_getter_docstring(self):
        class Foo(object):
            def __init__(self): self._spam = 1
            @PropertySub
            def spam(self):
                """spam wrapped in property subclass"""
                return self._spam
            @spam.setter
            def spam(self, value):
                """this docstring is ignored"""
                self._spam = value
        foo = Foo()
        self.assertEqual(foo.spam, 1)
        foo.spam = 2
        self.assertEqual(foo.spam, 2)
        self.assertEqual(
            Foo.spam.__doc__,
            "spam wrapped in property subclass")
        class FooSub(Foo):
            @Foo.spam.setter
            def spam(self, value):
                """another ignored docstring"""
                self._spam = 'eggs'
        foosub = FooSub()
        self.assertEqual(foosub.spam, 1)
        foosub.spam = 7
        self.assertEqual(foosub.spam, 'eggs')
        self.assertEqual(
            FooSub.spam.__doc__,
            "spam wrapped in property subclass")

    @unittest.skipIf(sys.flags.optimize >= 2,
                     "Docstrings are omitted with -O2 and above")
    def test_property_new_getter_new_docstring(self):

        class Foo(object):
            @PropertySub
            def spam(self):
                """a docstring"""
                return 1
            @spam.getter
            def spam(self):
                """a new docstring"""
                return 2
        self.assertEqual(Foo.spam.__doc__, "a new docstring")
        class FooBase(object):
            @PropertySub
            def spam(self):
                """a docstring"""
                return 1
        class Foo2(FooBase):
            @FooBase.spam.getter
            def spam(self):
                """a new docstring"""
                return 2
        self.assertEqual(Foo.spam.__doc__, "a new docstring")


class _PropertyUnreachableAttribute:
    msg_format = None
    obj = None
    cls = None

    def _format_exc_msg(self, msg):
        return self.msg_format.format(msg)

    @classmethod
    def setUpClass(cls):
        cls.obj = cls.cls()

    def test_get_property(self):
        with self.assertRaisesRegex(AttributeError, self._format_exc_msg("has no getter")):
            self.obj.foo

    def test_set_property(self):
        with self.assertRaisesRegex(AttributeError, self._format_exc_msg("has no setter")):
            self.obj.foo = None

    def test_del_property(self):
        with self.assertRaisesRegex(AttributeError, self._format_exc_msg("has no deleter")):
            del self.obj.foo


class PropertyUnreachableAttributeWithName(_PropertyUnreachableAttribute, unittest.TestCase):
    msg_format = r"^property 'foo' of 'PropertyUnreachableAttributeWithName\.cls' object {}$"

    class cls:
        foo = property()


class PropertyUnreachableAttributeNoName(_PropertyUnreachableAttribute, unittest.TestCase):
    msg_format = r"^property of 'PropertyUnreachableAttributeNoName\.cls' object {}$"

    class cls:
        pass

    cls.foo = property()


if __name__ == '__main__':
    unittest.main()
