##// END OF EJS Templates
repository: port peer interfaces to zope.interface...
Gregory Szorc -
r37336:39f7d4ee default
parent child Browse files
Show More
@@ -184,7 +184,7 b' class httppeer(wireproto.wirepeer):'
184 184 % (util.timer() - start, ret.code))
185 185 return ret
186 186
187 # Begin of _basepeer interface.
187 # Begin of ipeerconnection interface.
188 188
189 189 @util.propertycache
190 190 def ui(self):
@@ -205,9 +205,9 b' class httppeer(wireproto.wirepeer):'
205 205 def close(self):
206 206 pass
207 207
208 # End of _basepeer interface.
208 # End of ipeerconnection interface.
209 209
210 # Begin of _basewirepeer interface.
210 # Begin of ipeercommands interface.
211 211
212 212 def capabilities(self):
213 213 # self._fetchcaps() should have been called as part of peer
@@ -215,7 +215,7 b' class httppeer(wireproto.wirepeer):'
215 215 assert self._caps is not None
216 216 return self._caps
217 217
218 # End of _basewirepeer interface.
218 # End of ipeercommands interface.
219 219
220 220 # look up capabilities only when needed
221 221
@@ -7,8 +7,6 b''
7 7
8 8 from __future__ import absolute_import
9 9
10 import abc
11
12 10 from .i18n import _
13 11 from .thirdparty.zope import (
14 12 interface as zi,
@@ -17,7 +15,7 b' from . import ('
17 15 error,
18 16 )
19 17
20 class _basepeer(object):
18 class ipeerconnection(zi.Interface):
21 19 """Represents a "connection" to a repository.
22 20
23 21 This is the base interface for representing a connection to a repository.
@@ -26,14 +24,9 b' class _basepeer(object):'
26 24 This is not a complete interface definition and should not be used
27 25 outside of this module.
28 26 """
29 __metaclass__ = abc.ABCMeta
27 ui = zi.Attribute("""ui.ui instance""")
30 28
31 @abc.abstractproperty
32 def ui(self):
33 """ui.ui instance."""
34
35 @abc.abstractmethod
36 def url(self):
29 def url():
37 30 """Returns a URL string representing this peer.
38 31
39 32 Currently, implementations expose the raw URL used to construct the
@@ -45,62 +38,53 b' class _basepeer(object):'
45 38 value.
46 39 """
47 40
48 @abc.abstractmethod
49 def local(self):
41 def local():
50 42 """Returns a local repository instance.
51 43
52 44 If the peer represents a local repository, returns an object that
53 45 can be used to interface with it. Otherwise returns ``None``.
54 46 """
55 47
56 @abc.abstractmethod
57 def peer(self):
48 def peer():
58 49 """Returns an object conforming to this interface.
59 50
60 51 Most implementations will ``return self``.
61 52 """
62 53
63 @abc.abstractmethod
64 def canpush(self):
54 def canpush():
65 55 """Returns a boolean indicating if this peer can be pushed to."""
66 56
67 @abc.abstractmethod
68 def close(self):
57 def close():
69 58 """Close the connection to this peer.
70 59
71 60 This is called when the peer will no longer be used. Resources
72 61 associated with the peer should be cleaned up.
73 62 """
74 63
75 class _basewirecommands(object):
64 class ipeercommands(zi.Interface):
76 65 """Client-side interface for communicating over the wire protocol.
77 66
78 67 This interface is used as a gateway to the Mercurial wire protocol.
79 68 methods commonly call wire protocol commands of the same name.
80 69 """
81 __metaclass__ = abc.ABCMeta
82 70
83 @abc.abstractmethod
84 def branchmap(self):
71 def branchmap():
85 72 """Obtain heads in named branches.
86 73
87 74 Returns a dict mapping branch name to an iterable of nodes that are
88 75 heads on that branch.
89 76 """
90 77
91 @abc.abstractmethod
92 def capabilities(self):
78 def capabilities():
93 79 """Obtain capabilities of the peer.
94 80
95 81 Returns a set of string capabilities.
96 82 """
97 83
98 @abc.abstractmethod
99 def debugwireargs(self, one, two, three=None, four=None, five=None):
84 def debugwireargs(one, two, three=None, four=None, five=None):
100 85 """Used to facilitate debugging of arguments passed over the wire."""
101 86
102 @abc.abstractmethod
103 def getbundle(self, source, **kwargs):
87 def getbundle(source, **kwargs):
104 88 """Obtain remote repository data as a bundle.
105 89
106 90 This command is how the bulk of repository data is transferred from
@@ -109,15 +93,13 b' class _basewirecommands(object):'
109 93 Returns a generator of bundle data.
110 94 """
111 95
112 @abc.abstractmethod
113 def heads(self):
96 def heads():
114 97 """Determine all known head revisions in the peer.
115 98
116 99 Returns an iterable of binary nodes.
117 100 """
118 101
119 @abc.abstractmethod
120 def known(self, nodes):
102 def known(nodes):
121 103 """Determine whether multiple nodes are known.
122 104
123 105 Accepts an iterable of nodes whose presence to check for.
@@ -126,22 +108,19 b' class _basewirecommands(object):'
126 108 at that index is known to the peer.
127 109 """
128 110
129 @abc.abstractmethod
130 def listkeys(self, namespace):
111 def listkeys(namespace):
131 112 """Obtain all keys in a pushkey namespace.
132 113
133 114 Returns an iterable of key names.
134 115 """
135 116
136 @abc.abstractmethod
137 def lookup(self, key):
117 def lookup(key):
138 118 """Resolve a value to a known revision.
139 119
140 120 Returns a binary node of the resolved revision on success.
141 121 """
142 122
143 @abc.abstractmethod
144 def pushkey(self, namespace, key, old, new):
123 def pushkey(namespace, key, old, new):
145 124 """Set a value using the ``pushkey`` protocol.
146 125
147 126 Arguments correspond to the pushkey namespace and key to operate on and
@@ -151,15 +130,13 b' class _basewirecommands(object):'
151 130 namespace.
152 131 """
153 132
154 @abc.abstractmethod
155 def stream_out(self):
133 def stream_out():
156 134 """Obtain streaming clone data.
157 135
158 136 Successful result should be a generator of data chunks.
159 137 """
160 138
161 @abc.abstractmethod
162 def unbundle(self, bundle, heads, url):
139 def unbundle(bundle, heads, url):
163 140 """Transfer repository data to the peer.
164 141
165 142 This is how the bulk of data during a push is transferred.
@@ -167,17 +144,15 b' class _basewirecommands(object):'
167 144 Returns the integer number of heads added to the peer.
168 145 """
169 146
170 class _baselegacywirecommands(object):
147 class ipeerlegacycommands(zi.Interface):
171 148 """Interface for implementing support for legacy wire protocol commands.
172 149
173 150 Wire protocol commands transition to legacy status when they are no longer
174 151 used by modern clients. To facilitate identifying which commands are
175 152 legacy, the interfaces are split.
176 153 """
177 __metaclass__ = abc.ABCMeta
178 154
179 @abc.abstractmethod
180 def between(self, pairs):
155 def between(pairs):
181 156 """Obtain nodes between pairs of nodes.
182 157
183 158 ``pairs`` is an iterable of node pairs.
@@ -186,8 +161,7 b' class _baselegacywirecommands(object):'
186 161 requested pair.
187 162 """
188 163
189 @abc.abstractmethod
190 def branches(self, nodes):
164 def branches(nodes):
191 165 """Obtain ancestor changesets of specific nodes back to a branch point.
192 166
193 167 For each requested node, the peer finds the first ancestor node that is
@@ -196,23 +170,18 b' class _baselegacywirecommands(object):'
196 170 Returns an iterable of iterables with the resolved values for each node.
197 171 """
198 172
199 @abc.abstractmethod
200 def changegroup(self, nodes, kind):
173 def changegroup(nodes, kind):
201 174 """Obtain a changegroup with data for descendants of specified nodes."""
202 175
203 @abc.abstractmethod
204 def changegroupsubset(self, bases, heads, kind):
176 def changegroupsubset(bases, heads, kind):
205 177 pass
206 178
207 class peer(_basepeer, _basewirecommands):
208 """Unified interface and base class for peer repositories.
179 class ipeerbase(ipeerconnection, ipeercommands):
180 """Unified interface for peer repositories.
209 181
210 All peer instances must inherit from this class and conform to its
211 interface.
182 All peer instances must conform to this interface.
212 183 """
213
214 @abc.abstractmethod
215 def iterbatch(self):
184 def iterbatch():
216 185 """Obtain an object to be used for multiple method calls.
217 186
218 187 Various operations call several methods on peer instances. If each
@@ -236,7 +205,7 b' class peer(_basepeer, _basewirecommands)'
236 205 calls. However, they must all support this API.
237 206 """
238 207
239 def capable(self, name):
208 def capable(name):
240 209 """Determine support for a named capability.
241 210
242 211 Returns ``False`` if capability not supported.
@@ -244,6 +213,21 b' class peer(_basepeer, _basewirecommands)'
244 213 Returns ``True`` if boolean capability is supported. Returns a string
245 214 if capability support is non-boolean.
246 215 """
216
217 def requirecap(name, purpose):
218 """Require a capability to be present.
219
220 Raises a ``CapabilityError`` if the capability isn't present.
221 """
222
223 class ipeerbaselegacycommands(ipeerbase, ipeerlegacycommands):
224 """Unified peer interface that supports legacy commands."""
225
226 @zi.implementer(ipeerbase)
227 class peer(object):
228 """Base class for peer repositories."""
229
230 def capable(self, name):
247 231 caps = self.capabilities()
248 232 if name in caps:
249 233 return True
@@ -256,10 +240,6 b' class peer(_basepeer, _basewirecommands)'
256 240 return False
257 241
258 242 def requirecap(self, name, purpose):
259 """Require a capability to be present.
260
261 Raises a ``CapabilityError`` if the capability isn't present.
262 """
263 243 if self.capable(name):
264 244 return
265 245
@@ -267,7 +247,8 b' class peer(_basepeer, _basewirecommands)'
267 247 _('cannot %s; remote repository does not support the %r '
268 248 'capability') % (purpose, name))
269 249
270 class legacypeer(peer, _baselegacywirecommands):
250 @zi.implementer(ipeerbaselegacycommands)
251 class legacypeer(peer):
271 252 """peer but with support for legacy wire protocol commands."""
272 253
273 254 class completelocalrepository(zi.Interface):
@@ -377,7 +377,7 b' class sshv1peer(wireproto.wirepeer):'
377 377 'batch',
378 378 }
379 379
380 # Begin of _basepeer interface.
380 # Begin of ipeerconnection interface.
381 381
382 382 @util.propertycache
383 383 def ui(self):
@@ -398,14 +398,14 b' class sshv1peer(wireproto.wirepeer):'
398 398 def close(self):
399 399 pass
400 400
401 # End of _basepeer interface.
401 # End of ipeerconnection interface.
402 402
403 # Begin of _basewirecommands interface.
403 # Begin of ipeercommands interface.
404 404
405 405 def capabilities(self):
406 406 return self._caps
407 407
408 # End of _basewirecommands interface.
408 # End of ipeercommands interface.
409 409
410 410 def _readerr(self):
411 411 _forwardoutput(self.ui, self._pipee)
@@ -192,7 +192,7 b' class wirepeer(repository.legacypeer):'
192 192 See also httppeer.py and sshpeer.py for protocol-specific
193 193 implementations of this interface.
194 194 """
195 # Begin of basewirepeer interface.
195 # Begin of ipeercommands interface.
196 196
197 197 def iterbatch(self):
198 198 return remoteiterbatcher(self)
@@ -353,9 +353,9 b' class wirepeer(repository.legacypeer):'
353 353 ret = bundle2.getunbundler(self.ui, stream)
354 354 return ret
355 355
356 # End of basewirepeer interface.
356 # End of ipeercommands interface.
357 357
358 # Begin of baselegacywirepeer interface.
358 # Begin of ipeerlegacycommands interface.
359 359
360 360 def branches(self, nodes):
361 361 n = encodelist(nodes)
@@ -391,7 +391,7 b' class wirepeer(repository.legacypeer):'
391 391 bases=bases, heads=heads)
392 392 return changegroupmod.cg1unpacker(f, 'UN')
393 393
394 # End of baselegacywirepeer interface.
394 # End of ipeerlegacycommands interface.
395 395
396 396 def _submitbatch(self, req):
397 397 """run batch request <req> on the server
@@ -25,35 +25,6 b' from mercurial import ('
25 25
26 26 rootdir = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
27 27
28 def checkobject(o):
29 """Verify a constructed object conforms to interface rules.
30
31 An object must have __abstractmethods__ defined.
32
33 All "public" attributes of the object (attributes not prefixed with
34 an underscore) must be in __abstractmethods__ or appear on a base class
35 with __abstractmethods__.
36 """
37 name = o.__class__.__name__
38
39 allowed = set()
40 for cls in o.__class__.__mro__:
41 if not getattr(cls, '__abstractmethods__', set()):
42 continue
43
44 allowed |= cls.__abstractmethods__
45 allowed |= {a for a in dir(cls) if not a.startswith('_')}
46
47 if not allowed:
48 print('%s does not have abstract methods' % name)
49 return
50
51 public = {a for a in dir(o) if not a.startswith('_')}
52
53 for attr in sorted(public - allowed):
54 print('public attributes not in abstract interface: %s.%s' % (
55 name, attr))
56
57 28 def checkzobject(o):
58 29 """Verify an object with a zope interface."""
59 30 ifaces = zi.providedBy(o)
@@ -108,16 +79,34 b' def main():'
108 79 # Needed so we can open a local repo with obsstore without a warning.
109 80 ui.setconfig('experimental', 'evolution.createmarkers', True)
110 81
111 checkobject(badpeer())
112 checkobject(httppeer.httppeer(None, None, None, dummyopener()))
113 checkobject(localrepo.localpeer(dummyrepo()))
114 checkobject(sshpeer.sshv1peer(ui, 'ssh://localhost/foo', None, dummypipe(),
115 dummypipe(), None, None))
116 checkobject(sshpeer.sshv2peer(ui, 'ssh://localhost/foo', None, dummypipe(),
117 dummypipe(), None, None))
118 checkobject(bundlerepo.bundlepeer(dummyrepo()))
119 checkobject(statichttprepo.statichttppeer(dummyrepo()))
120 checkobject(unionrepo.unionpeer(dummyrepo()))
82 checkzobject(badpeer())
83
84 ziverify.verifyClass(repository.ipeerbaselegacycommands,
85 httppeer.httppeer)
86 checkzobject(httppeer.httppeer(None, None, None, dummyopener()))
87
88 ziverify.verifyClass(repository.ipeerbase,
89 localrepo.localpeer)
90 checkzobject(localrepo.localpeer(dummyrepo()))
91
92 ziverify.verifyClass(repository.ipeerbaselegacycommands,
93 sshpeer.sshv1peer)
94 checkzobject(sshpeer.sshv1peer(ui, 'ssh://localhost/foo', None, dummypipe(),
95 dummypipe(), None, None))
96
97 ziverify.verifyClass(repository.ipeerbaselegacycommands,
98 sshpeer.sshv2peer)
99 checkzobject(sshpeer.sshv2peer(ui, 'ssh://localhost/foo', None, dummypipe(),
100 dummypipe(), None, None))
101
102 ziverify.verifyClass(repository.ipeerbase, bundlerepo.bundlepeer)
103 checkzobject(bundlerepo.bundlepeer(dummyrepo()))
104
105 ziverify.verifyClass(repository.ipeerbase, statichttprepo.statichttppeer)
106 checkzobject(statichttprepo.statichttppeer(dummyrepo()))
107
108 ziverify.verifyClass(repository.ipeerbase, unionrepo.unionpeer)
109 checkzobject(unionrepo.unionpeer(dummyrepo()))
121 110
122 111 ziverify.verifyClass(repository.completelocalrepository,
123 112 localrepo.localrepository)
@@ -1,2 +1,2 b''
1 public attributes not in abstract interface: badpeer.badattribute
2 public attributes not in abstract interface: badpeer.badmethod
1 public attribute not declared in interfaces: badpeer.badattribute
2 public attribute not declared in interfaces: badpeer.badmethod
General Comments 0
You need to be logged in to leave comments. Login now