Merge lp:~richardw/pydoctor/moduleprovides-1132527 into lp:~mwhudson/pydoctor/dev

Proposed by Richard Wall
Status: Merged
Merged at revision: 595
Proposed branch: lp:~richardw/pydoctor/moduleprovides-1132527
Merge into: lp:~mwhudson/pydoctor/dev
Diff against target: 113 lines (+57/-3)
2 files modified
pydoctor/test/test_zopeinterface.py (+17/-1)
pydoctor/zopeinterface.py (+40/-2)
To merge this branch: bzr merge lp:~richardw/pydoctor/moduleprovides-1132527
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle Approve
Review via email: mp+150932@code.launchpad.net

Description of the change

Hi Michael,

I copied the existing code for handling implements and @implementer and adapted it to handle moduleProvides.

Added a new test case which I think demonstrates the new feature.

Tested on the twisted.names.client.lookup functions in the following Twisted branch:
 * https://twistedmatrix.com/trac/log/branches/moduleprovides-iresolver-6328

Seems to work and even handles documentation from Interface subclasses since your recent change.

Let me know what you think.

-RichardW.

To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Looks good to me, thanks! addInterfaceInfoToModule and addInterfaceInfoToClass seem a bit similar, but I'd forgotten how gross the data model there was so that can probably be fixed as some part of a general clean up. I'll merge now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'pydoctor/test/test_zopeinterface.py'
2--- pydoctor/test/test_zopeinterface.py 2013-02-24 22:40:48 +0000
3+++ pydoctor/test/test_zopeinterface.py 2013-02-27 22:40:26 +0000
4@@ -64,7 +64,6 @@
5 '''
6 implements_test(src)
7
8-
9 def implements_test(src):
10 mod = fromText(src, 'zi', systemcls=ZopeInterfaceSystem)
11 ifoo = mod.contents['IFoo']
12@@ -222,3 +221,20 @@
13 method = mod.contents['Implementation'].contents['method']
14 assert imethod in method.docsources(), list(method.docsources())
15
16+def test_docsources_from_moduleprovides():
17+ src = '''
18+ from zope import interface
19+
20+ class IBase(interface.Interface):
21+ def bar():
22+ """documentation"""
23+
24+ interface.moduleProvides(IBase)
25+
26+ def bar():
27+ pass
28+ '''
29+ mod = fromText(src, systemcls=ZopeInterfaceSystem)
30+ imethod = mod.contents['IBase'].contents['bar']
31+ function = mod.contents['bar']
32+ assert imethod in function.docsources(), list(function.docsources())
33
34=== modified file 'pydoctor/zopeinterface.py'
35--- pydoctor/zopeinterface.py 2013-02-24 22:40:48 +0000
36+++ pydoctor/zopeinterface.py 2013-02-27 22:40:26 +0000
37@@ -4,6 +4,19 @@
38 from compiler import ast
39 import re
40
41+
42+class ZopeInterfaceModule(model.Module):
43+ def setup(self):
44+ super(ZopeInterfaceModule, self).setup()
45+ self.implements_directly = [] # [name of interface]
46+
47+ @property
48+ def allImplementedInterfaces(self):
49+ """Return all the interfaces provided by this module
50+ """
51+ return list(self.implements_directly)
52+
53+
54 class ZopeInterfaceClass(model.Class):
55 isinterface = False
56 isschemafield = False
57@@ -50,7 +63,7 @@
58 def docsources(self):
59 for source in super(ZopeInterfaceFunction, self).docsources():
60 yield source
61- if not isinstance(self.parent, model.Class):
62+ if not isinstance(self.parent, (model.Class, model.Module)):
63 return
64 for interface in self.parent.allImplementedInterfaces:
65 io = self.system.objForFullName(interface)
66@@ -59,6 +72,24 @@
67 if self.name in io2.contents:
68 yield io2.contents[self.name]
69
70+def addInterfaceInfoToModule(module, interfaceargs):
71+ for arg in interfaceargs:
72+ if not isinstance(arg, tuple):
73+ fullName = module.expandName(ast_pp.pp(arg))
74+ else:
75+ fullName = arg[1]
76+ module.implements_directly.append(fullName)
77+ obj = module.system.objForFullName(fullName)
78+ if obj is not None:
79+ if not obj.isinterface:
80+ obj.system.msg(
81+ 'zopeinterface',
82+ 'probable interface %r not marked as such'%obj,
83+ thresh=1)
84+ obj.isinterface = True
85+ obj.kind = "Interface"
86+ obj.implementedby_directly = []
87+ obj.implementedby_directly.append(module.fullName())
88
89 def addInterfaceInfoToClass(cls, interfaceargs, implementsOnly):
90 cls.implementsOnly = implementsOnly
91@@ -193,6 +224,13 @@
92 if meth is not None:
93 meth(base, node)
94
95+ def visitCallFunc_zope_interface_moduleProvides(self, funcName, node):
96+ if not isinstance(self.builder.current, model.Module):
97+ self.default(node)
98+ return
99+
100+ addInterfaceInfoToModule(self.builder.current, node.args)
101+
102 def visitCallFunc_zope_interface_implements(self, funcName, node):
103 if not isinstance(self.builder.current, model.Class):
104 self.default(node)
105@@ -237,7 +275,7 @@
106
107
108 class ZopeInterfaceSystem(model.System):
109+ Module = ZopeInterfaceModule
110 Class = ZopeInterfaceClass
111 Function = ZopeInterfaceFunction
112 defaultBuilder = ZopeInterfaceASTBuilder
113-

Subscribers

People subscribed via source and target branches

to all changes:
to status/vote changes: