__pycache__/__init__.cpython-36.opt-1.pyc000064400000000172147204464040014105 0ustar003 \&@sdS)Nrrr'/usr/lib64/python3.6/xmlrpc/__init__.pys__pycache__/__init__.cpython-36.opt-2.pyc000064400000000172147204464040014106 0ustar003 \&@sdS)Nrrr'/usr/lib64/python3.6/xmlrpc/__init__.pys__pycache__/__init__.cpython-36.pyc000064400000000172147204464040013146 0ustar003 \&@sdS)Nrrr'/usr/lib64/python3.6/xmlrpc/__init__.pys__pycache__/client.cpython-36.opt-1.pyc000064400000103330147204464040013624 0ustar003 \\&@sjdZddlZddlZddlZddlmZddlmZddlZddl Z ddl m Z ddl Z ddlmZy ddlZWnek rdZYnXddZd ejdd ZdYZd[Zd\Zd]Zd^Zd_Zd`ZdaZdbZdcZddZdeZ dfZ!dgZ"Gddde#Z$Gddde$Z%Gddde$Z&Gddde$Z'e(Z)Z*ed d d Z+e+j,dd krJd!d"Z-n"e+j,d#d krdd$d"Z-nd%d"Z-[+d&d'Z.Gd(d)d)Z/d*d+Z0d,d-Z1Gd.d/d/Z2d0d1Z3e/e2fZ4Gd2d3d3Z5Gd4d5d5Z6Gd6d7d7Z7Gd8d9d9Z8Gd:d;d;Z9GddidAdBZ?djdCdDZ@dEdFZAdkdHdIZBGdJdKdKerXejCneDZEGdLdMdMZFGdNdOdOZGGdPdQdQeGZHGdRdSdSZIeIZJeKdTkrfeIdUZLyeMeLjNjOWn.e$k rZPzeMdVePWYddZP[PXnXe:eLZQeQjReQjSd dWeQjTd d yxeQD]ZUeMeUq"WWn.e$k rdZPzeMdVePWYddZP[PXnXdS)la An XML-RPC client interface for Python. The marshalling and response parser code can also be used to implement XML-RPC servers. Exported exceptions: Error Base class for client errors ProtocolError Indicates an HTTP protocol error ResponseError Indicates a broken response package Fault Indicates an XML-RPC fault package Exported classes: ServerProxy Represents a logical connection to an XML-RPC server MultiCall Executor of boxcared xmlrpc requests DateTime dateTime wrapper for an ISO 8601 string or time tuple or localtime integer value to generate a "dateTime.iso8601" XML-RPC value Binary binary data wrapper Marshaller Generate an XML-RPC params chunk from a Python data structure Unmarshaller Unmarshal an XML-RPC response from incoming XML event message Transport Handles an HTTP transaction to an XML-RPC server SafeTransport Handles an HTTPS transaction to an XML-RPC server Exported constants: (none) Exported functions: getparser Create instance of the fastest available parser & attach to an unmarshalling object dumps Convert an argument tuple or a Fault instance to an XML-RPC request (or response, if the methodresponse option is used). loads Convert an XML-RPC packet to unmarshalled data plus a method name (None if not present). N)datetime)Decimal)expat)BytesIOcCs$|jdd}|jdd}|jddS)N&z&z>)replace)sr %/usr/lib64/python3.6/xmlrpc/client.pyescapes  r z%d.%diiXi~i~i,~iiiYiZi[c@seZdZdZddZdS)ErrorzBase class for client errors.cCst|S)N)repr)selfr r r __str__sz Error.__str__N)__name__ __module__ __qualname____doc__rr r r r rsrc@s eZdZdZddZddZdS) ProtocolErrorz!Indicates an HTTP protocol error.cCs&tj|||_||_||_||_dS)N)r__init__urlerrcodeerrmsgheaders)rrrrrr r r rs  zProtocolError.__init__cCsd|jj|j|j|jfS)Nz<%s for %s: %s %s>) __class__rrrr)rr r r __repr__szProtocolError.__repr__N)rrrrrr r r r r rsrc@seZdZdZdS) ResponseErrorz$Indicates a broken response package.N)rrrrr r r r r!sr!c@s eZdZdZddZddZdS)Faultz#Indicates an XML-RPC fault package.cKstj|||_||_dS)N)rr faultCode faultString)rr#r$Zextrar r r rs zFault.__init__cCsd|jj|j|jfS)Nz <%s %s: %r>)rrr#r$)rr r r r szFault.__repr__N)rrrrrr r r r r r"sr"z%YZ0001cCs |jdS)Nz%Y%m%dT%H:%M:%S)strftime)valuer r r _iso8601_format sr'z%4YcCs |jdS)Nz%4Y%m%dT%H:%M:%S)r%)r&r r r r'scCs|jdjdS)Nz%Y%m%dT%H:%M:%S)r%zfill)r&r r r r'scCsLt|trt|St|ttjfs<|dkr2tj}tj|}d|ddS)Nrz%04d%02d%02dT%02d:%02d:%02d) isinstancerr'tupletimeZ struct_timeZ localtime)r&r r r _strftimes  r.c@sreZdZdZdddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZddZdS)DateTimezDateTime wrapper for an ISO 8601 string or time tuple or localtime integer value to generate 'dateTime.iso8601' XML-RPC value. rcCs t|tr||_n t||_dS)N)r+strr&r.)rr&r r r r)s zDateTime.__init__cCst|tr|j}|j}nzt|tr2|j}t|}n`t|trH|j}|}nJt|drd|j}|j}n.t|drv|jj p|t |}t d|jj |f||fS)N timetuplerzCan't compare %s and %s) r+r/r&rr'r0hasattrr1rrtype TypeError)rotherr oZotyper r r make_comparable/s$       zDateTime.make_comparablecCs|j|\}}||kS)N)r7)rr5r r6r r r __lt__DszDateTime.__lt__cCs|j|\}}||kS)N)r7)rr5r r6r r r __le__HszDateTime.__le__cCs|j|\}}||kS)N)r7)rr5r r6r r r __gt__LszDateTime.__gt__cCs|j|\}}||kS)N)r7)rr5r r6r r r __ge__PszDateTime.__ge__cCs|j|\}}||kS)N)r7)rr5r r6r r r __eq__TszDateTime.__eq__cCstj|jdS)Nz%Y%m%dT%H:%M:%S)r-strptimer&)rr r r r1XszDateTime.timetuplecCs|jS)N)r&)rr r r r`szDateTime.__str__cCsd|jj|jt|fS)Nz<%s %r at %#x>)rrr&id)rr r r r cszDateTime.__repr__cCst|j|_dS)N)r0stripr&)rdatar r r decodefszDateTime.decodecCs$|jd|j|j|jddS)Nzz )writer&)routr r r encodeis  zDateTime.encodeN)r)rrrrrr7r8r9r:r;r<r1rr rArDr r r r r/#s r/cCst}|j||S)N)r/rA)r@r&r r r _datetimens rEcCs tj|dS)Nz%Y%m%dT%H:%M:%S)rr=)r@r r r _datetime_typetsrFc@s:eZdZdZd ddZddZddZd d Zd d ZdS)BinaryzWrapper for binary data.NcCs>|dkrd}n&t|ttfs,td|jjt|}||_dS)Nz#expected bytes or bytearray, not %s)r+bytes bytearrayr4rrr@)rr@r r r rs zBinary.__init__cCs t|jdS)Nzlatin-1)r0r@)rr r r rszBinary.__str__cCst|tr|j}|j|kS)N)r+rGr@)rr5r r r r<s z Binary.__eq__cCstj||_dS)N)base64 decodebytesr@)rr@r r r rAsz Binary.decodecCs4|jdtj|j}|j|jd|jddS)Nz asciiz )rBrK encodebytesr@rA)rrCencodedr r r rDs  z Binary.encode)N) rrrrrrr<rArDr r r r rG}s  rGcCst}|j||S)N)rGrA)r@r&r r r _binarys rPc@s$eZdZddZddZddZdS) ExpatParsercCsDtjdd|_}||_|j|_|j|_|j|_ d}|j |ddS)N) rZ ParserCreate_parser_targetstartZStartElementHandlerendZEndElementHandlerr@ZCharacterDataHandlerxml)rtargetparserencodingr r r rszExpatParser.__init__cCs|jj|ddS)Nr)rRParse)rr@r r r feedszExpatParser.feedc Cs8y |j}Wntk rYnX|`|`|jdddS)NrHT)rRAttributeErrorrSrZ)rrXr r r closes  zExpatParser.closeN)rrrrr[r]r r r r rQs rQc@seZdZdZdddZiZddZdd Zd d Zeee d<d d Z e ee <ddZ e ee <e ZddZeee<efddZeee<ddZeee<eee<ddZeee<eee<efddZeee<ddZeee<ddZeee<eee <eed<dS) MarshalleravGenerate an XML-RPC params chunk from a Python data structure. Create a Marshaller instance for each set of parameters, and use the "dumps" method to convert your data (represented as a tuple) to an XML-RPC params chunk. To write a fault response, pass a Fault instance instead. You may prefer to use the "dumps" module function for this purpose. NFcCsi|_d|_||_||_dS)N)memor@rY allow_none)rrYr`r r r rszMarshaller.__init__cCsg}|j}|j}t|tr@|d||j|jd||dn8|dx&|D]}|d||||dqNW|ddj|}|S) Nz )r#r$z z z z z )append_Marshaller__dumpr+r"r#r$join)rvaluesrCrBdumpvresultr r r dumpss"      zMarshaller.dumpsc Csy|jt|}Wnjtk r|t|ds)r`r4)rr&rBr r r dump_nilszMarshaller.dump_nilcCs$|d||rdpd|ddS)Nz10z r )rr&rBr r r dump_boolszMarshaller.dump_boolcCs<|tks|tkrtd|d|tt||ddS)Nzint exceeds XML-RPC limitsz z )MAXINTMININT OverflowErrorr0int)rr&rBr r r dump_longs zMarshaller.dump_longcCs |d|t||ddS)Nzz )r)rr&rBr r r dump_double%s zMarshaller.dump_doublecCs |d||||ddS)Nzz r )rr&rBr r r r dump_unicode+s zMarshaller.dump_unicodecCs,|dtj|}||jd|ddS)Nz rMz )rKrNrA)rr&rBrOr r r dump_bytes1s zMarshaller.dump_bytescCs^t|}||jkrtdd|j|<|j}|dx|D]}|||q8W|d|j|=dS)Nz"cannot marshal recursive sequencesz z )r>r_r4rc)rr&rBirfrgr r r dump_array9s   zMarshaller.dump_arraycCst|}||jkrtdd|j|<|j}|dxP|jD]D\}}|dt|ts^td|d||||||dq z zdictionary key must be stringz%s z z )r>r_r4rcitemsr+r0)rr&rBr r}rfkrgr r r dump_structGs     zMarshaller.dump_structcCs |d|t||ddS)Nzz )r.)rr&rBr r r dump_datetimeYs zMarshaller.dump_datetimecCs2|jtkr ||_|j||`n|j|j|dS)N)rWRAPPERSrBrDrrj)rr&rBr r r dump_instance_s   zMarshaller.dump_instancerk)NF)!rrrrrrlrircrqr3rtboolryrxZdump_intrzfloatr r{r0r|rIrJr~r,listrdictrrrr/rGr r r r r^s<      r^c@sneZdZdZdEddZddZddZd d Zd d Zd dZ ddZ ddZ iZ ddZ e e d<ddZee d<ddZee d<ee d<ee d<ee d<ee d<ee d <d!d"Zee d#<ee d$<d%d&Zee d'<d(d)Zee d*<ee d+<d,d-Zee d.<d/d0Zee d1<d2d3Zee d4<d5d6Zee d7<d8d9Zee d:<d;d<Zee d=<d>d?Zee d@<dAdBZee dC<dDS)F UnmarshalleraUnmarshal an XML-RPC response, based on incoming XML event messages (start, data, end). Call close() to get the resulting data structure. Note that this reader is fairly tolerant, and gladly accepts bogus XML-RPC data without complaining (but not bogus XML). FcCsHd|_g|_g|_g|_d|_d|_d|_|jj|_|p:||_||_ dS)NFzutf-8) _type_stack_marks_data_value _methodname _encodingrb _use_datetime _use_bytes)r use_datetimeuse_builtin_typesr r r rs  zUnmarshaller.__init__cCs:|jdks|jrt|jdkr0tf|jdt|jS)Nfaultr)rrr!r"rr,)rr r r r]s  zUnmarshaller.closecCs|jS)N)r)rr r r getmethodnameszUnmarshaller.getmethodnamecCs ||_dS)N)r)rrYZ standaloner r r rVszUnmarshaller.xmlcCshd|kr|jdd}|dks&|dkr8|jjt|jg|_|jrZ||jkrZtd||dk|_dS)N:rarraystructzunknown tag %rr&) splitrrblenrrrrlr!)rtagZattrsr r r rTs zUnmarshaller.startcCs|jj|dS)N)rrb)rtextr r r r@szUnmarshaller.datacCspy|j|}WnNtk r\d|kr*dSy|j|jdd}Wntk rVdSXYnX||dj|jS)Nrrrar)rlrmrrdr)rrrpr r r rUs zUnmarshaller.endcCshy|j|}WnNtk r\d|kr*dSy|j|jdd}Wntk rVdSXYnX|||S)Nrrr)rlrmr)rrr@rpr r r end_dispatchs zUnmarshaller.end_dispatchcCs|jdd|_dS)Nr)rbr)rr@r r r end_nils zUnmarshaller.end_nilZnilcCs:|dkr|jdn|dkr(|jdntdd|_dS)NrsFrrTzbad boolean valuer)rbr4r)rr@r r r end_booleans   zUnmarshaller.end_booleanbooleancCs|jt|d|_dS)Nr)rbrxr)rr@r r r end_intszUnmarshaller.end_intZi1Zi2Zi4Zi8rxZ bigintegercCs|jt|d|_dS)Nr)rbrr)rr@r r r end_doubleszUnmarshaller.end_doubleZdoublercCs|jt|d|_dS)Nr)rbrr)rr@r r r end_bigdecimalszUnmarshaller.end_bigdecimalZ bigdecimalcCs&|jr|j|j}|j|d|_dS)Nr)rrArbr)rr@r r r end_strings  zUnmarshaller.end_stringstringnamecCs.|jj}|j|dg|j|d<d|_dS)Nr)rpoprr)rr@markr r r end_arrays zUnmarshaller.end_arrayrcCsd|jj}i}|j|d}x,tdt|dD]}||d|||<q.W|g|j|d<d|_dS)Nrrr)rrrrangerr)rr@rrrr}r r r end_structs zUnmarshaller.end_structrcCs6t}|j|jd|jr"|j}|j|d|_dS)NrMr)rGrArDrr@rbr)rr@r&r r r end_base64 s  zUnmarshaller.end_base64rKcCs,t}|j||jrt|}|j|dS)N)r/rArrFrb)rr@r&r r r end_dateTimes  zUnmarshaller.end_dateTimezdateTime.iso8601cCs|jr|j|dS)N)rr)rr@r r r end_valueszUnmarshaller.end_valuer&cCs d|_dS)Nparams)r)rr@r r r end_params#szUnmarshaller.end_paramsrcCs d|_dS)Nr)r)rr@r r r end_fault'szUnmarshaller.end_faultrcCs"|jr|j|j}||_d|_dS)N methodName)rrArr)rr@r r r end_methodName+s zUnmarshaller.end_methodNamerN)FF)rrrrrr]rrVrTr@rUrrlrrrrrrrrrrrrrrr r r r rssZ   rc@s$eZdZddZddZddZdS)_MultiCallMethodcCs||_||_dS)N)_MultiCallMethod__call_list_MultiCallMethod__name)rZ call_listrr r r r8sz_MultiCallMethod.__init__cCst|jd|j|fS)Nz%s.%s)rrr)rrr r r __getattr__;sz_MultiCallMethod.__getattr__cGs|jj|j|fdS)N)rrbr)rargsr r r __call__=sz_MultiCallMethod.__call__N)rrrrrrr r r r r5src@s eZdZdZddZddZdS)MultiCallIteratorzaIterates over the results of a multicall. Exceptions are raised in response to xmlrpc faults.cCs ||_dS)N)results)rrr r r rDszMultiCallIterator.__init__cCsR|j|}t|tikr.t|d|dn t|tgkrF|dStddS)Nr#r$rz#unexpected type in multicall result)rr3r" ValueError)rr}itemr r r __getitem__Gs  zMultiCallIterator.__getitem__N)rrrrrrr r r r r@src@s4eZdZdZddZddZeZddZdd Zd S) MultiCalla~server -> an object used to boxcar method calls server should be a ServerProxy object. Methods can be added to the MultiCall using normal method call syntax e.g.: multicall = MultiCall(server_proxy) multicall.add(2,3) multicall.get_address("Guido") To execute the multicall, call the MultiCall object e.g.: add_result, address = multicall() cCs||_g|_dS)N)_MultiCall__server_MultiCall__call_list)rserverr r r raszMultiCall.__init__cCsd|jjt|fS)Nz <%s at %#x>)rrr>)rr r r r eszMultiCall.__repr__cCs t|j|S)N)rr)rrr r r rjszMultiCall.__getattr__cCs:g}x"|jD]\}}|j||dq Wt|jjj|S)N)rr)rrbrrsystemZ multicall)rZmarshalled_listrrr r r rmszMultiCall.__call__N) rrrrrr rrrr r r r rPs rFcCsrtrHtrH|rt}tj}n|r&t}t}nt}t}tdd||t}t|}n"t||d}trbt|}nt |}||fS)zgetparser() -> parser, unmarshaller Create an instance of the fastest available parser, and attach it to an unmarshalling object. Return both objects. TF)rr) FastParserFastUnmarshallerrFrKrLrPrEr"rrQ)rrZ mkdatetimeZmkbytesrWrXr r r getparsers    rcCst|trd}n|rt|tr|s&d}tr4t|}n t||}|j|}|dkr^dt|}nd}|rx|d|d|df}n|r|d|d f}n|Sd j|S) adata [,options] -> marshalled data Convert an argument tuple or a Fault instance to an XML-RPC request (or response, if the methodresponse option is used). In addition to the data object, the following options can be given as keyword arguments: methodname: the method name for a methodCall packet methodresponse: true to create a methodResponse packet. If this option is used with a tuple, the tuple must be a singleton (i.e. it can contain only one element). encoding: the packet encoding (default is UTF-8) All byte strings in the data structure are assumed to use the packet encoding. Unicode strings are automatically converted, where necessary. rzutf-8z$ z z z z z z ra)r+r"r,FastMarshallerr^rir0rd)r methodnameZmethodresponserYr`mr@Z xmlheaderr r r ris2    ricCs2t||d\}}|j||j|j|jfS)zdata -> unmarshalled data, method name Convert an XML-RPC packet to unmarshalled data plus a method name (None if not present). If the XML-RPC packet represents a fault condition, this function raises a Fault exception. )rr)rr[r]r)r@rrpur r r loadss  rc Cs<tstt}tjd|dd}|j|WdQRX|jS)zhdata -> gzip encoded data Encode data using the gzip content encoding as described in RFC 1952 wbr)modefileobjZ compresslevelN)gzipNotImplementedErrorrGzipFilerBgetvalue)r@rpgzfr r r gzip_encodes r@cCststtjdt|dH}y$|dkr0|j}n|j|d}Wntk r\tdYnXWdQRX|dkrt||krtd|S)zrgzip encoded data -> unencoded data Decode data using the gzip content encoding as described in RFC 1952 rb)rrrrz invalid dataNz#max gzipped payload length exceeded)rrrrreadOSErrorrr)r@Z max_decoderZdecodedr r r gzip_decodes rc@s eZdZdZddZddZdS)GzipDecodedResponsezha file-like object to decode a response encoded with the gzip method, as described in RFC 1952. cCs.tstt|j|_tjj|d|jddS)Nr)rr)rrrriorr)rresponser r r r=szGzipDecodedResponse.__init__c Cs"ztjj|Wd|jjXdS)N)rrr]r)rr r r r]EszGzipDecodedResponse.closeN)rrrrrr]r r r r r9src@s$eZdZddZddZddZdS)_MethodcCs||_||_dS)N) _Method__send _Method__name)rsendrr r r rRsz_Method.__init__cCst|jd|j|fS)Nz%s.%s)rrr)rrr r r rUsz_Method.__getattr__cGs|j|j|S)N)rr)rrr r r rWsz_Method.__call__N)rrrrrrr r r r rOsrc@s~eZdZdZdeZdZdZdddZddd Z dd d Z d d Z ddZ ddZ ddZddZddZddZddZdS) Transportz1Handles an HTTP transaction to an XML-RPC server.zPython-xmlrpc/%sTNFcCs||_||_d|_g|_dS)N)NN)r_use_builtin_types _connection_extra_headers)rrrr r r rnszTransport.__init__cCs~xxdD]p}y|j||||Stjjk r8|r4Yqtk rt}z"|sb|jtjtjtjfkrdWYdd}~XqXqWdS)Nrr)rr) single_requesthttpclientZRemoteDisconnectedrerrnoZ ECONNRESETZ ECONNABORTEDZEPIPE)rhosthandler request_bodyverboser}er r r request~s  zTransport.requestcCsy6|j||||}|j}|jdkr4||_|j|SWn2tk rLYntk rh|jYnX|jddr~|j t |||j|j t |j dS)Nzcontent-lengthra) send_requestZ getresponseZstatusrparse_responser" Exceptionr] getheaderrrreasonrZ getheaders)rrrrrZ http_connZrespr r r rs"  zTransport.single_requestcCst|j|jdS)N)rr)rrr)rr r r rszTransport.getparsercCsri}t|tr|\}}tjj|\}}|rdtjj|}tj|jd}dj |j }dd|fg}ng}|||fS)Nzutf-8raZ AuthorizationzBasic ) r+r,urllibparseZ splituserZunquote_to_bytesrKrNrArdr)rrx509ZauthZ extra_headersr r r get_host_infos  zTransport.get_host_infocCsL|jr||jdkr|jdS|j|\}|_}|tjj|f|_|jdS)Nrr)rrrrrZHTTPConnection)rrchostrr r r make_connections  zTransport.make_connectioncCs |j\}}|rd|_|jdS)N)NN)rr])rr connectionr r r r]s zTransport.closecCs|j|}|jdd}|r&|jd|jrLtrL|jd|dd|jd n |jd||jd |jd |jf|j|||j |||S) NrZPOSTT)Zskip_accept_encodingAccept-Encodingr Content-Typetext/xmlz User-Agent)rr)rr) rrZset_debuglevelaccept_gzip_encodingrZ putrequestrb user_agent send_headers send_content)rrrrdebugrrr r r rs        zTransport.send_requestcCs"x|D]\}}|j||qWdS)N) putheader)rrrkeyvalr r r r szTransport.send_headerscCsR|jdk r0|jt|kr0tr0|jddt|}|jdtt||j|dS)NzContent-EncodingrzContent-Length)encode_thresholdrrrrr0Z endheaders)rrrr r r rs  zTransport.send_contentcCst|dr*|jdddkr$t|}q.|}n|}|j\}}x2|jd}|sLP|jr`tdt||j|q a logical connection to an XML-RPC server uri is the connection point on the server, given as scheme://host/target. The standard implementation always supports the "http" scheme. If SSL socket support is available (Python 2.0), it also supports "https". If the target part and the slash preceding it are both omitted, "/RPC2" is assumed. The following options can be given as keyword arguments: transport: a transport factory encoding: the request encoding (default is UTF-8) All 8-bit strings passed to the server proxy are assumed to use the given encoding. NF)rc Cstjj|\} }| dkr tdtjj|\|_|_|js@d|_|dkrz| dkr^t} d|i} nt} i} | f||d| }||_ |pd|_ ||_ ||_ dS) Nrhttpszunsupported XML-RPC protocolz/RPC2r)rrzutf-8)rr) rrZ splittyperZ splithost_ServerProxy__host_ServerProxy__handlerrr_ServerProxy__transport_ServerProxy__encoding_ServerProxy__verbose_ServerProxy__allow_none) rZuri transportrYrr`rrrr3rZ extra_kwargsr r r rs&  zServerProxy.__init__cCs|jjdS)N)rr])rr r r Z__closeszServerProxy.__closecCsPt|||j|jdj|jd}|jj|j|j||jd}t |dkrL|d}|S)N)rYr`xmlcharrefreplace)rrr) rirrrDrrrrrr)rrrrrr r r Z __requests   zServerProxy.__requestcCsd|jj|j|jfS)Nz <%s for %s%s>)rrrr)rr r r r szServerProxy.__repr__cCs t|j|S)N)r_ServerProxy__request)rrr r r rszServerProxy.__getattr__cCs.|dkr|jS|dkr|jStd|fdS)z|A workaround to get special attributes on the ServerProxy without interfering with the magic __getattr__ r]rzAttribute %r not foundN)_ServerProxy__closerr\)rattrr r r rs zServerProxy.__call__cCs|S)Nr )rr r r __enter__szServerProxy.__enter__cGs |jdS)N)r)rrr r r __exit__szServerProxy.__exit__)NNFFFF) rrrrrrrr rrrr r!r r r r rls r__main__zhttp://localhost:8000ZERROR liliiDii ipiԁiDiCiBiiii)FF)NNNF)FF)r)VrrKsysr-rdecimalrZ http.clientrZ urllib.parserZ xml.parsersrrrrr ImportErrorr version_infor rurvZ PARSE_ERRORZ SERVER_ERRORZAPPLICATION_ERRORZ SYSTEM_ERRORZTRANSPORT_ERRORZNOT_WELLFORMED_ERRORZUNSUPPORTED_ENCODINGZINVALID_ENCODING_CHARZINVALID_XMLRPCZMETHOD_NOT_FOUNDZINVALID_METHOD_PARAMSZINTERNAL_ERRORrrrr!r"rrZBooleanZ_day0r%r'r.r/rErFrGrPrrQr^rrrrrrrrrirrrrobjectrrrrrZServerrrr Z currentTimeZgetCurrentTimergZmultiZgetDatapowaddrr r r r s           K #!(C '  ' J  d)i    __pycache__/client.cpython-36.opt-2.pyc000064400000070632147204464040013635 0ustar003 \\&@sfddlZddlZddlZddlmZddlmZddlZddlZ ddl m Z ddl Z ddl mZy ddlZWnek rdZYnXddZdejdd ZdXZdZZd[Zd\Zd]Zd^Zd_Zd`ZdaZdbZdcZddZdeZ dfZ!Gddde"Z#Gddde#Z$Gddde#Z%Gddde#Z&e'Z(Z)ed d d Z*e*j+ddkrFd d!Z,n"e*j+d"dkr`d#d!Z,nd$d!Z,[*d%d&Z-Gd'd(d(Z.d)d*Z/d+d,Z0Gd-d.d.Z1d/d0Z2e.e1fZ3Gd1d2d2Z4Gd3d4d4Z5Gd5d6d6Z6Gd7d8d8Z7Gd9d:d:Z8Gd;d<d<Z9dZ:Z;Zd?Z=dhd@dAZ>didBdCZ?dDdEZ@djdGdHZAGdIdJdJerTejBneCZDGdKdLdLZEGdMdNdNZFGdOdPdPeFZGGdQdRdRZHeHZIeJdSkrbeHdTZKyeLeKjMjNWn.e#k rZOzeLdUeOWYddZO[OXnXe9eKZPePjQePjRd dVePjSd d yxePD]ZTeLeTqWWn.e#k r`ZOzeLdUeOWYddZO[OXnXdS)kN)datetime)Decimal)expat)BytesIOcCs$|jdd}|jdd}|jddS)N&z&z>)replace)sr %/usr/lib64/python3.6/xmlrpc/client.pyescapes  r z%d.%diiXi~i~i,~iiiYiZi[c@seZdZddZdS)ErrorcCst|S)N)repr)selfr r r __str__sz Error.__str__N)__name__ __module__ __qualname__rr r r r rsrc@seZdZddZddZdS) ProtocolErrorcCs&tj|||_||_||_||_dS)N)r__init__urlerrcodeerrmsgheaders)rrrrrr r r rs  zProtocolError.__init__cCsd|jj|j|j|jfS)Nz<%s for %s: %s %s>) __class__rrrr)rr r r __repr__szProtocolError.__repr__N)rrrrrr r r r rsrc@s eZdZdS) ResponseErrorN)rrrr r r r r sr c@seZdZddZddZdS)FaultcKstj|||_||_dS)N)rr faultCode faultString)rr"r#Zextrar r r rs zFault.__init__cCsd|jj|j|jfS)Nz <%s %s: %r>)rrr"r#)rr r r rszFault.__repr__N)rrrrrr r r r r!sr!z%YZ0001cCs |jdS)Nz%Y%m%dT%H:%M:%S)strftime)valuer r r _iso8601_format sr&z%4YcCs |jdS)Nz%4Y%m%dT%H:%M:%S)r$)r%r r r r&scCs|jdjdS)Nz%Y%m%dT%H:%M:%S)r$zfill)r%r r r r&scCsLt|trt|St|ttjfs<|dkr2tj}tj|}d|ddS)Nrz%04d%02d%02dT%02d:%02d:%02d) isinstancerr&tupletimeZ struct_timeZ localtime)r%r r r _strftimes  r-c@sneZdZdddZddZddZdd Zd d Zd d ZddZ ddZ ddZ ddZ ddZ ddZdS)DateTimercCs t|tr||_n t||_dS)N)r*strr%r-)rr%r r r r)s zDateTime.__init__cCst|tr|j}|j}nzt|tr2|j}t|}n`t|trH|j}|}nJt|drd|j}|j}n.t|drv|jj p|t |}t d|jj |f||fS)N timetuplerzCan't compare %s and %s) r*r.r%rr&r/hasattrr0rrtype TypeError)rotherr oZotyper r r make_comparable/s$       zDateTime.make_comparablecCs|j|\}}||kS)N)r6)rr4r r5r r r __lt__DszDateTime.__lt__cCs|j|\}}||kS)N)r6)rr4r r5r r r __le__HszDateTime.__le__cCs|j|\}}||kS)N)r6)rr4r r5r r r __gt__LszDateTime.__gt__cCs|j|\}}||kS)N)r6)rr4r r5r r r __ge__PszDateTime.__ge__cCs|j|\}}||kS)N)r6)rr4r r5r r r __eq__TszDateTime.__eq__cCstj|jdS)Nz%Y%m%dT%H:%M:%S)r,strptimer%)rr r r r0XszDateTime.timetuplecCs|jS)N)r%)rr r r r`szDateTime.__str__cCsd|jj|jt|fS)Nz<%s %r at %#x>)rrr%id)rr r r rcszDateTime.__repr__cCst|j|_dS)N)r/stripr%)rdatar r r decodefszDateTime.decodecCs$|jd|j|j|jddS)Nzz )writer%)routr r r encodeis  zDateTime.encodeN)r)rrrrr6r7r8r9r:r;r0rrr@rCr r r r r.#s r.cCst}|j||S)N)r.r@)r?r%r r r _datetimens rDcCs tj|dS)Nz%Y%m%dT%H:%M:%S)rr<)r?r r r _datetime_typetsrEc@s6eZdZd ddZddZddZdd Zd d ZdS) BinaryNcCs>|dkrd}n&t|ttfs,td|jjt|}||_dS)Nz#expected bytes or bytearray, not %s)r*bytes bytearrayr3rrr?)rr?r r r rs zBinary.__init__cCs t|jdS)Nzlatin-1)r/r?)rr r r rszBinary.__str__cCst|tr|j}|j|kS)N)r*rFr?)rr4r r r r;s z Binary.__eq__cCstj||_dS)N)base64 decodebytesr?)rr?r r r r@sz Binary.decodecCs4|jdtj|j}|j|jd|jddS)Nz asciiz )rArJ encodebytesr?r@)rrBencodedr r r rCs  z Binary.encode)N)rrrrrr;r@rCr r r r rF}s  rFcCst}|j||S)N)rFr@)r?r%r r r _binarys rOc@s$eZdZddZddZddZdS) ExpatParsercCsDtjdd|_}||_|j|_|j|_|j|_ d}|j |ddS)N) rZ ParserCreate_parser_targetstartZStartElementHandlerendZEndElementHandlerr?ZCharacterDataHandlerxml)rtargetparserencodingr r r rszExpatParser.__init__cCs|jj|ddS)Nr)rQParse)rr?r r r feedszExpatParser.feedc Cs8y |j}Wntk rYnX|`|`|jdddS)NrGT)rQAttributeErrorrRrY)rrWr r r closes  zExpatParser.closeN)rrrrrZr\r r r r rPs rPc@seZdZdddZiZddZddZd d Zeeed<d d Z e ee <d dZ e ee <e Z ddZeee<efddZeee<ddZeee<eee<ddZeee<eee<efddZeee<ddZeee<ddZeee<eee<eed<dS) MarshallerNFcCsi|_d|_||_||_dS)N)memor?rX allow_none)rrXr_r r r rszMarshaller.__init__cCsg}|j}|j}t|tr@|d||j|jd||dn8|dx&|D]}|d||||dqNW|ddj|}|S) Nz )r"r#z z z z z )append_Marshaller__dumpr*r!r"r#join)rvaluesrBrAdumpvresultr r r dumpss"      zMarshaller.dumpsc Csy|jt|}Wnjtk r|t|ds)r_r3)rr%rAr r r dump_nilszMarshaller.dump_nilcCs$|d||rdpd|ddS)Nz10z r )rr%rAr r r dump_boolszMarshaller.dump_boolcCs<|tks|tkrtd|d|tt||ddS)Nzint exceeds XML-RPC limitsz z )MAXINTMININT OverflowErrorr/int)rr%rAr r r dump_longs zMarshaller.dump_longcCs |d|t||ddS)Nzz )r)rr%rAr r r dump_double%s zMarshaller.dump_doublecCs |d||||ddS)Nzz r )rr%rAr r r r dump_unicode+s zMarshaller.dump_unicodecCs,|dtj|}||jd|ddS)Nz rLz )rJrMr@)rr%rArNr r r dump_bytes1s zMarshaller.dump_bytescCs^t|}||jkrtdd|j|<|j}|dx|D]}|||q8W|d|j|=dS)Nz"cannot marshal recursive sequencesz z )r=r^r3rb)rr%rAirerfr r r dump_array9s   zMarshaller.dump_arraycCst|}||jkrtdd|j|<|j}|dxP|jD]D\}}|dt|ts^td|d||||||dq z zdictionary key must be stringz%s z z )r=r^r3rbitemsr*r/)rr%rAr r|rekrfr r r dump_structGs     zMarshaller.dump_structcCs |d|t||ddS)Nzz )r-)rr%rAr r r dump_datetimeYs zMarshaller.dump_datetimecCs2|jtkr ||_|j||`n|j|j|dS)N)rWRAPPERSrArCrri)rr%rAr r r dump_instance_s   zMarshaller.dump_instancerj)NF) rrrrrkrhrbrpr2rsboolrxrwZdump_intryfloatr rzr/r{rHrIr}r+listrdictrrrr.rFr r r r r]s:      r]c@sjeZdZdDddZddZddZdd Zd d Zd d ZddZ ddZ iZ ddZ e e d<ddZ e e d<ddZee d<ee d<ee d<ee d<ee d<ee d<d d!Zee d"<ee d#<d$d%Zee d&<d'd(Zee d)<ee d*<d+d,Zee d-<d.d/Zee d0<d1d2Zee d3<d4d5Zee d6<d7d8Zee d9<d:d;Zee d<<d=d>Zee d?<d@dAZee dB<dCS)E UnmarshallerFcCsHd|_g|_g|_g|_d|_d|_d|_|jj|_|p:||_||_ dS)NFzutf-8) _type_stack_marks_data_value _methodname _encodingra _use_datetime _use_bytes)r use_datetimeuse_builtin_typesr r r rs  zUnmarshaller.__init__cCs:|jdks|jrt|jdkr0tf|jdt|jS)Nfaultr)rrr r!rr+)rr r r r\s  zUnmarshaller.closecCs|jS)N)r)rr r r getmethodnameszUnmarshaller.getmethodnamecCs ||_dS)N)r)rrXZ standaloner r r rUszUnmarshaller.xmlcCshd|kr|jdd}|dks&|dkr8|jjt|jg|_|jrZ||jkrZtd||dk|_dS)N:rarraystructzunknown tag %rr%) splitrralenrrrrkr )rtagZattrsr r r rSs zUnmarshaller.startcCs|jj|dS)N)rra)rtextr r r r?szUnmarshaller.datacCspy|j|}WnNtk r\d|kr*dSy|j|jdd}Wntk rVdSXYnX||dj|jS)Nrrr`r)rkrlrrcr)rrror r r rTs zUnmarshaller.endcCshy|j|}WnNtk r\d|kr*dSy|j|jdd}Wntk rVdSXYnX|||S)Nrrr)rkrlr)rrr?ror r r end_dispatchs zUnmarshaller.end_dispatchcCs|jdd|_dS)Nr)rar)rr?r r r end_nils zUnmarshaller.end_nilZnilcCs:|dkr|jdn|dkr(|jdntdd|_dS)NrrFrqTzbad boolean valuer)rar3r)rr?r r r end_booleans   zUnmarshaller.end_booleanbooleancCs|jt|d|_dS)Nr)rarwr)rr?r r r end_intszUnmarshaller.end_intZi1Zi2Zi4Zi8rwZ bigintegercCs|jt|d|_dS)Nr)rarr)rr?r r r end_doubleszUnmarshaller.end_doubleZdoublercCs|jt|d|_dS)Nr)rarr)rr?r r r end_bigdecimalszUnmarshaller.end_bigdecimalZ bigdecimalcCs&|jr|j|j}|j|d|_dS)Nr)rr@rar)rr?r r r end_strings  zUnmarshaller.end_stringstringnamecCs.|jj}|j|dg|j|d<d|_dS)Nr)rpoprr)rr?markr r r end_arrays zUnmarshaller.end_arrayrcCsd|jj}i}|j|d}x,tdt|dD]}||d|||<q.W|g|j|d<d|_dS)Nrrr)rrrrangerr)rr?rrr~r|r r r end_structs zUnmarshaller.end_structrcCs6t}|j|jd|jr"|j}|j|d|_dS)NrLr)rFr@rCrr?rar)rr?r%r r r end_base64 s  zUnmarshaller.end_base64rJcCs,t}|j||jrt|}|j|dS)N)r.r@rrEra)rr?r%r r r end_dateTimes  zUnmarshaller.end_dateTimezdateTime.iso8601cCs|jr|j|dS)N)rr)rr?r r r end_valueszUnmarshaller.end_valuer%cCs d|_dS)Nparams)r)rr?r r r end_params#szUnmarshaller.end_paramsrcCs d|_dS)Nr)r)rr?r r r end_fault'szUnmarshaller.end_faultrcCs"|jr|j|j}||_d|_dS)N methodName)rr@rr)rr?r r r end_methodName+s zUnmarshaller.end_methodNamerN)FF)rrrrr\rrUrSr?rTrrkrrrrrrrrrrrrrrr r r r rssX   rc@s$eZdZddZddZddZdS)_MultiCallMethodcCs||_||_dS)N)_MultiCallMethod__call_list_MultiCallMethod__name)rZ call_listrr r r r8sz_MultiCallMethod.__init__cCst|jd|j|fS)Nz%s.%s)rrr)rrr r r __getattr__;sz_MultiCallMethod.__getattr__cGs|jj|j|fdS)N)rrar)rargsr r r __call__=sz_MultiCallMethod.__call__N)rrrrrrr r r r r5src@seZdZddZddZdS)MultiCallIteratorcCs ||_dS)N)results)rrr r r rDszMultiCallIterator.__init__cCsR|j|}t|tikr.t|d|dn t|tgkrF|dStddS)Nr"r#rz#unexpected type in multicall result)rr2r! ValueError)rr|itemr r r __getitem__Gs  zMultiCallIterator.__getitem__N)rrrrrr r r r r@src@s0eZdZddZddZeZddZddZd S) MultiCallcCs||_g|_dS)N)_MultiCall__server_MultiCall__call_list)rserverr r r raszMultiCall.__init__cCsd|jjt|fS)Nz <%s at %#x>)rrr=)rr r r reszMultiCall.__repr__cCs t|j|S)N)rr)rrr r r rjszMultiCall.__getattr__cCs:g}x"|jD]\}}|j||dq Wt|jjj|S)N)rr)rrarrsystemZ multicall)rZmarshalled_listrrr r r rmszMultiCall.__call__N)rrrrrrrrr r r r rPs rFcCsrtrHtrH|rt}tj}n|r&t}t}nt}t}tdd||t}t|}n"t||d}trbt|}nt |}||fS)NTF)rr) FastParserFastUnmarshallerrErJrKrOrDr!rrP)rrZ mkdatetimeZmkbytesrVrWr r r getparsers    rcCst|trd}n|rt|tr|s&d}tr4t|}n t||}|j|}|dkr^dt|}nd}|rx|d|d|df}n|r|d|d f}n|Sd j|S) Nrzutf-8z$ z z z z z z r`)r*r!r+FastMarshallerr]rhr/rc)r methodnameZmethodresponserXr_mr?Z xmlheaderr r r rhs2    rhcCs2t||d\}}|j||j|j|jfS)N)rr)rrZr\r)r?rrpur r r loadss  rc Cs<tstt}tjd|dd}|j|WdQRX|jS)Nwbr)modefileobjZ compresslevel)gzipNotImplementedErrorrGzipFilerAgetvalue)r?rogzfr r r gzip_encodes r@cCststtjdt|dH}y$|dkr0|j}n|j|d}Wntk r\tdYnXWdQRX|dkrt||krtd|S)Nrb)rrrrz invalid dataz#max gzipped payload length exceeded)rrrrreadOSErrorrr)r?Z max_decoderZdecodedr r r gzip_decodes rc@seZdZddZddZdS)GzipDecodedResponsecCs.tstt|j|_tjj|d|jddS)Nr)rr)rrrriorr)rresponser r r r=szGzipDecodedResponse.__init__c Cs"ztjj|Wd|jjXdS)N)rrr\r)rr r r r\EszGzipDecodedResponse.closeN)rrrrr\r r r r r9src@s$eZdZddZddZddZdS)_MethodcCs||_||_dS)N) _Method__send _Method__name)rsendrr r r rRsz_Method.__init__cCst|jd|j|fS)Nz%s.%s)rrr)rrr r r rUsz_Method.__getattr__cGs|j|j|S)N)rr)rrr r r rWsz_Method.__call__N)rrrrrrr r r r rOsrc@szeZdZdeZdZdZdddZdddZdd d Z d d Z d dZ ddZ ddZ ddZddZddZddZdS) TransportzPython-xmlrpc/%sTNFcCs||_||_d|_g|_dS)N)NN)r_use_builtin_types _connection_extra_headers)rrrr r r rnszTransport.__init__cCs~xxdD]p}y|j||||Stjjk r8|r4Yqtk rt}z"|sb|jtjtjtjfkrdWYdd}~XqXqWdS)Nrr)rr) single_requesthttpclientZRemoteDisconnectedrerrnoZ ECONNRESETZ ECONNABORTEDZEPIPE)rhosthandler request_bodyverboser|er r r request~s  zTransport.requestcCsy6|j||||}|j}|jdkr4||_|j|SWn2tk rLYntk rh|jYnX|jddr~|j t |||j|j t |j dS)Nzcontent-lengthr`) send_requestZ getresponseZstatusrparse_responser! Exceptionr\ getheaderrrreasonrZ getheaders)rrrrrZ http_connZrespr r r rs"  zTransport.single_requestcCst|j|jdS)N)rr)rrr)rr r r rszTransport.getparsercCsri}t|tr|\}}tjj|\}}|rdtjj|}tj|jd}dj |j }dd|fg}ng}|||fS)Nzutf-8r`Z AuthorizationzBasic ) r*r+urllibparseZ splituserZunquote_to_bytesrJrMr@rcr)rrx509ZauthZ extra_headersr r r get_host_infos  zTransport.get_host_infocCsL|jr||jdkr|jdS|j|\}|_}|tjj|f|_|jdS)Nrr)rrrrrZHTTPConnection)rrchostrr r r make_connections  zTransport.make_connectioncCs |j\}}|rd|_|jdS)N)NN)rr\)rr connectionr r r r\s zTransport.closecCs|j|}|jdd}|r&|jd|jrLtrL|jd|dd|jd n |jd||jd |jd |jf|j|||j |||S) NrZPOSTT)Zskip_accept_encodingAccept-Encodingr Content-Typetext/xmlz User-Agent)rr)rr) rrZset_debuglevelaccept_gzip_encodingrZ putrequestra user_agent send_headers send_content)rrrrdebugrrr r r rs        zTransport.send_requestcCs"x|D]\}}|j||qWdS)N) putheader)rrrkeyvalr r r r szTransport.send_headerscCsR|jdk r0|jt|kr0tr0|jddt|}|jdtt||j|dS)NzContent-EncodingrzContent-Length)encode_thresholdrrrrr/Z endheaders)rrrr r r rs  zTransport.send_contentcCst|dr*|jdddkr$t|}q.|}n|}|j\}}x2|jd}|sLP|jr`tdt||j|q)rrrr)rr r r rszServerProxy.__repr__cCs t|j|S)N)r_ServerProxy__request)rrr r r rszServerProxy.__getattr__cCs.|dkr|jS|dkr|jStd|fdS)Nr\rzAttribute %r not found)_ServerProxy__closerr[)rattrr r r rs zServerProxy.__call__cCs|S)Nr )rr r r __enter__szServerProxy.__enter__cGs |jdS)N)r)rrr r r __exit__szServerProxy.__exit__)NNFFFF) rrrrrrrrrrrr r r r r rls r__main__zhttp://localhost:8000ZERROR liliiDii ipiԁiDiCiBiiii)FF)NNNF)FF)r)UrJsysr,rdecimalrZ http.clientrZ urllib.parserZ xml.parsersrrrrr ImportErrorr version_infor rtruZ PARSE_ERRORZ SERVER_ERRORZAPPLICATION_ERRORZ SYSTEM_ERRORZTRANSPORT_ERRORZNOT_WELLFORMED_ERRORZUNSUPPORTED_ENCODINGZINVALID_ENCODING_CHARZINVALID_XMLRPCZMETHOD_NOT_FOUNDZINVALID_METHOD_PARAMSZINTERNAL_ERRORrrrr r!rrZBooleanZ_day0r$r&r-r.rDrErFrOrrPr]rrrrrrrrrhrrrrobjectrrrr rZServerrrr Z currentTimeZgetCurrentTimerfZmultiZgetDatapowaddrr r r r s           K #!(C '  ' J  d)i    __pycache__/client.cpython-36.pyc000064400000103551147204464040012672 0ustar003 \\&@sjdZddlZddlZddlZddlmZddlmZddlZddl Z ddl m Z ddl Z ddlmZy ddlZWnek rdZYnXddZd ejdd ZdYZd[Zd\Zd]Zd^Zd_Zd`ZdaZdbZdcZddZdeZ dfZ!dgZ"Gddde#Z$Gddde$Z%Gddde$Z&Gddde$Z'e(Z)Z*ed d d Z+e+j,dd krJd!d"Z-n"e+j,d#d krdd$d"Z-nd%d"Z-[+d&d'Z.Gd(d)d)Z/d*d+Z0d,d-Z1Gd.d/d/Z2d0d1Z3e/e2fZ4Gd2d3d3Z5Gd4d5d5Z6Gd6d7d7Z7Gd8d9d9Z8Gd:d;d;Z9GddidAdBZ?djdCdDZ@dEdFZAdkdHdIZBGdJdKdKerXejCneDZEGdLdMdMZFGdNdOdOZGGdPdQdQeGZHGdRdSdSZIeIZJeKdTkrfeIdUZLyeMeLjNjOWn.e$k rZPzeMdVePWYddZP[PXnXe:eLZQeQjReQjSd dWeQjTd d yxeQD]ZUeMeUq"WWn.e$k rdZPzeMdVePWYddZP[PXnXdS)la An XML-RPC client interface for Python. The marshalling and response parser code can also be used to implement XML-RPC servers. Exported exceptions: Error Base class for client errors ProtocolError Indicates an HTTP protocol error ResponseError Indicates a broken response package Fault Indicates an XML-RPC fault package Exported classes: ServerProxy Represents a logical connection to an XML-RPC server MultiCall Executor of boxcared xmlrpc requests DateTime dateTime wrapper for an ISO 8601 string or time tuple or localtime integer value to generate a "dateTime.iso8601" XML-RPC value Binary binary data wrapper Marshaller Generate an XML-RPC params chunk from a Python data structure Unmarshaller Unmarshal an XML-RPC response from incoming XML event message Transport Handles an HTTP transaction to an XML-RPC server SafeTransport Handles an HTTPS transaction to an XML-RPC server Exported constants: (none) Exported functions: getparser Create instance of the fastest available parser & attach to an unmarshalling object dumps Convert an argument tuple or a Fault instance to an XML-RPC request (or response, if the methodresponse option is used). loads Convert an XML-RPC packet to unmarshalled data plus a method name (None if not present). N)datetime)Decimal)expat)BytesIOcCs$|jdd}|jdd}|jddS)N&z&z>)replace)sr %/usr/lib64/python3.6/xmlrpc/client.pyescapes  r z%d.%diiXi~i~i,~iiiYiZi[c@seZdZdZddZdS)ErrorzBase class for client errors.cCst|S)N)repr)selfr r r __str__sz Error.__str__N)__name__ __module__ __qualname____doc__rr r r r rsrc@s eZdZdZddZddZdS) ProtocolErrorz!Indicates an HTTP protocol error.cCs&tj|||_||_||_||_dS)N)r__init__urlerrcodeerrmsgheaders)rrrrrr r r rs  zProtocolError.__init__cCsd|jj|j|j|jfS)Nz<%s for %s: %s %s>) __class__rrrr)rr r r __repr__szProtocolError.__repr__N)rrrrrr r r r r rsrc@seZdZdZdS) ResponseErrorz$Indicates a broken response package.N)rrrrr r r r r!sr!c@s eZdZdZddZddZdS)Faultz#Indicates an XML-RPC fault package.cKstj|||_||_dS)N)rr faultCode faultString)rr#r$Zextrar r r rs zFault.__init__cCsd|jj|j|jfS)Nz <%s %s: %r>)rrr#r$)rr r r r szFault.__repr__N)rrrrrr r r r r r"sr"z%YZ0001cCs |jdS)Nz%Y%m%dT%H:%M:%S)strftime)valuer r r _iso8601_format sr'z%4YcCs |jdS)Nz%4Y%m%dT%H:%M:%S)r%)r&r r r r'scCs|jdjdS)Nz%Y%m%dT%H:%M:%S)r%zfill)r&r r r r'scCsLt|trt|St|ttjfs<|dkr2tj}tj|}d|ddS)Nrz%04d%02d%02dT%02d:%02d:%02d) isinstancerr'tupletimeZ struct_timeZ localtime)r&r r r _strftimes  r.c@sreZdZdZdddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZddZdS)DateTimezDateTime wrapper for an ISO 8601 string or time tuple or localtime integer value to generate 'dateTime.iso8601' XML-RPC value. rcCs t|tr||_n t||_dS)N)r+strr&r.)rr&r r r r)s zDateTime.__init__cCst|tr|j}|j}nzt|tr2|j}t|}n`t|trH|j}|}nJt|drd|j}|j}n.t|drv|jj p|t |}t d|jj |f||fS)N timetuplerzCan't compare %s and %s) r+r/r&rr'r0hasattrr1rrtype TypeError)rotherr oZotyper r r make_comparable/s$       zDateTime.make_comparablecCs|j|\}}||kS)N)r7)rr5r r6r r r __lt__DszDateTime.__lt__cCs|j|\}}||kS)N)r7)rr5r r6r r r __le__HszDateTime.__le__cCs|j|\}}||kS)N)r7)rr5r r6r r r __gt__LszDateTime.__gt__cCs|j|\}}||kS)N)r7)rr5r r6r r r __ge__PszDateTime.__ge__cCs|j|\}}||kS)N)r7)rr5r r6r r r __eq__TszDateTime.__eq__cCstj|jdS)Nz%Y%m%dT%H:%M:%S)r-strptimer&)rr r r r1XszDateTime.timetuplecCs|jS)N)r&)rr r r r`szDateTime.__str__cCsd|jj|jt|fS)Nz<%s %r at %#x>)rrr&id)rr r r r cszDateTime.__repr__cCst|j|_dS)N)r0stripr&)rdatar r r decodefszDateTime.decodecCs$|jd|j|j|jddS)Nzz )writer&)routr r r encodeis  zDateTime.encodeN)r)rrrrrr7r8r9r:r;r<r1rr rArDr r r r r/#s r/cCst}|j||S)N)r/rA)r@r&r r r _datetimens rEcCs tj|dS)Nz%Y%m%dT%H:%M:%S)rr=)r@r r r _datetime_typetsrFc@s:eZdZdZd ddZddZddZd d Zd d ZdS)BinaryzWrapper for binary data.NcCs>|dkrd}n&t|ttfs,td|jjt|}||_dS)Nz#expected bytes or bytearray, not %s)r+bytes bytearrayr4rrr@)rr@r r r rs zBinary.__init__cCs t|jdS)Nzlatin-1)r0r@)rr r r rszBinary.__str__cCst|tr|j}|j|kS)N)r+rGr@)rr5r r r r<s z Binary.__eq__cCstj||_dS)N)base64 decodebytesr@)rr@r r r rAsz Binary.decodecCs4|jdtj|j}|j|jd|jddS)Nz asciiz )rBrK encodebytesr@rA)rrCencodedr r r rDs  z Binary.encode)N) rrrrrrr<rArDr r r r rG}s  rGcCst}|j||S)N)rGrA)r@r&r r r _binarys rPc@s$eZdZddZddZddZdS) ExpatParsercCsDtjdd|_}||_|j|_|j|_|j|_ d}|j |ddS)N) rZ ParserCreate_parser_targetstartZStartElementHandlerendZEndElementHandlerr@ZCharacterDataHandlerxml)rtargetparserencodingr r r rszExpatParser.__init__cCs|jj|ddS)Nr)rRParse)rr@r r r feedszExpatParser.feedc Cs8y |j}Wntk rYnX|`|`|jdddS)NrHT)rRAttributeErrorrSrZ)rrXr r r closes  zExpatParser.closeN)rrrrr[r]r r r r rQs rQc@seZdZdZdddZiZddZdd Zd d Zeee d<d d Z e ee <ddZ e ee <e ZddZeee<efddZeee<ddZeee<eee<ddZeee<eee<efddZeee<ddZeee<ddZeee<eee <eed<dS) MarshalleravGenerate an XML-RPC params chunk from a Python data structure. Create a Marshaller instance for each set of parameters, and use the "dumps" method to convert your data (represented as a tuple) to an XML-RPC params chunk. To write a fault response, pass a Fault instance instead. You may prefer to use the "dumps" module function for this purpose. NFcCsi|_d|_||_||_dS)N)memor@rY allow_none)rrYr`r r r rszMarshaller.__init__cCsg}|j}|j}t|tr@|d||j|jd||dn8|dx&|D]}|d||||dqNW|ddj|}|S) Nz )r#r$z z z z z )append_Marshaller__dumpr+r"r#r$join)rvaluesrCrBdumpvresultr r r dumpss"      zMarshaller.dumpsc Csy|jt|}Wnjtk r|t|ds)r`r4)rr&rBr r r dump_nilszMarshaller.dump_nilcCs$|d||rdpd|ddS)Nz10z r )rr&rBr r r dump_boolszMarshaller.dump_boolcCs<|tks|tkrtd|d|tt||ddS)Nzint exceeds XML-RPC limitsz z )MAXINTMININT OverflowErrorr0int)rr&rBr r r dump_longs zMarshaller.dump_longcCs |d|t||ddS)Nzz )r)rr&rBr r r dump_double%s zMarshaller.dump_doublecCs |d||||ddS)Nzz r )rr&rBr r r r dump_unicode+s zMarshaller.dump_unicodecCs,|dtj|}||jd|ddS)Nz rMz )rKrNrA)rr&rBrOr r r dump_bytes1s zMarshaller.dump_bytescCs^t|}||jkrtdd|j|<|j}|dx|D]}|||q8W|d|j|=dS)Nz"cannot marshal recursive sequencesz z )r>r_r4rc)rr&rBirfrgr r r dump_array9s   zMarshaller.dump_arraycCst|}||jkrtdd|j|<|j}|dxP|jD]D\}}|dt|ts^td|d||||||dq z zdictionary key must be stringz%s z z )r>r_r4rcitemsr+r0)rr&rBr r}rfkrgr r r dump_structGs     zMarshaller.dump_structcCs |d|t||ddS)Nzz )r.)rr&rBr r r dump_datetimeYs zMarshaller.dump_datetimecCs2|jtkr ||_|j||`n|j|j|dS)N)rWRAPPERSrBrDrrj)rr&rBr r r dump_instance_s   zMarshaller.dump_instancerk)NF)!rrrrrrlrircrqr3rtboolryrxZdump_intrzfloatr r{r0r|rIrJr~r,listrdictrrrr/rGr r r r r^s<      r^c@sneZdZdZdEddZddZddZd d Zd d Zd dZ ddZ ddZ iZ ddZ e e d<ddZee d<ddZee d<ee d<ee d<ee d<ee d<ee d <d!d"Zee d#<ee d$<d%d&Zee d'<d(d)Zee d*<ee d+<d,d-Zee d.<d/d0Zee d1<d2d3Zee d4<d5d6Zee d7<d8d9Zee d:<d;d<Zee d=<d>d?Zee d@<dAdBZee dC<dDS)F UnmarshalleraUnmarshal an XML-RPC response, based on incoming XML event messages (start, data, end). Call close() to get the resulting data structure. Note that this reader is fairly tolerant, and gladly accepts bogus XML-RPC data without complaining (but not bogus XML). FcCsHd|_g|_g|_g|_d|_d|_d|_|jj|_|p:||_||_ dS)NFzutf-8) _type_stack_marks_data_value _methodname _encodingrb _use_datetime _use_bytes)r use_datetimeuse_builtin_typesr r r rs  zUnmarshaller.__init__cCs:|jdks|jrt|jdkr0tf|jdt|jS)Nfaultr)rrr!r"rr,)rr r r r]s  zUnmarshaller.closecCs|jS)N)r)rr r r getmethodnameszUnmarshaller.getmethodnamecCs ||_dS)N)r)rrYZ standaloner r r rVszUnmarshaller.xmlcCshd|kr|jdd}|dks&|dkr8|jjt|jg|_|jrZ||jkrZtd||dk|_dS)N:rarraystructzunknown tag %rr&) splitrrblenrrrrlr!)rtagZattrsr r r rTs zUnmarshaller.startcCs|jj|dS)N)rrb)rtextr r r r@szUnmarshaller.datacCspy|j|}WnNtk r\d|kr*dSy|j|jdd}Wntk rVdSXYnX||dj|jS)Nrrrar)rlrmrrdr)rrrpr r r rUs zUnmarshaller.endcCshy|j|}WnNtk r\d|kr*dSy|j|jdd}Wntk rVdSXYnX|||S)Nrrr)rlrmr)rrr@rpr r r end_dispatchs zUnmarshaller.end_dispatchcCs|jdd|_dS)Nr)rbr)rr@r r r end_nils zUnmarshaller.end_nilZnilcCs:|dkr|jdn|dkr(|jdntdd|_dS)NrsFrrTzbad boolean valuer)rbr4r)rr@r r r end_booleans   zUnmarshaller.end_booleanbooleancCs|jt|d|_dS)Nr)rbrxr)rr@r r r end_intszUnmarshaller.end_intZi1Zi2Zi4Zi8rxZ bigintegercCs|jt|d|_dS)Nr)rbrr)rr@r r r end_doubleszUnmarshaller.end_doubleZdoublercCs|jt|d|_dS)Nr)rbrr)rr@r r r end_bigdecimalszUnmarshaller.end_bigdecimalZ bigdecimalcCs&|jr|j|j}|j|d|_dS)Nr)rrArbr)rr@r r r end_strings  zUnmarshaller.end_stringstringnamecCs.|jj}|j|dg|j|d<d|_dS)Nr)rpoprr)rr@markr r r end_arrays zUnmarshaller.end_arrayrcCsd|jj}i}|j|d}x,tdt|dD]}||d|||<q.W|g|j|d<d|_dS)Nrrr)rrrrangerr)rr@rrrr}r r r end_structs zUnmarshaller.end_structrcCs6t}|j|jd|jr"|j}|j|d|_dS)NrMr)rGrArDrr@rbr)rr@r&r r r end_base64 s  zUnmarshaller.end_base64rKcCs,t}|j||jrt|}|j|dS)N)r/rArrFrb)rr@r&r r r end_dateTimes  zUnmarshaller.end_dateTimezdateTime.iso8601cCs|jr|j|dS)N)rr)rr@r r r end_valueszUnmarshaller.end_valuer&cCs d|_dS)Nparams)r)rr@r r r end_params#szUnmarshaller.end_paramsrcCs d|_dS)Nr)r)rr@r r r end_fault'szUnmarshaller.end_faultrcCs"|jr|j|j}||_d|_dS)N methodName)rrArr)rr@r r r end_methodName+s zUnmarshaller.end_methodNamerN)FF)rrrrrr]rrVrTr@rUrrlrrrrrrrrrrrrrrr r r r rssZ   rc@s$eZdZddZddZddZdS)_MultiCallMethodcCs||_||_dS)N)_MultiCallMethod__call_list_MultiCallMethod__name)rZ call_listrr r r r8sz_MultiCallMethod.__init__cCst|jd|j|fS)Nz%s.%s)rrr)rrr r r __getattr__;sz_MultiCallMethod.__getattr__cGs|jj|j|fdS)N)rrbr)rargsr r r __call__=sz_MultiCallMethod.__call__N)rrrrrrr r r r r5src@s eZdZdZddZddZdS)MultiCallIteratorzaIterates over the results of a multicall. Exceptions are raised in response to xmlrpc faults.cCs ||_dS)N)results)rrr r r rDszMultiCallIterator.__init__cCsR|j|}t|tikr.t|d|dn t|tgkrF|dStddS)Nr#r$rz#unexpected type in multicall result)rr3r" ValueError)rr}itemr r r __getitem__Gs  zMultiCallIterator.__getitem__N)rrrrrrr r r r r@src@s4eZdZdZddZddZeZddZdd Zd S) MultiCalla~server -> an object used to boxcar method calls server should be a ServerProxy object. Methods can be added to the MultiCall using normal method call syntax e.g.: multicall = MultiCall(server_proxy) multicall.add(2,3) multicall.get_address("Guido") To execute the multicall, call the MultiCall object e.g.: add_result, address = multicall() cCs||_g|_dS)N)_MultiCall__server_MultiCall__call_list)rserverr r r raszMultiCall.__init__cCsd|jjt|fS)Nz <%s at %#x>)rrr>)rr r r r eszMultiCall.__repr__cCs t|j|S)N)rr)rrr r r rjszMultiCall.__getattr__cCs:g}x"|jD]\}}|j||dq Wt|jjj|S)N)rr)rrbrrsystemZ multicall)rZmarshalled_listrrr r r rmszMultiCall.__call__N) rrrrrr rrrr r r r rPs rFcCsrtrHtrH|rt}tj}n|r&t}t}nt}t}tdd||t}t|}n"t||d}trbt|}nt |}||fS)zgetparser() -> parser, unmarshaller Create an instance of the fastest available parser, and attach it to an unmarshalling object. Return both objects. TF)rr) FastParserFastUnmarshallerrFrKrLrPrEr"rrQ)rrZ mkdatetimeZmkbytesrWrXr r r getparsers    rcCst|ttfstdt|tr&d}n"|rHt|trHt|dksHtd|sPd}tr^t|}n t||}|j|}|dkrdt|}nd}|r|d|d|d f}n|r|d |d f}n|Sd j |S) adata [,options] -> marshalled data Convert an argument tuple or a Fault instance to an XML-RPC request (or response, if the methodresponse option is used). In addition to the data object, the following options can be given as keyword arguments: methodname: the method name for a methodCall packet methodresponse: true to create a methodResponse packet. If this option is used with a tuple, the tuple must be a singleton (i.e. it can contain only one element). encoding: the packet encoding (default is UTF-8) All byte strings in the data structure are assumed to use the packet encoding. Unicode strings are automatically converted, where necessary. z(argument must be tuple or Fault instancerz"response tuple must be a singletonzutf-8z$ z z z z z z ra) r+r,r"AssertionErrorrFastMarshallerr^rir0rd)r methodnameZmethodresponserYr`mr@Z xmlheaderr r r ris6    ricCs2t||d\}}|j||j|j|jfS)zdata -> unmarshalled data, method name Convert an XML-RPC packet to unmarshalled data plus a method name (None if not present). If the XML-RPC packet represents a fault condition, this function raises a Fault exception. )rr)rr[r]r)r@rrpur r r loadss  rc Cs<tstt}tjd|dd}|j|WdQRX|jS)zhdata -> gzip encoded data Encode data using the gzip content encoding as described in RFC 1952 wbr)modefileobjZ compresslevelN)gzipNotImplementedErrorrGzipFilerBgetvalue)r@rpgzfr r r gzip_encodes r@cCststtjdt|dH}y$|dkr0|j}n|j|d}Wntk r\tdYnXWdQRX|dkrt||krtd|S)zrgzip encoded data -> unencoded data Decode data using the gzip content encoding as described in RFC 1952 rb)rrrrz invalid dataNz#max gzipped payload length exceeded)rrrrreadOSErrorrr)r@Z max_decoderZdecodedr r r gzip_decodes rc@s eZdZdZddZddZdS)GzipDecodedResponsezha file-like object to decode a response encoded with the gzip method, as described in RFC 1952. cCs.tstt|j|_tjj|d|jddS)Nr)rr)rrrriorr)rresponser r r r=szGzipDecodedResponse.__init__c Cs"ztjj|Wd|jjXdS)N)rrr]r)rr r r r]EszGzipDecodedResponse.closeN)rrrrrr]r r r r r9src@s$eZdZddZddZddZdS)_MethodcCs||_||_dS)N) _Method__send _Method__name)rsendrr r r rRsz_Method.__init__cCst|jd|j|fS)Nz%s.%s)rrr)rrr r r rUsz_Method.__getattr__cGs|j|j|S)N)rr)rrr r r rWsz_Method.__call__N)rrrrrrr r r r rOsrc@s~eZdZdZdeZdZdZdddZddd Z dd d Z d d Z ddZ ddZ ddZddZddZddZddZdS) Transportz1Handles an HTTP transaction to an XML-RPC server.zPython-xmlrpc/%sTNFcCs||_||_d|_g|_dS)N)NN)r_use_builtin_types _connection_extra_headers)rrrr r r rnszTransport.__init__cCs~xxdD]p}y|j||||Stjjk r8|r4Yqtk rt}z"|sb|jtjtjtjfkrdWYdd}~XqXqWdS)Nrr)rr) single_requesthttpclientZRemoteDisconnectedrerrnoZ ECONNRESETZ ECONNABORTEDZEPIPE)rhosthandler request_bodyverboser}er r r request~s  zTransport.requestcCsy6|j||||}|j}|jdkr4||_|j|SWn2tk rLYntk rh|jYnX|jddr~|j t |||j|j t |j dS)Nzcontent-lengthra) send_requestZ getresponseZstatusrparse_responser" Exceptionr] getheaderrrreasonrZ getheaders)rrrrrZ http_connZrespr r r rs"  zTransport.single_requestcCst|j|jdS)N)rr)rrr)rr r r rszTransport.getparsercCsri}t|tr|\}}tjj|\}}|rdtjj|}tj|jd}dj |j }dd|fg}ng}|||fS)Nzutf-8raZ AuthorizationzBasic ) r+r,urllibparseZ splituserZunquote_to_bytesrKrNrArdr)rrx509ZauthZ extra_headersr r r get_host_infos  zTransport.get_host_infocCsL|jr||jdkr|jdS|j|\}|_}|tjj|f|_|jdS)Nrr)rrrrrZHTTPConnection)rrchostrr r r make_connections  zTransport.make_connectioncCs |j\}}|rd|_|jdS)N)NN)rr])rr connectionr r r r]s zTransport.closecCs|j|}|jdd}|r&|jd|jrLtrL|jd|dd|jd n |jd||jd |jd |jf|j|||j |||S) NrZPOSTT)Zskip_accept_encodingAccept-Encodingr Content-Typetext/xmlz User-Agent)rr)rr) rrZset_debuglevelaccept_gzip_encodingrZ putrequestrb user_agent send_headers send_content)rrrrdebugrrr r r rs        zTransport.send_requestcCs"x|D]\}}|j||qWdS)N) putheader)rrrkeyvalr r r r szTransport.send_headerscCsR|jdk r0|jt|kr0tr0|jddt|}|jdtt||j|dS)NzContent-EncodingrzContent-Length)encode_thresholdrrrrr0Z endheaders)rrrr r r rs  zTransport.send_contentcCst|dr*|jdddkr$t|}q.|}n|}|j\}}x2|jd}|sLP|jr`tdt||j|q a logical connection to an XML-RPC server uri is the connection point on the server, given as scheme://host/target. The standard implementation always supports the "http" scheme. If SSL socket support is available (Python 2.0), it also supports "https". If the target part and the slash preceding it are both omitted, "/RPC2" is assumed. The following options can be given as keyword arguments: transport: a transport factory encoding: the request encoding (default is UTF-8) All 8-bit strings passed to the server proxy are assumed to use the given encoding. NF)rc Cstjj|\} }| dkr tdtjj|\|_|_|js@d|_|dkrz| dkr^t} d|i} nt} i} | f||d| }||_ |pd|_ ||_ ||_ dS) Nrhttpszunsupported XML-RPC protocolz/RPC2r)rrzutf-8)rr) rrZ splittyperZ splithost_ServerProxy__host_ServerProxy__handlerrr_ServerProxy__transport_ServerProxy__encoding_ServerProxy__verbose_ServerProxy__allow_none) rZuri transportrYrr`rrrr3rZ extra_kwargsr r r rs&  zServerProxy.__init__cCs|jjdS)N)rr])rr r r Z__closeszServerProxy.__closecCsPt|||j|jdj|jd}|jj|j|j||jd}t |dkrL|d}|S)N)rYr`xmlcharrefreplace)rrr) rirrrDrrrrrr)rrrrrr r r Z __requests   zServerProxy.__requestcCsd|jj|j|jfS)Nz <%s for %s%s>)rrrr)rr r r r szServerProxy.__repr__cCs t|j|S)N)r_ServerProxy__request)rrr r r rszServerProxy.__getattr__cCs.|dkr|jS|dkr|jStd|fdS)z|A workaround to get special attributes on the ServerProxy without interfering with the magic __getattr__ r]rzAttribute %r not foundN)_ServerProxy__closerr\)rattrr r r rs zServerProxy.__call__cCs|S)Nr )rr r r __enter__szServerProxy.__enter__cGs |jdS)N)r)rrr r r __exit__szServerProxy.__exit__)NNFFFF) rrrrrrrr rrrr!r"r r r r rls r__main__zhttp://localhost:8000ZERROR liliiDii ipiԁiDiCiBiiii)FF)NNNF)FF)r)VrrKsysr-rdecimalrZ http.clientrZ urllib.parserZ xml.parsersrrrrr ImportErrorr version_inforrurvZ PARSE_ERRORZ SERVER_ERRORZAPPLICATION_ERRORZ SYSTEM_ERRORZTRANSPORT_ERRORZNOT_WELLFORMED_ERRORZUNSUPPORTED_ENCODINGZINVALID_ENCODING_CHARZINVALID_XMLRPCZMETHOD_NOT_FOUNDZINVALID_METHOD_PARAMSZINTERNAL_ERRORrrrr!r"rrZBooleanZ_day0r%r'r.r/rErFrGrPrrQr^rrrrrrrrrirrrrobjectrrrrrZServerrrr Z currentTimeZgetCurrentTimergZmultiZgetDatapowaddrr r r r s           K #!(C '  ' J  d)i    __pycache__/server.cpython-36.opt-1.pyc000064400000071463147204464040013667 0ustar003 fK@sdZddlmZmZmZmZmZddlmZddl Z ddlZ ddl Z ddl Z ddl Z ddlZddlZddlZddlZy ddlZWnek rdZYnXd*ddZdd ZGd d d ZGd d d eZGddde jeZGdddeZGdddeZGdddejZGdddZGdddeZGdddeeZ GdddeeZ!e"dkrddl#Z#Gdd d Z$ed+~Z%e%j&e'e%j&d#d$d%e%j(e$dd&e%j)e*d'e*d(y e%j+Wn(e,k re*d)e j-dYnXWdQRXdS),a XML-RPC Servers. This module can be used to create simple XML-RPC servers by creating a server and either installing functions, a class instance, or by extending the SimpleXMLRPCServer class. It can also be used to handle XML-RPC requests in a CGI environment using CGIXMLRPCRequestHandler. The Doc* classes can be used to create XML-RPC servers that serve pydoc-style documentation in response to HTTP GET requests. This documentation is dynamically generated based on the functions and methods registered with the server. A list of possible usage patterns follows: 1. Install functions: server = SimpleXMLRPCServer(("localhost", 8000)) server.register_function(pow) server.register_function(lambda x,y: x+y, 'add') server.serve_forever() 2. Install an instance: class MyFuncs: def __init__(self): # make all of the sys functions available through sys.func_name import sys self.sys = sys def _listMethods(self): # implement this method so that system.listMethods # knows to advertise the sys methods return list_public_methods(self) + \ ['sys.' + method for method in list_public_methods(self.sys)] def pow(self, x, y): return pow(x, y) def add(self, x, y) : return x + y server = SimpleXMLRPCServer(("localhost", 8000)) server.register_introspection_functions() server.register_instance(MyFuncs()) server.serve_forever() 3. Install an instance with custom dispatch method: class Math: def _listMethods(self): # this method must be present for system.listMethods # to work return ['add', 'pow'] def _methodHelp(self, method): # this method must be present for system.methodHelp # to work if method == 'add': return "add(2,3) => 5" elif method == 'pow': return "pow(x, y[, z]) => number" else: # By convention, return empty # string if no help is available return "" def _dispatch(self, method, params): if method == 'pow': return pow(*params) elif method == 'add': return params[0] + params[1] else: raise ValueError('bad method') server = SimpleXMLRPCServer(("localhost", 8000)) server.register_introspection_functions() server.register_instance(Math()) server.serve_forever() 4. Subclass SimpleXMLRPCServer: class MathServer(SimpleXMLRPCServer): def _dispatch(self, method, params): try: # We are forcing the 'export_' prefix on methods that are # callable through XML-RPC to prevent potential security # problems func = getattr(self, 'export_' + method) except AttributeError: raise Exception('method "%s" is not supported' % method) else: return func(*params) def export_add(self, x, y): return x + y server = MathServer(("localhost", 8000)) server.serve_forever() 5. CGI script: server = CGIXMLRPCRequestHandler() server.register_function(pow) server.handle_request() )Faultdumpsloads gzip_encode gzip_decode)BaseHTTPRequestHandlerNTcCsJ|r|jd}n|g}x.|D]&}|jdr8td|qt||}qW|S)aGresolve_dotted_attribute(a, 'b.c.d') => a.b.c.d Resolves a dotted attribute name to an object. Raises an AttributeError if any attribute in the chain starts with a '_'. If the optional allow_dotted_names argument is false, dots are not supported and this function operates similar to getattr(obj, attr). ._z(attempt to access private attribute "%s")split startswithAttributeErrorgetattr)objattrallow_dotted_namesZattrsir%/usr/lib64/python3.6/xmlrpc/server.pyresolve_dotted_attribute{s     rcsfddtDS)zkReturns a list of attribute strings, found in the specified object, which represent callable attributescs*g|]"}|jd rtt|r|qS)r )r callabler ).0member)rrr s z'list_public_methods..)dir)rr)rrlist_public_methodssrc@speZdZdZdddZdddZddd Zd d Zd d ZdddZ ddZ ddZ ddZ ddZ ddZdS)SimpleXMLRPCDispatchera&Mix-in class that dispatches XML-RPC requests. This class is used to register XML-RPC method handlers and then to dispatch them. This class doesn't need to be instanced directly when used by SimpleXMLRPCServer but it can be instanced when used by the MultiPathXMLRPCServer FNcCs&i|_d|_||_|pd|_||_dS)Nzutf-8)funcsinstance allow_noneencodinguse_builtin_types)selfrrr rrr__init__s  zSimpleXMLRPCDispatcher.__init__cCs||_||_dS)aRegisters an instance to respond to XML-RPC requests. Only one instance can be installed at a time. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called by SimpleXMLRPCServer. If a registered function matches an XML-RPC request, then it will be called instead of the registered instance. If the optional allow_dotted_names argument is true and the instance does not have a _dispatch method, method names containing dots are supported and resolved, as long as none of the name segments start with an '_'. *** SECURITY WARNING: *** Enabling the allow_dotted_names options allows intruders to access your module's global variables and may allow intruders to execute arbitrary code on your machine. Only use this option on a secure, closed network. N)rr)r!rrrrrregister_instances!z(SimpleXMLRPCDispatcher.register_instancecCs|dkr|j}||j|<dS)zRegisters a function to respond to XML-RPC requests. The optional name argument can be used to set a Unicode name for the function. N)__name__r)r!Zfunctionnamerrrregister_functionsz(SimpleXMLRPCDispatcher.register_functioncCs|jj|j|j|jddS)zRegisters the XML-RPC introspection methods in the system namespace. see http://xmlrpc.usefulinc.com/doc/reserved.html )zsystem.listMethodszsystem.methodSignaturezsystem.methodHelpN)rupdatesystem_listMethodssystem_methodSignaturesystem_methodHelp)r!rrr register_introspection_functionss z7SimpleXMLRPCDispatcher.register_introspection_functionscCs|jjd|jidS)zRegisters the XML-RPC multicall method in the system namespace. see http://www.xmlrpc.com/discuss/msgReader$1208zsystem.multicallN)rr'system_multicall)r!rrrregister_multicall_functionssz3SimpleXMLRPCDispatcher.register_multicall_functionsc CsyPt||jd\}}|dk r(|||}n |j||}|f}t|d|j|jd}Wntk r}zt||j|jd}WYdd}~XnNtj\}} } z$ttdd|| f|j|jd}Wdd}} } XYnX|j |jdS) aDispatches an XML-RPC method from marshalled (XML) data. XML-RPC methods are dispatched from the marshalled (XML) data using the _dispatch method and the result is returned as marshalled data. For backwards compatibility, a dispatch function can be provided as an argument (see comment in SimpleXMLRPCRequestHandler.do_POST) but overriding the existing method through subclassing is the preferred means of changing method dispatch behavior. )r N)Zmethodresponserr)rrz%s:%s)rrxmlcharrefreplace) rr _dispatchrrrrsysexc_infoencode) r!datadispatch_methodpathparamsmethodresponsefaultexc_type exc_valueexc_tbrrr_marshaled_dispatchs&   z*SimpleXMLRPCDispatcher._marshaled_dispatchcCs^t|jj}|jdk rVt|jdr8|t|jjO}nt|jdsV|tt|jO}t|S)zwsystem.listMethods() => ['add', 'subtract', 'multiple'] Returns a list of the methods supported by the server.N _listMethodsr0)setrkeysrhasattrr?rsorted)r!methodsrrrr(s   z)SimpleXMLRPCDispatcher.system_listMethodscCsdS)a#system.methodSignature('add') => [double, int, int] Returns a list describing the signature of the method. In the above example, the add method takes two integers as arguments and returns a double result. This server does NOT support system.methodSignature.zsignatures not supportedr)r! method_namerrrr))s z-SimpleXMLRPCDispatcher.system_methodSignaturec Csd}||jkr|j|}nX|jdk rrt|jdr<|jj|St|jdsryt|j||j}Wntk rpYnX|dkr~dStj|SdS)zsystem.methodHelp('add') => "Adds two integers together" Returns a string containing documentation for the specified method.N _methodHelpr0) rrrBrFrrr pydocgetdoc)r!rEr8rrrr*6s"       z(SimpleXMLRPCDispatcher.system_methodHelpc Csg}x|D]}|d}|d}y|j|j||gWq tk rl}z|j|j|jdWYdd}~Xq tj\}}} z|jdd||fdWdd}}} XYq Xq W|S)zsystem.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => [[4], ...] Allows the caller to package multiple XML-RPC calls into a single request. See http://www.xmlrpc.com/discuss/msgReader$1208 Z methodNamer7) faultCode faultStringNr.z%s:%s)appendr0rrJrKr1r2) r!Z call_listresultsZcallrEr7r:r;r<r=rrrr,Us$  z'SimpleXMLRPCDispatcher.system_multicallcCsy|j|}Wntk r"YnX|dk r4||Std||jdk rt|jdrd|jj||Syt|j||j}Wntk rYnX|dk r||Std|dS)aDispatches the XML-RPC method. XML-RPC calls are forwarded to a registered function that matches the called XML-RPC method name. If no such function exists then the call is forwarded to the registered instance, if available. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called. Nzmethod "%s" is not supportedr0) rKeyError ExceptionrrBr0rrr )r!r8r7funcrrrr0ys(    z SimpleXMLRPCDispatcher._dispatch)FNF)F)N)NN)r$ __module__ __qualname____doc__r"r#r&r+r-r>r(r)r*r,r0rrrrrs  $   ) $rc@sfeZdZdZdZdZdZdZej dej ej BZ dd Z d d Zd d ZddZddZdddZdS)SimpleXMLRPCRequestHandlerzSimple XML-RPC request handler class. Handles all HTTP POST requests and attempts to decode them as XML-RPC requests. //RPC2ixr.Tz \s* ([^\s;]+) \s* #content-coding (;\s* q \s*=\s* ([0-9\.]+))? #q cCsbi}|jjdd}xJ|jdD]<}|jj|}|r|jd}|rHt|nd}|||jd<qW|S)NzAccept-EncodingrG,g?r.)headersgetr aepatternmatchgroupfloat)r!rZaeer\vrrraccept_encodingss  z+SimpleXMLRPCRequestHandler.accept_encodingscCs|jr|j|jkSdSdS)NT) rpc_pathsr6)r!rrris_rpc_path_valids z,SimpleXMLRPCRequestHandler.is_rpc_path_validc Cs|js|jdSyd}t|jd}g}x>|rjt||}|jj|}|sNP|j||t|d8}q.Wdj |}|j |}|dkrdS|j j |t |dd|j}Wntk r6}zp|jdt|j d o|j jr|jd t|tj} t| jd d d } |jd | |jdd|jWYdd}~XnX|jd|jdd|jdk rt||jkr|jjdd} | ryt|}|jddWntk rYnX|jdtt||j|jj|dS)zHandles the HTTP POST request. Attempts to interpret all HTTP POST requests as XML-RPC calls, which are forwarded to the server's _dispatch method for handling. N izcontent-lengthr.r0i_send_traceback_headerz X-exceptionASCIIbackslashreplacez X-tracebackzContent-length0z Content-typeztext/xmlgziprzContent-Encodingi(i) rd report_404intrYminZrfilereadrLlenjoindecode_request_contentserverr>r r6rO send_responserBrg send_headerstr traceback format_excr3 end_headersencode_thresholdrbrZrNotImplementedErrorwfilewrite) r!Zmax_chunk_sizeZsize_remainingLZ chunk_sizechunkr4r9r`Ztraceqrrrdo_POSTsX             z"SimpleXMLRPCRequestHandler.do_POSTc Cs|jjddj}|dkr|S|dkrtyt|Stk rR|jdd|Yqtk rp|jddYqXn|jdd||jdd |jdS) Nzcontent-encodingZidentityrlizencoding %r not supportedizerror decoding gzip contentzContent-lengthrj) rYrZlowerrr}rv ValueErrorrwr{)r!r4rrrrrts z1SimpleXMLRPCRequestHandler.decode_request_contentcCsF|jdd}|jdd|jdtt||j|jj|dS)Nis No such pagez Content-typez text/plainzContent-length)rvrwrxrrr{r~r)r!r9rrrrn/s   z%SimpleXMLRPCRequestHandler.report_404-cCs|jjrtj|||dS)z$Selectively log an accepted request.N)ru logRequestsr log_request)r!codesizerrrr8sz&SimpleXMLRPCRequestHandler.log_requestN)rUrVrm)rr)r$rQrRrSrcr|ZwbufsizeZdisable_nagle_algorithmrecompileVERBOSE IGNORECASEr[rbrdrrtrnrrrrrrTs G rTc@s.eZdZdZdZdZedddddfddZdS)SimpleXMLRPCServeragSimple XML-RPC server. Simple XML-RPC server that allows functions and a single instance to be installed to handle requests. The default implementation attempts to dispatch XML-RPC calls to the functions or instance installed in the server. Override the _dispatch method inherited from SimpleXMLRPCDispatcher to change this behavior. TFNcCs,||_tj||||tjj||||dS)N)rrr" socketserver TCPServer)r!addrrequestHandlerrrrbind_and_activater rrrr"QszSimpleXMLRPCServer.__init__)r$rQrRrSZallow_reuse_addressrgrTr"rrrrr>s  rc@s@eZdZdZedddddfddZddZd d Zd d d ZdS)MultiPathXMLRPCServera\Multipath XML-RPC Server This specialization of SimpleXMLRPCServer allows the user to create multiple Dispatcher instances and assign them to different HTTP request paths. This makes it possible to run two or more 'virtual XML-RPC servers' at the same port. Make sure that the requestHandler accepts the paths in question. TFNc Cs2tj||||||||i|_||_|p*d|_dS)Nzutf-8)rr" dispatchersrr)r!rrrrrrr rrrr"bs  zMultiPathXMLRPCServer.__init__cCs||j|<|S)N)r)r!r6Z dispatcherrrradd_dispatcherls z$MultiPathXMLRPCServer.add_dispatchercCs |j|S)N)r)r!r6rrrget_dispatcherpsz$MultiPathXMLRPCServer.get_dispatchercCs|y|j|j|||}Wn^tjdd\}}z2ttdd||f|j|jd}|j|jd}Wdd}}XYnX|S)Nr.z%s:%s)rrr/) rr>r1r2rrrrr3)r!r4r5r6r9r;r<rrrr>ss z)MultiPathXMLRPCServer._marshaled_dispatch)NN) r$rQrRrSrTr"rrr>rrrrrZsrc@s4eZdZdZd ddZddZdd Zd d d ZdS)CGIXMLRPCRequestHandlerz3Simple handler for XML-RPC data passed through CGI.FNcCstj||||dS)N)rr")r!rrr rrrr"sz CGIXMLRPCRequestHandler.__init__cCsP|j|}tdtdt|ttjjtjjj|tjjjdS)zHandle a single XML-RPC requestzContent-Type: text/xmlzContent-Length: %dN)r>printrrr1stdoutflushbufferr)r! request_textr9rrr handle_xmlrpcs  z%CGIXMLRPCRequestHandler.handle_xmlrpccCsd}tj|\}}tjj|||d}|jd}td||ftdtjjtdt|tt j j t j j j |t j j j dS)zHandle a single HTTP GET request. Default implementation indicates an error because XML-RPC uses the POST method. i)rmessageexplainzutf-8z Status: %d %szContent-Type: %szContent-Length: %dN)rZ responseshttpruZDEFAULT_ERROR_MESSAGEr3rZDEFAULT_ERROR_CONTENT_TYPErrr1rrrr)r!rrrr9rrr handle_gets   z"CGIXMLRPCRequestHandler.handle_getc Csz|dkr$tjjdddkr$|jnRyttjjdd}Wnttfk rVd}YnX|dkrltjj |}|j |dS)zHandle a single XML-RPC request passed through a CGI post method. If no XML data is given then it is read from stdin. The resulting XML-RPC response is printed to stdout along with the correct HTTP headers. NZREQUEST_METHODZGETZCONTENT_LENGTHr.rm) osenvironrZrror TypeErrorr1stdinrqr)r!rZlengthrrrhandle_requests   z&CGIXMLRPCRequestHandler.handle_request)FNF)N)r$rQrRrSr"rrrrrrrrs   rc@s>eZdZdZdiiifddZdiiidfddZddZdS) ServerHTMLDocz7Class used to generate pydoc HTML document for a serverNcCs^|p|j}g}d}tjd}x|j||} | s2P| j\} } |j|||| | j\} } }}}}| r|| jdd}|jd||fn|rdt|}|jd||| fn~|rdt|}|jd||| fnV|| | dd kr|j|j ||||n(|r$|jd |n|j|j ||| }q W|j|||d d j |S) zMark up some plain text, given a context of symbols to look for. Each context dictionary maps object names to anchor names.rzM\b((http|ftp)://\S+[\w/]|RFC[- ]?(\d+)|PEP[- ]?(\d+)|(self\.)?((?:\w|\.)+))\b"z"z%sz'http://www.rfc-editor.org/rfc/rfc%d.txtz(http://www.python.org/dev/peps/pep-%04d/r.(zself.%sNrG) escaperrsearchspanrLgroupsreplaceroZnamelinkrs)r!textrrclassesrDrMherepatternr\startendallschemeZrfcZpepZselfdotr%Zurlrrrmarkups8      zServerHTMLDoc.markupcCs$|r |jp dd|}d} d|j||j|f} tj|rrtj|} tj| jdd| j| j| j | j |j d} n%sr.N) annotations formatvaluez(...)rz'%sz
%s
z
%s
%s
)r$rinspectZismethodZgetfullargspecZ formatargspecargsZvarargsZvarkwZdefaultsrrZ isfunction isinstancetuplerHrIZgreyr preformat)r!objectr%modrrrDZclZanchorZnotetitlerZargspecZ docstringZdecldocrrr docroutines<           zServerHTMLDoc.docroutinec Csi}x,|jD] \}}d|||<||||<qW|j|}d|}|j|dd}|j||j|} | old| } |d| }g} t|j} x&| D]\}}| j|j|||dqW||jddd d j | }|S) z1Produce HTML documentation for an XML-RPC server.z#-z)%sz#ffffffz#7799eez %sz

%s

)rZMethodsz#eeaa77rG) itemsrZheadingrrrCrLrZ bigsectionrs) r! server_nameZpackage_documentationrDZfdictkeyvalueheadresultrcontentsZ method_itemsrrr docserver$s"     zServerHTMLDoc.docserver)r$rQrRrSrrrrrrrrs ),rc@s8eZdZdZddZddZddZdd Zd d Zd S) XMLRPCDocGeneratorzGenerates documentation for an XML-RPC server. This class is designed as mix-in and should not be constructed directly. cCsd|_d|_d|_dS)NzXML-RPC Server DocumentationzGThis server exports the following methods through the XML-RPC protocol.)rserver_documentation server_title)r!rrrr"DszXMLRPCDocGenerator.__init__cCs ||_dS)z8Set the HTML title of the generated server documentationN)r)r!rrrrset_server_titleLsz#XMLRPCDocGenerator.set_server_titlecCs ||_dS)z7Set the name of the generated HTML server documentationN)r)r!rrrrset_server_nameQsz"XMLRPCDocGenerator.set_server_namecCs ||_dS)z3Set the documentation string for the entire server.N)r)r!rrrrset_server_documentationVsz+XMLRPCDocGenerator.set_server_documentationc Csi}x|jD]}||jkr(|j|}n|jdk rddg}t|jdrV|jj||d<t|jdrr|jj||d<t|}|dkr|}qt|jdsyt|j|}Wqtk r|}YqXq|}n|||<qWt }|j |j |j |}|j tj|j|S)agenerate_html_documentation() => html documentation for the server Generates HTML documentation for the server using introspection for installed functions and instances that do not implement the _dispatch method. Alternatively, instances can choose to implement the _get_method_argstring(method_name) method to provide the argument string used in the documentation and the _methodHelp(method_name) method to provide the help text used in the documentation.N_get_method_argstringrrFr.r0)NN)r(rrrBrrFrrr rrrrZpagehtmlrr)r!rDrEr8Z method_infoZ documenterZ documentationrrrgenerate_html_documentation[s8          z.XMLRPCDocGenerator.generate_html_documentationN) r$rQrRrSr"rrrrrrrrr=s rc@seZdZdZddZdS)DocXMLRPCRequestHandlerzXML-RPC and documentation request handler class. Handles all HTTP POST requests and attempts to decode them as XML-RPC requests. Handles all HTTP GET requests and interprets them as requests for documentation. cCsf|js|jdS|jjjd}|jd|jdd|jdtt||j |j j |dS)z}Handles the HTTP GET request. Interpret all HTTP GET requests as requests for server documentation. Nzutf-8rkz Content-typez text/htmlzContent-length) rdrnrurr3rvrwrxrrr{r~r)r!r9rrrdo_GETs  zDocXMLRPCRequestHandler.do_GETN)r$rQrRrSrrrrrrsrc@s&eZdZdZedddddfddZdS)DocXMLRPCServerzXML-RPC and HTML documentation server. Adds the ability to serve server documentation to the capabilities of SimpleXMLRPCServer. TFNc Cs&tj||||||||tj|dS)N)rr"r)r!rrrrrrr rrrr"s zDocXMLRPCServer.__init__)r$rQrRrSrr"rrrrrsrc@s eZdZdZddZddZdS)DocCGIXMLRPCRequestHandlerzJHandler for XML-RPC data and documentation requests passed through CGIcCsT|jjd}tdtdt|ttjjtjjj|tjjjdS)z}Handles the HTTP GET request. Interpret all HTTP GET requests as requests for server documentation. zutf-8zContent-Type: text/htmlzContent-Length: %dN) rr3rrrr1rrrr)r!r9rrrrs z%DocCGIXMLRPCRequestHandler.handle_getcCstj|tj|dS)N)rr"r)r!rrrr"s z#DocCGIXMLRPCRequestHandler.__init__N)r$rQrRrSrr"rrrrrsr__main__c@s"eZdZddZGdddZdS)ExampleServicecCsdS)NZ42r)r!rrrgetDataszExampleService.getDatac@seZdZeddZdS)zExampleService.currentTimecCs tjjS)N)datetimeZnowrrrrgetCurrentTimesz)ExampleService.currentTime.getCurrentTimeN)r$rQrR staticmethodrrrrr currentTimesrN)r$rQrRrrrrrrrsr localhost@cCs||S)Nr)xyrrrsradd)rz&Serving XML-RPC on localhost port 8000zKIt is advisable to run this example server within a secure, closed network.z& Keyboard interrupt received, exiting.)T)rr).rSZ xmlrpc.clientrrrrrZ http.serverrrrrr1rrrHrryZfcntl ImportErrorrrrrTrrrrZHTMLDocrrrrrr$rrrur&powr#r-rZ serve_foreverKeyboardInterruptexitrrrrfs`    ,ErQ      __pycache__/server.cpython-36.opt-2.pyc000064400000043664147204464040013672 0ustar003 fK@sddlmZmZmZmZmZddlmZddlZddlZ ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZy ddlZWnek rdZYnXd)ddZddZGd d d ZGd d d eZGd dde jeZGdddeZGdddeZGdddejZGdddZGdddeZGdddeeZGdddeeZ e!dkrddl"Z"GdddZ#ed*~Z$e$j%e&e$j%d"d#d$e$j'e#dd%e$j(e)d&e)d'y e$j*Wn(e+k re)d(e j,dYnXWdQRXdS)+)Faultdumpsloads gzip_encode gzip_decode)BaseHTTPRequestHandlerNTcCsJ|r|jd}n|g}x.|D]&}|jdr8td|qt||}qW|S)N._z(attempt to access private attribute "%s")split startswithAttributeErrorgetattr)objattrallow_dotted_namesZattrsir%/usr/lib64/python3.6/xmlrpc/server.pyresolve_dotted_attribute{s     rcsfddtDS)Ncs*g|]"}|jd rtt|r|qS)r )r callabler ).0member)rrr s z'list_public_methods..)dir)rr)rrlist_public_methodssrc@sleZdZdddZdddZdddZd d Zd d Zdd dZddZ ddZ ddZ ddZ ddZ dS)SimpleXMLRPCDispatcherFNcCs&i|_d|_||_|pd|_||_dS)Nzutf-8)funcsinstance allow_noneencodinguse_builtin_types)selfrrr rrr__init__s  zSimpleXMLRPCDispatcher.__init__cCs||_||_dS)N)rr)r!rrrrrregister_instances!z(SimpleXMLRPCDispatcher.register_instancecCs|dkr|j}||j|<dS)N)__name__r)r!Zfunctionnamerrrregister_functionsz(SimpleXMLRPCDispatcher.register_functioncCs|jj|j|j|jddS)N)zsystem.listMethodszsystem.methodSignaturezsystem.methodHelp)rupdatesystem_listMethodssystem_methodSignaturesystem_methodHelp)r!rrr register_introspection_functionss z7SimpleXMLRPCDispatcher.register_introspection_functionscCs|jjd|jidS)Nzsystem.multicall)rr'system_multicall)r!rrrregister_multicall_functionssz3SimpleXMLRPCDispatcher.register_multicall_functionsc CsyPt||jd\}}|dk r(|||}n |j||}|f}t|d|j|jd}Wntk r}zt||j|jd}WYdd}~XnNtj\}} } z$ttdd|| f|j|jd}Wdd}} } XYnX|j |jdS)N)r )Zmethodresponserr)rrz%s:%s)rrxmlcharrefreplace) rr _dispatchrrrrsysexc_infoencode) r!datadispatch_methodpathparamsmethodresponsefaultexc_type exc_valueexc_tbrrr_marshaled_dispatchs&   z*SimpleXMLRPCDispatcher._marshaled_dispatchcCs^t|jj}|jdk rVt|jdr8|t|jjO}nt|jdsV|tt|jO}t|S)N _listMethodsr0)setrkeysrhasattrr?rsorted)r!methodsrrrr(s   z)SimpleXMLRPCDispatcher.system_listMethodscCsdS)Nzsignatures not supportedr)r! method_namerrrr))s z-SimpleXMLRPCDispatcher.system_methodSignaturec Csd}||jkr|j|}nX|jdk rrt|jdr<|jj|St|jdsryt|j||j}Wntk rpYnX|dkr~dStj|SdS)N _methodHelpr0) rrrBrFrrr pydocgetdoc)r!rEr8rrrr*6s"       z(SimpleXMLRPCDispatcher.system_methodHelpc Csg}x|D]}|d}|d}y|j|j||gWq tk rl}z|j|j|jdWYdd}~Xq tj\}}} z|jdd||fdWdd}}} XYq Xq W|S)NZ methodNamer7) faultCode faultStringr.z%s:%s)appendr0rrJrKr1r2) r!Z call_listresultsZcallrEr7r:r;r<r=rrrr,Us$  z'SimpleXMLRPCDispatcher.system_multicallcCsy|j|}Wntk r"YnX|dk r4||Std||jdk rt|jdrd|jj||Syt|j||j}Wntk rYnX|dk r||Std|dS)Nzmethod "%s" is not supportedr0) rKeyError ExceptionrrBr0rrr )r!r8r7funcrrrr0ys(    z SimpleXMLRPCDispatcher._dispatch)FNF)F)N)NN)r$ __module__ __qualname__r"r#r&r+r-r>r(r)r*r,r0rrrrrs   $   ) $rc@sbeZdZdZdZdZdZejdej ej BZ ddZ d d Z d d Zd dZddZdddZdS)SimpleXMLRPCRequestHandler//RPC2ixr.Tz \s* ([^\s;]+) \s* #content-coding (;\s* q \s*=\s* ([0-9\.]+))? #q cCsbi}|jjdd}xJ|jdD]<}|jj|}|r|jd}|rHt|nd}|||jd<qW|S)NzAccept-EncodingrG,g?r.)headersgetr aepatternmatchgroupfloat)r!rZaeer[vrrraccept_encodingss  z+SimpleXMLRPCRequestHandler.accept_encodingscCs|jr|j|jkSdSdS)NT) rpc_pathsr6)r!rrris_rpc_path_valids z,SimpleXMLRPCRequestHandler.is_rpc_path_validc Cs|js|jdSyd}t|jd}g}x>|rjt||}|jj|}|sNP|j||t|d8}q.Wdj |}|j |}|dkrdS|j j |t |dd|j}Wntk r6}zp|jdt|j do|j jr|jd t|tj} t| jd d d } |jd | |jd d|jWYdd}~XnX|jd|jdd|jdk rt||jkr|jjdd} | ryt|}|jddWntk rYnX|jd tt||j|jj|dS)N izcontent-lengthr.r0i_send_traceback_headerz X-exceptionASCIIbackslashreplacez X-tracebackzContent-length0z Content-typeztext/xmlgziprzContent-Encodingi(i) rc report_404intrXminZrfilereadrLlenjoindecode_request_contentserverr>r r6rO send_responserBrf send_headerstr traceback format_excr3 end_headersencode_thresholdrarYrNotImplementedErrorwfilewrite) r!Zmax_chunk_sizeZsize_remainingLZ chunk_sizechunkr4r9r_Ztraceqrrrdo_POSTsX             z"SimpleXMLRPCRequestHandler.do_POSTc Cs|jjddj}|dkr|S|dkrtyt|Stk rR|jdd|Yqtk rp|jddYqXn|jdd||jdd |jdS) Nzcontent-encodingZidentityrkizencoding %r not supportedizerror decoding gzip contentzContent-lengthri) rXrYlowerrr|ru ValueErrorrvrz)r!r4rrrrrss z1SimpleXMLRPCRequestHandler.decode_request_contentcCsF|jdd}|jdd|jdtt||j|jj|dS)Nis No such pagez Content-typez text/plainzContent-length)rurvrwrqrzr}r~)r!r9rrrrm/s   z%SimpleXMLRPCRequestHandler.report_404-cCs|jjrtj|||dS)N)rt logRequestsr log_request)r!codesizerrrr8sz&SimpleXMLRPCRequestHandler.log_requestN)rTrUrl)rr)r$rQrRrbr{ZwbufsizeZdisable_nagle_algorithmrecompileVERBOSE IGNORECASErZrarcrrsrmrrrrrrSs  G rSc@s*eZdZdZdZedddddfddZdS)SimpleXMLRPCServerTFNcCs,||_tj||||tjj||||dS)N)rrr" socketserver TCPServer)r!addrrequestHandlerrrrbind_and_activater rrrr"QszSimpleXMLRPCServer.__init__)r$rQrRZallow_reuse_addressrfrSr"rrrrr>s  rc@s<eZdZedddddfddZddZdd Zd d d ZdS) MultiPathXMLRPCServerTFNc Cs2tj||||||||i|_||_|p*d|_dS)Nzutf-8)rr" dispatchersrr)r!rrrrrrr rrrr"bs  zMultiPathXMLRPCServer.__init__cCs||j|<|S)N)r)r!r6Z dispatcherrrradd_dispatcherls z$MultiPathXMLRPCServer.add_dispatchercCs |j|S)N)r)r!r6rrrget_dispatcherpsz$MultiPathXMLRPCServer.get_dispatchercCs|y|j|j|||}Wn^tjdd\}}z2ttdd||f|j|jd}|j|jd}Wdd}}XYnX|S)Nr.z%s:%s)rrr/) rr>r1r2rrrrr3)r!r4r5r6r9r;r<rrrr>ss z)MultiPathXMLRPCServer._marshaled_dispatch)NN)r$rQrRrSr"rrr>rrrrrZs rc@s0eZdZd ddZddZddZd d d ZdS) CGIXMLRPCRequestHandlerFNcCstj||||dS)N)rr")r!rrr rrrr"sz CGIXMLRPCRequestHandler.__init__cCsP|j|}tdtdt|ttjjtjjj|tjjjdS)NzContent-Type: text/xmlzContent-Length: %d)r>printrqr1stdoutflushbufferr~)r! request_textr9rrr handle_xmlrpcs  z%CGIXMLRPCRequestHandler.handle_xmlrpccCsd}tj|\}}tjj|||d}|jd}td||ftdtjjtdt|tt j j t j j j |t j j j dS)Ni)rmessageexplainzutf-8z Status: %d %szContent-Type: %szContent-Length: %d)rZ responseshttprtZDEFAULT_ERROR_MESSAGEr3rZDEFAULT_ERROR_CONTENT_TYPErqr1rrrr~)r!rrrr9rrr handle_gets   z"CGIXMLRPCRequestHandler.handle_getc Csz|dkr$tjjdddkr$|jnRyttjjdd}Wnttfk rVd}YnX|dkrltjj |}|j |dS)NZREQUEST_METHODZGETZCONTENT_LENGTHr.rl) osenvironrYrrnr TypeErrorr1stdinrpr)r!rZlengthrrrhandle_requests   z&CGIXMLRPCRequestHandler.handle_request)FNF)N)r$rQrRr"rrrrrrrrs  rc@s:eZdZdiiifddZdiiidfddZddZdS) ServerHTMLDocNcCs^|p|j}g}d}tjd}x|j||} | s2P| j\} } |j|||| | j\} } }}}}| r|| jdd}|jd||fn|rdt|}|jd||| fn~|rdt|}|jd||| fnV|| | dd kr|j|j ||||n(|r$|jd |n|j|j ||| }q W|j|||dd j |S) NrzM\b((http|ftp)://\S+[\w/]|RFC[- ]?(\d+)|PEP[- ]?(\d+)|(self\.)?((?:\w|\.)+))\b"z"z%sz'http://www.rfc-editor.org/rfc/rfc%d.txtz(http://www.python.org/dev/peps/pep-%04d/r.(zself.%srG) escaperrsearchspanrLgroupsreplacernZnamelinkrr)r!textrrclassesrDrMherepatternr[startendallschemeZrfcZpepZselfdotr%Zurlrrrmarkups8      zServerHTMLDoc.markupcCs$|r |jp dd|}d} d|j||j|f} tj|rrtj|} tj| jdd| j| j| j | j |j d} n%sr.) annotations formatvaluez(...)rz'%sz
%s
z
%s
%s
)r$rinspectZismethodZgetfullargspecZ formatargspecargsZvarargsZvarkwZdefaultsrrZ isfunction isinstancetuplerHrIZgreyr preformat)r!objectr%modrrrDZclZanchorZnotetitlerZargspecZ docstringZdecldocrrr docroutines<           zServerHTMLDoc.docroutinec Csi}x,|jD] \}}d|||<||||<qW|j|}d|}|j|dd}|j||j|} | old| } |d| }g} t|j} x&| D]\}}| j|j|||dqW||jddd d j | }|S) Nz#-z)%sz#ffffffz#7799eez %sz

%s

)rZMethodsz#eeaa77rG) itemsrZheadingrrrCrLrZ bigsectionrr) r! server_nameZpackage_documentationrDZfdictkeyvalueheadresultrcontentsZ method_itemsrrr docserver$s"     zServerHTMLDoc.docserver)r$rQrRrrrrrrrrs),rc@s4eZdZddZddZddZddZd d Zd S) XMLRPCDocGeneratorcCsd|_d|_d|_dS)NzXML-RPC Server DocumentationzGThis server exports the following methods through the XML-RPC protocol.)rserver_documentation server_title)r!rrrr"DszXMLRPCDocGenerator.__init__cCs ||_dS)N)r)r!rrrrset_server_titleLsz#XMLRPCDocGenerator.set_server_titlecCs ||_dS)N)r)r!rrrrset_server_nameQsz"XMLRPCDocGenerator.set_server_namecCs ||_dS)N)r)r!rrrrset_server_documentationVsz+XMLRPCDocGenerator.set_server_documentationc Csi}x|jD]}||jkr(|j|}n|jdk rddg}t|jdrV|jj||d<t|jdrr|jj||d<t|}|dkr|}qt|jdsyt|j|}Wqtk r|}YqXq|}n|||<qWt }|j |j |j |}|j tj|j|S)N_get_method_argstringrrFr.r0)NN)r(rrrBrrFrrr rrrrZpagehtmlrr)r!rDrEr8Z method_infoZ documenterZ documentationrrrgenerate_html_documentation[s8          z.XMLRPCDocGenerator.generate_html_documentationN)r$rQrRr"rrrrrrrrr=s rc@seZdZddZdS)DocXMLRPCRequestHandlercCsf|js|jdS|jjjd}|jd|jdd|jdtt||j |j j |dS)Nzutf-8rjz Content-typez text/htmlzContent-length) rcrmrtrr3rurvrwrqrzr}r~)r!r9rrrdo_GETs  zDocXMLRPCRequestHandler.do_GETN)r$rQrRrrrrrrs rc@s"eZdZedddddfddZdS)DocXMLRPCServerTFNc Cs&tj||||||||tj|dS)N)rr"r)r!rrrrrrr rrrr"s zDocXMLRPCServer.__init__)r$rQrRrr"rrrrrsrc@seZdZddZddZdS)DocCGIXMLRPCRequestHandlercCsT|jjd}tdtdt|ttjjtjjj|tjjjdS)Nzutf-8zContent-Type: text/htmlzContent-Length: %d) rr3rrqr1rrrr~)r!r9rrrrs z%DocCGIXMLRPCRequestHandler.handle_getcCstj|tj|dS)N)rr"r)r!rrrr"s z#DocCGIXMLRPCRequestHandler.__init__N)r$rQrRrr"rrrrrsr__main__c@s"eZdZddZGdddZdS)ExampleServicecCsdS)NZ42r)r!rrrgetDataszExampleService.getDatac@seZdZeddZdS)zExampleService.currentTimecCs tjjS)N)datetimeZnowrrrrgetCurrentTimesz)ExampleService.currentTime.getCurrentTimeN)r$rQrR staticmethodrrrrr currentTimesrN)r$rQrRrrrrrrrsr localhost@cCs||S)Nr)xyrrrsradd)rz&Serving XML-RPC on localhost port 8000zKIt is advisable to run this example server within a secure, closed network.z& Keyboard interrupt received, exiting.)T)rr)-Z xmlrpc.clientrrrrrZ http.serverrrrrr1rrrHrrxZfcntl ImportErrorrrrrSrrrrZHTMLDocrrrrrr$rrrtr&powr#r-rZ serve_foreverKeyboardInterruptexitrrrrks^    ,ErQ      __pycache__/server.cpython-36.pyc000064400000071624147204464040012727 0ustar003 fK@sdZddlmZmZmZmZmZddlmZddl Z ddlZ ddl Z ddl Z ddl Z ddlZddlZddlZddlZy ddlZWnek rdZYnXd*ddZdd ZGd d d ZGd d d eZGddde jeZGdddeZGdddeZGdddejZGdddZGdddeZGdddeeZ GdddeeZ!e"dkrddl#Z#Gdd d Z$ed+~Z%e%j&e'e%j&d#d$d%e%j(e$dd&e%j)e*d'e*d(y e%j+Wn(e,k re*d)e j-dYnXWdQRXdS),a XML-RPC Servers. This module can be used to create simple XML-RPC servers by creating a server and either installing functions, a class instance, or by extending the SimpleXMLRPCServer class. It can also be used to handle XML-RPC requests in a CGI environment using CGIXMLRPCRequestHandler. The Doc* classes can be used to create XML-RPC servers that serve pydoc-style documentation in response to HTTP GET requests. This documentation is dynamically generated based on the functions and methods registered with the server. A list of possible usage patterns follows: 1. Install functions: server = SimpleXMLRPCServer(("localhost", 8000)) server.register_function(pow) server.register_function(lambda x,y: x+y, 'add') server.serve_forever() 2. Install an instance: class MyFuncs: def __init__(self): # make all of the sys functions available through sys.func_name import sys self.sys = sys def _listMethods(self): # implement this method so that system.listMethods # knows to advertise the sys methods return list_public_methods(self) + \ ['sys.' + method for method in list_public_methods(self.sys)] def pow(self, x, y): return pow(x, y) def add(self, x, y) : return x + y server = SimpleXMLRPCServer(("localhost", 8000)) server.register_introspection_functions() server.register_instance(MyFuncs()) server.serve_forever() 3. Install an instance with custom dispatch method: class Math: def _listMethods(self): # this method must be present for system.listMethods # to work return ['add', 'pow'] def _methodHelp(self, method): # this method must be present for system.methodHelp # to work if method == 'add': return "add(2,3) => 5" elif method == 'pow': return "pow(x, y[, z]) => number" else: # By convention, return empty # string if no help is available return "" def _dispatch(self, method, params): if method == 'pow': return pow(*params) elif method == 'add': return params[0] + params[1] else: raise ValueError('bad method') server = SimpleXMLRPCServer(("localhost", 8000)) server.register_introspection_functions() server.register_instance(Math()) server.serve_forever() 4. Subclass SimpleXMLRPCServer: class MathServer(SimpleXMLRPCServer): def _dispatch(self, method, params): try: # We are forcing the 'export_' prefix on methods that are # callable through XML-RPC to prevent potential security # problems func = getattr(self, 'export_' + method) except AttributeError: raise Exception('method "%s" is not supported' % method) else: return func(*params) def export_add(self, x, y): return x + y server = MathServer(("localhost", 8000)) server.serve_forever() 5. CGI script: server = CGIXMLRPCRequestHandler() server.register_function(pow) server.handle_request() )Faultdumpsloads gzip_encode gzip_decode)BaseHTTPRequestHandlerNTcCsJ|r|jd}n|g}x.|D]&}|jdr8td|qt||}qW|S)aGresolve_dotted_attribute(a, 'b.c.d') => a.b.c.d Resolves a dotted attribute name to an object. Raises an AttributeError if any attribute in the chain starts with a '_'. If the optional allow_dotted_names argument is false, dots are not supported and this function operates similar to getattr(obj, attr). ._z(attempt to access private attribute "%s")split startswithAttributeErrorgetattr)objattrallow_dotted_namesZattrsir%/usr/lib64/python3.6/xmlrpc/server.pyresolve_dotted_attribute{s     rcsfddtDS)zkReturns a list of attribute strings, found in the specified object, which represent callable attributescs*g|]"}|jd rtt|r|qS)r )r callabler ).0member)rrr s z'list_public_methods..)dir)rr)rrlist_public_methodssrc@speZdZdZdddZdddZddd Zd d Zd d ZdddZ ddZ ddZ ddZ ddZ ddZdS)SimpleXMLRPCDispatchera&Mix-in class that dispatches XML-RPC requests. This class is used to register XML-RPC method handlers and then to dispatch them. This class doesn't need to be instanced directly when used by SimpleXMLRPCServer but it can be instanced when used by the MultiPathXMLRPCServer FNcCs&i|_d|_||_|pd|_||_dS)Nzutf-8)funcsinstance allow_noneencodinguse_builtin_types)selfrrr rrr__init__s  zSimpleXMLRPCDispatcher.__init__cCs||_||_dS)aRegisters an instance to respond to XML-RPC requests. Only one instance can be installed at a time. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called by SimpleXMLRPCServer. If a registered function matches an XML-RPC request, then it will be called instead of the registered instance. If the optional allow_dotted_names argument is true and the instance does not have a _dispatch method, method names containing dots are supported and resolved, as long as none of the name segments start with an '_'. *** SECURITY WARNING: *** Enabling the allow_dotted_names options allows intruders to access your module's global variables and may allow intruders to execute arbitrary code on your machine. Only use this option on a secure, closed network. N)rr)r!rrrrrregister_instances!z(SimpleXMLRPCDispatcher.register_instancecCs|dkr|j}||j|<dS)zRegisters a function to respond to XML-RPC requests. The optional name argument can be used to set a Unicode name for the function. N)__name__r)r!Zfunctionnamerrrregister_functionsz(SimpleXMLRPCDispatcher.register_functioncCs|jj|j|j|jddS)zRegisters the XML-RPC introspection methods in the system namespace. see http://xmlrpc.usefulinc.com/doc/reserved.html )zsystem.listMethodszsystem.methodSignaturezsystem.methodHelpN)rupdatesystem_listMethodssystem_methodSignaturesystem_methodHelp)r!rrr register_introspection_functionss z7SimpleXMLRPCDispatcher.register_introspection_functionscCs|jjd|jidS)zRegisters the XML-RPC multicall method in the system namespace. see http://www.xmlrpc.com/discuss/msgReader$1208zsystem.multicallN)rr'system_multicall)r!rrrregister_multicall_functionssz3SimpleXMLRPCDispatcher.register_multicall_functionsc CsyPt||jd\}}|dk r(|||}n |j||}|f}t|d|j|jd}Wntk r}zt||j|jd}WYdd}~XnNtj\}} } z$ttdd|| f|j|jd}Wdd}} } XYnX|j |jdS) aDispatches an XML-RPC method from marshalled (XML) data. XML-RPC methods are dispatched from the marshalled (XML) data using the _dispatch method and the result is returned as marshalled data. For backwards compatibility, a dispatch function can be provided as an argument (see comment in SimpleXMLRPCRequestHandler.do_POST) but overriding the existing method through subclassing is the preferred means of changing method dispatch behavior. )r N)Zmethodresponserr)rrz%s:%s)rrxmlcharrefreplace) rr _dispatchrrrrsysexc_infoencode) r!datadispatch_methodpathparamsmethodresponsefaultexc_type exc_valueexc_tbrrr_marshaled_dispatchs&   z*SimpleXMLRPCDispatcher._marshaled_dispatchcCs^t|jj}|jdk rVt|jdr8|t|jjO}nt|jdsV|tt|jO}t|S)zwsystem.listMethods() => ['add', 'subtract', 'multiple'] Returns a list of the methods supported by the server.N _listMethodsr0)setrkeysrhasattrr?rsorted)r!methodsrrrr(s   z)SimpleXMLRPCDispatcher.system_listMethodscCsdS)a#system.methodSignature('add') => [double, int, int] Returns a list describing the signature of the method. In the above example, the add method takes two integers as arguments and returns a double result. This server does NOT support system.methodSignature.zsignatures not supportedr)r! method_namerrrr))s z-SimpleXMLRPCDispatcher.system_methodSignaturec Csd}||jkr|j|}nX|jdk rrt|jdr<|jj|St|jdsryt|j||j}Wntk rpYnX|dkr~dStj|SdS)zsystem.methodHelp('add') => "Adds two integers together" Returns a string containing documentation for the specified method.N _methodHelpr0) rrrBrFrrr pydocgetdoc)r!rEr8rrrr*6s"       z(SimpleXMLRPCDispatcher.system_methodHelpc Csg}x|D]}|d}|d}y|j|j||gWq tk rl}z|j|j|jdWYdd}~Xq tj\}}} z|jdd||fdWdd}}} XYq Xq W|S)zsystem.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => [[4], ...] Allows the caller to package multiple XML-RPC calls into a single request. See http://www.xmlrpc.com/discuss/msgReader$1208 Z methodNamer7) faultCode faultStringNr.z%s:%s)appendr0rrJrKr1r2) r!Z call_listresultsZcallrEr7r:r;r<r=rrrr,Us$  z'SimpleXMLRPCDispatcher.system_multicallcCsy|j|}Wntk r"YnX|dk r4||Std||jdk rt|jdrd|jj||Syt|j||j}Wntk rYnX|dk r||Std|dS)aDispatches the XML-RPC method. XML-RPC calls are forwarded to a registered function that matches the called XML-RPC method name. If no such function exists then the call is forwarded to the registered instance, if available. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called. Nzmethod "%s" is not supportedr0) rKeyError ExceptionrrBr0rrr )r!r8r7funcrrrr0ys(    z SimpleXMLRPCDispatcher._dispatch)FNF)F)N)NN)r$ __module__ __qualname____doc__r"r#r&r+r-r>r(r)r*r,r0rrrrrs  $   ) $rc@sfeZdZdZdZdZdZdZej dej ej BZ dd Z d d Zd d ZddZddZdddZdS)SimpleXMLRPCRequestHandlerzSimple XML-RPC request handler class. Handles all HTTP POST requests and attempts to decode them as XML-RPC requests. //RPC2ixr.Tz \s* ([^\s;]+) \s* #content-coding (;\s* q \s*=\s* ([0-9\.]+))? #q cCsbi}|jjdd}xJ|jdD]<}|jj|}|r|jd}|rHt|nd}|||jd<qW|S)NzAccept-EncodingrG,g?r.)headersgetr aepatternmatchgroupfloat)r!rZaeer\vrrraccept_encodingss  z+SimpleXMLRPCRequestHandler.accept_encodingscCs|jr|j|jkSdSdS)NT) rpc_pathsr6)r!rrris_rpc_path_valids z,SimpleXMLRPCRequestHandler.is_rpc_path_validc Cs|js|jdSyd}t|jd}g}x>|rjt||}|jj|}|sNP|j||t|d8}q.Wdj |}|j |}|dkrdS|j j |t |dd|j}Wntk r6}zp|jdt|j d o|j jr|jd t|tj} t| jd d d } |jd | |jdd|jWYdd}~XnX|jd|jdd|jdk rt||jkr|jjdd} | ryt|}|jddWntk rYnX|jdtt||j|jj|dS)zHandles the HTTP POST request. Attempts to interpret all HTTP POST requests as XML-RPC calls, which are forwarded to the server's _dispatch method for handling. N izcontent-lengthr.r0i_send_traceback_headerz X-exceptionASCIIbackslashreplacez X-tracebackzContent-length0z Content-typeztext/xmlgziprzContent-Encodingi(i) rd report_404intrYminZrfilereadrLlenjoindecode_request_contentserverr>r r6rO send_responserBrg send_headerstr traceback format_excr3 end_headersencode_thresholdrbrZrNotImplementedErrorwfilewrite) r!Zmax_chunk_sizeZsize_remainingLZ chunk_sizechunkr4r9r`Ztraceqrrrdo_POSTsX             z"SimpleXMLRPCRequestHandler.do_POSTc Cs|jjddj}|dkr|S|dkrtyt|Stk rR|jdd|Yqtk rp|jddYqXn|jdd||jdd |jdS) Nzcontent-encodingZidentityrlizencoding %r not supportedizerror decoding gzip contentzContent-lengthrj) rYrZlowerrr}rv ValueErrorrwr{)r!r4rrrrrts z1SimpleXMLRPCRequestHandler.decode_request_contentcCsF|jdd}|jdd|jdtt||j|jj|dS)Nis No such pagez Content-typez text/plainzContent-length)rvrwrxrrr{r~r)r!r9rrrrn/s   z%SimpleXMLRPCRequestHandler.report_404-cCs|jjrtj|||dS)z$Selectively log an accepted request.N)ru logRequestsr log_request)r!codesizerrrr8sz&SimpleXMLRPCRequestHandler.log_requestN)rUrVrm)rr)r$rQrRrSrcr|ZwbufsizeZdisable_nagle_algorithmrecompileVERBOSE IGNORECASEr[rbrdrrtrnrrrrrrTs G rTc@s.eZdZdZdZdZedddddfddZdS)SimpleXMLRPCServeragSimple XML-RPC server. Simple XML-RPC server that allows functions and a single instance to be installed to handle requests. The default implementation attempts to dispatch XML-RPC calls to the functions or instance installed in the server. Override the _dispatch method inherited from SimpleXMLRPCDispatcher to change this behavior. TFNcCs,||_tj||||tjj||||dS)N)rrr" socketserver TCPServer)r!addrrequestHandlerrrrbind_and_activater rrrr"QszSimpleXMLRPCServer.__init__)r$rQrRrSZallow_reuse_addressrgrTr"rrrrr>s  rc@s@eZdZdZedddddfddZddZd d Zd d d ZdS)MultiPathXMLRPCServera\Multipath XML-RPC Server This specialization of SimpleXMLRPCServer allows the user to create multiple Dispatcher instances and assign them to different HTTP request paths. This makes it possible to run two or more 'virtual XML-RPC servers' at the same port. Make sure that the requestHandler accepts the paths in question. TFNc Cs2tj||||||||i|_||_|p*d|_dS)Nzutf-8)rr" dispatchersrr)r!rrrrrrr rrrr"bs  zMultiPathXMLRPCServer.__init__cCs||j|<|S)N)r)r!r6Z dispatcherrrradd_dispatcherls z$MultiPathXMLRPCServer.add_dispatchercCs |j|S)N)r)r!r6rrrget_dispatcherpsz$MultiPathXMLRPCServer.get_dispatchercCs|y|j|j|||}Wn^tjdd\}}z2ttdd||f|j|jd}|j|jd}Wdd}}XYnX|S)Nr.z%s:%s)rrr/) rr>r1r2rrrrr3)r!r4r5r6r9r;r<rrrr>ss z)MultiPathXMLRPCServer._marshaled_dispatch)NN) r$rQrRrSrTr"rrr>rrrrrZsrc@s4eZdZdZd ddZddZdd Zd d d ZdS)CGIXMLRPCRequestHandlerz3Simple handler for XML-RPC data passed through CGI.FNcCstj||||dS)N)rr")r!rrr rrrr"sz CGIXMLRPCRequestHandler.__init__cCsP|j|}tdtdt|ttjjtjjj|tjjjdS)zHandle a single XML-RPC requestzContent-Type: text/xmlzContent-Length: %dN)r>printrrr1stdoutflushbufferr)r! request_textr9rrr handle_xmlrpcs  z%CGIXMLRPCRequestHandler.handle_xmlrpccCsd}tj|\}}tjj|||d}|jd}td||ftdtjjtdt|tt j j t j j j |t j j j dS)zHandle a single HTTP GET request. Default implementation indicates an error because XML-RPC uses the POST method. i)rmessageexplainzutf-8z Status: %d %szContent-Type: %szContent-Length: %dN)rZ responseshttpruZDEFAULT_ERROR_MESSAGEr3rZDEFAULT_ERROR_CONTENT_TYPErrr1rrrr)r!rrrr9rrr handle_gets   z"CGIXMLRPCRequestHandler.handle_getc Csz|dkr$tjjdddkr$|jnRyttjjdd}Wnttfk rVd}YnX|dkrltjj |}|j |dS)zHandle a single XML-RPC request passed through a CGI post method. If no XML data is given then it is read from stdin. The resulting XML-RPC response is printed to stdout along with the correct HTTP headers. NZREQUEST_METHODZGETZCONTENT_LENGTHr.rm) osenvironrZrror TypeErrorr1stdinrqr)r!rZlengthrrrhandle_requests   z&CGIXMLRPCRequestHandler.handle_request)FNF)N)r$rQrRrSr"rrrrrrrrs   rc@s>eZdZdZdiiifddZdiiidfddZddZdS) ServerHTMLDocz7Class used to generate pydoc HTML document for a serverNcCs^|p|j}g}d}tjd}x|j||} | s2P| j\} } |j|||| | j\} } }}}}| r|| jdd}|jd||fn|rdt|}|jd||| fn~|rdt|}|jd||| fnV|| | dd kr|j|j ||||n(|r$|jd |n|j|j ||| }q W|j|||d d j |S) zMark up some plain text, given a context of symbols to look for. Each context dictionary maps object names to anchor names.rzM\b((http|ftp)://\S+[\w/]|RFC[- ]?(\d+)|PEP[- ]?(\d+)|(self\.)?((?:\w|\.)+))\b"z"z%sz'http://www.rfc-editor.org/rfc/rfc%d.txtz(http://www.python.org/dev/peps/pep-%04d/r.(zself.%sNrG) escaperrsearchspanrLgroupsreplaceroZnamelinkrs)r!textrrclassesrDrMherepatternr\startendallschemeZrfcZpepZselfdotr%Zurlrrrmarkups8      zServerHTMLDoc.markupcCs$|r |jp dd|}d} d|j||j|f} tj|rrtj|} tj| jdd| j| j| j | j |j d} n%sr.N) annotations formatvaluez(...)rz'%sz
%s
z
%s
%s
)r$rinspectZismethodZgetfullargspecZ formatargspecargsZvarargsZvarkwZdefaultsrrZ isfunction isinstancetuplerHrIZgreyr preformat)r!objectr%modrrrDZclZanchorZnotetitlerZargspecZ docstringZdecldocrrr docroutines<           zServerHTMLDoc.docroutinec Csi}x,|jD] \}}d|||<||||<qW|j|}d|}|j|dd}|j||j|} | old| } |d| }g} t|j} x&| D]\}}| j|j|||dqW||jddd d j | }|S) z1Produce HTML documentation for an XML-RPC server.z#-z)%sz#ffffffz#7799eez %sz

%s

)rZMethodsz#eeaa77rG) itemsrZheadingrrrCrLrZ bigsectionrs) r! server_nameZpackage_documentationrDZfdictkeyvalueheadresultrcontentsZ method_itemsrrr docserver$s"     zServerHTMLDoc.docserver)r$rQrRrSrrrrrrrrs ),rc@s8eZdZdZddZddZddZdd Zd d Zd S) XMLRPCDocGeneratorzGenerates documentation for an XML-RPC server. This class is designed as mix-in and should not be constructed directly. cCsd|_d|_d|_dS)NzXML-RPC Server DocumentationzGThis server exports the following methods through the XML-RPC protocol.)rserver_documentation server_title)r!rrrr"DszXMLRPCDocGenerator.__init__cCs ||_dS)z8Set the HTML title of the generated server documentationN)r)r!rrrrset_server_titleLsz#XMLRPCDocGenerator.set_server_titlecCs ||_dS)z7Set the name of the generated HTML server documentationN)r)r!rrrrset_server_nameQsz"XMLRPCDocGenerator.set_server_namecCs ||_dS)z3Set the documentation string for the entire server.N)r)r!rrrrset_server_documentationVsz+XMLRPCDocGenerator.set_server_documentationc Cs i}x|jD]}||jkr(|j|}n|jdk rddg}t|jdrV|jj||d<t|jdrr|jj||d<t|}|dkr|}qt|jdsyt|j|}Wqtk r|}YqXq|}n dst d|||<qWt }|j |j |j |}|jtj|j|S) agenerate_html_documentation() => html documentation for the server Generates HTML documentation for the server using introspection for installed functions and instances that do not implement the _dispatch method. Alternatively, instances can choose to implement the _get_method_argstring(method_name) method to provide the argument string used in the documentation and the _methodHelp(method_name) method to provide the help text used in the documentation.N_get_method_argstringrrFr.r0zACould not find method in self.functions and no instance installed)NN)r(rrrBrrFrrr AssertionErrorrrrrZpagehtmlrr)r!rDrEr8Z method_infoZ documenterZ documentationrrrgenerate_html_documentation[s:           z.XMLRPCDocGenerator.generate_html_documentationN) r$rQrRrSr"rrrrrrrrr=s rc@seZdZdZddZdS)DocXMLRPCRequestHandlerzXML-RPC and documentation request handler class. Handles all HTTP POST requests and attempts to decode them as XML-RPC requests. Handles all HTTP GET requests and interprets them as requests for documentation. cCsf|js|jdS|jjjd}|jd|jdd|jdtt||j |j j |dS)z}Handles the HTTP GET request. Interpret all HTTP GET requests as requests for server documentation. Nzutf-8rkz Content-typez text/htmlzContent-length) rdrnrurr3rvrwrxrrr{r~r)r!r9rrrdo_GETs  zDocXMLRPCRequestHandler.do_GETN)r$rQrRrSrrrrrrsrc@s&eZdZdZedddddfddZdS)DocXMLRPCServerzXML-RPC and HTML documentation server. Adds the ability to serve server documentation to the capabilities of SimpleXMLRPCServer. TFNc Cs&tj||||||||tj|dS)N)rr"r)r!rrrrrrr rrrr"s zDocXMLRPCServer.__init__)r$rQrRrSrr"rrrrrsrc@s eZdZdZddZddZdS)DocCGIXMLRPCRequestHandlerzJHandler for XML-RPC data and documentation requests passed through CGIcCsT|jjd}tdtdt|ttjjtjjj|tjjjdS)z}Handles the HTTP GET request. Interpret all HTTP GET requests as requests for server documentation. zutf-8zContent-Type: text/htmlzContent-Length: %dN) rr3rrrr1rrrr)r!r9rrrrs z%DocCGIXMLRPCRequestHandler.handle_getcCstj|tj|dS)N)rr"r)r!rrrr"s z#DocCGIXMLRPCRequestHandler.__init__N)r$rQrRrSrr"rrrrrsr__main__c@s"eZdZddZGdddZdS)ExampleServicecCsdS)NZ42r)r!rrrgetDataszExampleService.getDatac@seZdZeddZdS)zExampleService.currentTimecCs tjjS)N)datetimeZnowrrrrgetCurrentTimesz)ExampleService.currentTime.getCurrentTimeN)r$rQrR staticmethodrrrrr currentTimesrN)r$rQrRrrrrrrrsr localhost@cCs||S)Nr)xyrrrsradd)rz&Serving XML-RPC on localhost port 8000zKIt is advisable to run this example server within a secure, closed network.z& Keyboard interrupt received, exiting.)T)rr).rSZ xmlrpc.clientrrrrrZ http.serverrrrrr1rrrHrryZfcntl ImportErrorrrrrTrrrrZHTMLDocrrrrrr$rrrur&powr#r-rZ serve_foreverKeyboardInterruptexitrrrrfs`    ,ErQ      __init__.py000064400000000046147204464040006662 0ustar00# This directory is a Python package. client.py000064400000137534147204464040006416 0ustar00# # XML-RPC CLIENT LIBRARY # $Id$ # # an XML-RPC client interface for Python. # # the marshalling and response parser code can also be used to # implement XML-RPC servers. # # Notes: # this version is designed to work with Python 2.1 or newer. # # History: # 1999-01-14 fl Created # 1999-01-15 fl Changed dateTime to use localtime # 1999-01-16 fl Added Binary/base64 element, default to RPC2 service # 1999-01-19 fl Fixed array data element (from Skip Montanaro) # 1999-01-21 fl Fixed dateTime constructor, etc. # 1999-02-02 fl Added fault handling, handle empty sequences, etc. # 1999-02-10 fl Fixed problem with empty responses (from Skip Montanaro) # 1999-06-20 fl Speed improvements, pluggable parsers/transports (0.9.8) # 2000-11-28 fl Changed boolean to check the truth value of its argument # 2001-02-24 fl Added encoding/Unicode/SafeTransport patches # 2001-02-26 fl Added compare support to wrappers (0.9.9/1.0b1) # 2001-03-28 fl Make sure response tuple is a singleton # 2001-03-29 fl Don't require empty params element (from Nicholas Riley) # 2001-06-10 fl Folded in _xmlrpclib accelerator support (1.0b2) # 2001-08-20 fl Base xmlrpclib.Error on built-in Exception (from Paul Prescod) # 2001-09-03 fl Allow Transport subclass to override getparser # 2001-09-10 fl Lazy import of urllib, cgi, xmllib (20x import speedup) # 2001-10-01 fl Remove containers from memo cache when done with them # 2001-10-01 fl Use faster escape method (80% dumps speedup) # 2001-10-02 fl More dumps microtuning # 2001-10-04 fl Make sure import expat gets a parser (from Guido van Rossum) # 2001-10-10 sm Allow long ints to be passed as ints if they don't overflow # 2001-10-17 sm Test for int and long overflow (allows use on 64-bit systems) # 2001-11-12 fl Use repr() to marshal doubles (from Paul Felix) # 2002-03-17 fl Avoid buffered read when possible (from James Rucker) # 2002-04-07 fl Added pythondoc comments # 2002-04-16 fl Added __str__ methods to datetime/binary wrappers # 2002-05-15 fl Added error constants (from Andrew Kuchling) # 2002-06-27 fl Merged with Python CVS version # 2002-10-22 fl Added basic authentication (based on code from Phillip Eby) # 2003-01-22 sm Add support for the bool type # 2003-02-27 gvr Remove apply calls # 2003-04-24 sm Use cStringIO if available # 2003-04-25 ak Add support for nil # 2003-06-15 gn Add support for time.struct_time # 2003-07-12 gp Correct marshalling of Faults # 2003-10-31 mvl Add multicall support # 2004-08-20 mvl Bump minimum supported Python version to 2.1 # 2014-12-02 ch/doko Add workaround for gzip bomb vulnerability # # Copyright (c) 1999-2002 by Secret Labs AB. # Copyright (c) 1999-2002 by Fredrik Lundh. # # info@pythonware.com # http://www.pythonware.com # # -------------------------------------------------------------------- # The XML-RPC client interface is # # Copyright (c) 1999-2002 by Secret Labs AB # Copyright (c) 1999-2002 by Fredrik Lundh # # By obtaining, using, and/or copying this software and/or its # associated documentation, you agree that you have read, understood, # and will comply with the following terms and conditions: # # Permission to use, copy, modify, and distribute this software and # its associated documentation for any purpose and without fee is # hereby granted, provided that the above copyright notice appears in # all copies, and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of # Secret Labs AB or the author not be used in advertising or publicity # pertaining to distribution of the software without specific, written # prior permission. # # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # -------------------------------------------------------------------- """ An XML-RPC client interface for Python. The marshalling and response parser code can also be used to implement XML-RPC servers. Exported exceptions: Error Base class for client errors ProtocolError Indicates an HTTP protocol error ResponseError Indicates a broken response package Fault Indicates an XML-RPC fault package Exported classes: ServerProxy Represents a logical connection to an XML-RPC server MultiCall Executor of boxcared xmlrpc requests DateTime dateTime wrapper for an ISO 8601 string or time tuple or localtime integer value to generate a "dateTime.iso8601" XML-RPC value Binary binary data wrapper Marshaller Generate an XML-RPC params chunk from a Python data structure Unmarshaller Unmarshal an XML-RPC response from incoming XML event message Transport Handles an HTTP transaction to an XML-RPC server SafeTransport Handles an HTTPS transaction to an XML-RPC server Exported constants: (none) Exported functions: getparser Create instance of the fastest available parser & attach to an unmarshalling object dumps Convert an argument tuple or a Fault instance to an XML-RPC request (or response, if the methodresponse option is used). loads Convert an XML-RPC packet to unmarshalled data plus a method name (None if not present). """ import base64 import sys import time from datetime import datetime from decimal import Decimal import http.client import urllib.parse from xml.parsers import expat import errno from io import BytesIO try: import gzip except ImportError: gzip = None #python can be built without zlib/gzip support # -------------------------------------------------------------------- # Internal stuff def escape(s): s = s.replace("&", "&") s = s.replace("<", "<") return s.replace(">", ">",) # used in User-Agent header sent __version__ = '%d.%d' % sys.version_info[:2] # xmlrpc integer limits MAXINT = 2**31-1 MININT = -2**31 # -------------------------------------------------------------------- # Error constants (from Dan Libby's specification at # http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php) # Ranges of errors PARSE_ERROR = -32700 SERVER_ERROR = -32600 APPLICATION_ERROR = -32500 SYSTEM_ERROR = -32400 TRANSPORT_ERROR = -32300 # Specific errors NOT_WELLFORMED_ERROR = -32700 UNSUPPORTED_ENCODING = -32701 INVALID_ENCODING_CHAR = -32702 INVALID_XMLRPC = -32600 METHOD_NOT_FOUND = -32601 INVALID_METHOD_PARAMS = -32602 INTERNAL_ERROR = -32603 # -------------------------------------------------------------------- # Exceptions ## # Base class for all kinds of client-side errors. class Error(Exception): """Base class for client errors.""" def __str__(self): return repr(self) ## # Indicates an HTTP-level protocol error. This is raised by the HTTP # transport layer, if the server returns an error code other than 200 # (OK). # # @param url The target URL. # @param errcode The HTTP error code. # @param errmsg The HTTP error message. # @param headers The HTTP header dictionary. class ProtocolError(Error): """Indicates an HTTP protocol error.""" def __init__(self, url, errcode, errmsg, headers): Error.__init__(self) self.url = url self.errcode = errcode self.errmsg = errmsg self.headers = headers def __repr__(self): return ( "<%s for %s: %s %s>" % (self.__class__.__name__, self.url, self.errcode, self.errmsg) ) ## # Indicates a broken XML-RPC response package. This exception is # raised by the unmarshalling layer, if the XML-RPC response is # malformed. class ResponseError(Error): """Indicates a broken response package.""" pass ## # Indicates an XML-RPC fault response package. This exception is # raised by the unmarshalling layer, if the XML-RPC response contains # a fault string. This exception can also be used as a class, to # generate a fault XML-RPC message. # # @param faultCode The XML-RPC fault code. # @param faultString The XML-RPC fault string. class Fault(Error): """Indicates an XML-RPC fault package.""" def __init__(self, faultCode, faultString, **extra): Error.__init__(self) self.faultCode = faultCode self.faultString = faultString def __repr__(self): return "<%s %s: %r>" % (self.__class__.__name__, self.faultCode, self.faultString) # -------------------------------------------------------------------- # Special values ## # Backwards compatibility boolean = Boolean = bool ## # Wrapper for XML-RPC DateTime values. This converts a time value to # the format used by XML-RPC. #

# The value can be given as a datetime object, as a string in the # format "yyyymmddThh:mm:ss", as a 9-item time tuple (as returned by # time.localtime()), or an integer value (as returned by time.time()). # The wrapper uses time.localtime() to convert an integer to a time # tuple. # # @param value The time, given as a datetime object, an ISO 8601 string, # a time tuple, or an integer time value. # Issue #13305: different format codes across platforms _day0 = datetime(1, 1, 1) if _day0.strftime('%Y') == '0001': # Mac OS X def _iso8601_format(value): return value.strftime("%Y%m%dT%H:%M:%S") elif _day0.strftime('%4Y') == '0001': # Linux def _iso8601_format(value): return value.strftime("%4Y%m%dT%H:%M:%S") else: def _iso8601_format(value): return value.strftime("%Y%m%dT%H:%M:%S").zfill(17) del _day0 def _strftime(value): if isinstance(value, datetime): return _iso8601_format(value) if not isinstance(value, (tuple, time.struct_time)): if value == 0: value = time.time() value = time.localtime(value) return "%04d%02d%02dT%02d:%02d:%02d" % value[:6] class DateTime: """DateTime wrapper for an ISO 8601 string or time tuple or localtime integer value to generate 'dateTime.iso8601' XML-RPC value. """ def __init__(self, value=0): if isinstance(value, str): self.value = value else: self.value = _strftime(value) def make_comparable(self, other): if isinstance(other, DateTime): s = self.value o = other.value elif isinstance(other, datetime): s = self.value o = _iso8601_format(other) elif isinstance(other, str): s = self.value o = other elif hasattr(other, "timetuple"): s = self.timetuple() o = other.timetuple() else: otype = (hasattr(other, "__class__") and other.__class__.__name__ or type(other)) raise TypeError("Can't compare %s and %s" % (self.__class__.__name__, otype)) return s, o def __lt__(self, other): s, o = self.make_comparable(other) return s < o def __le__(self, other): s, o = self.make_comparable(other) return s <= o def __gt__(self, other): s, o = self.make_comparable(other) return s > o def __ge__(self, other): s, o = self.make_comparable(other) return s >= o def __eq__(self, other): s, o = self.make_comparable(other) return s == o def timetuple(self): return time.strptime(self.value, "%Y%m%dT%H:%M:%S") ## # Get date/time value. # # @return Date/time value, as an ISO 8601 string. def __str__(self): return self.value def __repr__(self): return "<%s %r at %#x>" % (self.__class__.__name__, self.value, id(self)) def decode(self, data): self.value = str(data).strip() def encode(self, out): out.write("") out.write(self.value) out.write("\n") def _datetime(data): # decode xml element contents into a DateTime structure. value = DateTime() value.decode(data) return value def _datetime_type(data): return datetime.strptime(data, "%Y%m%dT%H:%M:%S") ## # Wrapper for binary data. This can be used to transport any kind # of binary data over XML-RPC, using BASE64 encoding. # # @param data An 8-bit string containing arbitrary data. class Binary: """Wrapper for binary data.""" def __init__(self, data=None): if data is None: data = b"" else: if not isinstance(data, (bytes, bytearray)): raise TypeError("expected bytes or bytearray, not %s" % data.__class__.__name__) data = bytes(data) # Make a copy of the bytes! self.data = data ## # Get buffer contents. # # @return Buffer contents, as an 8-bit string. def __str__(self): return str(self.data, "latin-1") # XXX encoding?! def __eq__(self, other): if isinstance(other, Binary): other = other.data return self.data == other def decode(self, data): self.data = base64.decodebytes(data) def encode(self, out): out.write("\n") encoded = base64.encodebytes(self.data) out.write(encoded.decode('ascii')) out.write("\n") def _binary(data): # decode xml element contents into a Binary structure value = Binary() value.decode(data) return value WRAPPERS = (DateTime, Binary) # -------------------------------------------------------------------- # XML parsers class ExpatParser: # fast expat parser for Python 2.0 and later. def __init__(self, target): self._parser = parser = expat.ParserCreate(None, None) self._target = target parser.StartElementHandler = target.start parser.EndElementHandler = target.end parser.CharacterDataHandler = target.data encoding = None target.xml(encoding, None) def feed(self, data): self._parser.Parse(data, 0) def close(self): try: parser = self._parser except AttributeError: pass else: del self._target, self._parser # get rid of circular references parser.Parse(b"", True) # end of data # -------------------------------------------------------------------- # XML-RPC marshalling and unmarshalling code ## # XML-RPC marshaller. # # @param encoding Default encoding for 8-bit strings. The default # value is None (interpreted as UTF-8). # @see dumps class Marshaller: """Generate an XML-RPC params chunk from a Python data structure. Create a Marshaller instance for each set of parameters, and use the "dumps" method to convert your data (represented as a tuple) to an XML-RPC params chunk. To write a fault response, pass a Fault instance instead. You may prefer to use the "dumps" module function for this purpose. """ # by the way, if you don't understand what's going on in here, # that's perfectly ok. def __init__(self, encoding=None, allow_none=False): self.memo = {} self.data = None self.encoding = encoding self.allow_none = allow_none dispatch = {} def dumps(self, values): out = [] write = out.append dump = self.__dump if isinstance(values, Fault): # fault instance write("\n") dump({'faultCode': values.faultCode, 'faultString': values.faultString}, write) write("\n") else: # parameter block # FIXME: the xml-rpc specification allows us to leave out # the entire block if there are no parameters. # however, changing this may break older code (including # old versions of xmlrpclib.py), so this is better left as # is for now. See @XMLRPC3 for more information. /F write("\n") for v in values: write("\n") dump(v, write) write("\n") write("\n") result = "".join(out) return result def __dump(self, value, write): try: f = self.dispatch[type(value)] except KeyError: # check if this object can be marshalled as a structure if not hasattr(value, '__dict__'): raise TypeError("cannot marshal %s objects" % type(value)) # check if this class is a sub-class of a basic type, # because we don't know how to marshal these types # (e.g. a string sub-class) for type_ in type(value).__mro__: if type_ in self.dispatch.keys(): raise TypeError("cannot marshal %s objects" % type(value)) # XXX(twouters): using "_arbitrary_instance" as key as a quick-fix # for the p3yk merge, this should probably be fixed more neatly. f = self.dispatch["_arbitrary_instance"] f(self, value, write) def dump_nil (self, value, write): if not self.allow_none: raise TypeError("cannot marshal None unless allow_none is enabled") write("") dispatch[type(None)] = dump_nil def dump_bool(self, value, write): write("") write(value and "1" or "0") write("\n") dispatch[bool] = dump_bool def dump_long(self, value, write): if value > MAXINT or value < MININT: raise OverflowError("int exceeds XML-RPC limits") write("") write(str(int(value))) write("\n") dispatch[int] = dump_long # backward compatible dump_int = dump_long def dump_double(self, value, write): write("") write(repr(value)) write("\n") dispatch[float] = dump_double def dump_unicode(self, value, write, escape=escape): write("") write(escape(value)) write("\n") dispatch[str] = dump_unicode def dump_bytes(self, value, write): write("\n") encoded = base64.encodebytes(value) write(encoded.decode('ascii')) write("\n") dispatch[bytes] = dump_bytes dispatch[bytearray] = dump_bytes def dump_array(self, value, write): i = id(value) if i in self.memo: raise TypeError("cannot marshal recursive sequences") self.memo[i] = None dump = self.__dump write("\n") for v in value: dump(v, write) write("\n") del self.memo[i] dispatch[tuple] = dump_array dispatch[list] = dump_array def dump_struct(self, value, write, escape=escape): i = id(value) if i in self.memo: raise TypeError("cannot marshal recursive dictionaries") self.memo[i] = None dump = self.__dump write("\n") for k, v in value.items(): write("\n") if not isinstance(k, str): raise TypeError("dictionary key must be string") write("%s\n" % escape(k)) dump(v, write) write("\n") write("\n") del self.memo[i] dispatch[dict] = dump_struct def dump_datetime(self, value, write): write("") write(_strftime(value)) write("\n") dispatch[datetime] = dump_datetime def dump_instance(self, value, write): # check for special wrappers if value.__class__ in WRAPPERS: self.write = write value.encode(self) del self.write else: # store instance attributes as a struct (really?) self.dump_struct(value.__dict__, write) dispatch[DateTime] = dump_instance dispatch[Binary] = dump_instance # XXX(twouters): using "_arbitrary_instance" as key as a quick-fix # for the p3yk merge, this should probably be fixed more neatly. dispatch["_arbitrary_instance"] = dump_instance ## # XML-RPC unmarshaller. # # @see loads class Unmarshaller: """Unmarshal an XML-RPC response, based on incoming XML event messages (start, data, end). Call close() to get the resulting data structure. Note that this reader is fairly tolerant, and gladly accepts bogus XML-RPC data without complaining (but not bogus XML). """ # and again, if you don't understand what's going on in here, # that's perfectly ok. def __init__(self, use_datetime=False, use_builtin_types=False): self._type = None self._stack = [] self._marks = [] self._data = [] self._value = False self._methodname = None self._encoding = "utf-8" self.append = self._stack.append self._use_datetime = use_builtin_types or use_datetime self._use_bytes = use_builtin_types def close(self): # return response tuple and target method if self._type is None or self._marks: raise ResponseError() if self._type == "fault": raise Fault(**self._stack[0]) return tuple(self._stack) def getmethodname(self): return self._methodname # # event handlers def xml(self, encoding, standalone): self._encoding = encoding # FIXME: assert standalone == 1 ??? def start(self, tag, attrs): # prepare to handle this element if ':' in tag: tag = tag.split(':')[-1] if tag == "array" or tag == "struct": self._marks.append(len(self._stack)) self._data = [] if self._value and tag not in self.dispatch: raise ResponseError("unknown tag %r" % tag) self._value = (tag == "value") def data(self, text): self._data.append(text) def end(self, tag): # call the appropriate end tag handler try: f = self.dispatch[tag] except KeyError: if ':' not in tag: return # unknown tag ? try: f = self.dispatch[tag.split(':')[-1]] except KeyError: return # unknown tag ? return f(self, "".join(self._data)) # # accelerator support def end_dispatch(self, tag, data): # dispatch data try: f = self.dispatch[tag] except KeyError: if ':' not in tag: return # unknown tag ? try: f = self.dispatch[tag.split(':')[-1]] except KeyError: return # unknown tag ? return f(self, data) # # element decoders dispatch = {} def end_nil (self, data): self.append(None) self._value = 0 dispatch["nil"] = end_nil def end_boolean(self, data): if data == "0": self.append(False) elif data == "1": self.append(True) else: raise TypeError("bad boolean value") self._value = 0 dispatch["boolean"] = end_boolean def end_int(self, data): self.append(int(data)) self._value = 0 dispatch["i1"] = end_int dispatch["i2"] = end_int dispatch["i4"] = end_int dispatch["i8"] = end_int dispatch["int"] = end_int dispatch["biginteger"] = end_int def end_double(self, data): self.append(float(data)) self._value = 0 dispatch["double"] = end_double dispatch["float"] = end_double def end_bigdecimal(self, data): self.append(Decimal(data)) self._value = 0 dispatch["bigdecimal"] = end_bigdecimal def end_string(self, data): if self._encoding: data = data.decode(self._encoding) self.append(data) self._value = 0 dispatch["string"] = end_string dispatch["name"] = end_string # struct keys are always strings def end_array(self, data): mark = self._marks.pop() # map arrays to Python lists self._stack[mark:] = [self._stack[mark:]] self._value = 0 dispatch["array"] = end_array def end_struct(self, data): mark = self._marks.pop() # map structs to Python dictionaries dict = {} items = self._stack[mark:] for i in range(0, len(items), 2): dict[items[i]] = items[i+1] self._stack[mark:] = [dict] self._value = 0 dispatch["struct"] = end_struct def end_base64(self, data): value = Binary() value.decode(data.encode("ascii")) if self._use_bytes: value = value.data self.append(value) self._value = 0 dispatch["base64"] = end_base64 def end_dateTime(self, data): value = DateTime() value.decode(data) if self._use_datetime: value = _datetime_type(data) self.append(value) dispatch["dateTime.iso8601"] = end_dateTime def end_value(self, data): # if we stumble upon a value element with no internal # elements, treat it as a string element if self._value: self.end_string(data) dispatch["value"] = end_value def end_params(self, data): self._type = "params" dispatch["params"] = end_params def end_fault(self, data): self._type = "fault" dispatch["fault"] = end_fault def end_methodName(self, data): if self._encoding: data = data.decode(self._encoding) self._methodname = data self._type = "methodName" # no params dispatch["methodName"] = end_methodName ## Multicall support # class _MultiCallMethod: # some lesser magic to store calls made to a MultiCall object # for batch execution def __init__(self, call_list, name): self.__call_list = call_list self.__name = name def __getattr__(self, name): return _MultiCallMethod(self.__call_list, "%s.%s" % (self.__name, name)) def __call__(self, *args): self.__call_list.append((self.__name, args)) class MultiCallIterator: """Iterates over the results of a multicall. Exceptions are raised in response to xmlrpc faults.""" def __init__(self, results): self.results = results def __getitem__(self, i): item = self.results[i] if type(item) == type({}): raise Fault(item['faultCode'], item['faultString']) elif type(item) == type([]): return item[0] else: raise ValueError("unexpected type in multicall result") class MultiCall: """server -> an object used to boxcar method calls server should be a ServerProxy object. Methods can be added to the MultiCall using normal method call syntax e.g.: multicall = MultiCall(server_proxy) multicall.add(2,3) multicall.get_address("Guido") To execute the multicall, call the MultiCall object e.g.: add_result, address = multicall() """ def __init__(self, server): self.__server = server self.__call_list = [] def __repr__(self): return "<%s at %#x>" % (self.__class__.__name__, id(self)) __str__ = __repr__ def __getattr__(self, name): return _MultiCallMethod(self.__call_list, name) def __call__(self): marshalled_list = [] for name, args in self.__call_list: marshalled_list.append({'methodName' : name, 'params' : args}) return MultiCallIterator(self.__server.system.multicall(marshalled_list)) # -------------------------------------------------------------------- # convenience functions FastMarshaller = FastParser = FastUnmarshaller = None ## # Create a parser object, and connect it to an unmarshalling instance. # This function picks the fastest available XML parser. # # return A (parser, unmarshaller) tuple. def getparser(use_datetime=False, use_builtin_types=False): """getparser() -> parser, unmarshaller Create an instance of the fastest available parser, and attach it to an unmarshalling object. Return both objects. """ if FastParser and FastUnmarshaller: if use_builtin_types: mkdatetime = _datetime_type mkbytes = base64.decodebytes elif use_datetime: mkdatetime = _datetime_type mkbytes = _binary else: mkdatetime = _datetime mkbytes = _binary target = FastUnmarshaller(True, False, mkbytes, mkdatetime, Fault) parser = FastParser(target) else: target = Unmarshaller(use_datetime=use_datetime, use_builtin_types=use_builtin_types) if FastParser: parser = FastParser(target) else: parser = ExpatParser(target) return parser, target ## # Convert a Python tuple or a Fault instance to an XML-RPC packet. # # @def dumps(params, **options) # @param params A tuple or Fault instance. # @keyparam methodname If given, create a methodCall request for # this method name. # @keyparam methodresponse If given, create a methodResponse packet. # If used with a tuple, the tuple must be a singleton (that is, # it must contain exactly one element). # @keyparam encoding The packet encoding. # @return A string containing marshalled data. def dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False): """data [,options] -> marshalled data Convert an argument tuple or a Fault instance to an XML-RPC request (or response, if the methodresponse option is used). In addition to the data object, the following options can be given as keyword arguments: methodname: the method name for a methodCall packet methodresponse: true to create a methodResponse packet. If this option is used with a tuple, the tuple must be a singleton (i.e. it can contain only one element). encoding: the packet encoding (default is UTF-8) All byte strings in the data structure are assumed to use the packet encoding. Unicode strings are automatically converted, where necessary. """ assert isinstance(params, (tuple, Fault)), "argument must be tuple or Fault instance" if isinstance(params, Fault): methodresponse = 1 elif methodresponse and isinstance(params, tuple): assert len(params) == 1, "response tuple must be a singleton" if not encoding: encoding = "utf-8" if FastMarshaller: m = FastMarshaller(encoding) else: m = Marshaller(encoding, allow_none) data = m.dumps(params) if encoding != "utf-8": xmlheader = "\n" % str(encoding) else: xmlheader = "\n" # utf-8 is default # standard XML-RPC wrappings if methodname: # a method call data = ( xmlheader, "\n" "", methodname, "\n", data, "\n" ) elif methodresponse: # a method response, or a fault structure data = ( xmlheader, "\n", data, "\n" ) else: return data # return as is return "".join(data) ## # Convert an XML-RPC packet to a Python object. If the XML-RPC packet # represents a fault condition, this function raises a Fault exception. # # @param data An XML-RPC packet, given as an 8-bit string. # @return A tuple containing the unpacked data, and the method name # (None if not present). # @see Fault def loads(data, use_datetime=False, use_builtin_types=False): """data -> unmarshalled data, method name Convert an XML-RPC packet to unmarshalled data plus a method name (None if not present). If the XML-RPC packet represents a fault condition, this function raises a Fault exception. """ p, u = getparser(use_datetime=use_datetime, use_builtin_types=use_builtin_types) p.feed(data) p.close() return u.close(), u.getmethodname() ## # Encode a string using the gzip content encoding such as specified by the # Content-Encoding: gzip # in the HTTP header, as described in RFC 1952 # # @param data the unencoded data # @return the encoded data def gzip_encode(data): """data -> gzip encoded data Encode data using the gzip content encoding as described in RFC 1952 """ if not gzip: raise NotImplementedError f = BytesIO() with gzip.GzipFile(mode="wb", fileobj=f, compresslevel=1) as gzf: gzf.write(data) return f.getvalue() ## # Decode a string using the gzip content encoding such as specified by the # Content-Encoding: gzip # in the HTTP header, as described in RFC 1952 # # @param data The encoded data # @keyparam max_decode Maximum bytes to decode (20MB default), use negative # values for unlimited decoding # @return the unencoded data # @raises ValueError if data is not correctly coded. # @raises ValueError if max gzipped payload length exceeded def gzip_decode(data, max_decode=20971520): """gzip encoded data -> unencoded data Decode data using the gzip content encoding as described in RFC 1952 """ if not gzip: raise NotImplementedError with gzip.GzipFile(mode="rb", fileobj=BytesIO(data)) as gzf: try: if max_decode < 0: # no limit decoded = gzf.read() else: decoded = gzf.read(max_decode + 1) except OSError: raise ValueError("invalid data") if max_decode >= 0 and len(decoded) > max_decode: raise ValueError("max gzipped payload length exceeded") return decoded ## # Return a decoded file-like object for the gzip encoding # as described in RFC 1952. # # @param response A stream supporting a read() method # @return a file-like object that the decoded data can be read() from class GzipDecodedResponse(gzip.GzipFile if gzip else object): """a file-like object to decode a response encoded with the gzip method, as described in RFC 1952. """ def __init__(self, response): #response doesn't support tell() and read(), required by #GzipFile if not gzip: raise NotImplementedError self.io = BytesIO(response.read()) gzip.GzipFile.__init__(self, mode="rb", fileobj=self.io) def close(self): try: gzip.GzipFile.close(self) finally: self.io.close() # -------------------------------------------------------------------- # request dispatcher class _Method: # some magic to bind an XML-RPC method to an RPC server. # supports "nested" methods (e.g. examples.getStateName) def __init__(self, send, name): self.__send = send self.__name = name def __getattr__(self, name): return _Method(self.__send, "%s.%s" % (self.__name, name)) def __call__(self, *args): return self.__send(self.__name, args) ## # Standard transport class for XML-RPC over HTTP. #

# You can create custom transports by subclassing this method, and # overriding selected methods. class Transport: """Handles an HTTP transaction to an XML-RPC server.""" # client identifier (may be overridden) user_agent = "Python-xmlrpc/%s" % __version__ #if true, we'll request gzip encoding accept_gzip_encoding = True # if positive, encode request using gzip if it exceeds this threshold # note that many servers will get confused, so only use it if you know # that they can decode such a request encode_threshold = None #None = don't encode def __init__(self, use_datetime=False, use_builtin_types=False): self._use_datetime = use_datetime self._use_builtin_types = use_builtin_types self._connection = (None, None) self._extra_headers = [] ## # Send a complete request, and parse the response. # Retry request if a cached connection has disconnected. # # @param host Target host. # @param handler Target PRC handler. # @param request_body XML-RPC request body. # @param verbose Debugging flag. # @return Parsed response. def request(self, host, handler, request_body, verbose=False): #retry request once if cached connection has gone cold for i in (0, 1): try: return self.single_request(host, handler, request_body, verbose) except http.client.RemoteDisconnected: if i: raise except OSError as e: if i or e.errno not in (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE): raise def single_request(self, host, handler, request_body, verbose=False): # issue XML-RPC request try: http_conn = self.send_request(host, handler, request_body, verbose) resp = http_conn.getresponse() if resp.status == 200: self.verbose = verbose return self.parse_response(resp) except Fault: raise except Exception: #All unexpected errors leave connection in # a strange state, so we clear it. self.close() raise #We got an error response. #Discard any response data and raise exception if resp.getheader("content-length", ""): resp.read() raise ProtocolError( host + handler, resp.status, resp.reason, dict(resp.getheaders()) ) ## # Create parser. # # @return A 2-tuple containing a parser and an unmarshaller. def getparser(self): # get parser and unmarshaller return getparser(use_datetime=self._use_datetime, use_builtin_types=self._use_builtin_types) ## # Get authorization info from host parameter # Host may be a string, or a (host, x509-dict) tuple; if a string, # it is checked for a "user:pw@host" format, and a "Basic # Authentication" header is added if appropriate. # # @param host Host descriptor (URL or (URL, x509 info) tuple). # @return A 3-tuple containing (actual host, extra headers, # x509 info). The header and x509 fields may be None. def get_host_info(self, host): x509 = {} if isinstance(host, tuple): host, x509 = host auth, host = urllib.parse.splituser(host) if auth: auth = urllib.parse.unquote_to_bytes(auth) auth = base64.encodebytes(auth).decode("utf-8") auth = "".join(auth.split()) # get rid of whitespace extra_headers = [ ("Authorization", "Basic " + auth) ] else: extra_headers = [] return host, extra_headers, x509 ## # Connect to server. # # @param host Target host. # @return An HTTPConnection object def make_connection(self, host): #return an existing connection if possible. This allows #HTTP/1.1 keep-alive. if self._connection and host == self._connection[0]: return self._connection[1] # create a HTTP connection object from a host descriptor chost, self._extra_headers, x509 = self.get_host_info(host) self._connection = host, http.client.HTTPConnection(chost) return self._connection[1] ## # Clear any cached connection object. # Used in the event of socket errors. # def close(self): host, connection = self._connection if connection: self._connection = (None, None) connection.close() ## # Send HTTP request. # # @param host Host descriptor (URL or (URL, x509 info) tuple). # @param handler Target RPC handler (a path relative to host) # @param request_body The XML-RPC request body # @param debug Enable debugging if debug is true. # @return An HTTPConnection. def send_request(self, host, handler, request_body, debug): connection = self.make_connection(host) headers = self._extra_headers[:] if debug: connection.set_debuglevel(1) if self.accept_gzip_encoding and gzip: connection.putrequest("POST", handler, skip_accept_encoding=True) headers.append(("Accept-Encoding", "gzip")) else: connection.putrequest("POST", handler) headers.append(("Content-Type", "text/xml")) headers.append(("User-Agent", self.user_agent)) self.send_headers(connection, headers) self.send_content(connection, request_body) return connection ## # Send request headers. # This function provides a useful hook for subclassing # # @param connection httpConnection. # @param headers list of key,value pairs for HTTP headers def send_headers(self, connection, headers): for key, val in headers: connection.putheader(key, val) ## # Send request body. # This function provides a useful hook for subclassing # # @param connection httpConnection. # @param request_body XML-RPC request body. def send_content(self, connection, request_body): #optionally encode the request if (self.encode_threshold is not None and self.encode_threshold < len(request_body) and gzip): connection.putheader("Content-Encoding", "gzip") request_body = gzip_encode(request_body) connection.putheader("Content-Length", str(len(request_body))) connection.endheaders(request_body) ## # Parse response. # # @param file Stream. # @return Response tuple and target method. def parse_response(self, response): # read response data from httpresponse, and parse it # Check for new http response object, otherwise it is a file object. if hasattr(response, 'getheader'): if response.getheader("Content-Encoding", "") == "gzip": stream = GzipDecodedResponse(response) else: stream = response else: stream = response p, u = self.getparser() while 1: data = stream.read(1024) if not data: break if self.verbose: print("body:", repr(data)) p.feed(data) if stream is not response: stream.close() p.close() return u.close() ## # Standard transport class for XML-RPC over HTTPS. class SafeTransport(Transport): """Handles an HTTPS transaction to an XML-RPC server.""" def __init__(self, use_datetime=False, use_builtin_types=False, *, context=None): super().__init__(use_datetime=use_datetime, use_builtin_types=use_builtin_types) self.context = context # FIXME: mostly untested def make_connection(self, host): if self._connection and host == self._connection[0]: return self._connection[1] if not hasattr(http.client, "HTTPSConnection"): raise NotImplementedError( "your version of http.client doesn't support HTTPS") # create a HTTPS connection object from a host descriptor # host may be a string, or a (host, x509-dict) tuple chost, self._extra_headers, x509 = self.get_host_info(host) self._connection = host, http.client.HTTPSConnection(chost, None, context=self.context, **(x509 or {})) return self._connection[1] ## # Standard server proxy. This class establishes a virtual connection # to an XML-RPC server. #

# This class is available as ServerProxy and Server. New code should # use ServerProxy, to avoid confusion. # # @def ServerProxy(uri, **options) # @param uri The connection point on the server. # @keyparam transport A transport factory, compatible with the # standard transport class. # @keyparam encoding The default encoding used for 8-bit strings # (default is UTF-8). # @keyparam verbose Use a true value to enable debugging output. # (printed to standard output). # @see Transport class ServerProxy: """uri [,options] -> a logical connection to an XML-RPC server uri is the connection point on the server, given as scheme://host/target. The standard implementation always supports the "http" scheme. If SSL socket support is available (Python 2.0), it also supports "https". If the target part and the slash preceding it are both omitted, "/RPC2" is assumed. The following options can be given as keyword arguments: transport: a transport factory encoding: the request encoding (default is UTF-8) All 8-bit strings passed to the server proxy are assumed to use the given encoding. """ def __init__(self, uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, context=None): # establish a "logical" server connection # get the url type, uri = urllib.parse.splittype(uri) if type not in ("http", "https"): raise OSError("unsupported XML-RPC protocol") self.__host, self.__handler = urllib.parse.splithost(uri) if not self.__handler: self.__handler = "/RPC2" if transport is None: if type == "https": handler = SafeTransport extra_kwargs = {"context": context} else: handler = Transport extra_kwargs = {} transport = handler(use_datetime=use_datetime, use_builtin_types=use_builtin_types, **extra_kwargs) self.__transport = transport self.__encoding = encoding or 'utf-8' self.__verbose = verbose self.__allow_none = allow_none def __close(self): self.__transport.close() def __request(self, methodname, params): # call a method on the remote server request = dumps(params, methodname, encoding=self.__encoding, allow_none=self.__allow_none).encode(self.__encoding, 'xmlcharrefreplace') response = self.__transport.request( self.__host, self.__handler, request, verbose=self.__verbose ) if len(response) == 1: response = response[0] return response def __repr__(self): return ( "<%s for %s%s>" % (self.__class__.__name__, self.__host, self.__handler) ) __str__ = __repr__ def __getattr__(self, name): # magic method dispatcher return _Method(self.__request, name) # note: to call a remote object with a non-standard name, use # result getattr(server, "strange-python-name")(args) def __call__(self, attr): """A workaround to get special attributes on the ServerProxy without interfering with the magic __getattr__ """ if attr == "close": return self.__close elif attr == "transport": return self.__transport raise AttributeError("Attribute %r not found" % (attr,)) def __enter__(self): return self def __exit__(self, *args): self.__close() # compatibility Server = ServerProxy # -------------------------------------------------------------------- # test code if __name__ == "__main__": # simple test program (from the XML-RPC specification) # local server, available from Lib/xmlrpc/server.py server = ServerProxy("http://localhost:8000") try: print(server.currentTime.getCurrentTime()) except Error as v: print("ERROR", v) multi = MultiCall(server) multi.getData() multi.pow(2,9) multi.add(1,2) try: for response in multi(): print(response) except Error as v: print("ERROR", v) server.py000064400000110513147204464040006432 0ustar00r"""XML-RPC Servers. This module can be used to create simple XML-RPC servers by creating a server and either installing functions, a class instance, or by extending the SimpleXMLRPCServer class. It can also be used to handle XML-RPC requests in a CGI environment using CGIXMLRPCRequestHandler. The Doc* classes can be used to create XML-RPC servers that serve pydoc-style documentation in response to HTTP GET requests. This documentation is dynamically generated based on the functions and methods registered with the server. A list of possible usage patterns follows: 1. Install functions: server = SimpleXMLRPCServer(("localhost", 8000)) server.register_function(pow) server.register_function(lambda x,y: x+y, 'add') server.serve_forever() 2. Install an instance: class MyFuncs: def __init__(self): # make all of the sys functions available through sys.func_name import sys self.sys = sys def _listMethods(self): # implement this method so that system.listMethods # knows to advertise the sys methods return list_public_methods(self) + \ ['sys.' + method for method in list_public_methods(self.sys)] def pow(self, x, y): return pow(x, y) def add(self, x, y) : return x + y server = SimpleXMLRPCServer(("localhost", 8000)) server.register_introspection_functions() server.register_instance(MyFuncs()) server.serve_forever() 3. Install an instance with custom dispatch method: class Math: def _listMethods(self): # this method must be present for system.listMethods # to work return ['add', 'pow'] def _methodHelp(self, method): # this method must be present for system.methodHelp # to work if method == 'add': return "add(2,3) => 5" elif method == 'pow': return "pow(x, y[, z]) => number" else: # By convention, return empty # string if no help is available return "" def _dispatch(self, method, params): if method == 'pow': return pow(*params) elif method == 'add': return params[0] + params[1] else: raise ValueError('bad method') server = SimpleXMLRPCServer(("localhost", 8000)) server.register_introspection_functions() server.register_instance(Math()) server.serve_forever() 4. Subclass SimpleXMLRPCServer: class MathServer(SimpleXMLRPCServer): def _dispatch(self, method, params): try: # We are forcing the 'export_' prefix on methods that are # callable through XML-RPC to prevent potential security # problems func = getattr(self, 'export_' + method) except AttributeError: raise Exception('method "%s" is not supported' % method) else: return func(*params) def export_add(self, x, y): return x + y server = MathServer(("localhost", 8000)) server.serve_forever() 5. CGI script: server = CGIXMLRPCRequestHandler() server.register_function(pow) server.handle_request() """ # Written by Brian Quinlan (brian@sweetapp.com). # Based on code written by Fredrik Lundh. from xmlrpc.client import Fault, dumps, loads, gzip_encode, gzip_decode from http.server import BaseHTTPRequestHandler import html import http.server import socketserver import sys import os import re import pydoc import inspect import traceback try: import fcntl except ImportError: fcntl = None def resolve_dotted_attribute(obj, attr, allow_dotted_names=True): """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d Resolves a dotted attribute name to an object. Raises an AttributeError if any attribute in the chain starts with a '_'. If the optional allow_dotted_names argument is false, dots are not supported and this function operates similar to getattr(obj, attr). """ if allow_dotted_names: attrs = attr.split('.') else: attrs = [attr] for i in attrs: if i.startswith('_'): raise AttributeError( 'attempt to access private attribute "%s"' % i ) else: obj = getattr(obj,i) return obj def list_public_methods(obj): """Returns a list of attribute strings, found in the specified object, which represent callable attributes""" return [member for member in dir(obj) if not member.startswith('_') and callable(getattr(obj, member))] class SimpleXMLRPCDispatcher: """Mix-in class that dispatches XML-RPC requests. This class is used to register XML-RPC method handlers and then to dispatch them. This class doesn't need to be instanced directly when used by SimpleXMLRPCServer but it can be instanced when used by the MultiPathXMLRPCServer """ def __init__(self, allow_none=False, encoding=None, use_builtin_types=False): self.funcs = {} self.instance = None self.allow_none = allow_none self.encoding = encoding or 'utf-8' self.use_builtin_types = use_builtin_types def register_instance(self, instance, allow_dotted_names=False): """Registers an instance to respond to XML-RPC requests. Only one instance can be installed at a time. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called by SimpleXMLRPCServer. If a registered function matches an XML-RPC request, then it will be called instead of the registered instance. If the optional allow_dotted_names argument is true and the instance does not have a _dispatch method, method names containing dots are supported and resolved, as long as none of the name segments start with an '_'. *** SECURITY WARNING: *** Enabling the allow_dotted_names options allows intruders to access your module's global variables and may allow intruders to execute arbitrary code on your machine. Only use this option on a secure, closed network. """ self.instance = instance self.allow_dotted_names = allow_dotted_names def register_function(self, function, name=None): """Registers a function to respond to XML-RPC requests. The optional name argument can be used to set a Unicode name for the function. """ if name is None: name = function.__name__ self.funcs[name] = function def register_introspection_functions(self): """Registers the XML-RPC introspection methods in the system namespace. see http://xmlrpc.usefulinc.com/doc/reserved.html """ self.funcs.update({'system.listMethods' : self.system_listMethods, 'system.methodSignature' : self.system_methodSignature, 'system.methodHelp' : self.system_methodHelp}) def register_multicall_functions(self): """Registers the XML-RPC multicall method in the system namespace. see http://www.xmlrpc.com/discuss/msgReader$1208""" self.funcs.update({'system.multicall' : self.system_multicall}) def _marshaled_dispatch(self, data, dispatch_method = None, path = None): """Dispatches an XML-RPC method from marshalled (XML) data. XML-RPC methods are dispatched from the marshalled (XML) data using the _dispatch method and the result is returned as marshalled data. For backwards compatibility, a dispatch function can be provided as an argument (see comment in SimpleXMLRPCRequestHandler.do_POST) but overriding the existing method through subclassing is the preferred means of changing method dispatch behavior. """ try: params, method = loads(data, use_builtin_types=self.use_builtin_types) # generate response if dispatch_method is not None: response = dispatch_method(method, params) else: response = self._dispatch(method, params) # wrap response in a singleton tuple response = (response,) response = dumps(response, methodresponse=1, allow_none=self.allow_none, encoding=self.encoding) except Fault as fault: response = dumps(fault, allow_none=self.allow_none, encoding=self.encoding) except: # report exception back to server exc_type, exc_value, exc_tb = sys.exc_info() try: response = dumps( Fault(1, "%s:%s" % (exc_type, exc_value)), encoding=self.encoding, allow_none=self.allow_none, ) finally: # Break reference cycle exc_type = exc_value = exc_tb = None return response.encode(self.encoding, 'xmlcharrefreplace') def system_listMethods(self): """system.listMethods() => ['add', 'subtract', 'multiple'] Returns a list of the methods supported by the server.""" methods = set(self.funcs.keys()) if self.instance is not None: # Instance can implement _listMethod to return a list of # methods if hasattr(self.instance, '_listMethods'): methods |= set(self.instance._listMethods()) # if the instance has a _dispatch method then we # don't have enough information to provide a list # of methods elif not hasattr(self.instance, '_dispatch'): methods |= set(list_public_methods(self.instance)) return sorted(methods) def system_methodSignature(self, method_name): """system.methodSignature('add') => [double, int, int] Returns a list describing the signature of the method. In the above example, the add method takes two integers as arguments and returns a double result. This server does NOT support system.methodSignature.""" # See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html return 'signatures not supported' def system_methodHelp(self, method_name): """system.methodHelp('add') => "Adds two integers together" Returns a string containing documentation for the specified method.""" method = None if method_name in self.funcs: method = self.funcs[method_name] elif self.instance is not None: # Instance can implement _methodHelp to return help for a method if hasattr(self.instance, '_methodHelp'): return self.instance._methodHelp(method_name) # if the instance has a _dispatch method then we # don't have enough information to provide help elif not hasattr(self.instance, '_dispatch'): try: method = resolve_dotted_attribute( self.instance, method_name, self.allow_dotted_names ) except AttributeError: pass # Note that we aren't checking that the method actually # be a callable object of some kind if method is None: return "" else: return pydoc.getdoc(method) def system_multicall(self, call_list): """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => \ [[4], ...] Allows the caller to package multiple XML-RPC calls into a single request. See http://www.xmlrpc.com/discuss/msgReader$1208 """ results = [] for call in call_list: method_name = call['methodName'] params = call['params'] try: # XXX A marshalling error in any response will fail the entire # multicall. If someone cares they should fix this. results.append([self._dispatch(method_name, params)]) except Fault as fault: results.append( {'faultCode' : fault.faultCode, 'faultString' : fault.faultString} ) except: exc_type, exc_value, exc_tb = sys.exc_info() try: results.append( {'faultCode' : 1, 'faultString' : "%s:%s" % (exc_type, exc_value)} ) finally: # Break reference cycle exc_type = exc_value = exc_tb = None return results def _dispatch(self, method, params): """Dispatches the XML-RPC method. XML-RPC calls are forwarded to a registered function that matches the called XML-RPC method name. If no such function exists then the call is forwarded to the registered instance, if available. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called. """ try: # call the matching registered function func = self.funcs[method] except KeyError: pass else: if func is not None: return func(*params) raise Exception('method "%s" is not supported' % method) if self.instance is not None: if hasattr(self.instance, '_dispatch'): # call the `_dispatch` method on the instance return self.instance._dispatch(method, params) # call the instance's method directly try: func = resolve_dotted_attribute( self.instance, method, self.allow_dotted_names ) except AttributeError: pass else: if func is not None: return func(*params) raise Exception('method "%s" is not supported' % method) class SimpleXMLRPCRequestHandler(BaseHTTPRequestHandler): """Simple XML-RPC request handler class. Handles all HTTP POST requests and attempts to decode them as XML-RPC requests. """ # Class attribute listing the accessible path components; # paths not on this list will result in a 404 error. rpc_paths = ('/', '/RPC2') #if not None, encode responses larger than this, if possible encode_threshold = 1400 #a common MTU #Override form StreamRequestHandler: full buffering of output #and no Nagle. wbufsize = -1 disable_nagle_algorithm = True # a re to match a gzip Accept-Encoding aepattern = re.compile(r""" \s* ([^\s;]+) \s* #content-coding (;\s* q \s*=\s* ([0-9\.]+))? #q """, re.VERBOSE | re.IGNORECASE) def accept_encodings(self): r = {} ae = self.headers.get("Accept-Encoding", "") for e in ae.split(","): match = self.aepattern.match(e) if match: v = match.group(3) v = float(v) if v else 1.0 r[match.group(1)] = v return r def is_rpc_path_valid(self): if self.rpc_paths: return self.path in self.rpc_paths else: # If .rpc_paths is empty, just assume all paths are legal return True def do_POST(self): """Handles the HTTP POST request. Attempts to interpret all HTTP POST requests as XML-RPC calls, which are forwarded to the server's _dispatch method for handling. """ # Check that the path is legal if not self.is_rpc_path_valid(): self.report_404() return try: # Get arguments by reading body of request. # We read this in chunks to avoid straining # socket.read(); around the 10 or 15Mb mark, some platforms # begin to have problems (bug #792570). max_chunk_size = 10*1024*1024 size_remaining = int(self.headers["content-length"]) L = [] while size_remaining: chunk_size = min(size_remaining, max_chunk_size) chunk = self.rfile.read(chunk_size) if not chunk: break L.append(chunk) size_remaining -= len(L[-1]) data = b''.join(L) data = self.decode_request_content(data) if data is None: return #response has been sent # In previous versions of SimpleXMLRPCServer, _dispatch # could be overridden in this class, instead of in # SimpleXMLRPCDispatcher. To maintain backwards compatibility, # check to see if a subclass implements _dispatch and dispatch # using that method if present. response = self.server._marshaled_dispatch( data, getattr(self, '_dispatch', None), self.path ) except Exception as e: # This should only happen if the module is buggy # internal error, report as HTTP server error self.send_response(500) # Send information about the exception if requested if hasattr(self.server, '_send_traceback_header') and \ self.server._send_traceback_header: self.send_header("X-exception", str(e)) trace = traceback.format_exc() trace = str(trace.encode('ASCII', 'backslashreplace'), 'ASCII') self.send_header("X-traceback", trace) self.send_header("Content-length", "0") self.end_headers() else: self.send_response(200) self.send_header("Content-type", "text/xml") if self.encode_threshold is not None: if len(response) > self.encode_threshold: q = self.accept_encodings().get("gzip", 0) if q: try: response = gzip_encode(response) self.send_header("Content-Encoding", "gzip") except NotImplementedError: pass self.send_header("Content-length", str(len(response))) self.end_headers() self.wfile.write(response) def decode_request_content(self, data): #support gzip encoding of request encoding = self.headers.get("content-encoding", "identity").lower() if encoding == "identity": return data if encoding == "gzip": try: return gzip_decode(data) except NotImplementedError: self.send_response(501, "encoding %r not supported" % encoding) except ValueError: self.send_response(400, "error decoding gzip content") else: self.send_response(501, "encoding %r not supported" % encoding) self.send_header("Content-length", "0") self.end_headers() def report_404 (self): # Report a 404 error self.send_response(404) response = b'No such page' self.send_header("Content-type", "text/plain") self.send_header("Content-length", str(len(response))) self.end_headers() self.wfile.write(response) def log_request(self, code='-', size='-'): """Selectively log an accepted request.""" if self.server.logRequests: BaseHTTPRequestHandler.log_request(self, code, size) class SimpleXMLRPCServer(socketserver.TCPServer, SimpleXMLRPCDispatcher): """Simple XML-RPC server. Simple XML-RPC server that allows functions and a single instance to be installed to handle requests. The default implementation attempts to dispatch XML-RPC calls to the functions or instance installed in the server. Override the _dispatch method inherited from SimpleXMLRPCDispatcher to change this behavior. """ allow_reuse_address = True # Warning: this is for debugging purposes only! Never set this to True in # production code, as will be sending out sensitive information (exception # and stack trace details) when exceptions are raised inside # SimpleXMLRPCRequestHandler.do_POST _send_traceback_header = False def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True, use_builtin_types=False): self.logRequests = logRequests SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding, use_builtin_types) socketserver.TCPServer.__init__(self, addr, requestHandler, bind_and_activate) class MultiPathXMLRPCServer(SimpleXMLRPCServer): """Multipath XML-RPC Server This specialization of SimpleXMLRPCServer allows the user to create multiple Dispatcher instances and assign them to different HTTP request paths. This makes it possible to run two or more 'virtual XML-RPC servers' at the same port. Make sure that the requestHandler accepts the paths in question. """ def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True, use_builtin_types=False): SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests, allow_none, encoding, bind_and_activate, use_builtin_types) self.dispatchers = {} self.allow_none = allow_none self.encoding = encoding or 'utf-8' def add_dispatcher(self, path, dispatcher): self.dispatchers[path] = dispatcher return dispatcher def get_dispatcher(self, path): return self.dispatchers[path] def _marshaled_dispatch(self, data, dispatch_method = None, path = None): try: response = self.dispatchers[path]._marshaled_dispatch( data, dispatch_method, path) except: # report low level exception back to server # (each dispatcher should have handled their own # exceptions) exc_type, exc_value = sys.exc_info()[:2] try: response = dumps( Fault(1, "%s:%s" % (exc_type, exc_value)), encoding=self.encoding, allow_none=self.allow_none) response = response.encode(self.encoding, 'xmlcharrefreplace') finally: # Break reference cycle exc_type = exc_value = None return response class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): """Simple handler for XML-RPC data passed through CGI.""" def __init__(self, allow_none=False, encoding=None, use_builtin_types=False): SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding, use_builtin_types) def handle_xmlrpc(self, request_text): """Handle a single XML-RPC request""" response = self._marshaled_dispatch(request_text) print('Content-Type: text/xml') print('Content-Length: %d' % len(response)) print() sys.stdout.flush() sys.stdout.buffer.write(response) sys.stdout.buffer.flush() def handle_get(self): """Handle a single HTTP GET request. Default implementation indicates an error because XML-RPC uses the POST method. """ code = 400 message, explain = BaseHTTPRequestHandler.responses[code] response = http.server.DEFAULT_ERROR_MESSAGE % \ { 'code' : code, 'message' : message, 'explain' : explain } response = response.encode('utf-8') print('Status: %d %s' % (code, message)) print('Content-Type: %s' % http.server.DEFAULT_ERROR_CONTENT_TYPE) print('Content-Length: %d' % len(response)) print() sys.stdout.flush() sys.stdout.buffer.write(response) sys.stdout.buffer.flush() def handle_request(self, request_text=None): """Handle a single XML-RPC request passed through a CGI post method. If no XML data is given then it is read from stdin. The resulting XML-RPC response is printed to stdout along with the correct HTTP headers. """ if request_text is None and \ os.environ.get('REQUEST_METHOD', None) == 'GET': self.handle_get() else: # POST data is normally available through stdin try: length = int(os.environ.get('CONTENT_LENGTH', None)) except (ValueError, TypeError): length = -1 if request_text is None: request_text = sys.stdin.read(length) self.handle_xmlrpc(request_text) # ----------------------------------------------------------------------------- # Self documenting XML-RPC Server. class ServerHTMLDoc(pydoc.HTMLDoc): """Class used to generate pydoc HTML document for a server""" def markup(self, text, escape=None, funcs={}, classes={}, methods={}): """Mark up some plain text, given a context of symbols to look for. Each context dictionary maps object names to anchor names.""" escape = escape or self.escape results = [] here = 0 # XXX Note that this regular expression does not allow for the # hyperlinking of arbitrary strings being used as method # names. Only methods with names consisting of word characters # and '.'s are hyperlinked. pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|' r'RFC[- ]?(\d+)|' r'PEP[- ]?(\d+)|' r'(self\.)?((?:\w|\.)+))\b') while 1: match = pattern.search(text, here) if not match: break start, end = match.span() results.append(escape(text[here:start])) all, scheme, rfc, pep, selfdot, name = match.groups() if scheme: url = escape(all).replace('"', '"') results.append('%s' % (url, url)) elif rfc: url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc) results.append('%s' % (url, escape(all))) elif pep: url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep) results.append('%s' % (url, escape(all))) elif text[end:end+1] == '(': results.append(self.namelink(name, methods, funcs, classes)) elif selfdot: results.append('self.%s' % name) else: results.append(self.namelink(name, classes)) here = end results.append(escape(text[here:])) return ''.join(results) def docroutine(self, object, name, mod=None, funcs={}, classes={}, methods={}, cl=None): """Produce HTML documentation for a function or method object.""" anchor = (cl and cl.__name__ or '') + '-' + name note = '' title = '%s' % ( self.escape(anchor), self.escape(name)) if inspect.ismethod(object): args = inspect.getfullargspec(object) # exclude the argument bound to the instance, it will be # confusing to the non-Python user argspec = inspect.formatargspec ( args.args[1:], args.varargs, args.varkw, args.defaults, annotations=args.annotations, formatvalue=self.formatvalue ) elif inspect.isfunction(object): args = inspect.getfullargspec(object) argspec = inspect.formatargspec( args.args, args.varargs, args.varkw, args.defaults, annotations=args.annotations, formatvalue=self.formatvalue) else: argspec = '(...)' if isinstance(object, tuple): argspec = object[0] or argspec docstring = object[1] or "" else: docstring = pydoc.getdoc(object) decl = title + argspec + (note and self.grey( '%s' % note)) doc = self.markup( docstring, self.preformat, funcs, classes, methods) doc = doc and '

%s
' % doc return '
%s
%s
\n' % (decl, doc) def docserver(self, server_name, package_documentation, methods): """Produce HTML documentation for an XML-RPC server.""" fdict = {} for key, value in methods.items(): fdict[key] = '#-' + key fdict[value] = fdict[key] server_name = self.escape(server_name) head = '%s' % server_name result = self.heading(head, '#ffffff', '#7799ee') doc = self.markup(package_documentation, self.preformat, fdict) doc = doc and '%s' % doc result = result + '

%s

\n' % doc contents = [] method_items = sorted(methods.items()) for key, value in method_items: contents.append(self.docroutine(value, key, funcs=fdict)) result = result + self.bigsection( 'Methods', '#ffffff', '#eeaa77', ''.join(contents)) return result class XMLRPCDocGenerator: """Generates documentation for an XML-RPC server. This class is designed as mix-in and should not be constructed directly. """ def __init__(self): # setup variables used for HTML documentation self.server_name = 'XML-RPC Server Documentation' self.server_documentation = \ "This server exports the following methods through the XML-RPC "\ "protocol." self.server_title = 'XML-RPC Server Documentation' def set_server_title(self, server_title): """Set the HTML title of the generated server documentation""" self.server_title = server_title def set_server_name(self, server_name): """Set the name of the generated HTML server documentation""" self.server_name = server_name def set_server_documentation(self, server_documentation): """Set the documentation string for the entire server.""" self.server_documentation = server_documentation def generate_html_documentation(self): """generate_html_documentation() => html documentation for the server Generates HTML documentation for the server using introspection for installed functions and instances that do not implement the _dispatch method. Alternatively, instances can choose to implement the _get_method_argstring(method_name) method to provide the argument string used in the documentation and the _methodHelp(method_name) method to provide the help text used in the documentation.""" methods = {} for method_name in self.system_listMethods(): if method_name in self.funcs: method = self.funcs[method_name] elif self.instance is not None: method_info = [None, None] # argspec, documentation if hasattr(self.instance, '_get_method_argstring'): method_info[0] = self.instance._get_method_argstring(method_name) if hasattr(self.instance, '_methodHelp'): method_info[1] = self.instance._methodHelp(method_name) method_info = tuple(method_info) if method_info != (None, None): method = method_info elif not hasattr(self.instance, '_dispatch'): try: method = resolve_dotted_attribute( self.instance, method_name ) except AttributeError: method = method_info else: method = method_info else: assert 0, "Could not find method in self.functions and no "\ "instance installed" methods[method_name] = method documenter = ServerHTMLDoc() documentation = documenter.docserver( self.server_name, self.server_documentation, methods ) return documenter.page(html.escape(self.server_title), documentation) class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): """XML-RPC and documentation request handler class. Handles all HTTP POST requests and attempts to decode them as XML-RPC requests. Handles all HTTP GET requests and interprets them as requests for documentation. """ def do_GET(self): """Handles the HTTP GET request. Interpret all HTTP GET requests as requests for server documentation. """ # Check that the path is legal if not self.is_rpc_path_valid(): self.report_404() return response = self.server.generate_html_documentation().encode('utf-8') self.send_response(200) self.send_header("Content-type", "text/html") self.send_header("Content-length", str(len(response))) self.end_headers() self.wfile.write(response) class DocXMLRPCServer( SimpleXMLRPCServer, XMLRPCDocGenerator): """XML-RPC and HTML documentation server. Adds the ability to serve server documentation to the capabilities of SimpleXMLRPCServer. """ def __init__(self, addr, requestHandler=DocXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True, use_builtin_types=False): SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests, allow_none, encoding, bind_and_activate, use_builtin_types) XMLRPCDocGenerator.__init__(self) class DocCGIXMLRPCRequestHandler( CGIXMLRPCRequestHandler, XMLRPCDocGenerator): """Handler for XML-RPC data and documentation requests passed through CGI""" def handle_get(self): """Handles the HTTP GET request. Interpret all HTTP GET requests as requests for server documentation. """ response = self.generate_html_documentation().encode('utf-8') print('Content-Type: text/html') print('Content-Length: %d' % len(response)) print() sys.stdout.flush() sys.stdout.buffer.write(response) sys.stdout.buffer.flush() def __init__(self): CGIXMLRPCRequestHandler.__init__(self) XMLRPCDocGenerator.__init__(self) if __name__ == '__main__': import datetime class ExampleService: def getData(self): return '42' class currentTime: @staticmethod def getCurrentTime(): return datetime.datetime.now() with SimpleXMLRPCServer(("localhost", 8000)) as server: server.register_function(pow) server.register_function(lambda x,y: x+y, 'add') server.register_instance(ExampleService(), allow_dotted_names=True) server.register_multicall_functions() print('Serving XML-RPC on localhost port 8000') print('It is advisable to run this example server within a secure, closed network.') try: server.serve_forever() except KeyboardInterrupt: print("\nKeyboard interrupt received, exiting.") sys.exit(0)