1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
|
<html>
<head>
<title>pylons.controllers.xmlrpc</title>
</head>
<body>
pylons.controllers.xmlrpc
<style>
.coverage pre {float: left; margin: 0px 1em; border: none;
padding: 0px; }
.num pre { margin: 0px }
.nocov, .nocov pre {background-color: #faa}
.cov, .cov pre {background-color: #cfc}
div.coverage div { clear: both; height: 1.1em}
</style>
<div class="stats">
Covered: 235 lines<br/>
Missed: 0 lines<br/>
Skipped 65 lines<br/>
Percent: 100 %<br/>
</div>
<div class="coverage">
<div class="cov"><span class="num"><pre> 1</pre></span><pre>"""The base WSGI XMLRPCController"""</pre></div>
<div class="cov"><span class="num"><pre> 2</pre></span><pre>import inspect</pre></div>
<div class="cov"><span class="num"><pre> 3</pre></span><pre>import logging</pre></div>
<div class="cov"><span class="num"><pre> 4</pre></span><pre>import types</pre></div>
<div class="cov"><span class="num"><pre> 5</pre></span><pre>import xmlrpclib</pre></div>
<div class="skip"><span class="num"><pre> 6</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 7</pre></span><pre>from paste.response import replace_header</pre></div>
<div class="skip"><span class="num"><pre> 8</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 9</pre></span><pre>from pylons.controllers import WSGIController</pre></div>
<div class="cov"><span class="num"><pre> 10</pre></span><pre>from pylons.controllers.util import abort, Response</pre></div>
<div class="skip"><span class="num"><pre> 11</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 12</pre></span><pre>__all__ = ['XMLRPCController']</pre></div>
<div class="skip"><span class="num"><pre> 13</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 14</pre></span><pre>log = logging.getLogger(__name__)</pre></div>
<div class="skip"><span class="num"><pre> 15</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 16</pre></span><pre>XMLRPC_MAPPING = ((basestring, 'string'), (list, 'array'), (bool, 'boolean'),</pre></div>
<div class="cov"><span class="num"><pre> 17</pre></span><pre> (int, 'int'), (float, 'double'), (dict, 'struct'), </pre></div>
<div class="cov"><span class="num"><pre> 18</pre></span><pre> (xmlrpclib.DateTime, 'dateTime.iso8601'),</pre></div>
<div class="cov"><span class="num"><pre> 19</pre></span><pre> (xmlrpclib.Binary, 'base64'))</pre></div>
<div class="skip"><span class="num"><pre> 20</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 21</pre></span><pre>def xmlrpc_sig(args):</pre></div>
<div class="cov"><span class="num"><pre> 22</pre></span><pre> """Returns a list of the function signature in string format based on a </pre></div>
<div class="cov"><span class="num"><pre> 23</pre></span><pre> tuple provided by xmlrpclib."""</pre></div>
<div class="cov"><span class="num"><pre> 24</pre></span><pre> signature = []</pre></div>
<div class="cov"><span class="num"><pre> 25</pre></span><pre> for param in args:</pre></div>
<div class="cov"><span class="num"><pre> 26</pre></span><pre> for type, xml_name in XMLRPC_MAPPING:</pre></div>
<div class="cov"><span class="num"><pre> 27</pre></span><pre> if isinstance(param, type):</pre></div>
<div class="cov"><span class="num"><pre> 28</pre></span><pre> signature.append(xml_name)</pre></div>
<div class="cov"><span class="num"><pre> 29</pre></span><pre> break</pre></div>
<div class="cov"><span class="num"><pre> 30</pre></span><pre> return signature</pre></div>
<div class="skip"><span class="num"><pre> 31</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre> 32</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 33</pre></span><pre>def xmlrpc_fault(code, message):</pre></div>
<div class="cov"><span class="num"><pre> 34</pre></span><pre> """Convienence method to return a Pylons response XMLRPC Fault"""</pre></div>
<div class="cov"><span class="num"><pre> 35</pre></span><pre> fault = xmlrpclib.Fault(code, message)</pre></div>
<div class="cov"><span class="num"><pre> 36</pre></span><pre> return Response(body=xmlrpclib.dumps(fault, methodresponse=True))</pre></div>
<div class="skip"><span class="num"><pre> 37</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre> 38</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 39</pre></span><pre>class XMLRPCController(WSGIController):</pre></div>
<div class="cov"><span class="num"><pre> 40</pre></span><pre> """XML-RPC Controller that speaks WSGI</pre></div>
<div class="skip"><span class="num"><pre> 41</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 42</pre></span><pre> This controller handles XML-RPC responses and complies with the </pre></div>
<div class="cov"><span class="num"><pre> 43</pre></span><pre> `XML-RPC Specification <http://www.xmlrpc.com/spec>`_ as well as</pre></div>
<div class="cov"><span class="num"><pre> 44</pre></span><pre> the `XML-RPC Introspection</pre></div>
<div class="cov"><span class="num"><pre> 45</pre></span><pre> <http://scripts.incutio.com/xmlrpc/introspection.html>`_ </pre></div>
<div class="cov"><span class="num"><pre> 46</pre></span><pre> specification.</pre></div>
<div class="skip"><span class="num"><pre> 47</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 48</pre></span><pre> By default, methods with names containing a dot are translated to</pre></div>
<div class="cov"><span class="num"><pre> 49</pre></span><pre> use an underscore. For example, the `system.methodHelp` is handled</pre></div>
<div class="cov"><span class="num"><pre> 50</pre></span><pre> by the method :meth:`system_methodHelp`.</pre></div>
<div class="skip"><span class="num"><pre> 51</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 52</pre></span><pre> Methods in the XML-RPC controller will be called with the method</pre></div>
<div class="cov"><span class="num"><pre> 53</pre></span><pre> given in the XMLRPC body. Methods may be annotated with a signature</pre></div>
<div class="cov"><span class="num"><pre> 54</pre></span><pre> attribute to declare the valid arguments and return types.</pre></div>
<div class="skip"><span class="num"><pre> 55</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 56</pre></span><pre> For example::</pre></div>
<div class="skip"><span class="num"><pre> 57</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 58</pre></span><pre> class MyXML(XMLRPCController):</pre></div>
<div class="cov"><span class="num"><pre> 59</pre></span><pre> def userstatus(self):</pre></div>
<div class="cov"><span class="num"><pre> 60</pre></span><pre> return 'basic string'</pre></div>
<div class="cov"><span class="num"><pre> 61</pre></span><pre> userstatus.signature = [ ['string'] ]</pre></div>
<div class="skip"><span class="num"><pre> 62</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 63</pre></span><pre> def userinfo(self, username, age=None):</pre></div>
<div class="cov"><span class="num"><pre> 64</pre></span><pre> user = LookUpUser(username)</pre></div>
<div class="cov"><span class="num"><pre> 65</pre></span><pre> response = {'username':user.name}</pre></div>
<div class="cov"><span class="num"><pre> 66</pre></span><pre> if age and age > 10:</pre></div>
<div class="cov"><span class="num"><pre> 67</pre></span><pre> response['age'] = age</pre></div>
<div class="cov"><span class="num"><pre> 68</pre></span><pre> return response</pre></div>
<div class="cov"><span class="num"><pre> 69</pre></span><pre> userinfo.signature = [['struct', 'string'],</pre></div>
<div class="cov"><span class="num"><pre> 70</pre></span><pre> ['struct', 'string', 'int']]</pre></div>
<div class="skip"><span class="num"><pre> 71</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 72</pre></span><pre> Since XML-RPC methods can take different sets of data, each set of</pre></div>
<div class="cov"><span class="num"><pre> 73</pre></span><pre> valid arguments is its own list. The first value in the list is the</pre></div>
<div class="cov"><span class="num"><pre> 74</pre></span><pre> type of the return argument. The rest of the arguments are the</pre></div>
<div class="cov"><span class="num"><pre> 75</pre></span><pre> types of the data that must be passed in.</pre></div>
<div class="skip"><span class="num"><pre> 76</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 77</pre></span><pre> In the last method in the example above, since the method can</pre></div>
<div class="cov"><span class="num"><pre> 78</pre></span><pre> optionally take an integer value both sets of valid parameter lists</pre></div>
<div class="cov"><span class="num"><pre> 79</pre></span><pre> should be provided.</pre></div>
<div class="skip"><span class="num"><pre> 80</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 81</pre></span><pre> Valid types that can be checked in the signature and their</pre></div>
<div class="cov"><span class="num"><pre> 82</pre></span><pre> corresponding Python types::</pre></div>
<div class="skip"><span class="num"><pre> 83</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 84</pre></span><pre> 'string' - str</pre></div>
<div class="cov"><span class="num"><pre> 85</pre></span><pre> 'array' - list</pre></div>
<div class="cov"><span class="num"><pre> 86</pre></span><pre> 'boolean' - bool</pre></div>
<div class="cov"><span class="num"><pre> 87</pre></span><pre> 'int' - int</pre></div>
<div class="cov"><span class="num"><pre> 88</pre></span><pre> 'double' - float</pre></div>
<div class="cov"><span class="num"><pre> 89</pre></span><pre> 'struct' - dict</pre></div>
<div class="cov"><span class="num"><pre> 90</pre></span><pre> 'dateTime.iso8601' - xmlrpclib.DateTime</pre></div>
<div class="cov"><span class="num"><pre> 91</pre></span><pre> 'base64' - xmlrpclib.Binary</pre></div>
<div class="skip"><span class="num"><pre> 92</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre> 93</pre></span><pre> The class variable ``allow_none`` is passed to xmlrpclib.dumps;</pre></div>
<div class="cov"><span class="num"><pre> 94</pre></span><pre> enabling it allows translating ``None`` to XML (an extension to the</pre></div>
<div class="cov"><span class="num"><pre> 95</pre></span><pre> XML-RPC specification)</pre></div>
<div class="skip"><span class="num"><pre> 96</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 97</pre></span><pre> .. note::</pre></div>
<div class="skip"><span class="num"><pre> 98</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 99</pre></span><pre> Requiring a signature is optional.</pre></div>
<div class="skip"><span class="num"><pre>100</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre>101</pre></span><pre> """</pre></div>
<div class="cov"><span class="num"><pre>102</pre></span><pre> allow_none = False</pre></div>
<div class="cov"><span class="num"><pre>103</pre></span><pre> max_body_length = 4194304</pre></div>
<div class="skip"><span class="num"><pre>104</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>105</pre></span><pre> def _get_method_args(self):</pre></div>
<div class="cov"><span class="num"><pre>106</pre></span><pre> return self.rpc_kargs</pre></div>
<div class="skip"><span class="num"><pre>107</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>108</pre></span><pre> def __call__(self, environ, start_response):</pre></div>
<div class="cov"><span class="num"><pre>109</pre></span><pre> """Parse an XMLRPC body for the method, and call it with the</pre></div>
<div class="cov"><span class="num"><pre>110</pre></span><pre> appropriate arguments"""</pre></div>
<div class="skip"><span class="num"><pre>111</pre></span><pre> # Pull out the length, return an error if there is no valid</pre></div>
<div class="skip"><span class="num"><pre>112</pre></span><pre> # length or if the length is larger than the max_body_length.</pre></div>
<div class="cov"><span class="num"><pre>113</pre></span><pre> log_debug = self._pylons_log_debug</pre></div>
<div class="cov"><span class="num"><pre>114</pre></span><pre> length = environ.get('CONTENT_LENGTH')</pre></div>
<div class="cov"><span class="num"><pre>115</pre></span><pre> if length:</pre></div>
<div class="cov"><span class="num"><pre>116</pre></span><pre> length = int(length)</pre></div>
<div class="cov"><span class="num"><pre>117</pre></span><pre> else:</pre></div>
<div class="skip"><span class="num"><pre>118</pre></span><pre> # No valid Content-Length header found</pre></div>
<div class="cov"><span class="num"><pre>119</pre></span><pre> if log_debug:</pre></div>
<div class="cov"><span class="num"><pre>120</pre></span><pre> log.debug("No Content-Length found, returning 411 error")</pre></div>
<div class="cov"><span class="num"><pre>121</pre></span><pre> abort(411)</pre></div>
<div class="cov"><span class="num"><pre>122</pre></span><pre> if length > self.max_body_length or length == 0:</pre></div>
<div class="cov"><span class="num"><pre>123</pre></span><pre> if log_debug:</pre></div>
<div class="cov"><span class="num"><pre>124</pre></span><pre> log.debug("Content-Length larger than max body length. Max: "</pre></div>
<div class="cov"><span class="num"><pre>125</pre></span><pre> "%s, Sent: %s. Returning 413 error",</pre></div>
<div class="cov"><span class="num"><pre>126</pre></span><pre> self.max_body_length, length)</pre></div>
<div class="cov"><span class="num"><pre>127</pre></span><pre> abort(413, "XML body too large")</pre></div>
<div class="skip"><span class="num"><pre>128</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>129</pre></span><pre> body = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))</pre></div>
<div class="cov"><span class="num"><pre>130</pre></span><pre> rpc_args, orig_method = xmlrpclib.loads(body)</pre></div>
<div class="skip"><span class="num"><pre>131</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>132</pre></span><pre> method = self._find_method_name(orig_method)</pre></div>
<div class="cov"><span class="num"><pre>133</pre></span><pre> func = self._find_method(method)</pre></div>
<div class="cov"><span class="num"><pre>134</pre></span><pre> if not func:</pre></div>
<div class="cov"><span class="num"><pre>135</pre></span><pre> if log_debug:</pre></div>
<div class="cov"><span class="num"><pre>136</pre></span><pre> log.debug("Method: %r not found, returning xmlrpc fault",</pre></div>
<div class="cov"><span class="num"><pre>137</pre></span><pre> method)</pre></div>
<div class="cov"><span class="num"><pre>138</pre></span><pre> return xmlrpc_fault(0, "No such method name %r" %</pre></div>
<div class="cov"><span class="num"><pre>139</pre></span><pre> method)(environ, start_response)</pre></div>
<div class="skip"><span class="num"><pre>140</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre>141</pre></span><pre> # Signature checking for params</pre></div>
<div class="cov"><span class="num"><pre>142</pre></span><pre> if hasattr(func, 'signature'):</pre></div>
<div class="cov"><span class="num"><pre>143</pre></span><pre> if log_debug:</pre></div>
<div class="cov"><span class="num"><pre>144</pre></span><pre> log.debug("Checking XMLRPC argument signature")</pre></div>
<div class="cov"><span class="num"><pre>145</pre></span><pre> valid_args = False</pre></div>
<div class="cov"><span class="num"><pre>146</pre></span><pre> params = xmlrpc_sig(rpc_args)</pre></div>
<div class="cov"><span class="num"><pre>147</pre></span><pre> for sig in func.signature:</pre></div>
<div class="skip"><span class="num"><pre>148</pre></span><pre> # Next sig if we don't have the same amount of args</pre></div>
<div class="cov"><span class="num"><pre>149</pre></span><pre> if len(sig)-1 != len(rpc_args):</pre></div>
<div class="cov"><span class="num"><pre>150</pre></span><pre> continue</pre></div>
<div class="skip"><span class="num"><pre>151</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre>152</pre></span><pre> # If the params match, we're valid</pre></div>
<div class="cov"><span class="num"><pre>153</pre></span><pre> if params == sig[1:]:</pre></div>
<div class="cov"><span class="num"><pre>154</pre></span><pre> valid_args = True</pre></div>
<div class="cov"><span class="num"><pre>155</pre></span><pre> break</pre></div>
<div class="skip"><span class="num"><pre>156</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>157</pre></span><pre> if not valid_args:</pre></div>
<div class="cov"><span class="num"><pre>158</pre></span><pre> if log_debug:</pre></div>
<div class="cov"><span class="num"><pre>159</pre></span><pre> log.debug("Bad argument signature recieved, returning "</pre></div>
<div class="cov"><span class="num"><pre>160</pre></span><pre> "xmlrpc fault")</pre></div>
<div class="cov"><span class="num"><pre>161</pre></span><pre> msg = ("Incorrect argument signature. %r recieved does not "</pre></div>
<div class="cov"><span class="num"><pre>162</pre></span><pre> "match %r signature for method %r" % \</pre></div>
<div class="cov"><span class="num"><pre>163</pre></span><pre> (params, func.signature, orig_method))</pre></div>
<div class="cov"><span class="num"><pre>164</pre></span><pre> return xmlrpc_fault(0, msg)(environ, start_response)</pre></div>
<div class="skip"><span class="num"><pre>165</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre>166</pre></span><pre> # Change the arg list into a keyword dict based off the arg</pre></div>
<div class="skip"><span class="num"><pre>167</pre></span><pre> # names in the functions definition</pre></div>
<div class="cov"><span class="num"><pre>168</pre></span><pre> arglist = inspect.getargspec(func)[0][1:]</pre></div>
<div class="cov"><span class="num"><pre>169</pre></span><pre> kargs = dict(zip(arglist, rpc_args))</pre></div>
<div class="cov"><span class="num"><pre>170</pre></span><pre> kargs['action'], kargs['environ'] = method, environ</pre></div>
<div class="cov"><span class="num"><pre>171</pre></span><pre> kargs['start_response'] = start_response</pre></div>
<div class="cov"><span class="num"><pre>172</pre></span><pre> self.rpc_kargs = kargs</pre></div>
<div class="cov"><span class="num"><pre>173</pre></span><pre> self._func = func</pre></div>
<div class="skip"><span class="num"><pre>174</pre></span><pre> </pre></div>
<div class="skip"><span class="num"><pre>175</pre></span><pre> # Now that we know the method is valid, and the args are valid,</pre></div>
<div class="skip"><span class="num"><pre>176</pre></span><pre> # we can dispatch control to the default WSGIController</pre></div>
<div class="cov"><span class="num"><pre>177</pre></span><pre> status = []</pre></div>
<div class="cov"><span class="num"><pre>178</pre></span><pre> headers = []</pre></div>
<div class="cov"><span class="num"><pre>179</pre></span><pre> exc_info = []</pre></div>
<div class="cov"><span class="num"><pre>180</pre></span><pre> def change_content(new_status, new_headers, new_exc_info=None):</pre></div>
<div class="cov"><span class="num"><pre>181</pre></span><pre> status.append(new_status)</pre></div>
<div class="cov"><span class="num"><pre>182</pre></span><pre> headers.extend(new_headers)</pre></div>
<div class="cov"><span class="num"><pre>183</pre></span><pre> exc_info.append(new_exc_info)</pre></div>
<div class="cov"><span class="num"><pre>184</pre></span><pre> output = WSGIController.__call__(self, environ, change_content)</pre></div>
<div class="cov"><span class="num"><pre>185</pre></span><pre> output = list(output)</pre></div>
<div class="cov"><span class="num"><pre>186</pre></span><pre> headers.append(('Content-Length', str(len(output[0]))))</pre></div>
<div class="cov"><span class="num"><pre>187</pre></span><pre> replace_header(headers, 'Content-Type', 'text/xml')</pre></div>
<div class="cov"><span class="num"><pre>188</pre></span><pre> start_response(status[0], headers, exc_info[0])</pre></div>
<div class="cov"><span class="num"><pre>189</pre></span><pre> return output</pre></div>
<div class="skip"><span class="num"><pre>190</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>191</pre></span><pre> def _dispatch_call(self):</pre></div>
<div class="cov"><span class="num"><pre>192</pre></span><pre> """Dispatch the call to the function chosen by __call__"""</pre></div>
<div class="cov"><span class="num"><pre>193</pre></span><pre> raw_response = self._inspect_call(self._func)</pre></div>
<div class="cov"><span class="num"><pre>194</pre></span><pre> if not isinstance(raw_response, xmlrpclib.Fault):</pre></div>
<div class="cov"><span class="num"><pre>195</pre></span><pre> raw_response = (raw_response,)</pre></div>
<div class="skip"><span class="num"><pre>196</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>197</pre></span><pre> response = xmlrpclib.dumps(raw_response, methodresponse=True,</pre></div>
<div class="cov"><span class="num"><pre>198</pre></span><pre> allow_none=self.allow_none)</pre></div>
<div class="cov"><span class="num"><pre>199</pre></span><pre> return response</pre></div>
<div class="skip"><span class="num"><pre>200</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>201</pre></span><pre> def _find_method(self, name):</pre></div>
<div class="cov"><span class="num"><pre>202</pre></span><pre> """Locate a method in the controller by the specified name and</pre></div>
<div class="cov"><span class="num"><pre>203</pre></span><pre> return it"""</pre></div>
<div class="skip"><span class="num"><pre>204</pre></span><pre> # Keep private methods private</pre></div>
<div class="cov"><span class="num"><pre>205</pre></span><pre> if name.startswith('_'):</pre></div>
<div class="cov"><span class="num"><pre>206</pre></span><pre> if self._pylons_log_debug:</pre></div>
<div class="cov"><span class="num"><pre>207</pre></span><pre> log.debug("Action starts with _, private action not allowed")</pre></div>
<div class="cov"><span class="num"><pre>208</pre></span><pre> return</pre></div>
<div class="skip"><span class="num"><pre>209</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>210</pre></span><pre> if self._pylons_log_debug:</pre></div>
<div class="cov"><span class="num"><pre>211</pre></span><pre> log.debug("Looking for XMLRPC method: %r", name)</pre></div>
<div class="cov"><span class="num"><pre>212</pre></span><pre> try:</pre></div>
<div class="cov"><span class="num"><pre>213</pre></span><pre> func = getattr(self, name, None)</pre></div>
<div class="cov"><span class="num"><pre>214</pre></span><pre> except UnicodeEncodeError:</pre></div>
<div class="cov"><span class="num"><pre>215</pre></span><pre> return</pre></div>
<div class="cov"><span class="num"><pre>216</pre></span><pre> if isinstance(func, types.MethodType):</pre></div>
<div class="cov"><span class="num"><pre>217</pre></span><pre> return func</pre></div>
<div class="skip"><span class="num"><pre>218</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>219</pre></span><pre> def _find_method_name(self, name):</pre></div>
<div class="cov"><span class="num"><pre>220</pre></span><pre> """Locate a method in the controller by the appropriate name</pre></div>
<div class="skip"><span class="num"><pre>221</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre>222</pre></span><pre> By default, this translates method names like </pre></div>
<div class="cov"><span class="num"><pre>223</pre></span><pre> 'system.methodHelp' into 'system_methodHelp'.</pre></div>
<div class="skip"><span class="num"><pre>224</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre>225</pre></span><pre> """</pre></div>
<div class="cov"><span class="num"><pre>226</pre></span><pre> return name.replace('.', '_')</pre></div>
<div class="skip"><span class="num"><pre>227</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>228</pre></span><pre> def _publish_method_name(self, name):</pre></div>
<div class="cov"><span class="num"><pre>229</pre></span><pre> """Translate an internal method name to a publicly viewable one</pre></div>
<div class="skip"><span class="num"><pre>230</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre>231</pre></span><pre> By default, this translates internal method names like</pre></div>
<div class="cov"><span class="num"><pre>232</pre></span><pre> 'blog_view' into 'blog.view'.</pre></div>
<div class="skip"><span class="num"><pre>233</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre>234</pre></span><pre> """</pre></div>
<div class="cov"><span class="num"><pre>235</pre></span><pre> return name.replace('_', '.')</pre></div>
<div class="skip"><span class="num"><pre>236</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>237</pre></span><pre> def system_listMethods(self):</pre></div>
<div class="cov"><span class="num"><pre>238</pre></span><pre> """Returns a list of XML-RPC methods for this XML-RPC resource"""</pre></div>
<div class="cov"><span class="num"><pre>239</pre></span><pre> methods = []</pre></div>
<div class="cov"><span class="num"><pre>240</pre></span><pre> for method in dir(self):</pre></div>
<div class="cov"><span class="num"><pre>241</pre></span><pre> meth = getattr(self, method)</pre></div>
<div class="skip"><span class="num"><pre>242</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>243</pre></span><pre> if not method.startswith('_') and isinstance(meth,</pre></div>
<div class="cov"><span class="num"><pre>244</pre></span><pre> types.MethodType):</pre></div>
<div class="cov"><span class="num"><pre>245</pre></span><pre> methods.append(self._publish_method_name(method))</pre></div>
<div class="cov"><span class="num"><pre>246</pre></span><pre> return methods</pre></div>
<div class="cov"><span class="num"><pre>247</pre></span><pre> system_listMethods.signature = [['array']]</pre></div>
<div class="skip"><span class="num"><pre>248</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>249</pre></span><pre> def system_methodSignature(self, name):</pre></div>
<div class="cov"><span class="num"><pre>250</pre></span><pre> """Returns an array of array's for the valid signatures for a</pre></div>
<div class="cov"><span class="num"><pre>251</pre></span><pre> method.</pre></div>
<div class="skip"><span class="num"><pre>252</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>253</pre></span><pre> The first value of each array is the return value of the</pre></div>
<div class="cov"><span class="num"><pre>254</pre></span><pre> method. The result is an array to indicate multiple signatures</pre></div>
<div class="cov"><span class="num"><pre>255</pre></span><pre> a method may be capable of.</pre></div>
<div class="skip"><span class="num"><pre>256</pre></span><pre> </pre></div>
<div class="cov"><span class="num"><pre>257</pre></span><pre> """</pre></div>
<div class="cov"><span class="num"><pre>258</pre></span><pre> method = self._find_method(self._find_method_name(name))</pre></div>
<div class="cov"><span class="num"><pre>259</pre></span><pre> if method:</pre></div>
<div class="cov"><span class="num"><pre>260</pre></span><pre> return getattr(method, 'signature', '')</pre></div>
<div class="cov"><span class="num"><pre>261</pre></span><pre> else:</pre></div>
<div class="cov"><span class="num"><pre>262</pre></span><pre> return xmlrpclib.Fault(0, 'No such method name')</pre></div>
<div class="cov"><span class="num"><pre>263</pre></span><pre> system_methodSignature.signature = [['array', 'string'],</pre></div>
<div class="cov"><span class="num"><pre>264</pre></span><pre> ['string', 'string']]</pre></div>
<div class="skip"><span class="num"><pre>265</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>266</pre></span><pre> def system_methodHelp(self, name):</pre></div>
<div class="cov"><span class="num"><pre>267</pre></span><pre> """Returns the documentation for a method"""</pre></div>
<div class="cov"><span class="num"><pre>268</pre></span><pre> method = self._find_method(self._find_method_name(name))</pre></div>
<div class="cov"><span class="num"><pre>269</pre></span><pre> if method:</pre></div>
<div class="cov"><span class="num"><pre>270</pre></span><pre> help = MethodHelp.getdoc(method)</pre></div>
<div class="cov"><span class="num"><pre>271</pre></span><pre> sig = getattr(method, 'signature', None)</pre></div>
<div class="cov"><span class="num"><pre>272</pre></span><pre> if sig:</pre></div>
<div class="cov"><span class="num"><pre>273</pre></span><pre> help += "\n\nMethod signature: %s" % sig</pre></div>
<div class="cov"><span class="num"><pre>274</pre></span><pre> return help</pre></div>
<div class="cov"><span class="num"><pre>275</pre></span><pre> return xmlrpclib.Fault(0, "No such method name")</pre></div>
<div class="cov"><span class="num"><pre>276</pre></span><pre> system_methodHelp.signature = [['string', 'string']]</pre></div>
<div class="skip"><span class="num"><pre>277</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre>278</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>279</pre></span><pre>class MethodHelp(object):</pre></div>
<div class="cov"><span class="num"><pre>280</pre></span><pre> """Wrapper for formatting doc strings from XMLRPCController</pre></div>
<div class="cov"><span class="num"><pre>281</pre></span><pre> methods"""</pre></div>
<div class="cov"><span class="num"><pre>282</pre></span><pre> def __init__(self, doc):</pre></div>
<div class="cov"><span class="num"><pre>283</pre></span><pre> self.__doc__ = doc</pre></div>
<div class="skip"><span class="num"><pre>284</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>285</pre></span><pre> def getdoc(method):</pre></div>
<div class="cov"><span class="num"><pre>286</pre></span><pre> """Return a formatted doc string, via inspect.getdoc, from the</pre></div>
<div class="cov"><span class="num"><pre>287</pre></span><pre> specified XMLRPCController method</pre></div>
<div class="skip"><span class="num"><pre>288</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>289</pre></span><pre> The method's help attribute is used if it exists, otherwise the</pre></div>
<div class="cov"><span class="num"><pre>290</pre></span><pre> method's doc string is used.</pre></div>
<div class="cov"><span class="num"><pre>291</pre></span><pre> """</pre></div>
<div class="cov"><span class="num"><pre>292</pre></span><pre> help = getattr(method, 'help', None)</pre></div>
<div class="cov"><span class="num"><pre>293</pre></span><pre> if help is None:</pre></div>
<div class="cov"><span class="num"><pre>294</pre></span><pre> help = method.__doc__</pre></div>
<div class="cov"><span class="num"><pre>295</pre></span><pre> doc = inspect.getdoc(MethodHelp(help))</pre></div>
<div class="cov"><span class="num"><pre>296</pre></span><pre> if doc is None:</pre></div>
<div class="cov"><span class="num"><pre>297</pre></span><pre> return ''</pre></div>
<div class="cov"><span class="num"><pre>298</pre></span><pre> return doc</pre></div>
<div class="cov"><span class="num"><pre>299</pre></span><pre> getdoc = staticmethod(getdoc)</pre></div>
<div class="skip"><span class="num"><pre>300</pre></span><pre></pre></div>
</div>
</body>
</html>
|