Skip to content

Commit

Permalink
Avoid redundant DocstringWarnings; provide location info (if possible)
Browse files Browse the repository at this point in the history
  • Loading branch information
d-maurer committed Feb 23, 2024
1 parent 333507c commit 9ca8fe7
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 2 deletions.
41 changes: 39 additions & 2 deletions src/ZPublisher/BaseRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ def ensure_publishable(self, obj, for_call=False):
"to `ZPublisher.zpublish` decorator or have a docstring to be "
"published.")
if deprecate_docstrings:
warn(DocstringWarning(url))
warn(DocstringWarning(obj, url))


def exec_callables(callables):
Expand Down Expand Up @@ -828,7 +828,44 @@ def typeCheck(obj, deny=itypes):


class DocstringWarning(DeprecationWarning):
def tag(self):
import inspect as i

def lineno(o, m=False):
"""try to determine where *o* has been defined.
*o* is either a function or a class.
"""
try:
_, lineno = i.getsourcelines(o)
except (OSError, TypeError):
return ""
return f"[{o.__module__}:{lineno}]" if m else f" at line {lineno}"

obj, url = self.args
desc = None
if i.ismethod(obj):
f = i.unwrap(obj.__func__)
c = obj.__self__.__class__
desc = f"'{c.__module__}.{c.__qualname__}' " \
f"method '{obj.__qualname__}'{lineno(f, 1)}"
elif i.isfunction(obj):
f = i.unwrap(obj)
desc = f"function '{f.__module__}.{f.__qualname__}'" \
f"{lineno(f)}"
else:
try:
cls_doc = "__doc__" not in obj.__dict__
except AttributeError:
cls_doc = True
if cls_doc:
c = obj.__class__
desc = f"'{c.__module__}.{c.__qualname__}'{lineno(c)}"
if desc is None:
desc = f"object at '{url}'"
return desc

def __str__(self):
return (f"The object at {self.args[0]} uses deprecated docstring "
return (f"{self.tag()} uses deprecated docstring "
"publication control. Use the `ZPublisher.zpublish` decorator "
"instead")
13 changes: 13 additions & 0 deletions src/ZPublisher/tests/docstring.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Resources for ``testBaseRequest.TestDocstringWarning``.
The tests there depend on line numbers in this module.
"""


def f():
"f"


class C:
"C"
g = f
37 changes: 37 additions & 0 deletions src/ZPublisher/tests/testBaseRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from zope.publisher.interfaces import IPublishTraverse
from zope.publisher.interfaces import NotFound as ztkNotFound
from ZPublisher import zpublish
from ZPublisher.BaseRequest import DocstringWarning

from . import docstring


@implementer(IPublishTraverse)
Expand Down Expand Up @@ -885,3 +888,37 @@ def test__str__returns_native_string(self):
root, folder = self._makeRootAndFolder()
r = self._makeOne(root)
self.assertIsInstance(str(r), str)


class TestDocstringWarning(unittest.TestCase):
def test_method(self):
c = docstring.C()
ds = DocstringWarning(c.g, "URL")
self.assertEqual(ds.tag(),
"'ZPublisher.tests.docstring.C' method "
"'f'[ZPublisher.tests.docstring:7]")

def test_function(self):
f = docstring.f
ds = DocstringWarning(f, "URL")
self.assertEqual(ds.tag(),
"function 'ZPublisher.tests.docstring.f' at line 7")

def test_instance_with_own_docstring(self):
c = docstring.C()
c.__doc__ = "c"
ds = DocstringWarning(c, "URL")
self.assertEqual(ds.tag(), "object at 'URL'")

def test_instance_with_inherited_docstring(self):
c = docstring.C()
ds = DocstringWarning(c, "URL")
self.assertEqual(ds.tag(), "'ZPublisher.tests.docstring.C' at line 11")

def test__str__(self):
ds = DocstringWarning("special", "URL")
self.assertEqual(
str(ds),
"'builtins.str' uses deprecated docstring "
"publication control. Use the `ZPublisher.zpublish` decorator "
"instead")

0 comments on commit 9ca8fe7

Please sign in to comment.