From 68b3711fa381ddf618297e665521824131d8024b Mon Sep 17 00:00:00 2001 From: Jason Madden Date: Thu, 18 May 2017 13:35:32 -0500 Subject: [PATCH] 100% coverage for ifacemodule/menu.py --- .coveragerc | 1 + src/zope/app/apidoc/ifacemodule/menu.py | 14 ++++++++------ src/zope/app/apidoc/ifacemodule/tests.py | 13 +++++++++++++ src/zope/app/apidoc/tests.py | 24 +++++++++++++++++++++++- src/zope/app/apidoc/utilities.py | 6 +++--- src/zope/app/apidoc/utilities.rst | 9 +++++++-- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/.coveragerc b/.coveragerc index f205e92e..f31f86eb 100644 --- a/.coveragerc +++ b/.coveragerc @@ -5,3 +5,4 @@ source = src exclude_lines = pragma: no cover if __name__ == '__main__': + raise NotImplementedError diff --git a/src/zope/app/apidoc/ifacemodule/menu.py b/src/zope/app/apidoc/ifacemodule/menu.py index 49d751f6..4b308c45 100644 --- a/src/zope/app/apidoc/ifacemodule/menu.py +++ b/src/zope/app/apidoc/ifacemodule/menu.py @@ -16,10 +16,12 @@ """ __docformat__ = 'restructuredtext' +import operator from zope.security.proxy import removeSecurityProxy import re whitepattern = re.compile(r'\s{2,}') +namegetter = operator.itemgetter('name') def getAllTextOfInterface(iface): """Get all searchable text from an interface""" @@ -50,11 +52,11 @@ def findInterfaces(self): for name, iface in self.context.items(): if (search_str in name or (not name_only and search_str in getAllTextOfInterface(iface))): - results.append( - {'name': name, + results.append({ + 'name': name, 'url': './%s/index.html' %name - }) - results.sort(key=lambda x: x['name']) + }) + results.sort(key=namegetter) return results def findAllInterfaces(self): @@ -66,11 +68,11 @@ def findAllInterfaces(self): for name, iface in self.context.items(): results.append({ 'name': name, - 'url': './%s/index.html' %name, + 'url': './%s/index.html' % name, 'counter': counter, 'doc': whitepattern.sub(' ', getAllTextOfInterface(iface)) }) counter += 1 - results.sort(key=lambda x: x['name']) + results.sort(key=namegetter) return results diff --git a/src/zope/app/apidoc/ifacemodule/tests.py b/src/zope/app/apidoc/ifacemodule/tests.py index a92e19c7..742e21e3 100644 --- a/src/zope/app/apidoc/ifacemodule/tests.py +++ b/src/zope/app/apidoc/ifacemodule/tests.py @@ -53,6 +53,19 @@ def testInterfaceDetailsView(self): self.assertIn('/++apidoc++/Code/zope/app/apidoc' '/ifacemodule/ifacemodule/index.html', body) + def testStaticMenu(self): + response = self.publish( + '/++apidoc++/Interface/staticmenu.html', + basic='mgr:mgrpw') + + self.assertEqual(response.getStatus(), 200) + body = response.getBody() + self.assertIn( + 'zope.app.apidoc.interfaces.IDocumentationModule', body) + self.checkForBrokenLinks(body, '/++apidoc++/Interface/staticmenu.html', + basic='mgr:mgrpw', + # This page is slow, only do a few + max_links=5) def test_suite(): diff --git a/src/zope/app/apidoc/tests.py b/src/zope/app/apidoc/tests.py index d47382dd..445c95ae 100644 --- a/src/zope/app/apidoc/tests.py +++ b/src/zope/app/apidoc/tests.py @@ -92,7 +92,8 @@ def tearDown(self): super(BrowserTestCase, self).tearDown() - def checkForBrokenLinks(self, orig_response, path, basic=None): + def checkForBrokenLinks(self, orig_response, path, + basic=None, max_links=None): response = self.publish(path, basic=basic) links = response.html.find_all('a') @@ -117,6 +118,11 @@ def checkForBrokenLinks(self, orig_response, path, basic=None): seen.add(href) self.publish(href, basic=basic) + if max_links is not None: + max_links -= 1 + if not max_links: + break + def publish(self, path, basic=None, form=None, headers=None, env=None): assert basic self._testapp.authorization = ('Basic', tuple(basic.split(':'))) @@ -157,6 +163,22 @@ def test_iconviewfactory(self): data = getViewFactoryData(factory) self.assertEqual(data['resource'], factory.rname) +class TestUtilities(unittest.TestCase): + + @unittest.skipUnless(str is bytes, "Only on py2") + def test_slot_methods(self): + from zope.app.apidoc.utilities import getFunctionSignature + self.assertEqual("()", getFunctionSignature(object.__init__)) + + @unittest.skipUnless(str is bytes, "Only on py2") + def test_unpack_methods(self): + from zope.app.apidoc.utilities import getFunctionSignature + import six + + six.exec_("def f((a, b)): pass") + + self.assertEqual("((a, b))", getFunctionSignature(locals()['f'])) + # Generally useful classes and functions @implementer(IContainmentRoot) diff --git a/src/zope/app/apidoc/utilities.py b/src/zope/app/apidoc/utilities.py index 51890207..488a0989 100644 --- a/src/zope/app/apidoc/utilities.py +++ b/src/zope/app/apidoc/utilities.py @@ -251,7 +251,7 @@ def getFunctionSignature(func, ignore_self=False): # Make sure the name is a string if isinstance(name, (tuple, list)): name = '(' + ', '.join(name) + ')' - elif not isinstance(name, str): + elif not isinstance(name, str): # pragma: no cover name = repr(name) if default is placeholder: @@ -370,10 +370,10 @@ def renderText(text, module=None, format=None, dedent=True): assert format in _format_dict.values() - text = dedentString(text) - if isinstance(text, bytes): text = text.decode('latin-1', 'replace') + + text = dedentString(text) source = createObject(format, text) renderer = getMultiAdapter((source, TestRequest())) diff --git a/src/zope/app/apidoc/utilities.rst b/src/zope/app/apidoc/utilities.rst index 02905991..d8c580c4 100644 --- a/src/zope/app/apidoc/utilities.rst +++ b/src/zope/app/apidoc/utilities.rst @@ -766,12 +766,17 @@ used. Clearly, you cannot specify both, the `module` and `format` argument. You specify the format as follows: - >>> utilities.renderText('Hello!\n', format='zope.source.rest') + >>> utilities.renderText(u'Hello!\n', format='zope.source.rest') u'

Hello!

\n' Note that the format string must be a valid source factory id; if the factory id is not given, 'zope.source.stx' is used. Thus, specifying the module is often safer (if available): - >>> utilities.renderText('Hello!\n', module=apidoc) + >>> utilities.renderText(u'Hello!\n', module=apidoc) + u'

Hello!

\n' + +Byte input is accepted, so long as it can be decoded: + + >>> utilities.renderText(b'Hello!\n', module=apidoc) u'

Hello!

\n'