comparison roundup/xmlrpc.py @ 6015:af1067e0f6d9

flake8 changes; move imports before first statements; whitespace normalization.
author John Rouillard <rouilj@ieee.org>
date Tue, 31 Dec 2019 21:56:14 -0500
parents ed02a1e0aa5d
children f7bd22bdef9d
comparison
equal deleted inserted replaced
6014:6ed03d01491d 6015:af1067e0f6d9
7 import logging 7 import logging
8 from roundup import hyperdb 8 from roundup import hyperdb
9 from roundup.exceptions import Unauthorised, UsageError 9 from roundup.exceptions import Unauthorised, UsageError
10 from roundup.date import Date, Range, Interval 10 from roundup.date import Date, Range, Interval
11 from roundup import actions 11 from roundup import actions
12 from roundup.anypy.strings import us2s
13 from traceback import format_exc
12 from roundup.anypy import xmlrpc_ 14 from roundup.anypy import xmlrpc_
13 SimpleXMLRPCDispatcher = xmlrpc_.server.SimpleXMLRPCDispatcher 15 SimpleXMLRPCDispatcher = xmlrpc_.server.SimpleXMLRPCDispatcher
14 Binary = xmlrpc_.client.Binary 16 Binary = xmlrpc_.client.Binary
15 from roundup.anypy.strings import us2s 17
16 from traceback import format_exc
17 18
18 def translate(value): 19 def translate(value):
19 """Translate value to becomes valid for XMLRPC transmission.""" 20 """Translate value to becomes valid for XMLRPC transmission."""
20 21
21 if isinstance(value, (Date, Range, Interval)): 22 if isinstance(value, (Date, Range, Interval)):
36 37
37 props = {} 38 props = {}
38 for arg in args: 39 for arg in args:
39 if isinstance(arg, Binary): 40 if isinstance(arg, Binary):
40 arg = arg.data 41 arg = arg.data
41 try : 42 try:
42 key, value = arg.split('=', 1) 43 key, value = arg.split('=', 1)
43 except ValueError : 44 except ValueError:
44 raise UsageError('argument "%s" not propname=value'%arg) 45 raise UsageError('argument "%s" not propname=value' % arg)
45 key = us2s(key) 46 key = us2s(key)
46 value = us2s(value) 47 value = us2s(value)
47 if value: 48 if value:
48 try: 49 try:
49 props[key] = hyperdb.rawToHyperdb(db, cl, itemid, 50 props[key] = hyperdb.rawToHyperdb(db, cl, itemid,
57 else: 58 else:
58 props[key] = None 59 props[key] = None
59 60
60 return props 61 return props
61 62
63
62 class RoundupInstance: 64 class RoundupInstance:
63 """The RoundupInstance provides the interface accessible through 65 """The RoundupInstance provides the interface accessible through
64 the Python XMLRPC mapping.""" 66 the Python XMLRPC mapping."""
65 67
66 def __init__(self, db, actions, translator): 68 def __init__(self, db, actions, translator):
71 73
72 def schema(self): 74 def schema(self):
73 s = {} 75 s = {}
74 for c in self.db.classes: 76 for c in self.db.classes:
75 cls = self.db.classes[c] 77 cls = self.db.classes[c]
76 props = [(n,repr(v)) for n,v in sorted(cls.properties.items())] 78 props = [(n, repr(v)) for n, v in sorted(cls.properties.items())]
77 s[c] = props 79 s[c] = props
78 return s 80 return s
79 81
80 def list(self, classname, propname=None): 82 def list(self, classname, propname=None):
81 cl = self.db.getclass(classname) 83 cl = self.db.getclass(classname)
82 if not propname: 84 if not propname:
83 propname = cl.labelprop() 85 propname = cl.labelprop()
84 result = [cl.get(itemid, propname) 86 result = [cl.get(itemid, propname)
85 for itemid in cl.list() 87 for itemid in cl.list()
86 if self.db.security.hasPermission('View', self.db.getuid(), 88 if self.db.security.hasPermission('View', self.db.getuid(),
87 classname, propname, itemid) 89 classname, propname,
90 itemid)
88 ] 91 ]
89 return result 92 return result
90 93
91 def filter(self, classname, search_matches, filterspec, 94 def filter(self, classname, search_matches, filterspec,
92 sort=[], group=[]): 95 sort=[], group=[]):
93 cl = self.db.getclass(classname) 96 cl = self.db.getclass(classname)
94 uid = self.db.getuid() 97 uid = self.db.getuid()
95 security = self.db.security 98 security = self.db.security
96 filterspec = security.filterFilterspec (uid, classname, filterspec) 99 filterspec = security.filterFilterspec(uid, classname, filterspec)
97 sort = security.filterSortspec (uid, classname, sort) 100 sort = security.filterSortspec(uid, classname, sort)
98 group = security.filterSortspec (uid, classname, group) 101 group = security.filterSortspec(uid, classname, group)
99 result = cl.filter(search_matches, filterspec, sort=sort, group=group) 102 result = cl.filter(search_matches, filterspec, sort=sort, group=group)
100 check = security.hasPermission 103 check = security.hasPermission
101 x = [id for id in result if check('View', uid, classname, itemid=id)] 104 x = [id for id in result if check('View', uid, classname, itemid=id)]
102 return x 105 return x
103 106
106 uid = self.db.getuid() 109 uid = self.db.getuid()
107 prop = cl.getkey() 110 prop = cl.getkey()
108 search = self.db.security.hasSearchPermission 111 search = self.db.security.hasSearchPermission
109 access = self.db.security.hasPermission 112 access = self.db.security.hasPermission
110 if (not search(uid, classname, prop) 113 if (not search(uid, classname, prop)
111 and not access('View', uid, classname, prop)): 114 and not access('View', uid, classname, prop)):
112 raise Unauthorised('Permission to lookup %s denied'%classname) 115 raise Unauthorised('Permission to lookup %s denied' % classname)
113 return cl.lookup(key) 116 return cl.lookup(key)
114 117
115 def display(self, designator, *properties): 118 def display(self, designator, *properties):
116 classname, itemid = hyperdb.splitDesignator(designator) 119 classname, itemid = hyperdb.splitDesignator(designator)
117 cl = self.db.getclass(classname) 120 cl = self.db.getclass(classname)
118 props = properties and list(properties) or list(cl.properties.keys()) 121 props = properties and list(properties) or list(cl.properties.keys())
119 props.sort() 122 props.sort()
120 for p in props: 123 for p in props:
121 if not self.db.security.hasPermission('View', self.db.getuid(), 124 if not self.db.security.hasPermission('View', self.db.getuid(),
122 classname, p, itemid): 125 classname, p, itemid):
123 raise Unauthorised('Permission to view %s of %s denied'% 126 raise Unauthorised('Permission to view %s of %s denied' %
124 (p, designator)) 127 (p, designator))
125 result = [(prop, cl.get(itemid, prop)) for prop in props] 128 result = [(prop, cl.get(itemid, prop)) for prop in props]
126 return dict(result) 129 return dict(result)
127 130
128 def create(self, classname, *args): 131 def create(self, classname, *args):
129 132 if not self.db.security.hasPermission('Create', self.db.getuid(),
130 if not self.db.security.hasPermission('Create', self.db.getuid(), classname): 133 classname):
131 raise Unauthorised('Permission to create %s denied'%classname) 134 raise Unauthorised('Permission to create %s denied' % classname)
132 135
133 cl = self.db.getclass(classname) 136 cl = self.db.getclass(classname)
134 137
135 # convert types 138 # convert types
136 props = props_from_args(self.db, cl, args) 139 props = props_from_args(self.db, cl, args)
137 140
138 # check for the key property 141 # check for the key property
139 key = cl.getkey() 142 key = cl.getkey()
140 if key and key not in props: 143 if key and key not in props:
141 raise UsageError('you must provide the "%s" property.'%key) 144 raise UsageError('you must provide the "%s" property.' % key)
142 145
143 for key in props: 146 for key in props:
144 if not self.db.security.hasPermission('Create', self.db.getuid(), 147 if not self.db.security.hasPermission('Create', self.db.getuid(),
145 classname, property=key): 148 classname, property=key):
146 raise Unauthorised('Permission to create %s.%s denied'%(classname, key)) 149 raise Unauthorised('Permission to create %s.%s denied' %
150 (classname, key))
147 151
148 # do the actual create 152 # do the actual create
149 try: 153 try:
150 result = cl.create(**props) 154 result = cl.create(**props)
151 self.db.commit() 155 self.db.commit()
152 except (TypeError, IndexError, ValueError) as message: 156 except (TypeError, IndexError, ValueError) as message:
153 # The exception we get may be a real error, log the traceback if we're debugging 157 # The exception we get may be a real error, log the traceback
158 # if we're debugging
154 logger = logging.getLogger('roundup.xmlrpc') 159 logger = logging.getLogger('roundup.xmlrpc')
155 for l in format_exc().split('\n'): 160 for l in format_exc().split('\n'):
156 logger.debug(l) 161 logger.debug(l)
157 raise UsageError (message) 162 raise UsageError(message)
158 return result 163 return result
159 164
160 def set(self, designator, *args): 165 def set(self, designator, *args):
161 166
162 classname, itemid = hyperdb.splitDesignator(designator) 167 classname, itemid = hyperdb.splitDesignator(designator)
163 cl = self.db.getclass(classname) 168 cl = self.db.getclass(classname)
164 props = props_from_args(self.db, cl, args, itemid) # convert types 169 props = props_from_args(self.db, cl, args, itemid) # convert types
165 for p in props.keys(): 170 for p in props.keys():
166 if not self.db.security.hasPermission('Edit', self.db.getuid(), 171 if not self.db.security.hasPermission('Edit', self.db.getuid(),
167 classname, p, itemid): 172 classname, p, itemid):
168 raise Unauthorised('Permission to edit %s of %s denied'% 173 raise Unauthorised('Permission to edit %s of %s denied' %
169 (p, designator)) 174 (p, designator))
170 try: 175 try:
171 result = cl.set(itemid, **props) 176 result = cl.set(itemid, **props)
172 self.db.commit() 177 self.db.commit()
173 except (TypeError, IndexError, ValueError) as message: 178 except (TypeError, IndexError, ValueError) as message:
174 # The exception we get may be a real error, log the traceback if we're debugging 179 # The exception we get may be a real error, log the
180 # traceback if we're debugging
175 logger = logging.getLogger('roundup.xmlrpc') 181 logger = logging.getLogger('roundup.xmlrpc')
176 for l in format_exc().split('\n'): 182 for l in format_exc().split('\n'):
177 logger.debug(l) 183 logger.debug(l)
178 raise UsageError (message) 184 raise UsageError(message)
179 return result 185 return result
180 186
181 187 builtin_actions = dict(retire=actions.Retire, restore=actions.Restore)
182 builtin_actions = dict (retire = actions.Retire, restore = actions.Restore)
183 188
184 def action(self, name, *args): 189 def action(self, name, *args):
185 """Execute a named action.""" 190 """Execute a named action."""
186 191
187 if name in self.actions: 192 if name in self.actions:
188 action_type = self.actions[name] 193 action_type = self.actions[name]
189 elif name in self.builtin_actions: 194 elif name in self.builtin_actions:
190 action_type = self.builtin_actions[name] 195 action_type = self.builtin_actions[name]
191 else: 196 else:
192 raise Exception('action "%s" is not supported %s' 197 raise Exception('action "%s" is not supported %s'
193 % (name, ','.join(self.actions.keys()))) 198 % (name, ','.join(self.actions.keys())))
194 action = action_type(self.db, self.translator) 199 action = action_type(self.db, self.translator)
195 return action.execute(*args) 200 return action.execute(*args)
196 201
197 202
198 class RoundupDispatcher(SimpleXMLRPCDispatcher): 203 class RoundupDispatcher(SimpleXMLRPCDispatcher):
202 def __init__(self, db, actions, translator, 207 def __init__(self, db, actions, translator,
203 allow_none=False, encoding=None): 208 allow_none=False, encoding=None):
204 SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) 209 SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
205 self.register_instance(RoundupInstance(db, actions, translator)) 210 self.register_instance(RoundupInstance(db, actions, translator))
206 self.register_multicall_functions() 211 self.register_multicall_functions()
207
208 212
209 def dispatch(self, input): 213 def dispatch(self, input):
210 return self._marshaled_dispatch(input) 214 return self._marshaled_dispatch(input)
211 215
212 def _dispatch(self, method, params): 216 def _dispatch(self, method, params):
213 217
214 retn = SimpleXMLRPCDispatcher._dispatch(self, method, params) 218 retn = SimpleXMLRPCDispatcher._dispatch(self, method, params)
215 retn = translate(retn) 219 retn = translate(retn)
216 return retn 220 return retn
217

Roundup Issue Tracker: http://roundup-tracker.org/