##// END OF EJS Templates
peer: use absolute_import
Gregory Szorc -
r25965:e6b56b2c default
parent child Browse files
Show More
@@ -1,122 +1,126 b''
1 # peer.py - repository base classes for mercurial
1 # peer.py - repository base classes for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from i18n import _
9 from __future__ import absolute_import
10 import error
10
11 import util
11 from .i18n import _
12 from . import (
13 error,
14 util,
15 )
12
16
13 # abstract batching support
17 # abstract batching support
14
18
15 class future(object):
19 class future(object):
16 '''placeholder for a value to be set later'''
20 '''placeholder for a value to be set later'''
17 def set(self, value):
21 def set(self, value):
18 if util.safehasattr(self, 'value'):
22 if util.safehasattr(self, 'value'):
19 raise error.RepoError("future is already set")
23 raise error.RepoError("future is already set")
20 self.value = value
24 self.value = value
21
25
22 class batcher(object):
26 class batcher(object):
23 '''base class for batches of commands submittable in a single request
27 '''base class for batches of commands submittable in a single request
24
28
25 All methods invoked on instances of this class are simply queued and
29 All methods invoked on instances of this class are simply queued and
26 return a a future for the result. Once you call submit(), all the queued
30 return a a future for the result. Once you call submit(), all the queued
27 calls are performed and the results set in their respective futures.
31 calls are performed and the results set in their respective futures.
28 '''
32 '''
29 def __init__(self):
33 def __init__(self):
30 self.calls = []
34 self.calls = []
31 def __getattr__(self, name):
35 def __getattr__(self, name):
32 def call(*args, **opts):
36 def call(*args, **opts):
33 resref = future()
37 resref = future()
34 self.calls.append((name, args, opts, resref,))
38 self.calls.append((name, args, opts, resref,))
35 return resref
39 return resref
36 return call
40 return call
37 def submit(self):
41 def submit(self):
38 pass
42 pass
39
43
40 class localbatch(batcher):
44 class localbatch(batcher):
41 '''performs the queued calls directly'''
45 '''performs the queued calls directly'''
42 def __init__(self, local):
46 def __init__(self, local):
43 batcher.__init__(self)
47 batcher.__init__(self)
44 self.local = local
48 self.local = local
45 def submit(self):
49 def submit(self):
46 for name, args, opts, resref in self.calls:
50 for name, args, opts, resref in self.calls:
47 resref.set(getattr(self.local, name)(*args, **opts))
51 resref.set(getattr(self.local, name)(*args, **opts))
48
52
49 def batchable(f):
53 def batchable(f):
50 '''annotation for batchable methods
54 '''annotation for batchable methods
51
55
52 Such methods must implement a coroutine as follows:
56 Such methods must implement a coroutine as follows:
53
57
54 @batchable
58 @batchable
55 def sample(self, one, two=None):
59 def sample(self, one, two=None):
56 # Handle locally computable results first:
60 # Handle locally computable results first:
57 if not one:
61 if not one:
58 yield "a local result", None
62 yield "a local result", None
59 # Build list of encoded arguments suitable for your wire protocol:
63 # Build list of encoded arguments suitable for your wire protocol:
60 encargs = [('one', encode(one),), ('two', encode(two),)]
64 encargs = [('one', encode(one),), ('two', encode(two),)]
61 # Create future for injection of encoded result:
65 # Create future for injection of encoded result:
62 encresref = future()
66 encresref = future()
63 # Return encoded arguments and future:
67 # Return encoded arguments and future:
64 yield encargs, encresref
68 yield encargs, encresref
65 # Assuming the future to be filled with the result from the batched
69 # Assuming the future to be filled with the result from the batched
66 # request now. Decode it:
70 # request now. Decode it:
67 yield decode(encresref.value)
71 yield decode(encresref.value)
68
72
69 The decorator returns a function which wraps this coroutine as a plain
73 The decorator returns a function which wraps this coroutine as a plain
70 method, but adds the original method as an attribute called "batchable",
74 method, but adds the original method as an attribute called "batchable",
71 which is used by remotebatch to split the call into separate encoding and
75 which is used by remotebatch to split the call into separate encoding and
72 decoding phases.
76 decoding phases.
73 '''
77 '''
74 def plain(*args, **opts):
78 def plain(*args, **opts):
75 batchable = f(*args, **opts)
79 batchable = f(*args, **opts)
76 encargsorres, encresref = batchable.next()
80 encargsorres, encresref = batchable.next()
77 if not encresref:
81 if not encresref:
78 return encargsorres # a local result in this case
82 return encargsorres # a local result in this case
79 self = args[0]
83 self = args[0]
80 encresref.set(self._submitone(f.func_name, encargsorres))
84 encresref.set(self._submitone(f.func_name, encargsorres))
81 return batchable.next()
85 return batchable.next()
82 setattr(plain, 'batchable', f)
86 setattr(plain, 'batchable', f)
83 return plain
87 return plain
84
88
85 class peerrepository(object):
89 class peerrepository(object):
86
90
87 def batch(self):
91 def batch(self):
88 return localbatch(self)
92 return localbatch(self)
89
93
90 def capable(self, name):
94 def capable(self, name):
91 '''tell whether repo supports named capability.
95 '''tell whether repo supports named capability.
92 return False if not supported.
96 return False if not supported.
93 if boolean capability, return True.
97 if boolean capability, return True.
94 if string capability, return string.'''
98 if string capability, return string.'''
95 caps = self._capabilities()
99 caps = self._capabilities()
96 if name in caps:
100 if name in caps:
97 return True
101 return True
98 name_eq = name + '='
102 name_eq = name + '='
99 for cap in caps:
103 for cap in caps:
100 if cap.startswith(name_eq):
104 if cap.startswith(name_eq):
101 return cap[len(name_eq):]
105 return cap[len(name_eq):]
102 return False
106 return False
103
107
104 def requirecap(self, name, purpose):
108 def requirecap(self, name, purpose):
105 '''raise an exception if the given capability is not present'''
109 '''raise an exception if the given capability is not present'''
106 if not self.capable(name):
110 if not self.capable(name):
107 raise error.CapabilityError(
111 raise error.CapabilityError(
108 _('cannot %s; remote repository does not '
112 _('cannot %s; remote repository does not '
109 'support the %r capability') % (purpose, name))
113 'support the %r capability') % (purpose, name))
110
114
111 def local(self):
115 def local(self):
112 '''return peer as a localrepo, or None'''
116 '''return peer as a localrepo, or None'''
113 return None
117 return None
114
118
115 def peer(self):
119 def peer(self):
116 return self
120 return self
117
121
118 def canpush(self):
122 def canpush(self):
119 return True
123 return True
120
124
121 def close(self):
125 def close(self):
122 pass
126 pass
General Comments 0
You need to be logged in to leave comments. Login now